Execution commands
These commands use physics-inspired names (nucleate, evolve, decay, spore, …). New to the vocabulary? See The physics vocabulary.
cs tackle
Tackle a molecule — claim before model selection and spawn ONE worker (for DAG walks use cs run)
Usage: cs tackle [OPTIONS] <MOLECULE>
EXAMPLES:
cs tackle task-example-0001 # worktree + tmux + Claude (one node)
cs tackle
--base makes the integration branch a property of the MOLECULE: the
worker's branch is cut from it, the name is persisted in the molecule's
state, and cs done merges back into it with no COSMON_BASE_BRANCH in
the environment. Without --base, the branch is cut from the ambient
HEAD and cs done falls back to COSMON_BASE_BRANCH → origin/HEAD → main,
exactly as before.
cs tackle is ALWAYS leaf — it spawns one worker on the named node and
never walks the DAG. To walk a DAG of N≥1 nodes (1 = leaf, N = full
orchestration), use cs run instead. Human only. Workers never
self-tackle. Pairs with cs done.
Dispatch claims are per molecule and precede model selection. If another tackle wins, this command exits non-zero and names its worker, adapter and selected model. An unpinned adapter default is reported as unrecorded.
The historical --leaf and --force-runtime flags are deprecated
no-ops since the verb-unification: the routing decision is now the
verb itself, not a flag on a polymorphic command.
SEE ALSO: cs run (DAG walk), cs done (teardown), cs wait (block on completion).
Arguments:
<MOLECULE>— Molecule ID, prefix, or fuzzy name (e.g. "ADR-15", "idea-2026")
Options:
-
--fleet <FLEET>— Fleet to use (default: molecule's fleet) -
--workdir <WORKDIR>— Working directory override (default: .worktrees/{mol-id}) -
--base <BRANCH>— Integration base branch for this molecule (default: the ambient HEAD of the main checkout).The worker's
feat/{mol-id}branch is cut from this ref instead of whatever the main checkout has checked out, and the branch name is persisted on the molecule socs donemerges back into it without anyCOSMON_BASE_BRANCHin the environment. Makes the base a property of the molecule rather than of the session that launched it. -
--no-worktree— Skip git worktree creation (use current directory) -
--dry-run— Skip tmux session — print the prompt to stdout instead -
--permission-mode <PERMISSION_MODE>— Permission mode for Claude (default: based on molecule kind) -
--force— Boolean flag: reclaim the molecule's live tmux session and respawn the worker. Also thaws a frozen molecule, returning it torunning. A session left behind by a dead worker is reclaimed without this flag -
--resume— Continue the molecule's interrupted in-process (openai/anthropic) attempt from its last complete tool-result checkpoint instead of starting a fresh log. Use with--forceto thaw a frozen molecule.Continuation reads the durable turn evidence on disk and nothing else. It is refused, with the reason, when the evidence does not prove it safe: a tool with no receipt (its effect is unknown and is never repeated), a request with no outcome (it may have been billed), a shell session whose state no record captures, no complete checkpoint, a changed formula, model, tool registry, briefing, worktree or loop ceiling, a spent wall-clock budget, or damaged evidence. Tool calls and turns already spent stay spent. Without this flag a dispatch starts a fresh attempt, as before.
-
--name <NAME>— Override the tmux session name. ASCII alphanumerics and hyphens are kept; everything else is replaced with-. Max 50 chars. Default:{slug}-{shortid}derived from the molecule topic + id -
--bypass-seal— Override the ADR-085 stress-test seal at dispatch (Layer 1).Without this flag,
cs tackleof a--class stress-testmolecule refuses dispatch unlessprior.md+prior.b3exist on disk and a matchingcs witness attestevent has been emitted. With it, the runtime writes a typedBypassReceiptto<molecule_dir>/bypass-receipt.jsonand emitsEventV2::SealBypassed, then proceeds with dispatch. Requires--bypass-reason "<…>"— silent overrides are forbidden by ADR-085 §3.5. -
--bypass-reason <TEXT>— One-line reason recorded in theBypassReceiptwhen--bypass-sealis used.Free-text but non-empty; the runtime refuses a blank reason because the entire point of the receipt is to surface accountability for the override (ADR-085 §3.5).
-
--adapter <NAME>— Worker-Spawn Port Adapter to dispatch (ADR-097 / C6; ADR-108 Q5a chain).Resolution order (highest priority first): this flag → durable molecule pin stamped by
cs nucleate --adapter→ formula-stepadapter = "<name>"pin →$COSMON_DEFAULT_ADAPTERenv var → per-galaxy.cosmon/config.toml::[adapters] default = "…"→ global~/.config/cosmon/config.toml::[adapters] default = "…"→ built-in"local"(the Ollama-backed in-process loop). Values are looked up against the registered Adapter table (claude,aider,openai,anthropic,llama-cpp,local, …). An unknown name aborts the dispatch with a typedAdapterNotFoundcarrying the list of available names — no silent fallback. To restore the legacy Claude-Code default pass--adapter claude,export COSMON_DEFAULT_ADAPTER=claude, or set[adapters]thendefault = "claude"in either config file.Capability gate (noogram/cosmon #4)
A formula may declare what its steps need of a worker (
requires_capabilities = ["shell", "vcs"]). A local adapter (local/ollama/llama-cpp/llama) is an in-process chat loop with no shell, no VCS and nocscommand, so such a pairing is refused with exit code 17 — before any worktree, pane or model preflight, and under--dry-runtoo. The molecule stays pending and re-tacklable. Re-run with a coding-agent adapter, or setCOSMON_SKIP_CAPABILITY_GATE=1to dispatch anyway. Formulas that declare nothing are unaffected on every adapter.Every invocation (with or without the flag) emits an
EventV2::AdapterSelectedenvelope so the cat-test (jq -c 'select(.type == "adapter_selected")') can answer "which Adapter ran for this molecule?" without parsing shell history.Composition with
cs run --resident(issue-#21, reconciled)The resident loop (
cs run --resident) is not a second resolver; it is a composer that delegates to this one chain. Its scheduler owns only the two dispatch intents — a per-molecule pin and the opt-incs run --adapter <name>run directive — and stamps them onto the shelledcs tackle. When neither is present it stamps no--adapterflag, so the remaining six-level chain runs unchanged in the child: formula step →$COSMON_DEFAULT_ADAPTER→ per-galaxy config → global config → thelocalfloor. The floor is therefore reached under--residentiff it is reached under a barecs tackle, and the operator's env and committed config are honoured identically on both paths — the #21 fix removed the resident-only--adapter localstamp that used to mask them. Seecs run --help(--adapter) andcosmon_runtime::resident. -
--model <MODEL_ID>— Per-molecule model pin — the model sibling of--adapter(see ADR-097).Resolution order (highest priority first): this flag → molecule
cosmon_modelvariable set at nucleation → formula-stepmodel = "<id>"pin →$COSMON_DEFAULT_MODEL(else the legacy$ANTHROPIC_MODEL) env var → per-galaxy.cosmon/config.toml::[adapters.<name>].default_model→ global~/.config/cosmon/config.toml::[adapters.<name>].default_model→ floorNone(cosmon pins no model; the adapter's own default applies — byte-identical to today's no-pin behaviour).Strong is never inherited. Every dispatch resolves the model fresh; a strong (frontier) model is reachable only from this flag, a child pin, or a formula-step pin — a positive per-molecule act — never from a config/env default that could silently make an entire fleet expensive (the
/model-hack leak this axis exists to close).The id is carried opaquely: cosmon keeps no model allowlist. When both the resolved adapter and model identify different named provider families, however, the pair is refused before spawn because the stock adapter cannot run it. Self-hosted endpoints and unrecognised model ids remain opaque and pass through. Config
default_modelrows are scoped per adapter because a model id only has meaning inside its adapter. -
--role-hint <ROLE>— Forensic-only role-of-origin hint propagated through toEventV2::AdapterSelected(ADR-097 / C6).Cosmon does not interpret this value — it is the academy-shim's channel for preserving the driver's vocabulary (a
--role researcherinvocation on the driver side becomesrole_hint: "researcher"on the cosmon event), so the role of origin survives the seam between driver (roles) and cosmon (adapters). Optional; absent for direct operator invocations. -
--reclaim-derived— Reclaim derived build output from other worktrees before spawning (issue 61, ADR-178).The pre-spawn pressure check. A dispatch is the one moment cosmon is guaranteed to be running and the moment disk demand grows — a new worktree and a new build directory — so it is where the actor that creates the leak pays for it. Nothing runs it on a timer: there is no daemon, no LRU and no background sweep, because nothing destructive may run unobserved.
It governs tier 1 only: rebuildable payload under the
[worktree_reclaim].evictroots of worktrees whose molecule is terminal (or absent) and whose build lock it could acquire. It cannot reach durable content —cs tacklenever consults durable eligibility, and no path in this workspace removes a worktree. -
--fallback-from-local <CAUSE>— Loud opt-in fallback from the local default to a remote oracle after a decidable local hard-failure (Q5b).Pass a
LocalFailureCausetoken —crash,oom,timeout,connection-refused, or any bespoke string (recorded verbatim asOther). This flag is the ONLY path from a local hard-failure to a remote oracle: there is no automatic in-loop fallback. It is meaningful only alongside a remote--adapter(claude / openai / anthropic / aider) — combining it with a local adapter is a contradiction and aborts the dispatch.When set,
cs tacklemints anEventV2::LocalFallbackline in the same atom as theRemoteEgressOptInegress grant, so a remote call carrying a fallback cause can never reach the wire without a matching loud audit record — silent fallback is impossible by construction. Soft "the output looked bad" judgement is NOT a valid cause: that is undecidable (Rice) and belongs to acceptance tests, not this routing flag. -
--by <ACTOR>— Actor class recording who dispatched this molecule — the anti-preemption lease.Accepts
human(the default when the flag is absent — a direct operator invocation) orruntime:<pid>(the resident runtimecs runpasses its own process id). The value is stamped onto the molecule'stackled_byfield when the molecule flips toRunning, so the walker can preserve a prior human claim: a human-claimed molecule is never raffled by the runtime, even if it briefly returns toPendingon a revision. This iscs tackle's only role in the lease — recording the claim; honouring it is the walker's job.Default value:
human -
--harness <KEY=VALUE>— Per-dispatch harness setting —key=value, repeatable (ADR-177 / issue #65).--modelpins which model runs; this pins how it runs, by handing the pair to the adapter's own override channel:codex→ one-c key=valueper entry, e.g.--harness model_reasoning_effort=high. To pin the service tier for this dispatch, use--harness service_tier=defaultfor Standard processing (Fast off), or--harness service_tier=priorityfor Fast processing.fastis also accepted as the Fast spelling; Fast availability depends on the selected model and account; -claude→--<key> <value>per entry, e.g.--harness effort=xhigh; - any other adapter → the dispatch fails at launch, naming the adapter. A setting is never silently dropped.
cosmon recognises no keys
The pair is carried verbatim to the harness and logged verbatim as sent. cosmon never normalises a key, rewrites a value, or keeps an allowlist — an unknown key fails in the harness's own parser, at launch, loudly, which is where knowledge about that harness's keys lives and stays current. A key cosmon recognised would become public API carried in files on other people's disks, with no mechanism by which its removal could be announced.
Precedence, merged per key
This flag → the executing step's
[steps.harness]table → the harness's own config. Merged key by key, never wholesale: overriding one key leaves every other key the step pinned exactly where it was. Rank 3 is not a cosmon surface — cosmon passing no key is the only way the harness's own default can apply.What the audit trail claims, and what it does not
Each resolved key lands on
events.jsonlas aharness_setting_selectedline carrying its source, the realized argv fragment, the channel, the harness version and the launch status. That receipt is ex-ante: it records what cosmon dispatched, minted before the process exists. Paired with the harness's own echo, the strongest true sentence is "cosmon requested E through channel C; the harness's own log reported E" — a two-party agreement, not a proof of behaviour. Nothing here supports "the step ran at E".
cs done
Done — terminal teardown for a molecule (merge + cleanup, human-callable)
A failed merge reports the merge error and any dirty checkout paths. [project] merge_subject may set the merge commit subject per galaxy; its template must include {mol_id}. Unset, the subject is unchanged. Tracked harvest state, including archive and event files, is committed before the next sibling merge; ignored molecule directories are skipped.
Usage: cs done [OPTIONS] <MOLECULE>
EXAMPLES:
cs done task-example-0001 # merge + teardown
cs done
Not-the-worker. Legitimate callers: humans, external schedulers
(cron/launchd), and transport watchdogs (tmux pane-died hooks via
cs done --if-completed). Required to close the nucleate → tackle →
wait → done cycle: without it the branch never merges and the tmux
worktree persists.
--if-completed is the hook-friendly gate: exits success without
touching state when the molecule is not Completed or already merged;
behaves identically to plain cs done otherwise. Supersedes the
former cs harvest verb (ADR-052 §D3).
BASE BRANCH — the branch this merge lands on is resolved once per run, in this order (first that answers wins):
- the molecule's own base, stamped by
cs tackle --base <branch> - the COSMON_BASE_BRANCH environment variable
git symbolic-ref refs/remotes/origin/HEAD- the literal main
Rung 1 is why a cs done fired from a tmux hook — whose environment
froze when the tmux server started and never saw a later export —
still merges onto the right trunk. Molecules tackled without --base
resolve through rungs 2-4 exactly as they always did. cs done still
refuses (NotOnBase) when HEAD is not the resolved base: git merges into
the current HEAD, never into a branch by name.
SEE ALSO: cs complete (state transition only), cs tackle (counterpart).
Arguments:
<MOLECULE>— Molecule ID to tear down
Options:
-
--reason <REASON>— Why this molecule is being closed. Traced trunk-side on the molecule.Optional here and mandatory over the wire (
POST /v1/molecules/{id}/done), and the asymmetry is deliberate. An operator standing at their own terminal is the author of the git history this harvest writes; a requester reaching the door over §8p is not, and the trunk-side reason is the only account a later reader has of why someone else's molecule was closed. Making it mandatory here too would break every hook, patrol sweep andcs runteardown that legitimately closes a molecule without a sentence to add — a usability amputation with no safety property behind it.What is not optional anywhere is honesty: when no reason is given, none is recorded. The withdrawn
landgesture fabricated a generic one, and a fabricated reason is indistinguishable, a year later, from one somebody meant. -
--force— Proceed even if the molecule is not in a terminal state -
--if-completed— Silent no-op when the molecule is notCompletedor already merged.Hook-friendly gate for callers that do not know whether the molecule is ready for teardown — tmux
pane-diedhooks, patrol sweeps, and the legacycs harvestalias. Exits success without touching state when the precondition is not met; otherwise, behaves exactly likecs done. Supersedes the stand-alonecs harvestverb (ADR-052). -
--dry-run— Compute and display the teardown plan without executing any steps.Reports what
cs donewould do: worktree state (clean/dirty), whether a merge is needed, whether the tmux session is alive, whether a fleet worker is registered, and whether the branch exists. -
--no-merge— Skip merging the worker's branch into the base branch -
--review-shell— Review a merge's changed shell surface and grant trust over the merged files before the post-merge gate. Requires an explicit operator reply; declining rolls the merge back and preserves the branch -
--no-worktree-remove— Skip removing the git worktree -
--no-branch-delete— Skip deleting the worker's branch after merge -
--no-kill— Skip killing the tmux session -
--strategy <STRATEGY>— Merge strategy for the worker's branch.merge(default) creates a merge commit (git merge --no-ff) so parallel workers can land independently even when main has moved.ff-onlypreserves a strictly linear history and refuses anything that is not a fast-forward; it is refused when native attribution is configured because a fast-forward creates no trailer carrier.Default value:
mergePossible values:
merge: Non-fast-forward merge (git merge --no-ff --no-edit)ff-only: Fast-forward-only merge (git merge --ff-only)
-
--no-auto-propel— Disable auto-propel escalation on merge conflict.By default, when a merge conflict is detected,
cs doneescalates by sending a resume signal to the worker with rebase instructions, then retries the merge after a backoff delay. This flag restores the old behavior: abort immediately and print a manual-resolution message.Mechanical-first escalation: see docs/architectural-invariants.md
-
--propel-message <PROPEL_MESSAGE>— Custom message sent to the worker during auto-propel escalation.The default instructs the worker to rebase onto the base branch, resolve conflicts, run tests, and NOT call
cs doneitself. -
--max-retries <MAX_RETRIES>— Maximum number of auto-propel escalation retries before giving upDefault value:
3 -
--skip-pre-done-hook— Skip the blocking[hooks] pre_donegate for this invocation.The
pre_donehook (when configured) runs before the merge and aborts teardown on a non-zero exit — the galaxy-owned Definition-of- Done gate. This flag is the human operator's kill-switch: it bypasses the gate entirely for a deliverable the operator knows is good but the script cannot see (e.g. evidence living outside the repo). Equivalent to setting theCOSMON_SKIP_PRE_DONE_HOOKenvironment variable. No effect when nopre_donehook is configured. -
--deploy-off-trunk— Run the[hooks] post_mergedeploy hook even when this harvest merges into a parked work branch rather than the reference trunk.By default the
post_mergehook is bounded to the trunk: it fires only when the resolved integration base is the galaxy's reference trunk (origin/HEAD, ormainas a last resort). The hook deploys — the canonicaljust installrefreshes the on-diskcsbinary — so running it after a merge into an older parked branch would silently rejuvenate the operator's tool, dropping whatever the parked branch predates (task-20260725-b64f). When the merge targets a parked branch the hook is skipped with a warning naming the reason.This flag is the operator's explicit escape hatch for the rare-but- legitimate case of deploying from a parked branch on purpose. No effect when no
post_mergehook is configured or when the merge already targets the trunk. -
--allow-protected-change— Merge even though the worker branch changed a path the molecule declared protected (cs nucleate --protect, issue #94).Without it,
cs donerefuses such a branch (protected_path_modified, exit 78) and names each protected path it changed. Protected paths are reference inputs; a branch that rewrites them can make any result "match". Pass this flag only when you, the operator, have read the change and it is intended — for example a reference dataset that was itself wrong. No effect on a molecule that declared no protected path.
cs sync
Sync — base-sync the current worktree from main, stamping a Base-Sync trailer
Usage: cs sync [OPTIONS]
Options:
-
--base <BASE>— Base branch to sync from (defaults tomain)Default value:
main -
--dry-run— Report what would happen without performing the merge
cs harvest
Harvest — close a completed-but-unmerged molecule by invoking cs done
Usage: cs harvest [OPTIONS] --molecule <MOLECULE>
EXAMPLES: cs harvest --molecule task-example-0001 # DEPRECATED — see below
DEPRECATED (ADR-052 §D3): use cs done --if-completed <mol> instead.
The canonical path carries byte-identical semantics: silent no-op when
the molecule is not Completed or already merged; full teardown
otherwise. This alias will be removed after one release cycle.
SEE ALSO: cs done --if-completed (canonical), cs patrol --harvest (belt-and-suspenders sweep).
Options:
-
--molecule <MOLECULE>— Molecule to harvest. Required —cs harvestoperates on one molecule per invocation. Usecs patrol --harvestfor the sweep variant -
--dry-run— Print whatcs harvestwould do without exec'ingcs done -
--from-pane-died— Flag the invocation as caused by a tmuxpane-diedhook.ADR-052 child #4 (I4 + I8 + I10): the probe must emit its observation before acting on it. When set,
cs harvestfirst appends aEventV2::WorkerExitedevent toevents.jsonl(reason =pane_died) and then runs the normal harvest logic. Absent this flag, noWorkerExitedis emitted — periodiccs patrol --harvestsweeps observe via witness, not via the kernel-level pane-died channel. -
--exit-code <EXIT_CODE>— Exit code reported by tmux#{pane_dead_status}when the pane died.Only meaningful together with
--from-pane-died. Accepts any signed 32-bit integer so the wait-status (which may encode signals) survives round-trip. Strings that fail to parse are treated as "no information" (Nonein the emitted event).
cs run
Run — walk a molecule DAG of N≥1 nodes via the resident runtime (ADR-016 Layer B)
Usage: cs run [OPTIONS] [MOLECULE]
EXAMPLES:
tmux new -d -s runtime cs run
Resident runtime — walks a DAG of N≥1 nodes. Calls cs tackle for each
ready node and cs done automatically as predecessors complete. The
single-node case (1 = leaf) is the same code path as the N-node case;
cs tackle <id> is the no-walk equivalent if the operator wants exactly
one worker without any runtime ceremony.
NEVER run cs run in the foreground; always detach via tmux so the
pilot stays responsive.
SEE ALSO: cs tackle (single node, no runtime), docs/handbook.md#one-primitive.
Arguments:
-
<MOLECULE>— Root molecule ID (supports prefix matching like other commands).Required for the legacy DAG-policy mode. With
--residentthe loop walks the whole ensemble, so this argument is optional (any value, including_, is accepted and ignored).Default value: ``
Options:
-
--policy <POLICY>— Scheduling policy to useDefault value:
dagPossible values:
dag,noop -
--timeout <TIMEOUT>— Maximum seconds before the runtime exits. 0 means no timeout (default)Default value:
0 -
--poll-interval <POLL_INTERVAL>— Seconds between runtime ticks. Lower values are more responsive but increase store I/ODefault value:
1 -
--no-teardown— Skip automatic teardown of completed molecules after the run.Teardown runs
cs doneon every molecule that reachedCompleted— and only those. ACollapsedmolecule is explicitly-abandoned work: it is terminal, butcs donealso merges the molecule's branch onto the trunk, so a collapsed branch must never be handed to it. A teardown that fails exits with the NAMED code 93 (teardown_failed): the branch is unmerged and the worktree / session is still standing, which a detached caller cannot learn any other way. -
--sweep-every <SWEEP_EVERY>— ADR-038 Limit 1: re-walk the store every N ticks to absorb descendants nucleated dynamically by workers (mission-controller decompose, deep-think step 4, etc.) that are not reachable from the runtime's root via pre-existing typed links. Zero disables the sweep (default) — the scope is frozen at compile-plan time, which is the pre-2026-04-14 behaviorDefault value:
0 -
--force-runtime— Override the ADR-048 backlog-sanity guard on runtime bootstrap.When a dirty backlog would normally refuse runtime bootstrap (sediment ≥ threshold, default 5),
--force-runtimebypasses the refusal and writes aruntime_guard_overrideaudit event toevents.jsonlso the override leaves a durable trail. -
--max-actions <MAX_ACTIONS>— B3 — decreasing action budget (moussage bounds). Each applied runtime action costs one unit; when the budget floor is reached the loop exits with the NAMED reasonbudget_exhausted(exit code 90) instead of dispatching further. This is the well-founded measure that makes an unbounded moussage total. 0 = unbounded (default, operator-local behaviour unchanged). Server-side callers (the tenant drain path) pass the binding-derived value — the bound is never client-writableDefault value:
0 -
--max-depth <MAX_DEPTH>— B1 — maximum DAG depth (longest dependency chain, in molecules). Checked at compile-plan time, BEFORE the loop starts: a plan deeper than the bound is refused with the NAMED errormax_depth_exceeded(exit code 92), never started. 0 = unbounded (default)Default value:
0 -
--max-molecules <MAX_MOLECULES>— B2 — maximum molecules tolerated in the fleet while draining. Checked at compile-plan time AND on every loop tick (so mid-run nucleations count); exceeding it exits with the NAMED reasonmolecule_quota_exceeded(exit code 91). 0 = unbounded (default)Default value:
0 -
--resident— ADR-095 — switch to the fully event-sourced Resident Runtime loop.When set, the legacy in-process
DagPolicyis bypassed and the new [cosmon_runtime::RuntimeLoop] takes over. The loop:- Shells out to
cs ensemble --json,cs tackle,cs doneexactly as a human operator would (RR-1). - Wakes on FS changes under.cosmon/state/(notify backend) plus a--poll-intervalheartbeat. - Writes an NDJSON trace line per loop iteration to.cosmon/state/runtime-trace.jsonl(RR-5). - Exits cleanly on SIGTERM / Ctrl-C. - Drains when the ensemble has nopendingand norunning.
Config-honoring dispatch (ADR-016 delib-20260531-c761, refined by issue #91). The loop seals
.cosmon/config.toml(+ the global~/.config/cosmon/config.toml) at launch and re-checks it before every dispatch. An on-disk edit is then one of:- Reloaded (no halt) — no running molecule's effective adapter settings changed. This includes edits outside
[adapters], edits to an adapter no running worker uses, and edits while none is running. The loop adopts the fresh config for its next dispatch and records aconfig-reloadedtrace line and summary count. - Halted fail-closed — a running molecule's effective adapter settings changed, or its adapter cannot be identified. The loop refuses to form its next dispatch, emitsEventV2::ConfigDriftDetected, and exits non-zero (EX_TEMPFAIL, 75) so a supervisor relaunches a fresh process that re-derives everything from disk — it never merges the new config into a live process.
The
csbinary image itself is never sealed (acs donemerge reinstalls it on every successful drain by design).Does not require
<molecule>— the loop walks the whole ensemble. The positional argument is accepted but ignored in resident mode; pass_if you have nothing to name. - Shells out to
-
--affinity— ADR-145 — model-affinity ordering of the ready frontier.On a single-resident-model local oracle (
ollama-g5: 48 GB ≈ one 120 B model in VRAM), an alternating frontier reloads the model (~40 GB off disk) on every dispatch. With--affinitythe runtime clusters same-model molecules contiguously and drains the resident model first, so a same-model batch pays the load cost once. The per-molecule model is PRE-RESOLVED from itscosmon_modelvariable, then its formula-stepmodel =pin, since a pending frontier molecule has noModelSelectedevent yet.Off by default: cloud dispatch (many models, no resident constraint) keeps pure critical-path order. The reorder is a permutation — the DAG semantics and the set of dispatched molecules are unchanged; only the order within a ready batch differs. Legacy DAG-policy mode only (not
--resident). -
--resident-model <RESIDENT_MODEL>— Model already warm in the oracle's VRAM at runtime start, so the affinity reorder drains its bucket first with no reload. Only read when--affinityis set; a cold start (unset) simply pays one extra load for the first bucket -
--adapter <NAME>— Opt-in run-wide adapter directive (resident mode only).The resident scheduler owns exactly one run-wide flag intent — this flag — and nothing below it (COSMON-DEV #21). Passing
--adapter <name>is the operator's explicit, conscious choice to spend on that adapter for this run: it stamps every pin-less molecule dispatched — both static frontier nodes and children a worker nucleates dynamically mid-run (the converge/committee loop). A per-molecule pin still wins over it.When this flag is absent, the scheduler stamps nothing: the shelled
cs tackleinherits the environment and runs the full canonical resolution chain itself (formula step →$COSMON_DEFAULT_ADAPTER→ per-galaxy config → global config → the built-inlocalfloor). So the operator's live env, session hammer, and committed config are all honoured under--residentexactly as they are under a barecs tackle— the resident loop no longer masks them with a rung-1--adapter localfloor (the #21 defect). Thelocalfloor is still reached iff nothing higher speaks, so an inadvertent paid dispatch remains impossible: a paid adapter is chosen only by a conscious flag, formula step, env export, or committed config. Seedocs/adr(ADR-095) and thecs tackleadapter-chain docs for the single canonical resolution order. -
--base <BRANCH>— Opt-in run-wide integration base (resident mode only).The base twin of
--adapter, with the same two-rung precedence: every pin-less molecule this run dispatches — one with no persisted base — is tackled with--base <BRANCH>, which persists the base on the molecule so itscs donemerges into<BRANCH>rather than the ambient HEAD. A molecule that already carries a base (cs nucleate --base, an earliercs tackle --base) keeps it: the per-molecule base wins.This is how a germinated polymer (
cs spore run,cs nucleate --from) is aimed at an integration branch without tackling each node by hand. The branch must exist locally; a dangling base is refused before the loop starts. -
--harness <KEY=VALUE>— Opt-in run-wide harness-settings directive (resident mode only, repeatable — ADR-177 / issue #86).The harness twin of
--adapter, but occupying rung 1 of the harness chain rather than the adapter chain:cs tackle --harness k=v's rung, applied run-wide. Unlike--adapterand--basethere is no per-molecule pin to defer to —[steps.harness]lives on the executing formula step, not the molecule — so this directive is stamped onto every dispatch the run makes (static frontier nodes and dynamically-nucleated children alike) as one--harness k=vper key, and merged per key with the step's own[steps.harness]table by the shelledcs tackle, the operator's flag winning (ADR-177 Decision 2). Grammar and semantics are exactlycs tackle --harness's:key=value, cosmon recognises no keys and carries the pair verbatim to the adapter's native override channel. Absent (the default), no--harnessflag reaches any dispatch and each step's own[steps.harness]pin, if any, is unmasked.
cs spore
Spore germinates a whole polymer from a shareable spore.toml template (validate / run / export, ADR-140)
Usage: cs spore <COMMAND>
EXAMPLES: cs spore install github:noogram/cosmon/spores/cosmon-dev # fetch + place cs spore validate ./spore.toml --var subject="octopus cognition" cs spore run ./bundle/ --var subject="..." --var axes=a,b,c cs spore run ./spore.toml --allow-unchecked-seal # sealed, no TLC cs spore export ./spore.toml --out dist/ # bundle hash + ASTRA cs spore validate ./spore.toml --json # NDJSON expansion
VERBS: install fetch a shareable bundle and place it in this project, copying its recipes into .cosmon/formulas/ so their pins reach dispatch. validate parse + expand as a dry run; prints the ordered nucleate call list, germinates nothing. run parse + expand + seal gate, then germinate the polymer into the live state store. --json emits one NDJSON line per molecule. export content-addressed bundle hash + ASTRA descriptive layer (D6).
SEAL (ADR-140 D4): a sealed spore fails closed unless --allow-unchecked-seal is passed; the status line never claims 'verified' when TLC did not run.
SEE ALSO: cs nucleate (one molecule), ADR-140, docs/design/spore-impl-dag-manifest.md.
Subcommands:
validate— Parse + expand a spore as a dry run; print the ordered nucleate call list without germinating anythingrun— Germinate the polymer: parse + expand + seal gate, then replay the call list against the live state storeexport— Emit a content-addressed bundle id and an ASTRA descriptive layer (ADR-140 D6) for sharing the sporeinstall— Fetch a shareable bundle and place it into this project, installing its recipes into.cosmon/formulas/so their per-step pins reach dispatch
cs spore validate
Parse + expand a spore as a dry run; print the ordered nucleate call list without germinating anything
Usage: cs spore validate [OPTIONS] <REF>
EXAMPLES: cs spore validate ./spore.toml --var subject="octopus cognition" cs spore validate ./bundle/ --var axes=a,b,c # directory ref cs spore validate ./spore.toml --json # NDJSON expansion
Dry run only: parse (N2) + expand (N3), print the ordered
'cs nucleate ... --blocked-by ...' call list, germinate nothing. The seal
is reported but never gated here; use it to inspect what 'cs spore run'
would create. Each --var is coerced into its declared ParamSchema type
before expansion; a list
SEE ALSO: cs spore run, cs spore export, ADR-140 D3.
Arguments:
<REF>— Path to aspore.tomlmanifest (or a directory containing one)
Options:
--var <KEY=VALUE>— Bind a parameter (repeatable:--var key=value). Values are coerced into the declaredParamSchematype before expansion--admission <FILE>— TOML admission evidence for a spore that declares[spore.admission]
cs spore run
Germinate the polymer: parse + expand + seal gate, then replay the call list against the live state store
Usage: cs spore run [OPTIONS] <REF>
EXAMPLES: cs spore run ./spore.toml --var subject="..." --var axes=a,b,c cs spore run ./bundle/ --fleet default # directory ref cs spore run ./spore.toml --allow-unchecked-seal # sealed, no TLC cs spore run ./spore.toml --json # one NDJSON line/molecule
Germinates the whole polymer: parse + expand + seal gate, then replays the call list against the live state store via the canonical 'cs nucleate' path. Every germinated molecule is tagged temp:warm and wired to its blocked-by predecessors. The seal status note goes to stderr so --json stdout stays clean NDJSON.
SEAL (ADR-140 D4): a spore with no [spore.seal] germinates freely. A sealed spore fails closed unless --allow-unchecked-seal is passed, in which case the status line reads 'seal: present, NOT verified' and never 'verified'.
SEE ALSO: cs spore validate (dry run), cs run (DAG of existing molecules).
Arguments:
<REF>— Path to aspore.tomlmanifest (or a directory containing one)
Options:
-
--var <KEY=VALUE>— Bind a parameter (repeatable:--var key=value) -
--admission <FILE>— TOML admission evidence, checked before any molecule is nucleated -
--allow-unchecked-seal— Germinate a sealed spore even though its.tlaproof was not verified this run (TLC unavailable). The status line stays honest:seal: present, NOT verified(ADR-140 D4). Without this flag a sealed spore fails closed -
--fleet <FLEET>— Fleet to germinate the polymer intoDefault value:
default -
--store-dir <DIR>— State store root (default: walk-up.cosmon)
cs spore export
Emit a content-addressed bundle id and an ASTRA descriptive layer (ADR-140 D6) for sharing the spore
Usage: cs spore export [OPTIONS] <REF>
EXAMPLES: cs spore export ./spore.toml # bundle hash to stdout cs spore export ./spore.toml --out dist/ # ASTRA into dist/ cs spore export ./bundle/ --json # machine-readable
Emits a content-addressed bundle id over the manifest and every recipe and seal file it references (BLAKE3, sorted paths), plus an ASTRA-compatible RO-Crate descriptive layer (ADR-140 D6) when [spore.astra].emit is true. The seal verdict is attached honestly: marked present/absent and never claimed verified. The bundle hash is stable: the same bundle content always yields the same id (content-addressing is the registry, ADR-039).
SEE ALSO: cs spore run, ADR-140 D6, ADR-039.
Arguments:
<REF>— Path to aspore.tomlmanifest (or a directory containing one)
Options:
--out <DIR>— Output directory for the ASTRA descriptive layer. Defaults to the manifest directory. The crate is always written here asro-crate-metadata.jsonunless[spore.astra].outputnames a different (manifest-relative) path
cs spore install
Fetch a shareable bundle and place it into this project, installing its recipes into .cosmon/formulas/ so their per-step pins reach dispatch
Usage: cs spore install [OPTIONS] <SOURCE>
EXAMPLES: cs spore install github:noogram/cosmon/spores/cosmon-dev cs spore install https://github.com/noogram/cosmon/tree/main/spores/cosmon-dev cs spore install ../shared/bundle --dest spores/shared # local copy cs spore install github:o/r@v1 --expect-hash blake3:... # verified fetch cs spore install github:o/r --dry-run --json # plan only
Fetches the bundle (git remote or local path), places it under
SOURCE: a local path, 'github:owner/repo[/subdir][@ref]', a GitHub tree/blob URL, or any other git remote (use --git-ref / --subdir to pin one).
REFUSALS, all before anything is written: a bundle whose hash does not match --expect-hash; a bundle missing a file its manifest declares; a symlink inside the fetched tree; a non-empty destination (without --force); and a registry that already holds a DIFFERENT recipe of the same name (without --force), since overwriting changes what already-germinated molecules run. An identical recipe is a no-op, so re-installing is idempotent.
SEE ALSO: cs spore validate (inspect what was installed), cs spore export (the id --expect-hash checks), docs/cs-spore.md.
Arguments:
<SOURCE>— Where the bundle comes from: a local path,github:owner/repo[/dir][@ref], a GitHub tree/blob URL, or any other git remote
Options:
--dest <DIR>— Where to place the bundle. Defaults to<project>/spores/<spore-name>/--git-ref <REF>— Branch, tag, or commit to fetch. Overrides a ref encoded in the source--subdir <PATH>— Path to the bundle inside the checkout. Overrides one encoded in the source; the way to install from a subdirectory of a non-GitHub remote--expect-hash <BLAKE3>— Refuse unless the fetched bundle hashes to exactly this id (as printed bycs spore export). Checked before anything is written--no-formulas— Place the bundle but do not copy its recipes into.cosmon/formulas/. The bundle then germinates without its per-step adapter/model pins--force— Overwrite a non-empty destination and replace conflicting recipes already in the registry. The copy is a merge: a file the new bundle carries replaces the one there, and a file it does not carry is left alone — nothing is deleted on your behalf--dry-run— Report what would be installed and write nothing--formulas-dir <DIR>— Formula registry to install recipes into (default: walk-up.cosmon/formulas)