v3.0.5 Ionic
v3.0.5 Ionic
Released: 2026-05-18
A patch on the Ionic line driven almost entirely by an external Codev consumer's production use of the sibling-architect pattern. Two substantial new features (multi-architect message routing, baked architectural decisions) and three workflow bugfixes — all caught and reported via the team channel.
Version note: 3.0.4 was published to the VS Code marketplace only (codev-vscode side). This release moves the entire lockstep —
@cluesmith/codev,@cluesmith/codev-core,@cluesmith/codev-types, andcodev-vscode— to 3.0.5 together. Solo-architect users see no behavior change from 3.0.3.
Multi-architect message routing (#755 → PR #757)
Codev workspaces have always assumed a single architect terminal. The sibling-architect pattern — where one human operator drives two or more architect agents in the same workspace, each owning a disjoint slice of work — has emerged in production usage on a large customer project. With one architect, afx send architect from any builder lands in the shared singleton; humans then manually decide "is this mine?" and copy-paste the message to the right architect. This release makes that routing automatic.
What's new
- Multiple architect terminals per workspace. Tower's in-memory
WorkspaceTerminals.architectand the localarchitectSQLite table (andterminal_sessions.role_id) now key on a stablenamerather than a singleton row. The schema migration (v9local,v13global) is forward-only per the project convention; existing single-architect workspaces are rekeyed transparently. - Naming policy. First architect started in a workspace defaults to
main; subsequent siblings auto-numberarchitect-2,architect-3, …. Either can be overridden with an explicit name via the newafx workspace add-architect [--name <name>]subcommand. Allowed charset:[a-z][a-z0-9-]*, max 64 chars; collisions rejected. - Spawn-time capture. Every
afx spawnnow writesspawned_by_architect: <name>onto the builder's persisted row, detected automatically from the architect terminal'sCODEV_ARCHITECT_NAMEenv var (injected by Tower at terminal-start). Spawns outside any architect terminal default tomain. - Affinity-aware routing. When a builder runs
afx send architect "...", the resolver now looks up that builder'sspawned_by_architectand delivers the message only to that architect's terminal — sibling architects do not receive it. Non-builder senders (cron-routed messages, manual sends from the workspace root) continue to resolve tomain(or the first registered architect ifmainis absent).
Backward compatibility
Zero behavior change for solo-architect workspaces:
/api/state.architectstays scalar (populated withmainor first registered).- The dashboard and VS Code extension see one architect tab, identical to today.
- Builders persisted before this release (no
spawned_by_architectfield) route tomainif present, else fail with a clear error listing the registered architects.
Why a new subcommand instead of afx architect --name
The existing afx architect runs a local Claude session with stdio: 'inherit' and explicitly disclaims Tower — it works in any directory, even outside a workspace. Adding --name semantics would break that no-Tower contract for current users. The new Tower-aware subcommand lives under the workspace noun (next to start, stop, rename), which keeps the existing command intact.
Security
- A builder spoofing
architect:<some-other-name>(a name that is not its ownspawned_by_architect) is rejected with a clear, test-asserted error. - Architect-gone (the spawning architect's terminal was killed) falls back to
mainif present; otherwise fails with a distinct error.
What's deferred
afx status --architect <filter>, surfacing all architects in /api/state, the THREAD.md template + lifecycle, cross-thread visibility, and thread-aware consult are tracked as follow-up issues. Issue #758 tracks the deferred end-to-end Tower-process integration test (the routing matrix is covered by 18 unit tests + direct SQLite + route-handler tests; the e2e is documented technical debt).
Baked architectural decisions for SPIR/AIR/ASPIR (#746 → PR #756)
Architects often have strong priors on a major decision (language, framework, deployment shape, key dependencies) before filing an issue. Until now those priors had nowhere structured to live — buried in prose, easy to miss, easy for CMAP reviewers to override in good faith. The result: spec drafted against an assumed default, iter-2 CMAP reviews that wrong assumption, architect intervenes at iter-3 to override — and iter-2's feedback becomes obsolete.
How to use it
Include a ## Baked Decisions section (any heading level, case-insensitive) in the GitHub issue body before spawning a SPIR/AIR/ASPIR builder. Example:
## Baked Decisions
- Language: Python (match shanutil)
- Framework: FastAPI
- Deployment: deferred to a follow-up specThe builder treats those decisions as fixed inputs to the spec. CMAP reviewers (Codex, Gemini, Claude) are told to honor them — they may COMMENT with concerns about a baked decision, but REQUEST_CHANGES is reserved for the case where the spec fails to honor a stated decision. The architect retains authority to rescind or amend a baked decision at any time via afx send.
Design properties
- Optional by default. Empty or missing section = full exploration, identical to today's behavior.
- No code surface. Pure prompt + documentation change — the LLM finds the section in the issue body and honors it because the prompt tells it to. No regex parser, no template-context plumbing. Handles variant section names and inline-in-prose baked decisions more robustly than a parser would.
- Architect-override carveout woven through every prompt. Builder prompts say "do not autonomously override" (not "forbidden to question") — so the architect can always rescind a baked decision and the prompt language doesn't fight them.
- Contradiction handling. If two baked decisions contradict each other, the builder pauses and flags via
afx sendrather than picking one. ReviewersREQUEST_CHANGESand ask the architect to clarify.
Test coverage
An 808-line test file covers grep assertions for the required instruction language across all 12 affected prompts (SPIR/ASPIR builder-prompt + drafting prompt + spec-review + plan-review, AIR builder-prompt + implement + impl-review + pr-review), pure-addition diff against 12 recorded baselines (so any inadvertent edit elsewhere in the prompts fails the test), and codev/ ↔ codev-skeleton/ byte-identical parity.
Bugfixes (#742, #744, #745)
Three workflow bugs reported by a Codev consumer using the bugfix protocol heavily:
Codex misapplied SPIR criteria to BUGFIX PRs (#742)
The bugfix protocol's consult-types/pr-review.md and impl-review.md templates were byte-identical to the SPIR versions, causing Codex to REQUEST_CHANGES on legitimate BUGFIX PRs for missing codev/specs/plans/reviews artifacts, for [Spec NNNN] commit format (BUGFIX uses Fix #N:), and for status.yaml.build_complete: false (porch-managed, not builder-fixable). Each PR cost 2–3 iter cycles of the builder writing protocol-defending rebuttals.
The fix rewrites both bugfix templates around what BUGFIX actually produces (GitHub Issue + fix + regression test) and adds an explicit Out of Scope section naming each of the three SPIR-only criteria to forbid. A regression test pins divergence from the SPIR templates so accidental re-syncing fails CI.
SPIR/ASPIR builder-prompt allowed per-phase PRs (#744)
The SPIR/ASPIR builder-prompt.md did not explicitly state the one-PR-per-spec convention; builders interpreted the plan's "each phase commits independently" as "each phase opens its own PR." A new PR Strategy section now makes this explicit, with an architect-override carveout for cases where the architect requests a PR earlier (e.g., for spec review, mid-implementation feedback, or slicing a large spec into shippable PRs).
The carveout phrasing — "do not autonomously open a PR per implementation phase" rather than absolute prohibition — is the pattern we now reuse for any builder-constraining prompt rule. Memorized for future prompt edits.
afx spawn dirty-worktree check was too strict on untracked files (#745)
git status --porcelain flags untracked files (?? status) alongside modified-tracked ones. Repos with chronic untracked artifacts (e.g., bin/ from pnpm local-install, .claude/scheduled_tasks.lock, build outputs) forced --force on every spawn, defeating the safety check entirely.
The check now uses git status --porcelain --untracked-files=no — it still catches the case where an architect git add-ed a new spec but forgot to commit (the index entry shows as tracked), while ignoring chronic untracked artifacts. Documented tradeoff: a file that's created but never staged won't trigger the check; if the architect wants that protection, git add before spawn restores it.
Other improvements
@openai/codex-sdkbumped 0.101.0 → 0.130.0 to clear an XProtect cert-revocation issue on macOS (#752, Amr).
Breaking changes
None. Solo-architect workspaces are unchanged. The new ## Baked Decisions section is opt-in (absence = no-op).
Install
npm install -g @cluesmith/codev@3.0.5
afx tower stop && afx tower startContributors
- External Codev consumer (Shannon) — reported the SPIR-vs-BUGFIX template mismatch, the SPIR one-PR ambiguity, the chronic-untracked spawn issue, the architect's-baked-decisions need, and the sibling-architect/multi-architect-routing pattern. Five tier-1 reports filed via team channel; this release ships every one.
- Amr Elsayed (@amrmelsayed) — codex SDK XProtect cert revocation fix.
- M Waleed Kadous (@waleedkadous) — architect role, driving spec/plan iterations and approvals.
- Builders working under SPIR, BUGFIX, and RESEARCH protocols.