Skip to content

Archon CLI v0.9.0

Latest

Choose a tag to compare

@Wirasm Wirasm released this 17 Aug 12:48
· 468 commits to dev since this release
671e2ee

Workflows become properly composable: a workflow can now declare the arguments it takes and the result it returns, ship as one self-contained folder, and be simulated end to end without contacting a provider. Alongside that, a workflow node's capabilities become what its YAML declares rather than whatever happens to be configured on the operator's machine — see Breaking before upgrading.

Breaking

  • Claude workflow nodes no longer inherit ambient skills and MCP servers. A Claude node now sees exactly the skills and MCP servers its YAML declares, plus the native tools Archon injects for the run. User, project, and plugin MCP configuration on the operator's machine no longer reaches workflow nodes: a node that relied on an ambiently configured server must declare it with mcp:, and one that relied on an ambient skill must list it under skills:. Declared skills are now also checked before spend — a skill that is installed but unreachable from the node's enabled settingSources fails up front instead of silently going missing, while built-in and plugin-qualified (plugin:skill) names warn and are left for the SDK to resolve. Direct Claude chat, CLAUDE.md, and built-in, filesystem, and inline agents are unchanged. (#2535)
  • An included command body must resolve, and may only reference its own workflow. command: and loop.command files inside an include: block are now resolved, validated, namespaced, and input-bound during load-time composition, recursing through nested loop_group bodies. Two previously tolerated shapes now fail: a body that references a node id outside the included workflow (it could bind whatever the caller happened to have) is rejected, and a body that cannot be resolved or read fails a fresh execution instead of warning and being skipped. Declare an input and pass it with with: instead of reaching outward. A paused loop still resumes from its persisted prompt snapshot even if its command file is later deleted. Included command bodies gained the other half of this trade: they can now use $INPUTS.<name>, which Phase 1 rejected outright. (#2534, #2532)

Added

  • Workflow signatures — inputs:, returns:, and with: on sub-runs. A workflow can declare the named arguments it accepts and which node's output is its result, and a workflow: sub-run node can bind those arguments by name with with: instead of passing a single opaque input: string. Values arrive as $INPUTS.<name> in prompts and command bodies, and as INPUTS_<UPPER_SNAKE> in bash:/script: node environments. Missing required inputs and undeclared arguments are rejected before any worktree, clone, or provider cost, and returns: gives a stable author-chosen result channel in place of guessing the terminal sink. Workflows without inputs: keep their existing passthrough behavior byte for byte. (#2523)
  • archon workflow run <name> --dry-run simulates a workflow without spending anything. An in-memory simulator walks the DAG — routing, when: conditions, strict $node.output references, gates, and loops — and prints a deterministic human or --json trace. No provider is contacted and nothing is persisted: no run row, events, sessions, or worktrees. Node outputs can be stubbed, approval behavior chosen, and code nodes actually executed with --exec-code (they are stubbed by default). (#2530)
  • Packaged workflows — one folder holds a workflow and everything it uses. .archon/workflows/<pack>/<workflow>/ is discovered as a package in both repo and home scope, and bare command: / script: references in that workflow's YAML bind to its own commands/ and scripts/ directories instead of the shared trees. Copying a workflow to another repo is now copying one folder rather than a scavenger hunt across three. Packaged resources are embedded in binary builds, and the Web API's workflow GET/PUT/DELETE lifecycle preserves the layout. Flat and one-level grouped YAML layouts are unaffected. (#2528)

Changed

  • Codex workflow nodes no longer advertise ambient skills automatically. Workflow commands and prompts now invoke installed Codex skills explicitly with $skill-name, an empty skills: [] declaration is valid, and unsupported YAML fields warn honestly instead of implying support. Direct Codex chat is unchanged. This is a behavioral guard rather than filesystem isolation, and Codex MCP configuration remains additive to ambient servers. (#2498, #2533)
  • A malformed settingSources entry can only narrow Claude's scope, never widen it. An unrecognized entry previously left the key unset, falling through to the permissive ['project', 'user'] default — so settingSources: [projct], written to lock a node to project scope, silently granted full user-scope ambient access. Unrecognized entries are now dropped and logged, and workflow validation shares one parser with execution so the two can no longer disagree about a node's effective sources. (#2535)
  • Agent instructions live in one file. AGENTS.md — which Codex, Pi, and OpenCode read natively — had drifted about six months behind CLAUDE.md. It is now the canonical instruction file, with CLAUDE.md reduced to a one-line pointer that Claude Code resolves as an import. No rule changed in the move. (#2497)

Fixed

  • A schema upgrade can no longer crash-loop on an index that predates its column. An index or COMMENT ON COLUMN placed beside its table body names a column that does not exist yet on an upgrade, because CREATE TABLE IF NOT EXISTS is a no-op there and the column only arrives in the later additive ALTER TABLE block. Since the schema applies in one transaction and re-throws, a single such statement aborted the whole apply and crash-looped every boot — on Postgres this broke startup and every CLI invocation for installs upgrading past #2414, and on SQLite it meant new SqliteAdapter(...) simply could not open a database created before parent_conversation_id existed. Every index and column comment now sits below the additive block. A new check:schema-upgrades CI job proves the current schema applies cleanly on top of every schema vintage ever released, re-applies idempotently, and lands on exactly the fresh-install shape. (#2513, #2552)
  • Workflow-level modelReasoningEffort: and webSearchMode: reach Codex. Both had been schema-declared, loader-validated, and documented as working workflow-level options since March, but the executor never read them off the workflow definition — a workflow declaring either parsed cleanly, warned about nothing, and ran at the config.yaml or SDK default. Declaring either on a non-Codex node now produces the same loud capability-mismatch warning every other unsupported field produces. (#2559)
  • The container write-back no longer mis-decodes hostile or merely unusual filenames. The two overlay walk scripts — the one place a container run writes the live root — decoded each entry by forking basename, dirname, and sed, which produced three reachable defects: a whiteout marker under a --prefixed directory was planted as a literal .wh.* file instead of deleting its target (no adversary required, just a leading dash); a whiteout whose name ended in a newline deleted a different, innocent file and could write outside the live root while reporting success; and a TAB inside a filename or symlink target forged the positionally-decoded fields after it, presenting an escaping symlink to the approval gate as safe. Shell parameter expansion replaces the forks, closing all three and cutting forks per entry from 8 to 4 for a regular file and 6 to 1 for a whiteout. (#2561)
  • Archon no longer guesses the default branch. getDefaultBranch ended its fallback chain by checking whether <remote>/main merely existed and returning it if so. On a repository shaped like this one — dev is the default and main is the release branch — a run silently cut its worktree from main and targeted its pull request at main, with nothing erroring at the moment it happened. When <remote>/HEAD is not a symbolic ref it now throws, naming --base, worktree.baseBranch, and the codebase default_branch field. (#2503)
  • WORKFLOW_ID is delivered to bash: and script: node subprocesses. It substituted into the node body but was missing from the environment bag, unlike ARTIFACTS_DIR, STATE_DIR, and LOG_DIR sitting beside it — so a heredoc'd python3 or node block reading os.environ failed inside the nested interpreter with a bare KeyError and no hint that its siblings worked fine. The e2e-deterministic fixture that demonstrated the wrong way to consume an output reference was corrected too. (#2511)
  • A dry run of the state migration no longer creates a database. scripts/migrate-state-dir.ts consulted the codebase registry unconditionally, and the SQLite adapter connects lazily and applies the full schema on first use — so a read-only run wrote a 704 KB database while printing Dry run — nothing was moved. (#2557)

Discussion thread — questions, or paste YAML that broke: #2574