Skip to content

v3.0.5 Ionic

Choose a tag to compare

@waleedkadous waleedkadous released this 18 May 20:26
· 4623 commits to main since this release

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, and codev-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.architect and the local architect SQLite table (and terminal_sessions.role_id) now key on a stable name rather than a singleton row. The schema migration (v9 local, v13 global) 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-number architect-2, architect-3, …. Either can be overridden with an explicit name via the new afx workspace add-architect [--name <name>] subcommand. Allowed charset: [a-z][a-z0-9-]*, max 64 chars; collisions rejected.
  • Spawn-time capture. Every afx spawn now writes spawned_by_architect: <name> onto the builder's persisted row, detected automatically from the architect terminal's CODEV_ARCHITECT_NAME env var (injected by Tower at terminal-start). Spawns outside any architect terminal default to main.
  • Affinity-aware routing. When a builder runs afx send architect "...", the resolver now looks up that builder's spawned_by_architect and 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 to main (or the first registered architect if main is absent).

Backward compatibility

Zero behavior change for solo-architect workspaces:

  • /api/state.architect stays scalar (populated with main or first registered).
  • The dashboard and VS Code extension see one architect tab, identical to today.
  • Builders persisted before this release (no spawned_by_architect field) route to main if 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 own spawned_by_architect) is rejected with a clear, test-asserted error.
  • Architect-gone (the spawning architect's terminal was killed) falls back to main if 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 spec

The 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 send rather than picking one. Reviewers REQUEST_CHANGES and 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-sdk bumped 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 start

Contributors

  • 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.