Changelog
This timeline covers the core ca plugin. See the GitHub Releases page for the same history with release assets. The host and sandbox adapters are versioned independently; read the Codex changelog, Pi changelog, and sandbox changelog for their release lines.
[Unreleased]
Section titled “[Unreleased]”[3.7.0] - 2026-10-30
Section titled “[3.7.0] - 2026-10-30”- Render a bounded, read-only native project work page with links to canonical work records and separate progress, check, delivery, and tracker labels.
- Report native or mixed work ownership during legacy board drift checks.
[3.6.0] - 2026-10-30
Section titled “[3.6.0] - 2026-10-30”- Route selected work, archival, and initialized Markdown acquisition through the owning local work store.
- Render a bounded, derived HTML overview for one native work item.
- Keep derived views outside canonical artifact ownership and leave checks unknown until their evidence is recorded separately.
- Keep the legacy task count when the native work directory is empty, and review harvested work before it joins a commit.
[3.5.0] - 2026-10-30
Section titled “[3.5.0] - 2026-10-30”- Add a local work-system journey with stable work IDs, selected artifact context, lifecycle updates, bounded lists, and retry-safe origin links.
- Retain the Markdown board as the sole owner in existing projects while new native projects use one work owner.
[3.4.5] - 2026-10-30
Section titled “[3.4.5] - 2026-10-30”- Refuse verification before arming when runtime markers are visible to Git, with a project ignore-rule remedy that preserves completion drift checks.
[3.4.4] - 2026-10-29
Section titled “[3.4.4] - 2026-10-29”- Validate artifact pages before reading their embedded model and reject unsafe or inconsistent rendered content. Report fingerprint probe failures distinctly and bound unreadable release-evidence diagnostics, distinguishing unreadable notes from invalid UTF-8.
- Keep fresh legacy context approval from arming an unrelated artifact action.
- Align the Claude host identity with its release manifest so installed hooks authenticate the package after the version bump.
- Treat a staged selected untracked Tribunal input as source drift while retaining separate diagnostics for failed fingerprint probes.
- Reject overlapping filtered artifact pages. Treat a changed Tribunal scope, declared evidence set, or committed source revision as drift even when a later evidence probe fails.
[3.4.3] - 2026-10-29
Section titled “[3.4.3] - 2026-10-29”- Artifact saves and legacy cutovers reject catalog count or byte-limit overflow before writing. Drift and limit errors identify the affected artifact path, and the Python bridge retains a bounded error field.
[3.4.2] - 2026-10-24
Section titled “[3.4.2] - 2026-10-24”- Recover a stranded Tribunal write lock only after confirming the exact lock digest and that no writer holds the run guard. Preserve the old lock as an archive and refuse recovery when the source-bound audit state has drifted.
[3.4.1] - 2026-10-24
Section titled “[3.4.1] - 2026-10-24”- Gate-event logging refuses linked or redirected destinations and records line breaks as escaped text.
[3.4.0] - 2026-10-24
Section titled “[3.4.0] - 2026-10-24”- Project context can now live as native HTML knowledge records:
.codearbiter/context/<name>.htmlfor the five context documents and.codearbiter/decomposition/project.htmlfor the greenfield interview. Each record has a stable ID, a basis (user-reported,source-observed,inferred,proposedorunknown), cited sources and the paths it governs. New scaffolds use this format; “/ca:init--format markdownkeeps the Markdown layout. hooks/knowledge.pyreads and changes records:relevant <paths>returns only the records that govern those paths,promoteadds an approved work item to the task board once,stalelists records whose cited files changed, andmerge-conflictresolves a Git conflict record by record.task-contextnow carries the knowledge records relevant to a task’s paths, with one explicit link hop. A damaged knowledge document is reported without hiding the others.knowledge.py convertprepares empty HTML documents and lists Markdown sections with a fingerprint token. The agent records their meaning and maps every section to saved records or notes;convert --finish <token> --coverage @checklist.jsonrefuses changed sources or uncovered sections, then switches formats in one journaled transaction that retains the original bytes.
Changed
Section titled “Changed”- The greenfield interview saves each question and answer as it happens and resumes with the open question that matters most, instead of restarting a fixed sequence. Initialization checks that the documents exist and parse; open questions no longer prevent it.
- Repositories that keep the Markdown format follow their unchanged
context-creationanddecomposeprocedures, now in each skill’sreferences/markdown-format.md. Nothing converts without an explicitconvertworkflow. knowledge.py promoteandtaskwrite.py add --fromno longer re-promote work that is already done or archived.
[3.3.0] - 2026-10-23
Section titled “[3.3.0] - 2026-10-23”Removed
Section titled “Removed”- Remove the
/ca:btw,/ca:commands,/ca:metricsand/ca:previewcommands. They carried maintenance cost without advancing agentic development. Ask questions directly instead of using/ca:btw. The plugin’sCOMMANDS.mdstill lists every command. The SessionStart briefing no longer points to a catalog command.
Changed
Section titled “Changed”- The command compatibility policy now allows a command to be removed in a
minor release when this changelog records the removal under “Removed”. It
previously required a separately approved major release. The generated
command catalogs publish the new
removalRequiresvalue and no longer carry theretainThroughandearliestRemovalfields. This is the maintainer’s decision of 2026-10-23.
[3.2.7] - 2026-10-21
Section titled “[3.2.7] - 2026-10-21”-
Keep ordinary uppercase instructions such as
Approve DATA migrationout of artifact reply capture unless that all-letter code belongs to a retained request. Genuine coded replies and mismatch protection remain intact. -
Recognize verifier authority only from the actual wrapper invocation, not inert PowerShell data mentioning its filename.
-
Permit bounded literal read-only Python diagnostics using isolated
-Istdin input and literalgit show HEAD:<protected-path>orPathreads. No arbitrary script, subprocess, shell expansion or write exemption is added. -
Ordinary approval, sprint, prerequisite, and reconciliation instructions no longer enter legacy reply-code capture. Historical requests and actual host permissions retain their checks.
-
Bounded literal JSON sent to the installed read-only diagnostic validator no longer triggers protected-state write guards merely by citing source paths. Ambiguous or executable shell forms remain guarded.
-
Explicit staging in a multiline batch no longer borrows flags from later commands. Every staging command retains wildcard, directory, continuation, and working-directory checks.
-
Explicit draft source refreshes now preserve started work and historical evidence instead of requiring an untouched initial approval pair. Source and plan revision checks and historical approval boundaries remain intact.
[3.2.6] - 2026-10-19
Section titled “[3.2.6] - 2026-10-19”- Engine model-validation errors now name what the schema accepts. A closed-enum refusal lists the allowed values (for example, applicability
modeaccepts"conditional","unconditional","invariant"and"not_applicable"), and an unknown key lists the record’s allowed fields. Before, both said only that the value was refused, so the accepted spelling had to be found in the schema files. The list stays within the 512-byte public diagnostic limit.
[3.2.5] - 2026-10-19
Section titled “[3.2.5] - 2026-10-19”- The H-05 (audit logs), H-11 (ADRs) and H-18 (
CONTEXT.md) shell guards blocked any interpreter command that merely named a protected path, so a read-onlypython -cread, an issue body citing the path, or anArtifactClientrequest whose record text named an audit log was refused as a write. Their interpreter legs now block only when the command shows write intent after the interpreter (a write, delete, copy, move or in-place edit call, a non-readopenmode, PowerShell content cmdlets, or dynamic execution such asexec,evalorsubprocess), or when the interpreter is handed a script or module argument. H-18 also lets asedwithout-ior awcommand readCONTEXT.md(#997, #911).
[3.2.4] - 2026-10-19
Section titled “[3.2.4] - 2026-10-19”- On Windows the artifact bridge read its binary’s architecture through
platform.machine(), which asks WMI and then thePROCESSOR_*environment variables. A read-only sandbox can block WMI and strip that environment, so reads failed withUNSUPPORTED_PLATFORM: unsupported architecture. The bridge now asks the kernel (IsWow64Process2) for the native machine, consults no environment, and still fails closed when the OS gives no answer (#986).
[3.2.3] - 2026-10-19
Section titled “[3.2.3] - 2026-10-19”- Evidence snapshots open each bound farm projection once, from the walk’s own read, and no longer list directories ahead of the walk when farm bindings exist. A stale binding no longer opens its projection twice (#962).
- A snapshot re-checks a cached directory anchor against its parent’s current entry each time it reuses it, and caps the anchor cache at 512 handles so a very wide root policy fails with
MAX_INPUTSinstead of exhausting file descriptors (#962). - On macOS the store opens files and directories non-blocking, so a FIFO planted in place of a listed file is refused instead of hanging the scan (#962).
- Git membership probes drop environment-injected Git configuration (
GIT_CONFIG_PARAMETERS,GIT_CONFIGandGIT_CONFIG_KEY_n/VALUE_npairs) except the bridge’s resolvedcore.excludesFile(#962). - A root below the top level of an enclosing Git work tree, such as a monorepo package, now uses that work tree’s membership scoped to the root instead of reading every file from disk. Ignored files there no longer count as inputs, so existing receipts for such roots go stale once. A root the enclosing work tree ignores fails closed (#962).
[3.2.2] - 2026-10-18
Section titled “[3.2.2] - 2026-10-18”- On Windows, verification through an npm workspace intermittently failed with
UNSUPPORTED_EXECUTABLE: nested npm launch qualification failed. The qualification probe ran npm with a minimal environment, so a fresh npm profile also made a registry update check, which could exceed the probe’s 15-second limit or print a notice. The probe now disables npm’s update notifier and stays offline.
[3.2.1] - 2026-10-18
Section titled “[3.2.1] - 2026-10-18”- A plan could claim verification coverage for a task path under
.git/, although the evidence snapshot never hashes.git. Such paths now reportUNCOVERED_INPUT(#908). - On Windows, a directory junction inside the repository was not refused by the store’s link checks, because current Go reports junctions as irregular files rather than symlinks. Junctions are now refused like symlinks (#909).
[3.2.0] - 2026-10-18
Section titled “[3.2.0] - 2026-10-18”- A new
init-storeengine operation creates a checkout’s local artifact store metadata on purpose, and only that. On Windows, a fresh clone or worktree reportsNO_LOCAL_STOREon every read until the store exists; the host bridge now runsinit-storeonce and retries the read once, so/featureand/sprintresume work in a new checkout. Reads themselves still never write, and a read-only checkout still getsNO_LOCAL_STORE.
[3.1.1] - 2026-10-18
Section titled “[3.1.1] - 2026-10-18”- A spec whose design had only one sane approach recorded its SMARTS rationale with not-applicable filler for every rationale part, because the rationale convention listed all parts unconditionally. The convention now applies the multi-part rationale only when a comparison ran; a single-option choice records exactly one block, its one-line statement and reason. Found by a live
/featurerun. - The SMARTS rationale convention and the spec-compliance reviewer no longer describe the rationale as belonging to an “approved” spec, since 3.0.0 retired spec approval.
[3.1.0] - 2026-10-17
Section titled “[3.1.0] - 2026-10-17”- SMARTS is now the six-lens design-quality rubric for material engineering solution choices, not only architectural variance. Workflows pick a depth (scan, comparison or delegated decision); SMARTS itself grants no approval and is not a command.
- A fifth verdict,
Unknown, records missing evidence with its missing observation and whether it is decision-critical. A decision-criticalUnknownblocks a strong recommendation and the selection of the option that carries it, and never stands in for user approval, a prerequisite or security authority. The engine validates thesmarts-plan-method/0.2.0record while historical0.1.0receipts keep their four-verdict contract. - SMARTS runs only where a material choice exists: brainstorming compares approaches when two or more are materially plausible (a single approach gets one line and no table), the
/featuresmall lane scans only a material choice,/fixcompares remediation strategies only after root cause, and refactor compares only distinct strategies. Writing-plans routes undecided design choices back to brainstorming, and verification checks the change against a recorded rationale for material invalidation only. - Specs carry a concise SMARTS design rationale (
SEC-SMARTS), and the per-lens historical detail loads lazily fromincludes/smarts/lenses.md.
Changed
Section titled “Changed”- The SMARTS concept page explains the three depths,
UnknownversusIndifferent, the context envelope and the authority boundaries.
[3.0.0] - 2026-10-14
Section titled “[3.0.0] - 2026-10-14”Changed
Section titled “Changed”-
Keep routine artifact context assistive and smaller: move optional strict legacy receipt, approval, and recovery reference procedures out of the default artifact include. Load them only when an explicit proof/old-state consumer needs them. No artifact permission gate or model reviewer is added.
-
Keep command-result applicability aligned with the exact referenced acceptance criteria and bounded task/shared source inputs plus known build controls. Distinguish
scoped_changed,scoped_unchangedandunassessedwithout pretending that a partial fingerprint proves tests, shared imports or independent review. -
Record mixed 0.3.1/0.3.2 engine compatibility and fail-closed old-client behavior in disposable cross-binary fixtures; preserve historical files, receipts and post-upgrade edits rather than promising a destructive downgrade.
-
Normal feature/sprint execution guidance uses advisory plan state and real checks instead of mandatory artifact approval codes or per-task reviewer fleets. Recorded-intent conflicts and material ADR supersession remain visible without becoming an additional permission protocol.
-
Add read-only
task-contextto deliver one bounded task and its directly referenced criteria/dependencies/prerequisites without an evidence snapshot, reviewer dispatch, or persistent context ticket. Stale and oversized requests fail explicitly; this is not a host-qualification claim. -
Start the assistive state-engine overhaul in PR #983: native work tracking no longer requires artifact approval codes or context tickets.
-
Record task-scoped prerequisite observations and completed implementation batches separately from verified acceptance, with compact symbol reads and human-readable HTML. New records use schema 0.3.2; historical reads retain their bytes and evidence.
-
Native plan authoring no longer requires artifact approval or every future reviewer/verification adapter; generated planning guidance uses coherent work units rather than mandatory five-minute slices.
-
Explicit batch reviews can select fresh passing reruns of still-reviewed work without recreating each task review. Original evidence remains distinct, and source/support/workspace integrity is still checked.
-
Align runtime adapter identities and the second Codex package manifest with the unreleased candidate versions.
-
Retire unanswered paired-approval and ARMED prerequisite prompts through existing internal helpers without obtaining another code; submitted pairs and confirmed prerequisites retain exact recovery, while old standalone approvals fail closed rather than guessing that no user replied.
-
Retire unanswered legacy reconciliation prompts with an explicit superseded disposition, without a new approval code. Committed or uncertain attempts retain exact replay/recovery; no task state or evidence is forged by cleanup.
-
Preserve ordinary task command results as bounded, caller-reported pass/fail/skip/unknown observations. Definition drift is visible, source freshness remains explicitly unassessed, and no review/approval is invented.
-
Canonicalize macOS temporary-directory aliases before validating the native reconciliation root, retaining the existing unsafe-path/attempt refusals.
-
This is an unreleased source candidate. Host-workflow conversion, full upgrade qualification, and publication remain tracked by the overhaul PR.
[2.26.4] - 2026-10-13
Section titled “[2.26.4] - 2026-10-13”- Fix task reconciliation for Unicode text while preserving armed requests and prompt-route integrity.
[2.26.3] - 2026-10-13
Section titled “[2.26.3] - 2026-10-13”- Validate new Codex native reviews against their evidence protocol instead of an exact host release. Accept additive host metadata while retaining identity checks and historical receipt contracts.
[2.26.2] - 2026-10-12
Section titled “[2.26.2] - 2026-10-12”- Allow initialized Windows artifact stores to be observed without write access (#971).
- Pin the repository, metadata directories, and lock file against replacement while preserving reader/writer exclusion. Missing or unsafe lock state refuses without initialization.
[2.26.1] - 2026-10-12
Section titled “[2.26.1] - 2026-10-12”- Reproduce normal ORT histogram conflicts in guarded legacy block resolution while preserving exact rendering and index/CAS controls (#968).
- Clarify unknown host qualification and complete the repository-scoped maintenance commands.
[2.26.0] - 2026-10-10
Section titled “[2.26.0] - 2026-10-10”Changed
Section titled “Changed”- Identify verification inputs by ship-set membership (ADR-0042): git index
entries present on disk plus untracked non-ignored files within the plan roots,
minus excludes. Outside git, membership comes from the filesystem; a failed git
probe fails closed with
INPUT_MEMBERSHIP_UNAVAILABLE, and an unmerged index fails closed until resolved. - Exempt exactly
.codearbiter/gate-events.logfrom snapshots. It is never counted and stays tracked as the audit trail; every other.codearbiterpath, includingoverrides.log, still counts. - Advance the verification-input manifest to
codearbiter.verification-inputs/0.2.0. Receipts bound to a 0.1.0 manifest read as stale and must be re-verified. - Open snapshot files through bounded handle opens and validate each evidence object at most once per operation. Raw reads are reused only up to a 64 MiB per-operation retained-byte budget, so past it an object can be read again; validation still happens once.
- Raise the
prompt-submithook timeout to 600 seconds so a long snapshot no longer times out the prompt seam (#931).
[2.25.9] - 2026-10-12
Section titled “[2.25.9] - 2026-10-12”- Rebind a revised initial draft specification and plan through an explicit, same-pair operation with exact source and plan checks. Keep both artifacts unapproved and refuse execution evidence; ordinary approved-source binding and later combined approval remain required.
[2.25.8] - 2026-10-12
Section titled “[2.25.8] - 2026-10-12”- Recognize normal verbose unittest rows for fully qualified required test identities. Preserve exact identity matching and refusal of duplicate, skipped, failed or missing required results (#955).
[2.25.7] - 2026-10-12
Section titled “[2.25.7] - 2026-10-12”- Restore reviewed legacy code-map metadata updates and explicit per-block Git conflict resolution with bounded helpers, preserving native ownership, stale-input checks, unselected text and the Git index (#967).
- Explain debug packet shapes and link the trusted schema and a synthetic unresolved example before one-shot validation (#951).
- Document brownfield host prerequisites before scaffolding, preserving containment, native approval and partial-state recovery gates (#950).
[2.25.6] - 2026-10-10
Section titled “[2.25.6] - 2026-10-10”- Read complete task verification definitions through a bounded native projection during typed-plan approval preflight. Preserve command validation, source snapshot and final identity ordering, aggregated diagnostics and refusal before approval arming when any page is malformed, incomplete or stale.
[2.25.5] - 2026-10-10
Section titled “[2.25.5] - 2026-10-10”- Preserve shared evidence validation for Codex native V2 reviews, binding parent activity to child identity and the original transcript while refusing steering, stale associations and invalid completions.
- Keep large verification contexts in immutable references with bounded result capacity, retaining the existing evidence limits and completion checks.
[2.25.4] - 2026-10-10
Section titled “[2.25.4] - 2026-10-10”- Retain native completion-review contexts by validated immutable reference, reserving bounded result growth before launch without increasing request, decision or native-context limits. List the complete result fields and separate task obligations in the review prompt (#921).
- Fingerprint complete completion-review workspaces up to 1 GiB independently of the 256 MiB selected verification-input budget. Preserve full content hashing, freshness checks, and the 32 MiB member and 50,000 entry limits.
- Bind a native normalized completion closure during fresh verification so publishing its own evidence does not look like source drift. Retain raw before/after command checks, validated-output checks, and historical profiles.
[2.25.3] - 2026-10-09
Section titled “[2.25.3] - 2026-10-09”- Keep managed Git hooks working with a restricted PATH while preserving trusted executable identities, cross-host path resolution and stale-registration checks.
[2.25.2] - 2026-10-08
Section titled “[2.25.2] - 2026-10-08”- Recognize the scoped Pi package in shared workflow preflight and report its unavailable approval support without enabling the workflow.
- Preserve exact native Pi approval input bindings in the shared adapter while refusing ordinary prompt input and unqualified paired approval.
[2.25.1] - 2026-10-07
Section titled “[2.25.1] - 2026-10-07”- Reduce plan approval preflight latency by batching validated task reads.
[2.25.0] - 2026-10-05
Section titled “[2.25.0] - 2026-10-05”- Read the shared Git hook’s stale-registration list correctly with multiple entries and Windows line endings, so the current security checker owns the verdict.
- Resolve a genuine legacy code-map merge conflict using the exact committed current version, preserving context protection, provenance and index entries.
- Preserve Git’s configured trust policy during recovery and Tribunal inventory.
- Estimate Tribunal verification from average packet tokens plus the allowance, removing the extra factor of four.
- Add semantic-contract and change-closure Tribunal lenses, with applicability, evidence requirements, and false-positive guards across the thirteen-card roster.
- Collect deterministic inventory without running project code, prepare bounded review packets, and resolve review settings from the active host’s capabilities.
Changed
Section titled “Changed”- Bind Tribunal resume to the exact reviewed source, allocate unique run directories, preserve cross-lens leads, and group corroborating findings by root cause.
- Require separate verification of serious findings and keep unresolved claims out of confirmed fix work. Complete issue-filing and optional telemetry dispositions separately from the report, preserving explicit consent and aggregate-only feedback.
[2.24.6] - 2026-10-07
Section titled “[2.24.6] - 2026-10-07”- Wait up to 120 seconds (was 30) for the structured-artifact engine before timing out. On a
large repository a whole-tree input snapshot takes about 30 seconds on Windows, so every
verification, review publish and approval arm failed with
TIMEOUT. SetCODEARBITER_ENGINE_TIMEOUT(seconds, up to 3600) to change the bound; a malformed value is refused rather than ignored. The bound is a wait limit only and relaxes no check.
[2.24.5] - 2026-10-05
Section titled “[2.24.5] - 2026-10-05”- Publish a review whose reply contains non-ASCII text (an em dash, accented or emoji
characters). The authority adapter hashed the observation payload and producer
result as ASCII-escaped JSON while the engine hashes raw UTF-8, so such a review
failed with
OBSERVATION_UNVERIFIED. Observation digests now use the engine’s canonical form. - Pin the farm build and test dependency graph to
source-map-js1.2.2, closing the excessive source-map allocation advisory GHSA-68fv-2mgg-jv7q.
[2.24.4] - 2026-10-05
Section titled “[2.24.4] - 2026-10-05”- Accept native artifact IDs without requiring
SPEC-andPLAN-prefixes when preparing feature-author and reviewer context. Preserve exact IDs and reject malformed identities using the native protocol’s identifier grammar. - Restore typed record reordering so an existing plan can move an independent checkpoint without replacing its IDs or losing execution history. A changed order still requires normal approval before execution.
[2.24.3] - 2026-10-05
Section titled “[2.24.3] - 2026-10-05”- Keep host hook runtime markers out of review input snapshots, so an independent review no longer goes stale because the reviewer read files. Plans can no longer root verification inputs in, or claim coverage of, that marker directory. Review and verification requests armed by an older engine go stale after upgrading; re-arm them.
[2.24.2] - 2026-10-04
Section titled “[2.24.2] - 2026-10-04”- Keep prerequisite confirmations and reply codes valid for the same 24-hour window, and show the deadline when requesting approval.
- State the accepted reviewer finding severities so informational findings do not accidentally invalidate a review.
- Correct Pi approval guidance to describe the missing authority adapter.
[2.24.1] - 2026-10-04
Section titled “[2.24.1] - 2026-10-04”- Complete Claude reviews whose start and launch result arrive together. The two hooks could each miss the other’s half of the join, so about half of async reviews were rejected after the reviewer reported. The join is now serialized.
[2.24.0] - 2026-10-03
Section titled “[2.24.0] - 2026-10-03”- Add bounded repository-context writing, recovery, selective refresh and task-scoped context delivery while preserving human-owned records and initialization state.
- Require exact native qualification receipts and cold installed context checks before assembled Claude and Codex candidates admit context writes. Source-only builds remain disabled; live host containment and contribution qualification remain separate.
- Preserve Unicode whitespace in activation frontmatter while requiring a real initialized marker outside fenced code and comments.
- Resolve nested source membership through anchored paths and synchronize adapter version identities with the release manifests.
- Account for failed attempts, new source membership, actor changes and compaction without treating unknown evidence as current or granting action authority.
- Validate diagnostic handoffs before repair or task follow-ups, preserving the caller’s authority and checking that the evidence is current.
- Keep diagnostic outcomes, regression reuse and helper invocation consistent across the generated host packages.
[2.23.5] - 2026-10-04
Section titled “[2.23.5] - 2026-10-04”- Evidence-context validation now accepts the native engine’s literal UTF-8 Unicode bytes while retaining canonical-byte, digest, and frozen-context checks. Approved task text with Unicode can reach verification and review.
[2.23.4] - 2026-10-03
Section titled “[2.23.4] - 2026-10-03”- Claude Code reviews completed again on Claude Code 2.1.286. That host reports a 1M-context
reviewer model as
claude-opus-5-5[1m], which the launch correlation refused, so every spec and quality review was rejected without a receipt.resolvedModelnow admits one trailing context tag; every other host identifier keeps the strict form. - The reviewer’s report is now read from its
SubagentHandbackcall, which 2.1.286 uses in place oflast_assistant_messageonSubagentStop. Only the bound reviewer’s delivered handback in the launching session counts, a second handback rejects the review, and when a host supplies both forms they must match. - Recovering an already-abandoned oversized review now reports
request was already abandonedinstead of a misleading binding failure. - The crypto/secret commit gate (H-09b/H-10b) no longer expires a recorded pass after 30 minutes. A pass now stays valid for exactly the lines it reviewed, in the files it reviewed them in, like the migration gate; any new, changed, or moved sensitive line still blocks until reviewed.
[2.23.3] - 2026-10-03
Section titled “[2.23.3] - 2026-10-03”- Completion reviews explicitly bind the selected verification run, its linked worktrees and immutable supporting evidence. The native engine checks that binding through task and scope acceptance, and the reviewer must assess performed work rather than only the plan. Existing pre-verification review ordering remains supported.
[2.23.2] - 2026-10-03
Section titled “[2.23.2] - 2026-10-03”- Named verification now supports a root npm script delegating once to a uniquely selected workspace runner. The declared root command remains intact, both npm argument boundaries are honored, and every inspected manifest is retained in launch provenance. Unsupported or ambiguous delegation fails before execution.
[2.23.1] - 2026-09-27
Section titled “[2.23.1] - 2026-09-27”- The statusline’s git dirty-state probe no longer takes
.git/index.lock. It is killed at a 100 ms budget, and a plaingit statuskilled while rewriting a stale index could leave a stale lock that blocked the next commit (reproduced: 5 of 200 renders at that timing, 0 of 200 with the fix).
[2.23.0] - 2026-09-27
Section titled “[2.23.0] - 2026-09-27”Changed
Section titled “Changed”- The statusline’s Session and Today cost is now reconstructed from the parent transcript and every subagent transcript, with each request counted once across streaming snapshots and forked-subagent replays. Advisor iterations are priced at their own model. Cache writes, server tools, fast mode and US-only inference are priced at pinned list rates.
- Each figure carries a coverage label:
api≈complete,api≥a lower bound,api≈?no defensible figure, andhost≈(Session only) for Claude Code’s own estimate when reconstruction is unavailable. A trailing*marks a stale snapshot, shown when a redraw loses the ledger lock; the bar never falls back to zeros. - Accounting state moved to bounded per-session files under
~/.codearbiter/ledger.json.sessions/. A redraw reads a fixed byte budget, so steady-state cost no longer grows with history. Deferred work resumes on the next redraw. - The subagent panel renders from ledger summaries and no longer parses child transcripts.
- Streaming snapshots and fork replays no longer double-count tokens or cost.
- Subagent usage is no longer missing from Session and Today totals.
[2.22.6] - 2026-09-27
Section titled “[2.22.6] - 2026-09-27”- Keep reconciliation bookkeeping outside verification inputs so an unchanged workspace can be reconciled without locked-file failures or stale approvals.
[2.22.5] - 2026-09-26
Section titled “[2.22.5] - 2026-09-26”- Explain input-manifest entry kinds to independent reviewers so normative artifact identities are not compared with raw HTML hashes.
[2.22.4] - 2026-09-26
Section titled “[2.22.4] - 2026-09-26”-
Count measured partial token usage toward proven budget overruns while keeping incomplete totals unknown; retain exact source identities without storing blobs.
-
Retain strict HTML intent-response identity checks and per-document source healing.
-
Bound oversized UTF-8 code-map diagnostics without rewriting human content.
- Internal closed scout-report decoding and test-owned observation accounting; onboarding dispatch and context-writing integration are not enabled by these helpers.
[2.22.3] - 2026-09-26
Section titled “[2.22.3] - 2026-09-26”Removed
Section titled “Removed”- Retire the
new-skillcommand,skill-authorworkflow and bundled template, including generated host entries. This maintainer-approved compatibility break has no replacement alias; resource edits use the existing change workflows.
-
Restore Codex CLI 0.145 review capture through an explicitly qualified native V1 interface, binding the child UUID and first result while rejecting steering, reused evidence and unsupported V2 launches.
-
Recover pristine, never-launched Codex 0.13.11 review requests using their exact historical prompt, preserving all retained evidence and integrity checks.
-
Preserve native specification, plan and retained evidence bytes across Git checkouts and staging on hosts with automatic line-ending conversion.
-
Select the exact Codex marketplace entry during installation checks, rejecting ambiguous, disabled or mismatched entries.
-
Complete context-creation, decomposition and release entry ownership while preserving initialization aliases, operational procedures and dry-run limits.
-
Redact complete multiline secret spans before formatting mutation diagnostics or truncating gate output for worker feedback.
-
Consolidate
reconcileunderdecision-variancewith shorter discovery metadata and a private analysis card. Report-only and scoped requests avoid an unnecessary decision interview; prior choices and sprint method authority are retained. -
Preserve append-only history when reaffirming a stale architectural decision, and require ADR marker cleanup on controlled failure as well as success.
-
Resolve ADR authoring markers through the same host project-root function as the ADR guards, retain that path for cleanup, and distinguish first-record directory creation from unreadable storage.
-
Consolidate ADR authoring and read-only status under one concise owner; load authoring and acceptance details only on demand, preserving explicit entries and full-stem identity without creating records during a status request.
-
Consolidate tribunal, threat modeling, manual drift, post-merge cleanup and PR entry procedures under concise skill owners. Retain explicit entries and mode authority; select PR watch/cleanup before creation preflight and avoid wrapper reloads or repeated branch-fate questions for an explicit open-PR request.
-
Generate debug and refactor entries from their owning skills, retaining all investigation and parity gates while removing duplicate routing policies.
-
Bound rendered farm enrichment, including labels and notices; preserve UTF-8 boundaries and actual retry failure context without extra authoring calls.
-
Recover farm merge conflicts against a verified integration commit, retaining prior output and rechecking the current protected-test baseline.
-
Cover connection and response-body failure lifecycles; clarify that unavailable mutation measurements warn independently of the measured-score threshold.
-
Bound farm provider-directed retry waits and close discarded responses before backoff; preserve independent progress without regenerating against a cooldown.
-
Preserve valid provider-reported tokens when worker output is rejected; validate response shapes and counters without coercion, extra requests or weaker gates.
-
Keep built-in mutation nonzero exits as unclassified rejection evidence, not measured kills; preserve adverse bounds, diagnostics and autonomous review.
-
Match whole, same-kind farm literals rather than substrings or conventional comments; retain existing rejection thresholds and name the actual small-file risk evidence.
-
Bound built-in farm mutation trials by their remaining budget; retain timeout diagnostics and completed adverse evidence without crediting an interrupted score.
-
Credit external farm mutation scores only from successful normalized stdout; preserve adverse failed-hook evidence and stop on unverified process cleanup.
-
Isolate farm regression Git and subprocess environments from the invoking shell.
-
Qualify retained farm candidates before discarding alternatives or retrying. Preserve complete native CI qualification within a bounded 30-minute job budget.
-
Resolve farm dependencies before overlapping-file arbitration, so an unready lower-ID task cannot block its own prerequisite. Preserve ready-sibling ordering.
-
Evaluate canary models and samples on one frozen commit in isolated detached worktrees, without changing integration or existing task branches. Report the effective candidate model and incomplete cleanup instead of hiding it.
-
Keep worker/test/verification gates and the separate HTML farm restriction intact.
[2.22.2] - 2026-09-26
Section titled “[2.22.2] - 2026-09-26”- Native artifact reviews use a bounded prompt pointing to the full frozen evidence context. The adapter checks its canonical bytes and digest before launch and publication, so large source manifests no longer fill the prompt.
- Never-launched ARMED reviews can be abandoned without producing authority or losing their history, including bounded oversized requests from older adapters.
- Concurrent authority operations reject stale request writes, so a stale abandonment cannot erase a newer launch or receipt, and a stale launch cannot revive an abandoned request.
[2.22.1] - 2026-09-26
Section titled “[2.22.1] - 2026-09-26”- Check all plan verification commands and input snapshots before requesting approval, including paired approvals; report unsupported runners and ineffective repository-relative exclusions together.
- Collect exact Playwright JSON results and supported simple npm scripts; reject ambiguous, skipped, duplicate and retried named results.
- Launch Windows npm through pinned native Node and npm CLI files, preserving literal arguments and rejecting runtime drift. Retain the qualified launch contract in verification evidence.
- Recognize both supported quote styles in verifier calls and preserve actionable oversized-input diagnostics without allowing explicit roots to bypass exclusions.
[2.22.0] - 2026-09-26
Section titled “[2.22.0] - 2026-09-26”- Approve a structured artifact by typing a four-character code, for example
approve K7MQ, instead of pasting a long token. The hook expands it to the exact armed reply, so the engine and recorded evidence are unchanged. - On Claude Code, approve by clicking an Approve option in the host’s own question dialog; the recorded origin names that seam.
- Replies with extra spacing, invisible characters, backticks, quotes or a closing period are no longer ignored; a reply that still cannot match now says why instead of failing silently.
[2.21.17] - 2026-09-25
Section titled “[2.21.17] - 2026-09-25”- Accept null diagnostics from successful HTML intent validation without bypassing invalid-spec, stale-read or issue-coverage checks; reject malformed collections.
[2.21.16] - 2026-09-25
Section titled “[2.21.16] - 2026-09-25”Changed
Section titled “Changed”- Release every plugin independently and idempotently on merge; a failed plugin no longer blocks the others, and re-running the release job is the recovery path. Three provenance checks now warn instead of blocking: npm attestation re-verification, the Codex ruleset audit, and the release-skill pre-tag proof (ADR-0040).
- Ship the native artifact engine to every Claude Code install: the qualified
release archive is published to the
ca-marketplacedistribution branch and the marketplace catalog installscafrom it (ADR-0040). - Name the concrete per-host repair in the
CAPABILITY_MISSINGdiagnostic.
[2.21.15] - 2026-09-24
Section titled “[2.21.15] - 2026-09-24”- Check the installed host’s required HTML workflow resources and hook registrations before new full-lane authoring. Unsupported or incomplete hosts stop early without creating fallback artifacts; legacy Markdown and the inline small feature lane retain their existing behavior.
- Include complete LICENSE and Go runtime notices in every installable governance-plugin subtree and verify their exact-source package bytes.
- Clarify the native-helper security inventory, retire operative wording from the inactive CLA, and document explicit statusline uninstall.
[2.21.14] - 2026-09-24
Section titled “[2.21.14] - 2026-09-24”- Claude Code verification and independent-review authority for structured
HTML plans: the verify wrapper is authorized and corroborated from Claude’s
Bash hooks, and spec and quality reviews run through a pinned read-only
ca:authority-reviewerbound by launchtool_use_id, childagentId, and the reviewer’s first stop only. The engine accepts a separateclaude-review/0.1.0profile; Codex behavior is unchanged and Pi still stops at this boundary.
[2.21.13] - 2026-09-24
Section titled “[2.21.13] - 2026-09-24”- Correct first-release re-entry after a declaration lands through a normal merge, squash, or fast-forward. An empty adoption-bounded payload window now requires an explicit confirm-or-replace decision, never silent widening.
- Require successful release-tree inspection and empty porcelain output at every direct clean-tree gate. Failed or timed-out probes stop before the next operation instead of being mistaken for a clean tree.
- Exercise the installed release guards and declaration/ledger re-entry with real consumer histories, and distinguish partial fixtures from full journeys.
[2.21.12] - 2026-09-23
Section titled “[2.21.12] - 2026-09-23”- Add one-reply initial HTML sprint approval and explicitly delegated SMARTS task-method revisions, with native atomic recovery and unchanged acceptance gates.
- Generate commit and new-skill command entries from their owning skills, preserving plain-language skill discovery and explicit command compatibility without independently maintained wrapper policies.
- Preserve the caller’s coherent sprint scope and required spec-to-plan continuation without manufacturing method-selection approval questions.
- Distinguish initial artifact approval from existing delegation and require the current qualified host-owned authority path; no new host support is implied.
- Keep complete authored HTML checkpoint membership across resume and review, without adding attended execution pauses to autonomous sprint work.
[2.21.11] - 2026-09-23
Section titled “[2.21.11] - 2026-09-23”- Add closed, host-observed verification, independent-review, recovery, and reconciliation authority for structured artifacts, with immutable evidence bindings and fail-closed cross-repository routing.
- Converge qualified Codex release archives and marketplace installs on one content-addressed distribution identity with race-safe promotion records.
- Bind workspace snapshots to tracked deletions, gitlinks, symlinks, and ignored targets; reject mismatched verification digests and unsafe authority paths.
- Recover interrupted user reconciliation with durable idempotent retries and exact pre-mutation cancellation instead of leaving an unresolvable prompt.
- Reject unproven recovery attempts, including partial commits and deleted workspace parents, while preserving exact retries and cancellation guidance.
[2.21.10] - 2026-09-22
Section titled “[2.21.10] - 2026-09-22”- Resolve cross-host git-hook path-form races: the shared registry and its generated pre-commit/pre-push shim now translate between Windows-native, Git-Bash/MSYS, and WSL drvfs path spellings (ADR-0038), the installer’s two-phase shim write is lock-serialized and rolls back on a partial failure, a foreign-spelled trusted identity now produces a diagnostic instead of a silent exit, and a sibling host’s differently-spelled drop-in directory is no longer treated as stale on every SessionStart.
[2.21.9] - 2026-09-22
Section titled “[2.21.9] - 2026-09-22”- Route understood requests to the existing workflow without compulsory command syntax; keep questions and draft-only requests non-mutating.
- Recover ordinary quality failures inside an approved sprint through the original gates and current typed evidence, without adding routine user checkpoints or expanding authority. HTML farm remains disabled.
[2.21.8] - 2026-09-22
Section titled “[2.21.8] - 2026-09-22”- Bound the internal release-tree Git status probe with a timeout so it reports an actionable failure instead of hanging or being mistaken for a mutation (#627).
- Disambiguate
releasehash’s overloaded exit code so malformed usage and an unknown target each report their own outcome instead of both reading as “never confirmed” (#627). - Refuse a release baseline that does not resolve as a verified ancestor of the candidate’s history, before any release edit, closing a silent version-retargeting gap (#570).
- Fail before any back-fill or release tracked-file write when the routed commit-gate’s prerequisites or branch restrictions are unmet, and correct back-fill’s “never again” claim to be checkout/file-scoped rather than project-global (#570).
- Make Back-fill declare and publish an operator-authored exact-SHA changelog reconciliation ledger before first-release re-entry, so published pre-footer history can release without rewriting commits or weakening the footer gate (#570).
- Surface
feat!,feat(scope)!, andBREAKING CHANGE:commits with an explicit Breaking marker in composed release notes, and prefer the first breaking entry for a major-bump headline (#570). - Restructure the release skill’s monolithic Phase-2 procedure into named, ordered, behavior-preserving substeps with an invariant-to-test traceability map (#623).
[2.21.7] - 2026-09-20
Section titled “[2.21.7] - 2026-09-20”- Add a host-owned structured-plan prerequisite adapter that binds exact user confirmations to current prerequisite records and recovers idempotently across capture or mutation failures without widening receipt authority.
[2.21.6] - 2026-09-20
Section titled “[2.21.6] - 2026-09-20”- Make merge readiness execute the same automatic-release candidate check as release preflight, and preserve main CI runs until their release trigger can be emitted instead of cancelling them when a later merge lands.
[2.21.5] - 2026-09-19
Section titled “[2.21.5] - 2026-09-19”- Route structured-artifact approval through host-owned prompts, issue one-shot receipts only after explicit user approval, preserve the approval-evidence mode in packaged receipts, and fail closed where Pi cannot prompt.
[2.21.4] - 2026-09-19
Section titled “[2.21.4] - 2026-09-19”/ca:standup’s archival sweep now creates its own dedicated chore branch before archiving anything and hands off to/ca:chore docs, instead of writing directly toopen-tasks.md/done-tasks.mdon whatever branch was current with no commit path at all (#573).commit-gate’s Phase 6 board-edit exemption no longer over-attributes an unconditional “any deleted entry is scope creep” rule to ADR-0008; a docs chore whose own Phase 3 classification is the board change is in-scope by that classification directly.
[2.21.3] - 2026-09-18
Section titled “[2.21.3] - 2026-09-18”- Default new full-lane feature and sprint work to qualified typed HTML specifications and plans while preserving exact-format legacy pairs and keeping HTML farm dispatch disabled.
- Accept a manually exercised Codex candidate as current release proof only when its canonical package bytes still match and its exact same-repository CI run completed successfully.
[2.21.2] - 2026-09-18
Section titled “[2.21.2] - 2026-09-18”- Make the portable release lane preserve space-containing payload pathspecs,
verify back-filled Cargo manifests, floor first-release history before
classification, tolerate the expected zero-tag state under
pipefail, and bind provenance object and commit identities to one remote snapshot. Use the portable Python command in theca-pigeneration declaration, force helper record output to LF on Windows, qualify hosted-owned asset cohorts without executing their local sentinels, reject duplicate committed release-note sections before tag mutation, and bind automatic publication to the exact changelog commit plus the candidate’s exact manifest blobs. - Ensure a release-proof-only correction selects both proof validation and the exact-head package cohort needed by automatic publication.
[2.21.1] - 2026-09-18
Section titled “[2.21.1] - 2026-09-18”- Require a merged default-branch commit and green hosted exact-head evidence before release tag composition, and establish one POSIX shell before the portable workflow runs on Windows.
- Give the Windows artifact pin guard enough time to start on native ARM64 and wait for it to release the verified executable before returning, preventing false farm failures and locked temporary repositories.
[2.21.0] - 2026-09-17
Section titled “[2.21.0] - 2026-09-17”- Add provenance-bound structured-artifact native packages, exact-host cold-install qualification, installed-host diagnostics, and serialized release/read-back gates. New full-lane feature and sprint work remains Markdown by default; typed HTML is available only as an explicitly requested, fail-closed pilot, and the HTML farm remains disabled pending its separate qualification.
[2.20.2] - 2026-09-17
Section titled “[2.20.2] - 2026-09-17”gate-events.logno longer accumulates REMIND/WARN noise — only BLOCK events (actual enforcement decisions) are persisted.remind()/warn()remain full-strength on stderr, unchanged in every other respect.- Structured-artifact Python bridge, workflow, package, farm, and conformance fixtures now resolve only their test-owned temporary directories to physical paths, matching the existing Go fixture rule so hosted macOS symlink roots and Windows path aliases do not masquerade as production containment failures.
- The reviewed reference HTML pair and its supporting assets are pinned to LF checkout bytes so Windows autocrlf cannot manufacture renderer drift.
- The macOS Python bridge and farm dispatcher now launch a private ephemeral
executable image written only from the already verified package descriptor,
because macOS does not permit native execution through
/dev/fd; Linux and Windows pinning is unchanged and no PATH or repository fallback is introduced.
[2.20.1] - 2026-09-17
Section titled “[2.20.1] - 2026-09-17”core/pysrc/_cleanuplib.py: a follow-on to 2.20.0’s T-03 remediation, closing findings a further independent review surfaced after that fix had already merged.parse_branch_ref_inventorystill split onstr.splitlines()— the same hazard already fixed in the sibling worktree parser — letting a branch name containing a Unicode line-boundary character truncate its for-each-ref line and fabricate a phantom second record carrying the real branch’s own OID and a confirmed-absent upstream. Also fixed: a CRLF-terminated worktree porcelain line could silently lose itslocked/detached/bareflag (fail-unsafe forlocked);%(upstream)pointing at another local branch (refs/heads/..., not justrefs/remotes/...) was not stripped to its short name; andclassify_worktree_loss_surface’sretaincould come back a non-bool value for a non-bool caller input.
[2.20.0] - 2026-09-17
Section titled “[2.20.0] - 2026-09-17”core/pysrc/_cleanuplib.py: adds T-03, the authoritative branch/worktree inventory ADR-0036 named as one of three preconditions for superseding safety-core.md #6 (alongside the already-built T-04 proof evaluator and T-05 guarded mutation backend). New pure helpers:parse_branch_ref_inventory(full-OID branch facts fromgit for-each-ref, neverbranch -vv’s abbreviated form — a line without exactly the format’s 4 tab-separated fields is fully unreadable, not partially trusted),parse_worktree_inventory/parse_worktree_inventory_nul(newline- and NUL-delimitedgit worktree list --porcelain; the main worktree is identified by Git’s own first-record ordering guarantee, never a repo-root string comparison),bind_branch_occupancy(cross-references the real worktree list rather than a display-only marker; an unavailable worktree list marks occupancy unreadable, never confirmed-unoccupied),classify_worktree_loss_surface(dirty/untracked/ignored/locked/current/nested-repo content all retain a worktree; an unreadable status, or an unreadable input of any kind, is never folded into clean), andvalidate_resource_path(an exact-match allowlist guard against the caller’s own authorized targets, returning the resolved path — not a “nested under the repo root” rule, since Git worktrees are conventionally siblings of the repository root, not descendants).
core/pysrc/_cleanuplib.py: closes 3 blocking and 5 high-severity gaps an independent review found in T-03 as first merged (verdict: NO-GO). The main worktree is no longer identified by comparing a path string against a caller-supplied repo root (wrong on every linked worktree, and on any Windows-vs-forward-slash path mismatch); an unavailable worktree list no longer defaults branch occupancy to “confirmed unoccupied”; a for-each-ref line without exactly 4 tab-separated fields is now fully unreadable rather than partially trusted; the filesystem-path guard is now an exact-allowlist match returning the resolved path, replacing a “nested under the repo root” rule that refused every real (sibling) worktree; and the worktree-loss classifier now accepts an explicit read-error signal and never lets an unreadable input leak through as a false “safe to remove.” The CI job that runs this suite is now itself wired in, closing the same orphaned-suite gap the T-04/T-05 fix below (2.18.9) had to close for its own tests. Still true and not claimed otherwise: this closes the inventory gap but does not by itself satisfy ADR-0036’s gate — this remediation pass has not itself been independently re-reviewed, and nothing here is wired into a live route (T-06’s job).
[2.19.0] - 2026-09-16
Section titled “[2.19.0] - 2026-09-16”- Add a disabled-by-default, extensible structured-artifact engine foundation for canonical HTML specifications and implementation plans, with bounded typed operations, Linux and Windows recovery semantics, verified native bridges, descriptor-relative Unix installation, and required three-host CI. The Windows developer installer fails closed pending a reviewed release-packaging boundary, and HTML farm dispatch remains blocked pending integration and qualification.
[2.18.9] - 2026-09-17
Section titled “[2.18.9] - 2026-09-17”core/pysrc/_cleanuplib.py: closes 6 blocking and several high-severity gaps an independent review found in the T-03/T-04/T-05 cleanup-framework backend against ADR-0036’s supersession gate (verdict: NO-GO on the backend as it stood).execute_branch_deletionnow requires aProofResultand refuses an unproven target outright — “proven-merged” is no longer caller honor; the force/atomic-delete path is unlocked only byproof.method == "pr_delivery", never a caller-supplied flag;evaluate_merge_proof’s ancestry path is now repository-qualified (previously only the PR-delivery path checked the target’s repository); worktree occupancy is revalidated fresh via a callable at every mutation attempt, not a static snapshot; a claimed-successful delete is reverified before being recorded “applied”; a read failure is never folded into “branch confirmed absent” in reconciliation or the guard; the journal’s retention bound now comfortably exceeds the proposal’s own named 40-branch batch example; andrepository_idis threaded through and validated for consistency. The journal file is renamed.cleanup-journal.json(was.resources.json). Still true and not claimed otherwise: nothing in this repository calls this module in production, and wiring it into a live route remains T-06’s job.
[2.18.8] - 2026-09-17
Section titled “[2.18.8] - 2026-09-17”core/pysrc/_cleanuplib.py: the cleanup-framework’s shared decision and interaction vocabulary (T-02) — typedScope,Target, andDecisionobjects with explicitunknown/erroroutcome states, plus two pure classifiers:scope_covers(a scope never authorizes a resource kind or member it didn’t explicitly name) andrequired_confirmation_count(how many new confirmations an operation needs, based only on its authorization source — zero for an already-bound direct instruction, snapshot reply, or accepted work lifecycle; exactly one for an unauthorized proposal; always one more for an unresolved unique-content loss, regardless of how many). Not yet wired into any live cleanup route; consumed by T-06’s routing work and by this task’s own fixtures only.
[2.18.7] - 2026-09-17
Section titled “[2.18.7] - 2026-09-17”core/pysrc/_cleanuplib.py: a repository-bound operation journal and a guarded, revalidating branch-deletion executor for the cleanup-framework mutation backend (T-05, branch-deletion slice). The executor journals intent before mutating, revalidates a branch’s tip immediately before every delete attempt (including the forced retry), refuses current/default/explicitly-protected/worktree-occupied branches, and reconciles any still-pending record from actual repository state rather than retrying blindly. Not yet wired into any live cleanup route. Worktree-removal guarding and filesystem-operation constraints are separate, not-yet-built increments sharing this same pattern.
- CI now runs the T-04 integration-proof evaluator’s and T-05’s own unit test suites (
test_cleanuplib.py,test_cleanuplib_mutation.py) — both had been merged without a CI step invoking them, so they ran locally but were invisible to the pipeline.
[2.18.6] - 2026-09-17
Section titled “[2.18.6] - 2026-09-17”core/pysrc/_cleanuplib.py: a repository-qualified integration-proof evaluator (evaluate_merge_proof) for routine branch cleanup. Proves a candidate branch tip’s content landed on an authorized integration target via ancestry (noghrequired) or an exact, repository-qualified PR-delivery record; tree-equality is accepted only as corroboration and never grants eligibility by itself. Not yet wired into any live cleanup route — a standalone, unit-tested decision function pending the guarded mutation backend and policy wiring the cleanup-framework proposal sequences after it.
[2.18.5] - 2026-09-16
Section titled “[2.18.5] - 2026-09-16”core/pysrc/_standuplib.py’s worktree inventory now captures lock state, detached-HEAD status, and the exact OID fromgit worktree list --porcelainoutput instead of silently dropping them; a locked worktree is now excluded outright from standup’s hygiene-candidate list.
[2.18.4] - 2026-09-16
Section titled “[2.18.4] - 2026-09-16”includes/routing-table.md’s Hard gate column had drifted behind already-shipped skill behavior: the standup row required per-item confirmation for every worktree removal even thoughcommands/standup.mdalready permits one named enumerated group, and the post-merge-cleanup row named ancestry +branch -donly even thoughskills/post-merge-cleanup/SKILL.mdalready documents the PR-record squash-proof path and its restricted-Dexception.
[2.18.3] - 2026-09-16
Section titled “[2.18.3] - 2026-09-16”marker_name_for()now case-folds every path segment before encoding, matching_canon/lookup_policy’s existing case-insensitive registry comparison, so a differently-cased Write/Edit target no longer computes a marker name that was never minted (#624).
- Backfill
.codearbiter/code-map.mdand its provenance record for this repository’s own project state.
[2.18.2] - 2026-09-15
Section titled “[2.18.2] - 2026-09-15”- Keep exhaustive repository and cross-platform verification on exact-head hosted CI instead of requiring contributors to replay the full matrix locally before committing or opening a pull request.
[2.18.1] - 2026-09-14
Section titled “[2.18.1] - 2026-09-14”- Permit explicit changelog reconciliation only for exact published commits through a reviewed, default-branch-bound ledger while retaining strict failure for ordinary missing footers.
[2.18.0] - 2026-09-13
Section titled “[2.18.0] - 2026-09-13”- Support declared numeric release policies and exact verified asset inventories while preserving SemVer defaults and explicit publication authorization.
[2.17.11] - 2026-09-13
Section titled “[2.17.11] - 2026-09-13”- Continue active authorized work across startup, resume, and compact hook boundaries while retaining the idle-session command prompt.
[2.17.10] - 2026-09-08
Section titled “[2.17.10] - 2026-09-08”- Resolve genuine append-only audit-log conflicts through a fail-closed helper that preserves both branch histories and records the immediate H-05 authorization, with shared audit-path locks and a locked mandatory-override writer preventing concurrent row loss.
[2.17.9] - 2026-09-07
Section titled “[2.17.9] - 2026-09-07”- Use the same documented done-tasks template for initialization and first-use archiving, with byte-identical UTF-8 headers on Windows and POSIX.
[2.17.8] - 2026-09-06
Section titled “[2.17.8] - 2026-09-06”- Keep task-board lifecycles Git-clean by locally excluding the retained OS-lock sidecar during initialization, with an explicit repair option for existing repositories.
[2.17.7] - 2026-09-06
Section titled “[2.17.7] - 2026-09-06”- Distinguish ordinary return-code identifiers such as
rc2from cipher configuration in the crypto/TLS commit gate.
[2.17.6] - 2026-09-06
Section titled “[2.17.6] - 2026-09-06”- Recover an unsettled mode-enter audit row on a repeated request instead of reporting an ineffective posture as a no-op.
[2.17.5] - 2026-09-06
Section titled “[2.17.5] - 2026-09-06”Changed
Section titled “Changed”- Correct privacy disclosures and align task archival documentation with the established standup-owned policy.
[2.17.4] - 2026-09-05
Section titled “[2.17.4] - 2026-09-05”- Upgrade earlier codeArbiter-managed Git hook shims after ownership-banner wording changes while preserving foreign hooks.
[2.17.3] - 2026-09-05
Section titled “[2.17.3] - 2026-09-05”- Preserve ADR source commits through PR merges so lifecycle validation remains reproducible after branch deletion and a fresh clone.
[2.17.2] - 2026-09-04
Section titled “[2.17.2] - 2026-09-04”- Retain release tag identity receipts and refuse subsequent publication when prior tag provenance is incomplete.
Changed
Section titled “Changed”- Isolate rendering tests from ambient color settings and verify that they restore the caller’s environment without modifying user state.
[2.17.1] - 2026-09-03
Section titled “[2.17.1] - 2026-09-03”- Prevent read-only filename searches from falsely triggering protected-state interpreter guards while preserving mutation enforcement.
[2.17.0] - 2026-09-02
Section titled “[2.17.0] - 2026-09-02”- Command discovery now groups the supported core lanes while retaining advanced operations and compatibility routes in generated host catalogs.
- Release-state, route-graph, and documentation-inventory drift now fail closed against canonical source, with tag-only or unverified Releases rejected.
[2.16.0] - 2026-09-02
Section titled “[2.16.0] - 2026-09-02”- Accepted ADRs now have content-bound lifecycle records, sealed obligation sets, and evidence-derived implementation and verification states.
- Destructive-operation policy now uses one four-item registry with generated host parity and item-for-item enforcement.
[2.15.10] - 2026-09-02
Section titled “[2.15.10] - 2026-09-02”- Hook registration and doctor now bind every Git probe to the requested repository, resolve effective hook paths through Git, and fail closed when linked-worktree ownership cannot be proven.
[2.15.9] - 2026-09-02
Section titled “[2.15.9] - 2026-09-02”- Release-note reconstruction now accepts only exact changelog headings,
rejects ambiguous
Unreleasedand duplicate sections, and reads the regular-file blob from the exact tag and repository root without inherited Git repository overrides or replacement objects.
[2.15.8] - 2026-09-01
Section titled “[2.15.8] - 2026-09-01”- Review and generic parallel batches now terminate at a read-only verdict aggregator, while checkpoint persistence remains a separate non-overwriting writer invoked only by the explicit checkpoint workflow.
[2.15.7] - 2026-09-01
Section titled “[2.15.7] - 2026-09-01”- Update notices now select only the Claude
v*release series, keep cache freshness and latest-version state separate from Codex and Pi, and retain the Claude marketplace update command.
[2.15.6] - 2026-08-26
Section titled “[2.15.6] - 2026-08-26”Changed
Section titled “Changed”- Plugin-root discovery now treats the executing module location as authoritative, validates the internal normalized root separately from Claude’s native root, and fails closed on mismatch, traversal, symlink escape, or an invalid package anchor.
- Shared status-line and hook wiring now preserve host-native root semantics while consuming the same deterministically generated internal kernel across adapters.
[2.15.5] - 2026-08-24
Section titled “[2.15.5] - 2026-08-24”- Linked-worktree commits now read content-bound security and migration gate markers from the shared main-checkout marker root while keeping branch, diff, and migration-file reads anchored to the operation worktree.
[2.15.4] - 2026-08-23
Section titled “[2.15.4] - 2026-08-23”- Lock-contention regression tests now use deterministic retry clocks and real-lock event handshakes instead of scheduler-sensitive elapsed-time ceilings and timed holds. This removes intermittent CI failures while preserving the production 0.2-second fail-soft lock budget unchanged.
[2.15.3] - 2026-08-21
Section titled “[2.15.3] - 2026-08-21”- Codex desktop wrapped execution now preserves its explicit worktree directory through the shared H-01 guard. A valid feature-worktree commit is no longer evaluated as an unrelated session checkout on
main; direct protected-branch commits remain blocked.
[2.15.2] — 2026-08-13
Section titled “[2.15.2] — 2026-08-13”- The orchestration mode is now stored one file per session under
.codearbiter/.markers/mode.d/, replacing the single shared map. Two sessions in one checkout could previously overwrite each other’s posture: a session that leftdangerousforarbitercould havedangeroussilently reinstated by a concurrent write, still authorized by its own earlier audit row. Each session now writes only its own entry, so no flip can revert or drop another’s. - The mode-plane staleness warning reads each session’s own entry, so an unrelated session starting up no longer resets the clock on a session that has sat in
dangerous.
[2.15.1] — 2026-08-13
Section titled “[2.15.1] — 2026-08-13”Changed
Section titled “Changed”$ca-spikenow carries only its committed findings file back to the parent before deleting the disposable spike branch. Exploratory code and spike commits remain outside implementation history.
[2.15.0] — 2026-08-12
Section titled “[2.15.0] — 2026-08-12”- Orchestration mode plane (ADR-0030):
arbiter,dangerous, andops. The injected persona is nowsafety-core.mdplus the active mode’s body, composed per turn, and the mode is flipped by a whole-prompt-anchored control token intercepted at the prompt seam with no model turn. opsmode: an advisory carve-out permitting in-channel work that starts, observes, or exercises a running system, keyed on the durable artifact produced. Anything mutating tracked files, the index, git history, or published state stays routed and refused.
Changed
Section titled “Changed”ORCHESTRATOR.mdis renamedarbiter.mdand reframed as the arbiter mode’s body rather than an always-on kernel. Its header records the former name so historical citations stay resolvable.- Persona injection moved off
SessionStartto the per-turn prompt seam; a once-per-session event cannot express a mid-session posture change. The startup block is now per-mode composable emitters. devmode becomesdangerous: a general gates-off posture for any repository, with no maintainer-only env gate. No enforcement hook reads the mode, so every gate fires in all modes.
Removed
Section titled “Removed”- The
devandarbitermode-entry commands. The mode bodies are the surface. The shared source catalog undercore/surface/commands/drops from 40 to 38, andca’s own visible catalog from 39 to 38 — each host excludes entries it cannot serve, so a source count is never a host count.
- A compaction could silently clear a live mode, because the mode plane borrowed the legacy marker’s owner record to decide whether it had seen a session before. It now keeps its own anchor.
- Mode and marker state resolved through two different roots in three places; in a linked worktree a transition pair could split across two audit logs, or a stale session go undetected.
[2.14.1] — 2026-08-12
Section titled “[2.14.1] — 2026-08-12”- Shared bash guard refresh.
_bashguardlibis re-vendored here fromcore/pysrc/, socacarries the same guard as its siblings. The behavior it corrects is Codex execution-workdir handling: an explicit workdir is honored, so H-01’s branch check reads the repository the command actually runs in rather than the process’s own directory. Nothing changes for a Claude session — this host never sets that workdir — but the payload did, so the version advances with it.
[2.14.0] — 2026-08-08
Section titled “[2.14.0] — 2026-08-08”Changed
Section titled “Changed”- The nine chain-internal skills (
brainstorming,writing-plans,executing-plans,subagent-driven-development,tdd,using-git-worktrees,dispatching-parallel-agents,secret-handling,crypto-compliance) carrydisable-model-invocation: true— their descriptions no longer load into every session’s registry (ADR-0028). Every route to them is now an explicit{{PLUGIN_ROOT}}/skills/<name>/SKILL.mdpath load (routing-table preamble + per-site citations), so chains never depended on the hidden entries. - Frontmatter scalars that start with
[/{or contain": "or" | "are JSON-quoted across commands and skills (the_yaml_safe_scalarpredicate, now also a skill-author house rule) — portability hygiene for hosts that parse frontmatter strictly.
- Documented harness behavior:
feature,fix, andnew-skillare reserved names suppressed from the model-facing registry by the host (typed invocation unaffected; intent routing runs through ORCHESTRATOR.md). Recorded in docs/investigations/token-efficiency.md.
[2.13.0] — 2026-08-08
Section titled “[2.13.0] — 2026-08-08”Changed
Section titled “Changed”- Tribunal roster consolidated (ADR-0027): the eleven
tribunal-<lens>-revieweragents are replaced by one generictribunal-lens-reviewerdispatched once per active lens with a title-first lens assignment. The lens cards underskills/tribunal/references/lenses/are now the roster and carry each lens’s scope emphasis and required reading; agent count 28 → 18. - Gate reviewers share
includes/reviewer-contract.md(findings format, review output template, out-of-scope rule) and the backend/frontend authors shareincludes/author-tdd-workflow.mdinstead of restating those blocks per agent. - Docs site: the eleven per-lens agent pages are replaced by a generated
/reference/tribunal-lenses/<lens>/collection sourced from the lens cards, with redirects from the old agent URLs.
[2.12.1] — 2026-08-07
Section titled “[2.12.1] — 2026-08-07”/ca:release’s--dry-runno longer executes a declaredrebuild/generatecommand — it previously ran the row’s rebuild unconditionally, overwriting a committed build artifact despite promising not to write anything. Found and fixed by a required pre-tag blind agent-judgment exercise.- Phase 3’s
resume_publishpath can now reconstruct release notes from the committed CHANGELOG via a newchangelog-sectionCLI subcommand, instead of depending on a scratch file that does not survive a session boundary.
[2.12.0] — 2026-08-07
Section titled “[2.12.0] — 2026-08-07”- Recorded intent now precedes autonomous scoring and spec shaping (ADR-0025).
SMARTS gains a scoped Step 0 recorded-intent check: it applies to
/ca:sprintscoring andbrainstorming, whiledecision-variance, thegrader, and thedecision-challengerare exempt by name, so arbitration keeps ranking the record via the Phase 4 authority order instead of conforming to it. The check ranks an “answered” outcome by that same order (a user steer outranks the log, the log outranks an accepted ADR, an ADR outranks the plans artifacts) and never conforms downward silently. /ca:sprintreads the decision record before Phase 1 spec approval and surfaces plausibly-touched ADRs and deferrals at the interactive gate. An auto-decision that would contradict an accepted ADR or a recorded deferral is a hard gate, with a stale-record valve: gate-time pre-rulings carry, a deferral whose recorded re-evaluation trigger has occurred is reopened rather than treated as a contradiction, and each record stops a sprint at most once. Sprint-log entries carry anintent:field pinned after theconfidence:token, keeping harvested board titles clean (fixture-proven).brainstormingchecks feature framings against recorded deferrals and backlog items (a resurrection is a fork to ask) and candidate approaches against accepted ADRs (a contradiction surfaces with its citation and pairs with a supersession fork; it is never silently dropped or recommended bare). All new reads are index-first and fail-soft: a repository with no decomposition record proceeds untouched, and brownfield repos gain no new block.- The contract is pinned across every host projection by
test_recorded_intent_surface.py(24 deletion mutants killed; ca-codex carries noagents/surface and is exempted explicitly), wired into CI as an explicit step. ADR-0026 (destructive operations declared in the routing table, amending ADR-0022) is ratified in this release; its implementation ships with the follow-up kernel restructure.
[2.11.17] — 2026-08-06
Section titled “[2.11.17] — 2026-08-06”- Corrected the 2.11.0 changelog entry’s protected-state-registry description
to name its three enrolled consumers (
release-targets.md,open-tasks.md,done-tasks.md) instead of claiming it ships empty; the same stale “ships empty” claim in_protectedstatelib.pyand_bashguardlib.pyis corrected to match. - The release skill’s Phase 3 release-notes command used bracket notation
(
--latest[=false]), which is prose shorthand and not shellghaccepts; split into the two runnable commands the surrounding prose already describes. - Pre-flight’s clean-tree requirement and the later rebuild step read as contradictory in isolation; added a one-sentence note distinguishing the entry condition from the later, deliberately-reconciled exception.
medium-documentswas cited by bare name in the release skill’s changelog step while every sibling include in the same sentence carries a full path; pathed it to match.- Fixed a markdownlint MD018 trip in
security-controls.md(a line began with#175, which reads as an unspaced ATX heading marker). load_targets()folded everyOSErrorreading a declared release-targets file intoAbsentBlockError, so a file that exists but cannot be read (permissions, a directory at that path, a transient I/O error) was misreported as “no release-targets block” instead of “could not read it.” AddedUnreadableTargetsFileError, a sibling ofAbsentBlockError, so the two failure modes are distinguishable and the CLI exits 4 (not 3) for the unreadable case.check_skill_proof_fresh.pyraisedAttributeErrorinstead of a clean error list when a proof artifact’s top-level JSON value was an array ornullrather than an object.test_release_trace.pypinnedPRE_CHANGE_SHAwith an 8-character abbreviation instead of the full 40-character SHA.test_consumer_smoke.pymigratedshutil.rmtree’s cleanup callback from the deprecatedonerror=(3-arg, exc_info tuple) spelling toonexc=(3-arg, exception instance).- The context-creation skill’s single-target
release-targets.mdtemplate omittedlatest-eligible: true, disagreeing with the release skill’s own back-fill detector (detect_candidate_target), which emits it for the identical shape. - Added a real-registry regression case for a stale H-22 protected-state marker (previously only exercised against a synthetic injected registry).
row_assertions()reported a blankrebuild: ""string as a declared command instead of “not declared”, inconsistent with the siblingprovenance_manifestfield two lines below it in the same function, which already strips blanks.select_release_target_by_name()returned the bare string""— outside its own documented<target>|none|multiple|unknownvocabulary — for a pair with a blank NAME (e.g."=1.2.3"); it is now ignored like a pair with no=at all.- The docs site’s
.codearbiter/directory reference listeddone-tasks.mdas written only by/ca:task archive, omitting/ca:standup’s per-item archival sweep, which the very next paragraph already describes archiving into the same file through the same helper. release.yml’s preflight step carried a leftover comment describing the OLD positionalselect_release_targetcall’saritycontract, directly above the correct explanation of the NAME-KEYEDselect-target-namedcall that actually runs there today.
Documentation
Section titled “Documentation”- Marked
specs/release-portable-fixture.mdimplemented (was “awaiting approval”) now that #576 shipped it, and repaired three markdown-table breaks and a stale coverage-proof cross-reference (A-6.7/A-6.8) inplans/portable-release-and-protected-state.md.
[2.11.16] — 2026-08-06
Section titled “[2.11.16] — 2026-08-06”run-pre-tagnow resolves a POSIX-compatible shell (Git for Windows’ ownbash.exe) to dispatch a target’s declaredpre-tagcommands, instead of always dispatching throughcmd.exeon Windows — so a row spelled"$PY" <script>(the #601 convention) now runs correctly on every platform, not just POSIX. A Windows host with no POSIX shell reachable at all now reports a distinct “could not run” diagnosis (exit 9) rather than misreading the absence as drift. This repository’s own.codearbiter/release-targets.mdpre-tagrows are rewritten from hardcodedpython3to"$PY"now that the fix makes it portable (#602).
[2.11.15] — 2026-08-05
Section titled “[2.11.15] — 2026-08-05”- INDEX.md / routing-table.md consistency is now a CI-checked invariant
instead of an authoring discipline:
check_routing_index_parity.pyfails the build when a skill/routine/agent is missing its INDEX row, an INDEX row points at nothing, orincludes/routing-table.mdroutes to a name that does not exist — across all four generated surfaces (core/surface,ca,ca-codex,ca-pi).skill-author’s routing- integration phase now cites the check instead of re-stating the hand-verification it replaces (#592).
[2.11.14] — 2026-08-05
Section titled “[2.11.14] — 2026-08-05”/ca:release --dry-runis now real: it runs Pre-flight and Phase 1’s read-only version derivation, then reports the target, the derived version and rationale, the per-commit classification, and the resolved declared row, without writing a changelog entry, bumping a manifest, committing, or tagging (#565).- A new
uncovered_intenthelper (_intentlib.py) backstopswriting-plans’ bijective plan/criteria check with a citation check against the spec’s own scope bullets and a linked issue’s acceptance checkboxes, catching a criterion that both a plan and its own spec quietly missed (#566).
writing-plans’ Phase 4 gate is reframed to state only what bijection actually proves — that a plan and itsAC-NNledger agree with each other, never that the ledger itself is complete — and bothbrainstormingandwriting-plansnow ask an explicit negative-judgment question (“if every criterion passed, what would still be broken?”) that a bijective check cannot mechanize (#566).
[2.11.13] — 2026-08-05
Section titled “[2.11.13] — 2026-08-05”- Six
.github/scripts/test_release_lib.pygovernance rules that pin load-bearing sentences in the release skill — the footer BLOCK / never-auto-fill rule, the publish read-back rule, the immutable-tag hard rule, the pre-tag BLOCK-on-nonzero rule, and two re-run HIGH rules (tag_shapeeling, back-fill’slatest-eligibledeclaration) — had every anchor token also occurring elsewhere in the skill, so the sentence each one names could be deleted while the rule stayed green. Each is now re-anchored on a span unique to its own guarded sentence, verified against the source and all three rendered payloads (ca,ca-codex,ca-pi), with a pinned RED/GREEN mutation proof against the real skill text (#571).
[2.11.12] — 2026-08-05
Section titled “[2.11.12] — 2026-08-05”- The git-level hook backstop (#161) could run from an arbitrarily stale
host plugin cache — a Codex install that predated the #279 sensitive-scan
exemption resurrected that exact false positive, blocking a commit whose
only “sensitive” lines were the crypto/secret gate’s own machine-written
audit rows, with no in-session exit but an override. Each live host’s
session now records a content-addressed freshness heartbeat
(
.git/codearbiter-hooksd/<plugin>.seen) alongside its registered enforcer entry; the generated shim skips a registered entry whose heartbeat is missing or stale relative to a fresher registered sibling, deferring the verdict to whichever entry a live session most recently confirmed, rather than letting an unrefreshed cache author a block./ca:doctornow surfaces a stale drop-in entry before it can produce a false block (#556).
[2.11.11] — 2026-08-05
Section titled “[2.11.11] — 2026-08-05”- The H-11 authoring-marker freshness window is now a single declaration
(
_hooklib.MARKER_FRESHNESS_MINUTES), imported by every enforcement flank that used to hardcode its own copy of the literal (pre-write.py,pre-edit.py,_bashguardlib.py,git-enforce.py,_protectedstatelib.py) — a change to the window now moves every flank together instead of silently desyncing them (#567). _releaselib.py’s unreachable_PRERELEASE_MARKERSdead code — proven unreachable behind the anchored release-tag regex — is removed rather than left as unexplained dead code shipped to every consumer (#568).
[2.11.10] — 2026-08-05
Section titled “[2.11.10] — 2026-08-05”- Linked-worktree sessions could record a security/migration gate pass that
the H-09b/H-10b/H-14 commit guards would never see:
security-pass.pyandmigration-pass.py, run bare via a Bash tool call (noCLAUDE_PROJECT_DIRin that shell), wrote their marker under the worktree’s own (gitignored).codearbiter/.markers/, while the guards read it from the main checkout. A newmarker_root()seam (hostapi.Host) gives both sides the same main-checkout answer without moving the diff/migration SCAN root, which must stay bound to the tree actually being committed (#604). test_colorlib.py’s palette-compatibility tests read the real project’s.codearbiter/state when rendered via subprocess with no explicitcwd, so a maintainer’s own accumulated audit-log rows could make a required custom-palette color intermittently disappear from the assertion window. Isolated to a synthetic, in-fixture.codearbiter/(or none at all), plus a new test that appends adversarial override/gate-event/task rows and proves the palette-completeness check still holds (#552).- Ten
test_git_hooks.py/test_repo_resolution.pytests failed whenever the suite itself ran from inside a linked git worktree (subagents do this routinely):_githooks’s own__file__resolved to an ephemeral path, which the existingis_ephemeral_pathsafety check (#441/ADR-0014) correctly refused to register into a fixture’s shared drop-in dir. Fixtures now resolve_githooks’s enforcer path from a durable temp-dir copy of the hooks payload (durable_plugin_copy, the #442 fix’s existing pattern).
[2.11.9] — 2026-08-05
Section titled “[2.11.9] — 2026-08-05”- H-05/H-11/H-18 (the
.codearbiteraudit logs, ADRs underdecisions/, andCONTEXT.md) gain the interpreter leg H-22/H-19 already carried — an inline-code one-liner (python3 -c "open('overrides.log','w')...",py -c,pwsh -Command) no longer walks past all three shell flanks (#574). - H-22’s git-restore leg now also covers restoring the ENCLOSING DIRECTORY
of a registered file (
git checkout HEAD -- .codearbiter/), not only the bare basename, and a package manager’sinstallSUBCOMMAND (pip install,npm install,cargo install, …) no longer false-blocks against coreutils’installverb (#575). - The Codex host notes’ hook-safe audit-log append recipe no longer directs
Windows PowerShell 5.1 users to bare
>>, which can write a UTF-16LE tail onto an existing UTF-8 log; the recipe now uses an explicit UTF-8-no-BOM[System.IO.File]::AppendAllTextappend with a documented verification step (#594).
[2.11.8] — 2026-08-05
Section titled “[2.11.8] — 2026-08-05”- Every command/skill surface that spelled the interpreter fallback as
python3 X || python Xnow resolves the interpreter once, by presence, before invoking a helper (#577). The||fold branches on the helper’s EXIT CODE, so any helper answer that carries information as a nonzero code (e.g.taskwrite.py archive’s “archive could not be read”) got silently re-run underpythonand had its verdict replaced by the second run’s.plugins/*/hooks/hooks.jsonis deliberately unchanged — its pass/fail hooks carry no exit-code vocabulary to lose.
[2.11.7] — 2026-08-05
Section titled “[2.11.7] — 2026-08-05”Changed
Section titled “Changed”tddPhase 2 gains a rationalization guard: the four known excuses for skipping the red test (“too simple to fail first”, test-after equivalence, “would restate the implementation”, “already covered”) paired with their rebuttals — the already-covered rebuttal carrying its own falsifying instrument. A/B-validated against the prior skill before shipping (7/7 hard requirements both arms, zero over-blocking, sharper domain grounding).skill-authorPhase 4 adopts the evidence-lens checklist (issue #612): rationalization guards at tempting gates, instruments over self-report, recommendation with counter-case, mechanize-don’t-accrete, and letter-vs-spirit — plus A/B validation for behavior-changing gate revisions.
[2.11.6] — 2026-08-05
Section titled “[2.11.6] — 2026-08-05”Changed
Section titled “Changed”- The orchestrator persona is restructured on measured A/B evidence (#609): hard rules move to the head of the document, a rationalization guard and a letter-vs-spirit rule intercept gate-skipping, every user-facing ask leads with a recommendation and its strongest counter-case, a suspicious gate is diagnosed before any bypass, and the startup-presentation instructions move out of the always-on persona and into the SessionStart briefing itself — roughly 20% shorter always-on persona with no observed behavioral regression across the tested scenario suite.
[2.11.5] — 2026-08-04
Section titled “[2.11.5] — 2026-08-04”Changed
Section titled “Changed”- Modernized the
brainstormingskill for capable models: bundled ideas split before refinement, candidate approaches shaped with one recommendation, parameter-level choices decided and recorded while genuine forks are asked in full, a breaker stops non-converging refinement loops, and the spec is mechanically self-reviewed and adversarially challenged before approval.
[2.11.4] — 2026-08-04
Section titled “[2.11.4] — 2026-08-04”- The orchestrator no longer asks “did you mean” when it has already resolved
the exact command and its complete argument.
ORCHESTRATOR.md§6 now draws the tier-1/tier-2 boundary (ADR-0022) by what is already resolved rather than by temperament: an exact command with a complete argument and no competing candidate is unambiguous by definition and routes directly. Tier 2 is reserved for a genuinely incomplete reading — an argument you’d have to invent, or a second plausible command — and the destructive set.
[2.11.3] — 2026-08-04
Section titled “[2.11.3] — 2026-08-04”post-merge-cleanup(#586): Phase 1’s containment proof no longer relies on SHA-ancestry alone, which fails for every ordinary squash merge in this repo’s default merge mode. A squash merge is now proven by the merged PR record (headRefOid== HEAD), reported alongside the ancestry check’s negative result as a fact rather than a failure. Phase 3’s blocked-checkout STOP now distinguishes a genuinely conflicting kept artifact from a stale local default ref. Phase 4 fast-forwards the local default ref before checking it out, so a stale ref can no longer be misattributed to a kept artifact. Phase 5 documents whygit branch -dcan already accept a squash-merged branch via its upstream, and sanctionsgit branch -Donly when this run’s Phase 1 proof was the PR-record squash proof and-drefused.standup(#596): stale worktrees can now be confirmed for removal as one explicitly enumerated group naming every member, instead of forcing one confirmation per worktree; declining the group falls back to per-item confirmation. Branch pruning documents the matching squash-merge-Dexception.
[2.11.2] — 2026-08-04
Section titled “[2.11.2] — 2026-08-04”- Gave the release lane’s internal tree-state probe the same audit-scratch
exemption the skill already requires everywhere else, so a mid-window
gate-events.logappend is no longer misdiagnosed as a mutating pre-tag command. - Split
run-pre-tag’s failure diagnosis into four distinct exit codes: a declared command that ran and reported drift, one that mutated the tree, one whose interpreter or program could not be located at all, and a tree-state probe failure — each with its own remedy, so “could not run” is never reported as “ran and disagreed”. - Exported the resolved interpreter to every declared release-lane command
via a
PYenvironment variable, so a declared row can portably spell"$PY"instead of a hardcoded interpreter. - Mechanized the release lane’s version-bump arithmetic behind a new
apply-bumpsubcommand, closing the one step still left to hand derivation. - Floored the release lane’s first-release footer check on the earliest
addition of either
CONTEXT.mdorrelease-targets.md, so a Back-fill consumer’s own first release can clear Phase 1 step 3.
[2.11.1] — 2026-08-03
Section titled “[2.11.1] — 2026-08-03”- Restored fresh-clone release-trace verification by pinning its historical reference to the reachable pre-migration commit with the same release-library bytes.
- Stabilized repeated statusline-render tests by isolating their unrelated repository-dirty probes.
- Kept the landing page’s guarantee cards aligned by resetting inherited sibling-flow spacing at the card boundary.
[2.11.0] — 2026-07-31
Section titled “[2.11.0] — 2026-07-31”-
A protected-state registry, enforced as hook class
H-22. Project-state files under.codearbiter/can now be guarded, each registry entry carrying its own policy rather than one uniform rule:marker-gatedadmits a write only under a fresh authoring marker,helper-onlyhard-blocks every tool path so a sanctioned helper’s own file I/O is the only route, andappend-onlyadmits mutation solely through an append verb.open-tasks.mdis deliberately not marker-gated.taskwrite.pyis already its only blessed writer, and because it writes with Python file I/O whose argv never names the file, it is invisible to every flank by construction. A marker would therefore add nothing for the helper while admitting an agent that hand-composes board markdown under it, which is the inversion of the goal.The class registers on all three flanks. A one-flank implementation passes a Write-door test while
echo … >> filestill lands, sopre-write,pre-edit, and the shell guard each carry it. Two non-regressions are pinned because they are load-bearing rather than convenient:git add open-tasks.mdmust pass, sincecommit-gateruns exactly that on every retained board flip and a git verb in the list would make commit-gate block itself; and a filename appearing in a helper’s argv as description text must pass.The shipped registry enrolls three consumers:
.codearbiter/release-targets.md(marker-gated),.codearbiter/open-tasks.md(helper-only), and.codearbiter/done-tasks.md(append-only). It stays code constants rather than disk-loaded state, which would otherwise let a repo un-protect its own board by editing a file. Recorded as ADR-0024. -
The release mechanism is now portable.
_releaselibsplits into a host-neutral mechanism undercore/pysrc/, generated byte-identically into all three governance plugins, and repo-specific data that moves into a declared.codearbiter/release-targets.md. Repo facts that were defaults become required parameters, since a default is how a repo assumption survives a portability refactor unnoticed.This closes a defect that made
/ca:releaseunrunnable anywhere but here: its first pre-flight step called a helper that was never in the plugin payload.
-
A consumer whose tag prefix contained
-beta,-rc, or-alphalost every release in that series. The pre-release filter substring-tested the whole tag including the prefix, so a project taggingweb-beta-v1.2.0received the never-released sentinel and would have been offered a first-release baseline despite having releases. The test now applies to the version portion only. Invisible in this repository, live in a consumer’s. -
The release skill cited a CI path that only exists in this repository. A parenthetical pointed at
.github/actions/publish-release/action.ymlto explain where the tag-peeling helper came from. That file ships in no payload, so every consumer read a pointer to nothing - the exact this-repo contamination the portable-fixture work exists to remove. The explanation stands without the path. -
The tag was written before the check that says whether writing it was safe. Phase 2 named
git tag -afirst and classified the publish state afterwards, so an agent following the step in written order created the ref and only then asked whether it should have.git tagnow appears once, in thepublish_freshbranch, after classification. -
Three of
classify’s six arguments had no stated source, and a fourth had no local one.head_sha,tag_version, andmanifest_versionwere named but never sourced, so each was supplied from whatever the reader inferred;release_nondraft’s only origin,gh release view, reports “no remote” and “no such release” through the same non-zero exit. All four now carry an explicit derivation, and the ambiguousghfailure STOPs instead of passing a guess into the one branch that decides whether a published release is republished. -
<summary>in the Release title convention was never defined. It appeared exactly once in the skill - in the convention itself - so the title of every published Release was improvised. It is now derived from the changelog section the release already composed. -
Every Markdown heading was silently deleted from composed tag messages.
git tag’s default cleanup mode isstrip, which treats#-prefixed lines as comments and removes them. A Keep-a-Changelog section is entirely#-prefixed, so the version heading and every group heading vanished, leaving an undifferentiated bullet list that no longer says which version it describes. This already happened to this repository’s publishedv2.8.13, and a published tag is immutable, so it can only be superseded. The lane now passes--cleanup=verbatimand then re-reads what git actually stored to confirm the heading survived - neither of the two guards the skill already named could see this, because both read the section file rather than the tag. -
The publish classifier was fed a stale version and an un-negated flag. Two arguments added one commit earlier were sourced wrongly.
manifest_versionsaid to read the manifest “as Pre-flight read it” - but Pre-flight reads it before the version bump, and the stale value makes the classifier returnabort_mismatch, a terminal stop, on a release where nothing is wrong.release_nondraftwas sourced fromgh release view --json isDraft, which emits a JSON object rather than a bare boolean and carries the opposite polarity, soalready_publishedwas unreachable. Both now carry an exact command and, for the second, an explicit inversion. -
A check the skill required could not be run. Both phases named
release_dates_consistentand Phase 2 called it mandatory, but no CLI subcommand exposed it, so it was reachable only by importing the module - something the skill never instructs. Added asdates-match. -
The first release of every back-filled project died on a sentinel. With no tag yet in a series, the tag helper returns the literal string
<none>, and the skill spelled the commit windowLAST_TAG..HEAD- so the command it handed the operator wasgit log <none>..HEAD, which exits 128 withfatal: bad revision. The prose called that state “normal, not an error” while giving a command that cannot survive it, and it lands on exactly the consumers the back-fill lane exists to serve. The window is now derived into$WINDOW(HEADwhen there is no tag,<tag>..HEADotherwise) before any command uses it. -
Version derivation now has one base instead of two floors. The bump applies to
$BASE_VERSION- the maximum of the last tag’s version and the highest version any declared manifest carries - and the strictly-greater assertion runs once against it. The two-floor form this replaces hard-blocked a legitimate release: a project holding av1.2.0tag and a1.4.2manifest derived1.3.0from the tag, then failed its own manifest floor, and the step said only “must exit 0” with no remedy. It also demanded a comparison against the last tag, which on a first release is the string<none>- not a version, so that comparison was unrunnable on exactly the path back-fill exists to serve. One base removes both. -
The manifest reader now follows the file’s format. Only the JSON form was named, so a declared
pyproject.tomlraisedJSONDecodeError. The<manifest_version>argument also reads the first declared manifest while the base reads the maximum across all of them - deliberate, but safe only because the bump touches every declared path, so that coupling is now stated rather than left to be discovered when a partial bump turns a healthy release into a terminal stop with a misleading reason. -
A project that had shipped without tagging was released backward. With no tag in its series the lane took
0.0.0as the base, so a package whose manifest already read1.4.2derived0.1.0- and the manifest bump then wrote that over it, moving the project’s own version backward. Every gate passed, the manifest-equality assertion included, because the bump had just made it equal. The base is now the highest version any declared manifest carries, taken across all of them rather than the first, and the strictly-greater assertion runs against that floor as well as against the last tag - through a newsemver-greatercommand, since the arithmetic the hard rules say must never be guessed had no tool behind it. -
Three smaller wiring defects on the ordinary path. The possibly-empty tag sha was passed unquoted, and on the fresh-publish path - the common case
- an empty unquoted argument does not become an empty positional, it
vanishes, so the classifier received five arguments and exited 2. Reading
the manifest version named no command where every neighbouring argument
named one. And the tag round-trip check read
git tag -l --format=%(contents), a reconstruction that appends a newline and so cannot detect a byte difference even in principle; it now reads the raw object.
- an empty unquoted argument does not become an empty positional, it
vanishes, so the classifier received five arguments and exited 2. Reading
the manifest version named no command where every neighbouring argument
named one. And the tag round-trip check read
[2.10.8] — 2026-07-30
Section titled “[2.10.8] — 2026-07-30”Changed
Section titled “Changed”-
_hooklibsheds activation, completing the #321 partition (slice 4 of 4). The hook core finishes at 557 lines, from 1,263 - a 56% reduction across four slices._activationlibnow owns which Host the process runs under, where the project root is, and whether the arbiter is switched on, together with the two process-lifetime caches those answers share._HOSTis deliberately not re-exported: importing a mutable global binds its value, so a laterset_host()would rebind it in the owning module and leave a stale copy behind forever. The accessors are re-exported instead, and a test proves both modules share one cache in both directions._hooklibre-exports every name with a consumer, so the public surface is unchanged and parity rests on 1,185 pre-existing hook tests that did not move.No behaviour change.
[2.10.7] — 2026-07-30
Section titled “[2.10.7] — 2026-07-30”Changed
Section titled “Changed”-
_hooklibsheds its path-scope detection (#321, slice 3 of 4). The hook core drops from 880 to 663 lines - 1,263 before the partition began, so three slices have taken nearly half off the god module._scopelibnow owns which repo paths are database migrations (H-14), CI/CD workflow files (H-15), and deployment / IaC manifests (H-16), plus the security-controls.md reader and glob compiler they share.The cleanest seam of the four: this cluster referenced NOTHING from the rest of
_hooklib, and nothing referenced it. Its only dependency wasnorm_path, already on the_pathnormfloor._hooklibre-exports every moved name - including the private ones, which have real consumers - so the public surface is unchanged and parity rests on 1,185 pre-existing hook tests that did not move.No behaviour change.
[2.10.6] — 2026-07-30
Section titled “[2.10.6] — 2026-07-30”Changed
Section titled “Changed”-
_hooklibsheds its protected-path classifiers (#321, slice 2 of 4). The hook core drops from 1,050 to 880 lines - 1,263 before the partition began._protectedlibnow owns which repo paths are append-only audit logs (H-05), ADR decision files (H-11), the activation manifest, and the gate-marker directory.repo_reljoinednorm_pathon the_pathnormfloor, because it references no module symbol and the remaining slices need it too.Measured the same way slice 1 was: one outward reference, zero inward.
_hooklibre-exports every moved name, so all consumers are untouched and parity rests on 1,185 pre-existing hook tests that did not move. The public surface is preserved exactly - nothing lost, nothing gained.No behaviour change.
[2.10.5] — 2026-07-30
Section titled “[2.10.5] — 2026-07-30”Changed
Section titled “Changed”-
_hooklibsheds its H-09b/H-10b sensitive-scan concern (#321, slice 1 of 4). The 1,263-line hook core drops to 1,051._sensitivelibnow owns the crypto and secret detectors, the pinned security diff argv, the path-aware diff walk, and the digests that bind a recorded gate pass to the lines it reviewed;_pathnormholdsnorm_pathas the dependency floor beneath every path classifier.The seam was measured rather than guessed: the cluster referenced exactly ONE symbol from the rest of
_hooklib, and nothing in the rest of_hooklibreferenced the cluster._hooklibre-exports every moved name, so all 59 consuming files are untouched and behavioural parity rests on 1,185 pre-existing hook tests that did not move.No behaviour change.
[2.10.4] — 2026-07-29
Section titled “[2.10.4] — 2026-07-29”-
The symlink-safe worktree writer accepts an absolute destination spelled through a link (#541).
writeWorktreeFilecanonicalized the worktree ROOT but resolved the caller’s absolute path as-is, then compared the two — so a caller building a destination from the root it had itself passed in was refused for writing inside its own worktree. Same root cause as #539, one module down, and it never reproduced on a host whose paths are already canonical.Only the ANCESTOR chain is canonicalized; the final component stays literal, so a symlinked destination is still refused rather than written through. Like #539 this tightens the guard: a path whose ancestors traverse a link out of the root is now caught by containment instead of relying on a later check.
-
A timed-out farm test no longer abandons a live subprocess (#542). Every launch in
farm.test.tsis a real child process and none were tracked, so a vitest timeout left one running with the temp directory as its cwd and the teardown then failedEBUSY— reporting the cleanup instead of the timeout that caused it. Children are now reaped before the directory is removed, and the removal tolerates Windows’ asynchronous handle release.The heaviest case (12 tasks at
FARM_CONCURRENCY6) also gets a budget drawn from measurement rather than a nudge: 3553 ms isolated on a developer box against a 5000 ms default, 5331 ms under load on a CI runner. It is now 30 s — bounded, so a genuine hang still fails. The case itself is unchanged; concurrency stays at 6 and every assertion stands.
[2.10.3] — 2026-07-28
Section titled “[2.10.3] — 2026-07-28”-
The farm worktree containment check canonicalizes both paths before comparing them (#539). It was lexical, and
path.resolveneither expands a Windows 8.3 short name nor follows a link — so two spellings of one directory compared as different paths and a worktree root genuinely inside the repo was refused, with a message telling the operator to point it inside the repo where it already was. The only escape wasFARM_ALLOW_EXTERNAL_WORKTREE_ROOT=1, which disables the guard outright to work around a false positive in it.Surfaced by #521’s coverage-union job the first time this tree ran on Windows CI: 15 failures, all downstream of one refusal, because the runner’s tmpdir is
C:\Users\RUNNER~1\...while git reportsC:/Users/runneradmin/.... It does not reproduce on a developer box whose profile path is already 8.3-clean.The change tightens the guard: resolving links means a junction inside the repo whose target is outside is now refused, where the lexical check accepted it. That was never exploitable —
fs.rmremoves the link rather than recursing through it, measured — but accepting it was still wrong. A missing root is normal and is canonicalized by walking up to the deepest existing ancestor; any realpath failure that is not absence refuses, per #163.
[2.10.2] — 2026-07-28
Section titled “[2.10.2] — 2026-07-28”Changed
Section titled “Changed”-
A quoted coverage figure is now the union across a tree’s supported hosts, per tree (#521). The command is identical on every platform; the report is not. Code behind a platform fork cannot execute off its own platform, so a single-host report scores the other platform’s arm as uncovered no matter how well tested it is — measured here,
exec.tsreads 87.50% branches on Windows against 76.38% on Linux, an 11-point gap that is entirelyawaitTaskkillplus the win32treeKillarm on one side and the POSIX arm on the other.That matters beyond arithmetic:
treeKillis a process-containment path, so under a single-host rule a genuine gap in it is indistinguishable from the platform artifact.includes/maturity-coverage.mdgains the rule andtddPhase 5 now requires the measuring host to be named. Trees with no platform fork stay single-host — a union of identical reports is the same report.
[2.10.1] — 2026-07-28
Section titled “[2.10.1] — 2026-07-28”-
The farm dispatcher serializes access to git’s worktree registry (#515).
.git/worktrees/is a shared registry that git mutates non-atomically:git worktree addscans the existing entries while creating its own, so a second concurrent add could read a sibling’s directory after it existed but before itscommondirwas written. The dispatcher ran up toFARM_CONCURRENCYprepare sequences at once with no lock, so one task would intermittently escalate atattempts: 0withworktree add failed: … failed to read .git/worktrees/<other>/commondir, flipping an otherwise green run’s exit code from 0 to 2.Measured directly against real git: six concurrent prepare sequences over 40 rounds produced two failures with that signature, and zero when serialized.
Worktree creation, removal and prune now run under a dedicated lock, separate from the existing merge lock so that short registry calls never queue behind a long merge. Concurrency is unchanged — the worker API call, the gate and the tests all still run in parallel; only the brief registry mutations are serialized, and the retry backoff deliberately runs outside the lock so one worker’s retry schedule cannot stall the others.
[2.10.0] — 2026-07-27
Section titled “[2.10.0] — 2026-07-27”A MINOR bump, not a patch: this window adds ca-pi as a fourth sibling plugin,
/ca:cleanup, inbound-PR review, multi-plugin release lanes, and the §6 routing
model — nine feat commits since the 2.9.1 section, no breaking changes.
Cut so the fixes below actually reach installed users. They had been merged onto
an untagged 2.9.1, and claude plugin update is a no-op while the manifest
version string is unchanged — so a populated 2.9.1 plugin cache stayed frozen
at the pre-fix payload. The maintainer’s own session was still being blocked by
the pre-fix copy of a hook guard whose fix had already merged. The gate that is
supposed to catch this keys on the git tag rather than the manifest, and v2.9.1
was never tagged; that gap is #530.
-
decision-variancecould not record a decision. Its Phase 4 is required to append every SMARTS arbitration to.codearbiter/decisions/decision-log.md“immediately, never batched” — and H-11 refused every write to it, because H-11’s path rule matched any.mdunderdecisions/and therefore governed the arbitration log as immutable ADR history requiring the/adrauthoring marker. Onlydecision-lifecyclearms that marker, so any arbitration outside an/adrsession made a decision it could not write down (#528).The log is not an ADR. It is an append-only audit artifact — its own format doc states H-05’s rule verbatim (“strictly append-only … to supersede, append a new entry”) — so it is now governed by H-05 instead: append freely, never rewrite. ADR files beside it keep the marker gate unchanged, and the carve-out is exactly one path wide:
old-decision-log.mdand a nestedsub/decision-log.mdare still ADRs. (decision-log.md.bakis in neither guard set — it does not end in.md, so it was never an ADR path either.)Adversarial review caught two holes in the first cut of this, both of which left the append-only log destructible from the shell. The carve-out was case-insensitive while H-05 — the guard taking over for that file — is case-sensitive on both flanks, so a case-varied spelling was stripped from one guard’s view and invisible to the other; on Windows/NTFS and default macOS/APFS that spelling resolves to the real file. And
New-Item -Force, which truncates, was covered by H-11 but not H-05, so the log lost that verb on reclassification — a gap the flat audit logs shared, now closed for all of them. The carve-out also lacked a right-edge anchor, so the log’s path shielded any token beginning with it.Consequence of the deadlock, for the record: blocked from writing DECISION-0029 during this session, the assistant cited it in
farm.tsanyway — a dangling governance pointer that would have shipped insidefarm.js. Caught in review and retracted (#526). -
The coverage gate’s no-tooling exemption required no evidence.
tddPhase 5 andrefactorPhase 2/6 are BLOCK gates that may be passed when a surface has no coverage tooling, but the trigger was a bare self-assertion by the agent running the phase — and “I could not find the command” is indistinguishable, from the inside, from “this surface has none”. The two demand opposite responses: the first is a STOP under the skills’ own hard rule, the second is the exemption. So an agent that merely failed to locate the command could walk through a BLOCK gate by describing its own failure as a property of the repo, which is the shape of issue #507 — a gate that reads as satisfied without ever executing.The exemption now requires the record to name the surface and quote, from
tech-stack.md, either the whole Coverage section or the passage stating the absence for that surface by name. A partial quote that stops before the commands does not count, and a section that merely never mentions the surface must be quoted in full so the silence is visible and judged rather than asserted. No citation, no exemption: the phase STOPs. The record travels into the PR description, so the claim is still falsifiable when a human reviews and not only while the lane is live.This repo takes the exemption.
site/and the Python hooks have no coverage command, andtech-stack.mdhad a local copy of the old, laxer rule for exactly those surfaces — naming onlyrefactorPhase 2, telling an agent to “say so” rather than cite. That copy is now a pointer, which is the whole point: the conditions live inincludes/maturity-coverage.mdand nowhere else. -
The farm’s mutation-escalation note stated survivor counts it had invented. It interpolated the number of mutants evaluated under a “survived” label, so a task whose test caught 1 of 10 was rejected with “mutation score 0.10 (10 mutants survived)” — a claim the score in the same sentence disproves. This note is the entire operator-facing explanation for a hard-escalated task and is fed back into the next worker’s prompt, so a wrong count both misled a human and misinformed a retry (#525).
The root cause was the
MutationResulttype, not the format string. A pluggableFARM_MUTATION_CMDis only required to print a trailing JSON line with a numericscore;totalandsurvivedare optional. But the type declared all three fields as always present, so the parser had to invent the missing ones — an empty survivor list and a99denominator — and once invented, nothing downstream could tell a fabricated count from a measured one.evaluatedandsurvivorsare now optional, absent when the producer did not report them, and the note states a survivor count only when there is one to state.If you use a pluggable
FARM_MUTATION_CMD, a hook that reports only a score now yieldsgaming: mutation score 0.05 — …with no survivor clause, where it previously claimed(99 mutants survived). A hook that reports survivors but no total yields(9 survived)rather than inventing a denominator. A hook whose survivor ids are not strings keeps its true count; an earlier cut of this fix filtered them out and reported(0/10 survived)while escalating the task for its survivors.Behaviour change to the escalation gate, for hook users only. The
evaluated >= 5floor exists to refuse hard-rejecting a task on thin evidence. It previously substituted99for an unreported mutant count, so a hook that never said how many mutants it ran cleared the floor and could get a task rejected on no evidence at all. It now requires a count the hook actually reported.Measured across 27 hook shapes, exactly four change, all in the same direction (escalate → warn) and all under the same rule — the producer stated no usable count:
{"score":0.05}(absent),"total":null,"total":[10], and"total":1e400(Infinity). Nothing changes for the built-in mutator, which always reports a count, nor for any hook that reports a real one, and nothing newly escalates.A count is read as reported when it is a number or a numeric string, so
"total":"10"from a shell hook that quotes its numbers still clears the floor exactly as before. An intermediate version of this fix rejected quoted numbers, which silently disabled the anti-gaming gate for such hooks at every count. -
tddPhase 5 andrefactorPhase 2/6 can actually run. Both instructed “run the coverage command fromtech-stack.md” and both forbid guessing one - and no coverage command existed, in any tree, for any of the four plugins. So every run reached the phase, found nothing to run, and passed through on a gap. A BLOCK gate that cannot execute is worse than an absent one: it reads as satisfied in every lane, which is the same defect class as issue #501’s five suites that ran on nothing (#507).refactorwas the worse casualty. Phase 2 is “Behavioral parity coverage proof” - the gate that justifies the lane by showing the tests can detect a behavior change BEFORE production code is touched - and it rested entirely on a command that did not exist. -
The threshold table never said WHICH metric, and the omission was load-bearing rather than cosmetic: a report gives four numbers that disagree, so ”≥ 70%” with no column named is not something anyone can be held to. It is now lines and branches, both binding. Lines catches code no test reaches (issue #504 was exactly that - a
catchwith zero executions inside a 750-test suite); branches catches the untaken half of a condition a test does reach, which lines alone reports as covered. -
A contract test now asserts that any command a gate reads from
tech-stack.mdis actually defined there, so the next gate cannot ship pointing at nothing. It goes further than the text check that shape usually gets, because adversarial review broke three weaker versions of it in succession:- it runs for the files it guards — the gate prose and
tech-stack.mdare registered in theimpactfilter and the push trigger, so a PR that only deletes the coverage section no longer skips the one job that checks it (the same omission as #384, #403/#404 and #416); - it resolves the command, asserting the named
npm run <script>exists in the named manifest rather than trusting that the prose is self-consistent; - it is complete by construction, deriving the expected set from the
plugins/*/toolsmanifests, so a new tree cannot be added undocumented; - it is checked in both directions, so an entry guarding nothing fails
loudly instead of looking like protection. Running that check for the first
time surfaced a third command reader nobody had noticed —
dependency-reviewerreads anauditcommand from the same file.
Every branch above is mutation-verified: six mutations, each confirmed to fire, against a control that passes.
- it runs for the files it guards — the gate prose and
-
/ca:reviewcan review an inbound GitHub pull request, not only the diff you just wrote:/ca:review #123fetches that PR’s diff and runs the same fleet, the same path matrix, and the samefinding-triage->checkpoint-aggregatorfunnel. A gate that only reviews its own author’s change is a linter, not a team gate, and reviewing code you did NOT write is where it earns its keep (issue #80).Deliberately an ARGUMENT rather than a
/ca:review-prcommand. The scope resolver already took one, the fleet is scope-agnostic, and every phase downstream operates on a diff regardless of where it came from - so a second command would be a whole public surface (the catalog, three host projections, the README counts, the site sidebar) whose only distinguishing feature is where the diff was fetched from. The command count is unchanged.Three guards ride with it. A missing or unauthenticated
ghSTOPs rather than falling back to the working diff, which would report a verdict on the wrong change under the PR’s name. The diff is resolved ONCE, because the fleet runs in parallel and a PR updated mid-review would otherwise have reviewers reading different code. And posting the verdict is a separate, confirmed step that never uses--approveor--request-changes: a comment on someone else’s PR is public the moment it lands, and those two flags carry merge authority this command does not have. -
/ca:releasereleases any of the four plugins, as one command taking the target as its argument (defaultca, so a bare/ca:releaseis unchanged). It could only ever targetcabefore, becauseLAST_TAGresolution matched^vMAJOR.MINOR.PATCHand nothing else - so the three siblings had version guards in CI, a changelog, and a tag namespace, but no sanctioned command that could read any of them. Every phase is now written once against a Targets table rather than four times: one row per plugin giving its tag namespace, manifest, changelog, payload scope, shipped bundles, and whether it may claim the repo-wide “Latest” badge (onlycamay). No new command was added - four commands would be four public surfaces to govern and carry for one operation whose only difference is which row it reads (#382). -
_releaselib.last_tag_selecttakes the tag namespace as a parameter, andRELEASE_TAG_PREFIXESis now the single source of truth for it - the same register the hosted release lanes’tag-prefixinputs are asserted against, so the command and the workflow cannot disagree about a namespace. Series isolation is a property of the ANCHORED match rather than an exclusion list to maintain:^vcannot matchca-pi-v0.1.30, so a fifth plugin cannot leak into an existing series by being forgotten somewhere (#382). -
/ca:add-depgains a bounded Ephemeral tool run section. The command applied to any download-and-execute, so a one-time analysis tool was pushed through project-dependency review — and with no command owning that action, the routing loop reached for/ca:overridefor an operation that adds no risk at all. The distinguishing test is now the dependency graph, not the download: anything entering a manifest, a lockfile, or a base image takes the existing review unchanged. The carve-out keeps the part of supply-chain review that still applies — an exact pinned version and the approved registry — and requires one confirmation rather than a review, because the operator has already decided not to adopt. A manifest or lockfile change is prohibited and verified withgit status --porcelainafter the run rather than trusted: a tool that writes one has adopted itself, and that stops and takes the full review. It is a section rather than a command because a new command would add a public surface across three hosts to govern an action whose whole definition is that it changes nothing (issue #346, ADR-0023). -
Added
/ca:cleanupand itspost-merge-cleanupskill: the already-merged branch transition, which no command owned. It fetches, provesHEADis an ancestor of the fetched default branch, classifies every dirty and untracked artifact as unique, redundant, or superseded, resolves each under its own confirmation, fast-forwards with--ff-only, and deletes the merged local branch withbranch -d. Anything not provably redundant or superseded counts as unique and is never discarded unbidden; stashes are report-and-route only; the remote branch is never touched. Branch deletion keys off proven ancestry rather than: gone]upstream state, so a squash-merged branch whose remote still exists is recognised as landed (issue #308). -
Added
ca-pi, the fourth sibling plugin and third governance host, generated from the same Python and markdown core as Claude Code and Codex CLI. -
Added a dependency-free, Git-installed Pi package with
/ca-*aliases,/skill:ca-*fallbacks, project-trust-gated activation, final tool wrappers, native compaction, bounded child dispatch, farm preview routing, diagnostics, and cross-platform contract tests for Pi 0.80.5 and Pi 0.80.6. -
Added the reproducible Pi install/live-test runbook and converted the host parity ledger to source-visible Claude Code/Codex CLI/Pi evidence.
Changed
Section titled “Changed”-
The release skill named two independently-versioned plugins; the repository has four. It now names every series (
v*,ca-codex-v*,ca-sandbox-v*,ca-pi-v*) and routes a sibling release to the hosted dispatch lane instead of leaving it undefined./ca:releasestill ownscaitself. The stale count was load-bearing in one place: the guidance for resolvingLAST_TAGand for setting--latestreasoned about “both plugins”, which understated by two the set of tags that can shadow ca’s baseline or take the “Latest” badge (#382). -
ORCHESTRATOR §6 now routes on understood intent instead of naming a command and then asking the user to retype it. Unambiguous, non-destructive intent routes directly into the command with every gate intact; probable intent asks once, naming the command; genuinely unclear intent gets the chooser. Clarity and risk are separate axes, so anything irreversible or gate-bypassing —
/ca:override, merge to the default branch, branch or worktree deletion, release and tag publication,/ca:deventry — still asks even when the intent is obvious. The invariant §6 protects is preserved by construction: the orchestrator routes the command and never improvises the operation, and a missing owner is a routing gap to surface, never a reason to reach for/ca:override(ADR-0022, issue #308). -
Marked the complete
ca-piadapter as a Feature Forgepreview. It is available and welcomed for real use, with automated and hosted promotion evidence complete, while broader real-world testing continues before any claim of 100% validation or stable status.
Security
Section titled “Security”- Pi child work now crosses a minimal provider-specific environment, strict bounded RPC/JSONL schemas, an enforcement-only child extension, attested startup, and whole-process-tree cleanup on cancel, timeout, and failure.
- Pi repository-aware activation requires both the existing opt-in marker and affirmative host project trust; unknown or foreign tool replacements fail closed.
-
A sibling release now DECLINES the repo-wide “Latest” badge explicitly instead of omitting the flag. Omitting
--latestis not neutral: GitHub defaultsmake_latestto true for any non-prerelease, so every namespaced sibling silently claimed it. Caught by publishing -ca-pi-v0.1.32, the first sanctioned ca-pi release, displacedca v2.8.13from the position every visitor sees. The badge was restored withgh release edit --latest, a metadata change that moves no ref; the ca-pi release stays exactly where it was published.The test that should have caught it asserted
--latestwas ABSENT from the command log, which is the defect restated as an assertion - absence of the flag WAS the bug, so a test demanding absence could only ever agree with it. It now asserts the refusal is present, with a fail-closed case for any value other than"true". -
git commit-graphis no longer gated as though it weregit commit(#485). A word boundary sits betweencommitand-, so the H-09b/H-10b matcher took everycommit-*verb. The cost was not the annoyance: the gate told the operator to run the crypto-compliance gate for a command that writes no objects and creates no commit, leaving only a pass that certifies nothing or an/ca:overrideinvented to cover a coverage hole. It bit at the worst moment too, since a stale commit-graph is exactly what a batch of--delete-branchmerges leaves behind.commit-treestays in scope deliberately: it creates a commit object, and a crafted commit plusupdate-refis a real path around H-01. Anything else in thecommit-*space is still gated, so an unfamiliar verb fails closed rather than open. -
The prose-separator-dash detector reads a paragraph at a time instead of a line at a time (#484). It required word characters on both sides of the dash ON THE SAME LINE, so a separator that landed at a soft-wrap boundary scored zero in both directions - the right-hand span on the next line, or the left-hand span on the previous one. Three real violations in the site’s own pages had to be found by hand for that reason. Joining stops at every block boundary (blank line, list item, heading, table row, thematic break, fence), and each finding still carries the line of its own dash.
-
A secret in a farm plan no longer persists in the run’s permanent receipt.
plan.metawas serialized verbatim into.farm/runs/<runId>/farm-report.jsonand its Markdown sibling, and the run-scoped change made that permanent: the old.farm/farm-report.jsonwas clobbered by the next run, while.farm/runs/accumulates with no prune path.meta.setup,setupEachAttemptandsetupInputsare raw shell-command arrays andapiBaseUrlis a URL, so a token in a setup command was a perfectly legal plan that landed on disk forever. Every free-textmetafield is now redacted at the sink, once, for both receipts. Note this is redaction and not an allowlist:checkPlanObjectis already a closed-object check that rejects unknownmetakeys at parse, so the allowlist the issue proposed would have duplicated an existing control and caught nothing — the allowed fields were the exposed ones (issue #439). -
The artifacts block and the diff-evidence reasons now pass through the file’s own redaction chokepoint, so raw
gitstderr and filesystem error text cannot reach either receipt un-redacted. -
The outbound redactor recognises four credential shapes an adversarial run proved were reaching a receipt intact: GitLab PATs (
glpat-), OpenAI project keys (sk-proj-), basic auth embedded in a clone URL, and bearer tokens. Acurl -u user:passrule is deliberately not added — that shape collides withdocker run -u 1000:1000, and the gap is recorded rather than papered over. -
atomicWriteFilepreserves an existing destination’s permission bits instead of resetting them to the umask default, opens its temp fileO_EXCL, and cleans up when the write fails rather than only when the rename does. The test that claimed to cover that path only exercised the rename. -
The shipped
farm.jsbundle is now executed by the test suite, not merely regenerated and byte-compared.includes/farm.mdtells operators to runnode <plugin>/tools/farm.js, but the integration launcher ranfarm.tsthrough the tsx loader and the unit suite importedfarm.ts— so the merge gate proved source behaviour and deterministic generation, and never that the ESM bundle starts, parses argv, resolves its bundled modules, or preserves exit semantics under plain Node. A byte-identical artifact is not a working one. A focused shard now covers plan validation, a missing credential, the loopback API’s success and failure paths, and report emission against the rebuilt bundle; a parity test runs one fixture through both entry points and compares exit code, tally, and report; and a negative control proves a syntactically valid but behaviourally altered bundle fails the shard while everyfarm.tstest stays green. CI rebuilds before testing so the shard runs against a fresh artifact (issue #407). -
The test suites no longer write outside their own temp directories. Running the hook suite rewrote the developer’s real
~/.claude/settings.json— both the statusline command and its owner key repointed at whatever plugin root the test process resolved — and littered~/.codearbiter/with a ledger, its lock, five session shards and an update cache. Four modules did it, none using theredirect_homehelper that already sat beside them, and CI never noticed because a fresh runner has no settings to clobber. All four now take a module-level isolation fixture, which covers every test class added later rather than relying on one more rememberedsetUp(issue #442). -
The hook suite no longer leaks file handles or child processes. Unclosed
settings.json/CONTEXT.mdreads, five never-reaped subprocesses, and an implicitly reclaimedHTTPErrorproducedResourceWarnings — and on Windows an open handle blocksTemporaryDirectorycleanup while a live child holds a temp path, so teardown raised instead of the assertion failing. That is why the same unchanged tree wentFAILED (errors=2)on one run andOKon the next three. Handles are closed, subprocesses are reaped throughaddCleanupregardless of assertion outcome, and the two detached background spawnssession-start.pyfires are stubbed in the harness rather than launched for real (issue #462). -
A new CI gate keeps both closed: each suite runs under a pristine redirected home seeded with a stale-but-real
settings.json, and must leave it byte-identical while emitting noResourceWarning. The guard proves its own detector can fail, so a green result means something. -
The per-plugin payload-version gates no longer fire on a dev-only change under
plugins/*/tools/. That directory is a build tree — TypeScript sources, a vitest config, a lockfile — and none of it runs on an installed machine, so a dependabot lockfile bump used to demand a manifest advance and a CHANGELOG heading describing a change no user can observe. The cost was not the noise: a version bump is supposed to mean “installed users need this”, and a gate that fires on nothing trains contributors to bump a version to silence it. The committed esbuild artifacts inside that directory (farm.js,sandbox.js) do ship and still trigger the gate, as does everything outside it — including ca-pi’sextensions/bundles, which were never in the excluded scope (issue #435). -
A session started inside a linked worktree no longer repoints the main repository’s git-level enforcement at a path that dies with that worktree. The shared
<plugin>.pathenforcer entry lives in the git common dir, so every linked worktree writes the main repo’s copy — and the SessionStart self-heal pinned it to whatever plugin root the session happened to load, which inside a worktree is the worktree’s own. Pruning the worktree then left H-01, H-03, H-05, H-09b, H-10b, H-11 and H-19 pointing at nothing, with no announcement: the repo keeps looking governed. An ephemeral enforcer is now refused in both the producer (_githooks._write_path_entry) and the caller (session-start.py), leaving the previously registered install in place — a stale-but-durable enforcer still enforces, an absent one does not. A stale but durable path is still refreshed, so the guard cannot become a kill-switch (issue #441; same bug class as #438’s statusline pin, sharing its_durabilitylib.is_ephemeral_pathpredicate). -
FARM_RUN_IDno longer accepts a Windows reserved device name.NUL,CON,AUX,PRN,COM1-COM9andLPT1-LPT9match the run id’s character class perfectly, and Windows resolves them ahead of any extension, soNUL,nulandcom1.log.1all name a device rather than a directory. Since the run id became a directory name under.farm/runs/, that mademkdirthrow outside the run’s cleanup scope and took the run’s receipts - its recovery record - with it. Refused at startup on every platform, because an orchestrator’sFARM_RUN_IDtravels between machines. Matched on the stem only, soconsole,nulls,COM0andCOM10remain valid (issue #440). -
A hook payload that is valid JSON but not an object (
[],3,"str",true,null) is normalized to an empty payload atread_input()rather than handed to the guards as a non-dict. Downstream,tool_input()evaluates(data or {}).get(...), so the falsy shapes were only accidentally safe and the truthy ones raisedAttributeErrorout of the guard. The hook envelope is host-produced, not model-produced, so an unreadable shape is the same compatibility event as unreadable syntax and now takes the same documented warn-and-proceed path (ADR-0020). The ca-codex adapter still fails closed on the same payload: it is a router, not a guard, and that asymmetry is now recorded in both the ADR and the adapter. -
Prune dry-run records, audit logs, CLI, footer, and cold-cache metrics now separate model-visible context savings from file-only sidecar cleanup; sidecar bytes no longer inflate the context-benefit decision or arm the cold-cache nudge.
-
Prune hooks now ignore and repair malformed per-session state instead of allowing invalid legacy values to escape fail-open handling.
-
Farm runs now own their receipts. Every run publishes its stream, per-task diffs, and JSON/Markdown report under
.farm/runs/<run-id>/, so two farm processes against one repository can no longer erase each other’s artifacts; the familiar top-level.farm/paths remain as a latest pointer. Every report write is atomic (same-directory temp file, rename), so a crash mid-publication leaves the previous complete artifact instead of truncated JSON.FARM_RUN_IDpins a run’s id and artifact directory, and minted run ids widened to 64 bits now that the id names a directory rather than only a log field. Concurrent runs still share git state; the farm docs now name the exact settings (FARM_INTEGRATION_BRANCH,FARM_WORKTREE_ROOT, non-overlapping task ids) that a second simultaneous run needs. -
A farm run that cannot publish its authoritative, run-scoped report now fails with a dedicated exit code 3 and suppresses the success
Report:breadcrumb, instead of exiting 0 and pointing operators at a file that was never written. A failure to refresh the non-authoritative top-level latest pointer is reported as a warning and does not fail the run. Streaming-rail and per-task diff write failures are no longer swallowed: the published report records the rail as incomplete and names the tasks whose diff evidence is unavailable, with a true total alongside the bounded list.
[2.9.1] — 2026-07-20
Section titled “[2.9.1] — 2026-07-20”- Tribunal runs recover exact per-reviewer token usage from Claude Code subagent transcripts, retaining fresh input, cache creation, cache reads, output, and explicit unavailable reasons.
[2.9.0] — 2026-07-12
Section titled “[2.9.0] — 2026-07-12”Statusline customization and correctness hardening across concurrent sessions.
- Five opt-in statusline palettes (
violet,blue,green,amber, andmono) plus a bounded, partial custom JSON palette. Violet remains the byte-identical default; invalid configuration fails softly, andNO_COLORremains authoritative. - Recent subagent rows now show the recorded model,
model:mixed, ormodel:?, captured during the existing bounded transcript scan.
- Farm API calls now reject credential-bearing base URLs, revalidate at each network boundary, refuse automatic redirects, and keep provider-controlled response bodies out of logs and retry/report diagnostics.
- Concurrent statusline renders no longer lose ledger updates, session-start metadata, or aggregate token/cost totals.
- Linked Git worktrees report their branch correctly, third-party statusline commands are no longer mistaken for codeArbiter-owned settings, and the display-only dirty check has a 100 ms latency budget.
- Windows audit events survive same-process and dual-host process bursts while retaining bounded, fail-open lock behavior.
- Prune warm-reset coverage no longer depends on wall-clock scheduling, and docs-site hook snapshots no longer pin exact source line numbers.
[2.8.13] — 2026-07-12
Section titled “[2.8.13] — 2026-07-12”Host-aware runtime vocabulary, plus dual-host audit-trail hardening.
- Audit-log lines in
gate-events.lognow record the writing host (host=claude/host=codex), restoring per-writer attribution now that two hosts can share one.codearbiter/store (ADR-0012). gate-events.logappends are now protected by a Windows byte-range lock and the file is created0o600, so concurrent sessions cannot interleave or truncate audit lines.
Changed
Section titled “Changed”- Every runtime-emitted command reference (startup briefing, NOT-INITIALIZED
pointers, H-12/H-18 gate messages, doctor lines, the init scaffold’s stub
text) now flows through the host seam (
Host.cmd_ref), so the same vendored core names/ca:<cmd>under Claude Code and$ca-<cmd>under Codex (ADR-0011 M3). Claude output is string-identical to 2.8.12. - The markdown surface (
commands/,skills/,includes/,COMMANDS.md,SPRINT.md,ORCHESTRATOR.md) is now rendered fromcore/surface/templates bytools/build-surface.py— byte-identical to the previous hand-maintained tree, with CI (--check) holding it there.
[2.8.12] — 2026-07-09
Section titled “[2.8.12] — 2026-07-09”Internal host-abstraction seam; no behavior change under Claude Code.
Changed
Section titled “Changed”- Per-op guard loop (ADR-0011, M2).
pre-write.pyguards canonical per-file ops fromHost.iter_file_ops(a Claude Write maps to exactly one op with the pre-seam fields, so its verdict path is byte-identical), with new fail-closed branches for patch-style edit/delete/opaque kinds that only a write-batching host (Codexapply_patch) can produce.pre-bash.py/pre-edit.pyroutetool_inputthrough the host seam (pass-through on Claude). Proven by the unmodified 794-test suite plus the new cross-host verdict-parity suite. - Shared-core extraction (ADR-0011, M1). All 42 host-neutral hook files are now canonical in
core/pysrc/and vendored byte-identically intoplugins/ca/hooks/bytools/sync-core.py(--checkgates drift in CI). A newhostapi.pyseam carries host specifics (project-root resolution, tool-name normalization, capability flags);plugins/ca/hooks/_host.pypins the Claude Code host. Entry scripts are now importablerun(host)functions with identical CLI, exit-code, and fail-open contracts — proven by the unmodified 794-test suite. Groundwork for theca-codexsibling plugin.
[2.8.11] — 2026-07-02
Section titled “[2.8.11] — 2026-07-02”Durable sink for mechanical gate decisions, plus an audit staleness warning.
- Durable gate-events sink (#186).
block()/remind()/warn()— the three primitives every one of the 16 entry hooks funnels every gate decision through — now best-effort append a structured line ([ISO-8601Z] KIND [tag] hook=<script> | msg) to.codearbiter/gate-events.log, so BLOCK/REMIND/WARN events are durable and greppable instead of visible only in the live transcript. The write is fail-open: a locked, missing, or unwritable log never changes a hook’s exit code nor suppresses a BLOCK. The log is append-only (added to theAUDIT_LOG_BASENAMESsingle source thatAUDIT_LOG_NAMESand all three H-05 flanks derive from, so the protected set cannot drift). - Audit staleness-warn (CONFIRM-09). A
UserPromptSubmitcheck warns (non-blocking) when an active/sprintor/devflow has not appended its expected audit-log line within a bounded window, resolving the audit-completeness half of the log-write-compulsion question. It is a warn, never a hard gate; the H-05 integrity guards remain the sole true STOP.
[2.8.10] — 2026-07-02
Section titled “[2.8.10] — 2026-07-02”Lower SessionStart latency on the linchpin hook.
Changed
Section titled “Changed”- Cut SessionStart blocking work (#194). The hooks-install re-probe now skips its git spawns when a cheap, spawn-free on-disk check proves the shims are current — fail-safe by construction (a grammar-free
hookspathscan of.git/config; any doubt, including a latercore.hooksPathchange, falls through to a real install, so the git-enforce backstop can never be silently left unwired). The five independentassemble_summarygit reads now run concurrently, and the first-of-day briefing threads its already-readCONTEXT.md/open-tasks.md/open-questions.mdtext through instead of re-reading. Injected startup state is byte-identical.
[2.8.9] — 2026-07-02
Section titled “[2.8.9] — 2026-07-02”The mechanical guards now judge the repository the git operation actually fires in.
- Hook repo-resolution (#190). The
.git/hooksgit-enforce backstop resolves its target viagit rev-parse --show-toplevelfrom its own working directory (notCLAUDE_PROJECT_DIR), so agit -C <other> commitis gated against<other>.pre-bash.py’sgit_cwdnow finds-Cpast global options and composes a repeated-Crun the way git itself does (fold-left), closing a fail-open on crafted spellings; a-Ctarget that is not a real directory fails closed.session-start.pyandtaskwrite.pydrop divergent localproject_root()copies for the shared,CLAUDE_PROJECT_DIR-first_hooklib.project_root.
[2.8.8] — 2026-07-02
Section titled “[2.8.8] — 2026-07-02”Changed
Section titled “Changed”- Thin entry points for the babysit/metrics/preview command helpers (#179). Three command surfaces that ran a lib as a script or embedded multi-statement
python -cblocks now call dedicated thin entry hooks, so the logic is import-covered bypy_compileand tests. Output is byte-identical.
[2.8.7] — 2026-07-02
Section titled “[2.8.7] — 2026-07-02”- Atomic state writes and a single-parse prune (#191, #188). The prune-state, git-hook shim, and statusline-settings writers route through a unique-temp +
os.replaceatomic write, so a torn write leaves the prior file intact (a partial shim can no longer silently disable the #161 backstop, and concurrent sessions no longer collide on a fixed.tmp). The prune hook now reads and parses the transcript once per prompt instead of twice.
[2.8.6] — 2026-07-02
Section titled “[2.8.6] — 2026-07-02”Changed
Section titled “Changed”- Statusline thin-entry refactor (#178).
statusline.pydrops from 1186 to 642 lines, with its concern-groups extracted into focused libs behind a thin entry point. Behavior is proven unchanged by the existing suite with assertions unmodified.
[2.8.5] — 2026-07-02
Section titled “[2.8.5] — 2026-07-02”Security
Section titled “Security”- Tail-anchored audit-log append and a literal
--no-verifyblock (#172, #175). The H-05 append check now admits an audit-log Edit only as a strict tail append and rejects areplace_allon an audit-log path outright, closing a hole where a mid-file insertion or multi-site suffix rewrite passed as an “append”. A new H-20 guard blocks a literal--no-verify/-nongit commit(including bundled and attached-value short-flag clusters, mirroring git’s own parsing) and ongit push, because that flag skips the.git/hooksgit-enforce backstop.
[2.8.4] — 2026-07-02
Section titled “[2.8.4] — 2026-07-02”- Update-available notifier (#209). A best-effort, once-daily, fail-silent check compares the installed plugin version against the latest GitHub Release and surfaces a one-line
update available X → Ynotice at SessionStart and in the statusline. The network refresh is off the SessionStart hot path (a detached child; the hooks only read the cache), HTTPS-only per ADR-0003, unauthenticated, sends no repo or user data. The README documents native marketplace auto-update as the official mechanism.
[2.8.3] — 2026-07-02
Section titled “[2.8.3] — 2026-07-02”- Farm dispatcher hardening (#192, #187, #183). The cost-arbitrage farm now bounds response-body reads, completes its abort accounting, validates numeric environment overrides, surfaces mutation-hook failures instead of swallowing them, and covers the entitlement probe.
[2.8.2] — 2026-07-02
Section titled “[2.8.2] — 2026-07-02”Security
Section titled “Security”- Guards fail closed on a crash or an unreadable git state (#189, #193). A crash inside a
pre-bash/pre-edit/pre-writeguard, or a git-read error while resolving branch/diff state, now blocks (H-00) rather than allowing the operation through, and the git-enforce backstops gained coverage. A guard that cannot determine whether an operation is safe treats it as unsafe.
[2.8.1] — 2026-07-02
Section titled “[2.8.1] — 2026-07-02”Opening of the tribunal remediation campaign: supply-chain hardening plus the quick-kill fixes.
Security
Section titled “Security”- Pin GitHub Actions to commit SHAs and add dependabot (#202). Every workflow action is pinned to a full commit SHA (not a moving tag), dependabot is configured for actions and npm, and the
cat-file/env-bind surfaces in CI are hardened.
- Tribunal quick-kills (#197). Atomic provenance/state writes, typed spawn options, and fail-closed CI scripts, closing the first wave of tribunal findings (#174, #176, #177, #182, #184, #185, #195).
[2.8.0] — 2026-07-01
Section titled “[2.8.0] — 2026-07-01”The tribunal release: a deep, resumable, whole-codebase audit lane, hardened by a full post-landing review and an eleventh lens, plus a fix for the false fail-closed commit-gate block that work surfaced.
/ca:tribunal— the deep resumable codebase-audit lane (#157, #168, #170). Convenes eleven bespoketribunal-*-reviewerspecialist lenses (appsec, architecture, coverage, infra, migration, observability, performance, reliability, secrets-supply, test-fidelity, typesafety) over the whole codebase in recorded priority waves. Each finding persists as its own crash-durable file under.codearbiter/reports/<run-id>/alongside append-only triage/run logs, so an interrupted run resumes from disk across sessions and days; a triage pass recalibrates severity and confidence against a defined, severity-tiered confidence gate; approved findings file as deduped GitHub issues, only on explicit authorization. Rare and opt-in by design: never a required gate, never blocks a merge or commit. The infra lens covers CI/CD workflow security, container posture, IaC, and deploy manifests.
- The commit gate no longer fails closed on commit messages containing
;,|,&, or agit -Cmention (#169). The H-09b/H-10b/H-14 pre-commit scan truncated its argument parse at the first separator character inside a quoted or heredoc commit-message body; the leftover fragment leaked message words into a pathspec query whose failure blocked the commit as an unreadable diff. Heredoc bodies are now stripped before parsing, with the raw command retained as a fallback matcher so nothing scans less than before; the argument capture is quote-aware; and a fail-closed block message now carries the underlying git error, so the next read failure is diagnosable at a glance.
[2.6.1] — 2026-07-01
Section titled “[2.6.1] — 2026-07-01”A security-hardening release. Five P1 reports (thanks to @tg12) showed the enforcement layer being enforced against a forgeable or lexical surface (a writable activation file, writable gate markers, raw path strings, a literal command string, an env-controlled delete root) rather than the real underlying operation. Each is closed, and the rest of the repo was swept for the same class in every case. Also fixes a task-id parsing gap and finishes two stale AGPLv3 relicense surfaces.
Security
Section titled “Security”- The activation switch can no longer be flipped off from inside the repo it governs (#159). Every enforcement hook stays dormant unless
.codearbiter/CONTEXT.mdfrontmatter readsarbiter: enabled, yet nothing protected that file, so writingarbiter: disabled(or corrupting the frontmatter) silenced every gate. The Write/Edit guards (H-18) now block a CONTEXT.md change whose resulting content dropsarbiter: enabledor breaks the frontmatter, and the Bash pre-hook blocks the shell flank. A legitimatestage:change that keeps the flag enabled still passes. - Gate-pass markers can no longer be forged by a direct write (#160). The
.codearbiter/.markers/tokens that turn a hard BLOCK into an allow were ordinary writable repo files, so a hand-written marker forged a security, migration, or ADR gate pass. The Write/Edit guards (H-19) now block tool writes to any marker, and the Bash pre-hook blocks shell redirects and file verbs namingsecurity-gate-passedormigration-gate-passed. The sanctioned recorder scripts and the/ca:adrauthoring marker still work. - Symlink aliases no longer bypass the audit-log and ADR guards (#162). The Write and Edit guards classified the raw
file_path, so a symlink whose visible path lacked.codearbiter/slipped a write onto an append-only audit log or an immutable ADR. Every protected-path check now resolves the real path (the approach the Read and post-write hooks already used) and matches both the raw and resolved forms.NotebookEdit, previously wired to no hook, is now covered too. - Git mutations are enforced below the command spelling (#161). The Bash pre-hook gates
git commit,push, andaddby matching the literal command string, so shell indirection such asg=git; c=commit; $g $cbuilt a real commit the hook never saw, with no enforcement beneath it. codeArbiter now installs repo-levelpre-commitandpre-pushhooks that enforce the protected-branch, force-push, and crypto/secret/migration gates at the git operation itself, where spelling no longer matters. They reuse the same detection primitives as the Bash hook so the two cannot drift, never overwrite a pre-existing hook, and install idempotently at init and on session start. - Farm worktree deletes are contained to the repo-scoped farm root (#163). The dispatcher resolved a worktree path from the env-controlled
FARM_WORKTREE_ROOTplus a plan-controlled task id and recursively force-deleted it before git validated it, so a broad or misconfigured root plus a plausible id could delete an unrelated directory. The resolved root must now live inside the repository unlessFARM_ALLOW_EXTERNAL_WORKTREE_ROOT=1is set, every worktree path is asserted strictly inside that root before deletion, and the reserved ids.and..are rejected.
- A mistyped multi-part
--idno longer strands a task (#158)./ca:task add --idaccepted a value with more than two dot-separated parts and minted an un-targetable four-segment id that start/done could not reach and the board linter could not see. The id is now validated as a singleGROUP.TYPEpair and rejected with a clear message otherwise, and the board reader recognizes an over-segmented id so it can be surfaced and repaired. - Release-skill changelog heading and license declarations aligned (#151). The
/ca:releaseskill now documents the Keep-a-Changelog## [X.Y.Z]heading the repo and its release guards use, replacing the last reference to the bare## vX.Y.Zform. The plugin manifest now declaresAGPL-3.0-only(correcting a staleMIT), and the README license notice no longer implies a commercial license is currently on offer, completing the AGPLv3 relicense across those surfaces.
[2.6.0] — 2026-06-27
Section titled “[2.6.0] — 2026-06-27”codeArbiter 2.6.0 spans several tracks. The headline additions are context-drift provenance (passive drift detection, a coarse code map, and commit-gate auto-heal) and file-scoped just-in-time context injection, which surfaces the governing decision, control, or spec at the moment an agent reads a file. The --farm preview gains best-of-N sampling and iterative retries for first-time-go accuracy, and commit-gate now lands task-board transitions atomically with the work (ADR-0008). This release also relicenses the project from MIT to AGPLv3 with a proprietary dual-licensing path; see the License note under Changed.
- Best-of-N sampling against the gate (
FARM_SAMPLES, default 1). Because the gate is a deterministic pass/fail oracle and each task runs in an isolated worktree, N candidates are drawn in parallel and the first to pass the gate is accepted. Each sample runs in its own scratch worktree cut from the integration HEAD; the winner’s files are taken into the task worktree and merged, the losers discarded. Total in-flight worker calls never exceedFARM_CONCURRENCY— a shared limiter, so sampling shares the budget rather than multiplying it.FARM_SAMPLES=1is byte-for-byte today’s single-candidate path (pinned by a regression test). (report F1) - Sampling parameters on the worker call (
FARM_TEMPERATURE,FARM_MAX_TOKENS). The chat body now carriestemperature(default 0; auto-bumped to 0.7 whenFARM_SAMPLES>1so samples diversify) and an optionalmax_tokenscap (default unset = provider default, today’s behavior). (report F4) - Best-of-N cost transparency.
farm-report.jsonrecords both the summed sample-token spend and the accepted candidate’s own tokens (acceptedPromptTokens/acceptedCompletionTokens), so the N×-tokens trade-off is visible rather than hidden. (report F1) - Task-board transitions land atomically with the work (ADR-0008, #142). commit-gate is now the single board-sync chokepoint. A done-flip
[~]→[x], start-flip[ ]→[~], or a single queued add toopen-tasks.mdis recognized by a new_taskboardlib.classify_board_diffclassifier, retained by commit-gate Phase 6 (not flagged as scope creep), and staged by Phase 7 into the same commit as the work — so the flip is invisible onmainuntil merge, then lands atomically, and an abandoned PR abandons the flip with it. No more laggingchore(board)PR or cross-session board drift. A new/ca:standupadvisory drift sweep (hooks/boardsync.py reconcile, read-only and best-effort) surfaces any merged-but-not-flipped task; the fix still routes through/ca:task. - Context-drift detection, a code map, and commit-gate auto-heal (#145). codeArbiter records which source files back each derived
.codearbiter/doc. When a tracked source changes, a single SessionStart line flags the drift,.codearbiter/code-map.mdgives a coarse orientation map, commit-gate auto-heal re-baselines the provenance or proposes a doc update with the work commit, and/ca:context-checkruns the audit on demand. A drifted claim is suppressed rather than surfaced as if it were fresh. - File-scoped just-in-time context injection (#146). A
PreToolUse:Readhook injects a budgeted (≤150-token), freshness-gated pointer to the security control, accepted ADR, approved spec, or fresh provenance claim that governs the file being read, in that priority order, then always allows the Read. A non-governed Read injects nothing and makes no git call. A spec opts in with an optional**Governs:**header line.
Changed
Section titled “Changed”- Retries are now iterative. On a retry — a failed gate, or a sampling round with no green — the worker is shown its own previous in-scope output, not just the gate-failure tail, so it refines rather than restarts blind. The prior output rides the same
FARM_ENRICH_MAX_BYTESbyte-cap and secret-redaction chokepoint as all injected context; out-of-scope drift is never carried forward. (report F2) - The follow-up harvest runs pre-commit. commit-gate’s raise-new harvest moved from after-the-commit to Phase 7 before staging, so a discovered follow-up task rides the work commit as a contingent default; a follow-up that must survive PR abandonment is filed as a GitHub issue instead of the board. (ADR-0008, #142)
- Relicensed from MIT to AGPLv3 with proprietary dual-licensing (#147, ADR-0009). The open-source distribution moves to the GNU AGPLv3, whose network-use clause closes the hosted-fork loophole that MIT leaves open. Copyright is held solely by the owner, who reserves a proprietary dual-licensing path for a planned closed-source SaaS; future contributions require a CLA (see
CLA.md). The change is forward-only, so code already published under MIT stays available under MIT. This supersedes ADR-0006’s broad-adoption posture. SeeLICENSEand the README for the full terms.
- Mutation-hook least privilege (#143). The pluggable mutation hook (
FARM_MUTATION_CMD) no longer inherits the dispatcher’s API key or OAuth token, giving it least-privilege parity with every other child command. - Heredoc commit messages (#139). The commit gate no longer false-blocks a multi-line
git commit -F - <<EOFcommit message (H-09b). /ca:releasehardening (#138). The release skill resolves the baseline tag, the notes heading, release-date consistency, and half-finished-publish recovery through tested helpers, and rebuildsfarm.jsunconditionally on every release.
[2.5.2] — 2026-06-25
Section titled “[2.5.2] — 2026-06-25”Deep-review (docs/reports/2026-06-24-root/) remediation, in two parts. The quick-kill batch is mechanical robustness, diagnosability, and hot-path hardening with no enforcement-behavior change (guard matrix, cold-install, and statusline render verified unchanged or byte-identical). The HARD-GATE batch closes real gaps in the crypto/secret commit gate and the append-only audit guards; each enforcement change shipped test-first (a RED test proving the gap, then the fix), with the full guard matrix, cold-install, migration backstop, and hook unit suites green.
Security
Section titled “Security”- Commit-time gates can no longer be bypassed by
git commit <pathspec>. Agit commit <path>records the worktree content of the named paths (bypassing the index), but the H-09b/H-10b crypto-secret gate and the H-14 migration gate scanned only the staged (--cached) diff — so an unstaged crypto/secret/migration change named as a pathspec committed with no recorded review. Both gates now union the worktree diff scoped to the named pathspecs (an unrelated worktree change elsewhere is not dragged in). The crypto/secret scan and the H-14 file-list read now also fail closed whengit diffcannot be read (timeout/error) instead of silently passing. (appsec-001/002, reliability-003) - Farm child commands no longer inherit dispatcher secrets.
run()scrubsFARM_API_KEYandCLAUDE_CODE_OAUTH_TOKENfrom the environment passed to every child (git, operator gate/setup/test, mutation) — the API key is used only by the in-processfetch. Least-privilege defense-in-depth; shrinks the blast radius of the operator-authored gate-command shell boundary (CodeQLjs/shell-command-injection-from-environment#5, traced non-exploitable and dismissed). - Two detection blind spots in the crypto/secret commit gate are closed.
CRYPTO_REdid not match RC2 or Blowfish (both forbidden bysecurity-controls.md), so a commit adding either passed the H-09b gate with no crypto-compliance review.SECRET_RE’s leading word-boundary never fired when a secret keyword was the trailing segment of a compound identifier, so a hardcodedFARM_API_KEY = "..."committed clean past H-10b. Both now match. The outbound farm redactor and the commit-gate secret pattern are also pinned to a shared, CI-checked corpus (secret-detection-corpus.json) asserted against both, so they can no longer silently drift apart. (secrets-001/002, architecture-001, #132) - The H-05 append-only audit-log guard no longer accepts an empty-
old_stringEdit. Becausenew.startswith("")is always true, an Edit with an emptyold_stringonoverrides.log/triage.log/sprint-log.mdslipped the append-only check entirely; it now blocks outright. The variable-indirection residual risk and the known truncation-spelling gaps (exec N>,>>>, process substitution) are now documented insecurity-controls.mdso the policy matches the enforced scope. (migration-003, appsec-003, observability-005, #132) - A session-boundary
/ca:devexit now closes the audit pair. When SessionStart clears a live dev marker (a prior session entered/ca:devand ended without/ca:arbiter), it appends a syntheticDEV: exitline tooverrides.logbefore removing the marker, so the audit trail no longer keeps an orphanedDEV: enterwith no matching close. (observability-001, #133)
- The task board can’t be lost to a crashed write.
taskwrite.pywritesopen-tasks.mdatomically (temp file in the board’s own directory +os.replace), so an interrupted write leaves the prior board intact. (migration-001) - Farm dispatcher robustness + diagnosability. A per-command wall-clock timeout (
FARM_GATE_TIMEOUT_MS, default 5m; git stays unbounded) kills a hung gate/setup/mutation child so a stuck command can no longer wedge a run and stall the final report; the worktree-cleanupfinallyis guarded against an early failure; plan validation emits named field errors instead of an opaque crash; a run-id correlatesfarm-results.jsonllines and the report header. Response/parse shape guards turn malformed API or mutation-hook output into actionable errors instead of silent empties. (reliability-001/004, migration-004, observability-003, dx-001/002/003) - ca-sandbox surfaces real failure causes.
docker create/cpexit codes are checked and the failed-clone path captures a bounded slice of git stderr into the thrown error, so a failed sandbox build/clone no longer reports only a bare exit code. (reliability-002, observability-004) - Task-board lib input guards.
_taskboardlib.set_state/promoteno longer raise or silently mutate state on an unexpected value; valid value sets are documented. (dx-004/005) - Gate-pass markers are written atomically.
migration-pass.pyandsecurity-pass.pywrite their pass markers through a temp file plusos.replace(shared_hooklib.write_text_atomic), so a crash mid-write can no longer leave a half-written marker that the backstop reads as an unrecognized digest and spuriously re-blocks the next commit. Fail-closed behavior is unchanged. (migration-002, #133)
Changed
Section titled “Changed”- Hook hot-path and statusline render cost reduced (behavior-preserving).
_hooklibcaches the controls read (mtime-keyed, per ephemeral hook process) and precompiles its default path-globs at import; the statusline caches per-render state reads and its cost-ledger subsystem moved into a dedicated_ledgerlib.py. Verified: guard matrix 79/0, cold-install 134/0, and the statusline render byte-identical. (performance-001..005, architecture-005/007) - Public-API header blocks added to
_hooklib.pyand_sloplib.pyper the coding standard. (dx-007) - Audit-guard path sets centralized in
_hooklib(behavior-preserving). The append-only-log and ADR-decisions path patterns, previously triplicated inline acrosspre-write/pre-edit/pre-bash, now have a single definition (is_audit_log/AUDIT_LOG_NAMES,is_decisions_path/DECISIONS_DIR_RE), so adding an audit artifact touches one file instead of three. The detached-HEAD protected-tip check also resolves in onegit show-refspawn instead of three sequentialgit rev-parsecalls, with the same block/allow decisions. (architecture-004, performance-006, #132, #133)
- Added integration/coverage for existing behavior with no source change: custom CI/deploy scope grammar, the H-12 governed-path reminder (incl. superseded-ADR), and
validateRepoUrlscp double-colon rejection; plus a_ledgerlibsuite. (coverage-003/004/005)
Documentation
Section titled “Documentation”- Full pre-release docs pass. Tightened the always-loaded orchestrator core (collapsed the duplicated non-negotiables, trimmed the register, made the lazy-load routers state one deterministic trigger-to-route surface) and reconciled the governance docs to the now-merged enforcement (the forbidden-crypto list, the secret-sweep pattern, and the audit-trail section that now names the automated
session-cleanupDEV: exitwrite). Corrected stale references (/ca:arbiterno longer instructs a manual dev-exit line the hook already writes;auth-crypto-reviewerand the post-write reminder now list rc2/blowfish). The docs site gains an Enforcement & Security page and a complete Hooks reference documenting every hook (event, location, controls, and fail posture).
[2.5.1] — 2026-06-23
Section titled “[2.5.1] — 2026-06-23”- Scope-touch reminders now fire on macOS and Windows (
H-12/H-15/H-16/H-13).post-write-edit.pyderived its repo-relative path with a lexicalos.path.relpath. When the hook payload’sfile_pathandgit rev-parse --show-toplevelnamed the same repo via divergent forms (a symlinked/varvs/private/varon macOS, an 8.3 short name on Windows), the path came out..-prefixed and every path-scoped reminder was silently dropped. A new_hooklib.repo_rel()canonicalizes both sides withrealpathfirst. (#125) /ca:releaseis now scoped to thecaplugin (ADR-0007). The skill assumed a single-plugin repo:LAST_TAGresolved via baregit describe(returning aca-sandboxtag), the bump and commit window spanned the whole repo, the derived version was never asserted againstplugin.json, and the README/catalog surfaces had no sync step. All are now scoped toplugins/ca/and enforced, including a read-back of the published Release. (#125)
[2.5.0] — 2026-06-22
Section titled “[2.5.0] — 2026-06-22”- Advisory scope-touch detection for CI, deploy/IaC, and auth (
H-15/H-16/H-17). After a write/edit,post-write-edit.pynow reminds when a CI/CD workflow (H-15), a deployment/IaC manifest (H-16), or narrow high-signal auth logic (H-17) is touched, pointing atsecurity-reviewer. These are advisory only — no commit block: a workflow runs only once merged and IaC bites only on apply, so a hard per-commit gate would impede iterative infra work while the PR review still catches the change (the irreversible-once-committed harms — secret/migration/crypto — keep their blocking gates). commit-gate now dispatchessecurity-revieweron a staged CI/deploy touch even on bare/commit/ the small lane, closing the same lane-skip gapH-14closed for migrations. CI and deploy paths are detected by default glob sets, extendable/narrowable viaci-paths/deploy-pathsblocks insecurity-controls.md(same grammar asmigration-paths); the migration, CI, and deploy detectors now share onepath_in_globsmatcher in_hooklib.py. Resolves the scope-touch half of #73. (#73) /ca:metrics— governance trend glance (issue #79). Read-only command computing override rate, small-lane rate, and sprint low-confidence ratio over 20-commit windows, each with a direction arrow (↑/↓/→) vs. the prior window. Optional--window Nto adjust the window size. Bare numbers only — not a second/ca:auditpacket; writes nothing.- Task-board lifecycle +
/ca:taskwriter and follow-up harvest (#118).open-tasks.mdgains a kanban-style lifecycle ([ ]queued,[~]in-progress,[x]done) with content-bearing IDs, so the in-flight count and stale-task nudge read real state instead of counting every bullet. The board now surfaces malformed or undated entries at SessionStart rather than letting work silently drop off. New/ca:task add|start|doneis the sanctioned board mutator, and each gated workflow’s terminal step harvests its un-actioned residue (NEEDS-TRIAGE markers, the checkpoint DEFERRABLE table, low-confidence sprint decisions) into the durable backlog.
--farmsetup-doc error messages now point at the file that actually ships (#119). The no-model and no-API-key guards cited a never-scaffolded.codearbiter/farm.md; they now point at${CLAUDE_PLUGIN_ROOT}/includes/farm.md, which is part of the plugin payload.- The crypto and secret commit gates now catch the Node/TS forms (#120).
CRYPTO_REdetects the TypeScript TLS-verification-disable patterns (therejectUnauthorizedbypass and the Node TLS-reject env override), not only the Python form; andSECRET_REmatches object-literal secrets ("api_key": "…") plus high-entropy key prefixes (AKIA,ghp_,sk-ant-), not only=-style assignments. Thefarm.tsoutbound redactor is aligned so the gate and the redactor never disagree.
[2.4.6] — 2026-06-19
Section titled “[2.4.6] — 2026-06-19”Changed
Section titled “Changed”- Trimmed the always-on
ORCHESTRATOR.mdkernel. The verbose/devmaintainer-override body moved to a new on-demandincludes/dev-mode.md(loaded only on/ca:devor/ca:arbiter), and the--farmsummary compressed to a one-line pointer atSPRINT.md/includes/farm.md. The kernel retains the/devsecurity invariant (env-gated onCODEARBITER_DEV=1, entry/exit logged append-only, load the detail before suspending any gate) as a stub; the§0.1terminology lock and§7Override stay in-kernel, and§3/§5/§6/§7heading numbers are unchanged so hook citations stay accurate. Behavior-preserving — reduces the per-session SessionStart injection by ~21 lines. (#75)
Security
Section titled “Security”- Cleared 17 Dependabot alerts and hardened the farm test harness. Bumped the vulnerable
dev-dependency pins under
plugins/ca/tools/(package.json/package-lock.json) and tightened process spawning infarm.test.tsso the test harness no longer shells out unsafely. Dev/test-only — no change to runtime plugin behavior. (#106)
[2.4.5] — 2026-06-19
Section titled “[2.4.5] — 2026-06-19”- Migration commit-time backstop (
H-14): agit committhat stages a database migration is blocked until a migration-review pass is recorded for that file. commit-gate dispatches themigration-revieweragent on a staged migration and, on PASS, records a content-digest marker (.codearbiter/.markers/migration-gate-passed) via the newhooks/migration-pass.py;pre-bash.pyH-14 then admits the commit only when every staged migration is covered. Binding is by file-content digest with no freshness window — an edit to a reviewed migration re-blocks (closing TOCTOU and enforcing migration immutability at commit time). Migration paths are detected by a default glob set, extendable/narrowable via amigration-pathsblock insecurity-controls.md. Closes the bare-/commit//featuresmall-lane gap where no lane dispatched the reviewer and no hook fired. (#77)
[2.4.4] — 2026-06-18
Section titled “[2.4.4] — 2026-06-18”- Cold-miss nudge [Feature Forge —
preview]: an opt-inUserPromptSubmitspeed bump that blocks once, with an advisory on stderr, when a large banked prune delta is about to re-cache on bloated in-memory context (idle ≥ 240 s, freed tokens ≥ 80k,CODEARBITER_PRUNE_NUDGE=on). Returns exit code 2 once; a resubmit proceeds. The once-per-cold-windowcold_nudgedmarker is persisted inprune-state.jsonand reset on any warm submit. Strictly fail-open: any internal error returns 0 and never blocks the session. This is the first non-zero exit path inhook_run. Advisory content is derived from state numbers only (no transcript text). (#69)
[2.4.2] — 2026-06-16
Section titled “[2.4.2] — 2026-06-16”- Closed six confirmed hook-enforcement bypasses surfaced by the 2026-06-15 repo review, each
with a red→green test:
git push --all/--mirrorcould publish protected refs from any branch (H-01);>|force-clobber slipped the log-truncation and ADR-redirect guards (H-05/H-11); the Write/Edit ADR gate matched only numeric-prefixed names, so drafts and nesteddecisions/*.mdslipped (H-11);sprint-log.mdwas not in the append-only set (H-05);hooks.jsonmatched onlyEdit, lettingMultiEditsidestep the audit-log/ADR guards; and a detached-HEAD / case-sensitive branch check let a commit ontomain’s tip slip. Adds direct tests forpre-write.pyandsecurity-pass.pyplus a self-heal characterization test. (#68)
Changed
Section titled “Changed”- Deduped skill overlap and unified the ADR format (behavior-preserving skill-prose cleanups from
the 2026-06-15 review). ADRs now share one
references/adr-template.md, anddecomposeemits parseablestatus:frontmatter so/ca:adr-statusreads every ADR uniformly. Five duplications were extracted to shared leaves (--farmplan extension, fresh-run verification, maturity→coverage table, crypto/secret on-pass block, cut-doc list). Thefinishing-a-development-branchopen-PR path now executes the/ca:prsteps inline instead of re-routing (which looped under/sprint), and the stale inline command catalog was removed in favor of rendering fromCOMMANDS.md. (#68)
[2.4.1] — 2026-06-14
Section titled “[2.4.1] — 2026-06-14”- Anti-slop copy pass now runs on the
/ca:choredocs lane. User-facing docs authored through the docs lane previously got no copy-law pass, so the core §3.A em/en dash prose-separator tell (the highest-signal AI text marker) could ship unflagged. The docs lane now applies theanti-slop-designpass beforecommit-gate, and a new advisoryH-13PostToolUse reminder surfaces separator dashes in user-facing docs (repo-root community docs anddocs/**) as you write, exempting code, URLs, numeric/date ranges, and lone table-cell dashes. (#60)
PRIVACY.md. Records the no-data-by-default posture (no telemetry, no network calls in default operation, all state local to the repo) and the two opt-in flows that touch data: the--farmprovider calls and the prune dry-mode local metrics. Supplies the Privacy Policy URL for the Claude Community Marketplace listing. (#63)
Changed
Section titled “Changed”- Clarified that
/ca:devis the gates-off escape hatch, not the required lane for editing codeArbiter’s own command, hook, or persona bodies. Normal development of those files flows through the ordinary gated lanes and ships via PR + release. (#64)
[2.4.0] — 2026-06-14
Section titled “[2.4.0] — 2026-06-14”Changed
Section titled “Changed”- Reframed
farmas a pluggable execution backend (cheap / premium / agentic). The dispatcher now runs every task through aWorkerinterface seam rather than calling the HTTP chat endpoint directly; the HTTP-chat author is one implementation. The worker owns the apply step, and a task-level containment sweep runs post-apply for any worker type, so path-traversal and read-only-test guards hold regardless of backend. Behavior-preserving for the existing flow. The namefarmand itspreview(Feature Forge) status are unchanged.
- Prompt enrichment for workers. Outgoing requests now include the read-only source of the task’s
failing test and the current contents of existing in-scope files, so a worker sees the contract it
must satisfy. The injected context is byte-capped (configurable, mindful of
FARM_REQUEST_TIMEOUT_MS) with a visible truncation marker, and is run through a redaction pass over thesecurity-controls.mdsecret-pattern set — planted secrets, including multi-line PEM keys, are never transmitted. - Optional per-task
model.task.modelis accepted in the plan schema (additionalProperties:falsehonored) and resolves astask.model ?? meta.model, enabling design-for cross-model execution. - Scope-aware scheduling. A task overlapping an unfinished sibling’s
filesInScopeis removed from readiness (not merely merge-serialized) until that sibling is green and merged; ordering is derived and id-tiebroken. - Regenerate-on-conflict. A merge conflict now resets to the new integration HEAD and re-runs the worker once (the post-loop merge moved into the attempt loop) before escalating, instead of escalating instantly.
- Streaming results rail. Each settled task is appended to
.farm/farm-results.jsonlin completion order as it settles, alongside the finalfarm-report.json.
[2.3.1] — 2026-06-14
Section titled “[2.3.1] — 2026-06-14”Changed
Section titled “Changed”- Moved the
--farm(OpenCode Zen) cost-arbitrage backend under Feature Forge. It is labeledpreviewin the command catalog and the sprint body, documented in both READMEs’ Feature Forge section, and carries a preview banner in its setup doc.CONFIRM-05records the promotion bar (the evidence that moves the farm from preview to stable). No behavior change to the farm itself.
[2.3.0] — 2026-06-14
Section titled “[2.3.0] — 2026-06-14”/ca:releasenow publishes the GitHub Release. A new Phase 3 creates the GitHub Release viagh release createunder the same explicit authorization that pushes the tag, reusing the changelog section composed in Phase 1 as the release notes. Closes the gap where the skill cut and pushed a tag but left the Releases page empty until someone ranghby hand.
[2.2.0] — 2026-06-14
Section titled “[2.2.0] — 2026-06-14”anti-slop-designreference anddesign-quality-revieweragent. A lazy-loaded include bundle (includes/anti-slop-design/: an INDEX router, an always-loaded core, craft leaves, and per-medium leaves for documents, dataviz, slides, web, CLI, and diagrams) that keeps generated user-facing output from defaulting to generic AI-slop. A read-onlydesign-quality-reviewerenforces it, dispatched byfrontend-authoron UI changes;/ca:prandreleaseapply the reference inline to PR-body and CHANGELOG prose. Governs generated artifacts only, not the framework’s own docs.docs/patterns/lazy-load-bundles.mddocumenting the lazy-load reference-bundle pattern.
- Statusline subagent rows show a wider, more useful label: it fills the available row width instead of a fixed 22 columns, and is derived from a title-like first line with reminder and role-assignment preambles stripped.
- Statusline honors the
NO_COLORenvironment variable, and an expired rate-limit reset now reads--instead of a bare dash.
Changed
Section titled “Changed”- Unified the five blocking reviewer agents (security, auth-crypto, migration, dependency, coverage)
onto one output grammar:
CRITICAL/HIGH/MEDIUM/LOWbuckets plus a single gate-status line. - Tightened public-facing copy: purged em-dash prose separators from the README, plugin README, and demo-script, and corrected the agent count to 15.
[2.1.1] — 2026-06-13
Section titled “[2.1.1] — 2026-06-13”Changed
Section titled “Changed”- Project moved to the
arbiterForgeGitHub organization. Canonical home is nowgithub.com/arbiterForge/codeArbiter. Plugin metadata (homepage,repository,author), the self-hosted marketplaceowner, install instructions, and all doc links point at the new org. The oldSUaDtL/codeArbiterURLs continue to redirect. No behavior, gate, or payload logic changed — metadata and documentation only.
[2.1.0] — 2026-06-13
Section titled “[2.1.0] — 2026-06-13”First stable minor since the 2.0 plugin rewrite. Consolidates the 2.1.0-beta.1…beta.6
pre-releases into one release. Everything here ships stable and dormant-by-default (inert in a
repo without arbiter: enabled). Per-feature maturity is governed by the Feature Forge, not by
the version string: the session-transcript pruner is the lone preview feature — opt-in via
CODEARBITER_PRUNE, promoted by real-world data, never on by default. See Feature Forge in the
README. The per-beta history remains in the git tag log.
/ca:standup+ SessionStart morning briefing — read-only hygiene briefing on the first session of each local day (a one-line offer thereafter): branch divergence, merged-but-unpruned branches, stale worktrees, stashes/dirty state. The hook only reports;/ca:standupperforms cleanups under per-action confirmation (ff-only pull on a clean tree, prune of merged branches — never current or default, stale-worktree removal, report-only stashes). Remotegit fetchis detached and non-blocking. Newhooks/_standuplib.pywith fullunittestcoverage./ca:watch <PR>— PR CI babysitter — watches a PR’s checks to completion via server-sidegh pr checks --watch(zero model tokens while CI runs). On red it diagnoses (CODEARBITER_BABYSIT_ONRED:proposedefault |branch); on green it notifies and offers the merge — never auto-merges, and a default-branch merge still routes through the hard gate. GlobalCODEARBITER_BABYSIT(default off) auto-attaches a watcher when/ca:propens a PR; never set on the user’s behalf. Newhooks/_babysitlib.pywithunittestcoverage.- Session-transcript pruner (
/ca:prune) — Feature Forge preview, ships off. Trims clutter from Claude Code JSONL transcripts at safe quiescence boundaries. Ten strategies acrossgentle/standard/aggressivetiers; protected tail keeps the K most recent tool turns verbatim; unknown line types pass through byte-identical; 7-check validation battery with rollback; live-race-safe write protocol. After-each-turn service mode (UserPromptSubmit/PreCompact, gains land at resume/compaction, off by default), a✂ N% · Xs agostatusline segment, and a/ca:doctorpayload check. Dry mode (CODEARBITER_PRUNE=dry) records every would-be prune to an append-only JSONL log (~/.codearbiter/metrics/prune-dry.jsonl) — sizes/savings/verdicts only, no transcript content — the evidence base for thedry → ongo/no-go. Backed byhooks/_prunelib.py; 40+ unit tests. - Feature Forge (README) — a section with its own hero (
docs/feature-forge.svg) framing preview features as opt-in, dormant, and promoted by real-world data; plus aFeature Forge: prune dataissue form and chooser config so returning adrylog is drag-attach-submit. Demo shot list (docs/demo-script.md) and a README placeholder for an in-motion GIF. - Spinner verbs wired during plugin install/uninstall.
pre-edit.pyhook test suite (tests/test_pre_edit.py) — H-05 append-only guard and H-11 ADR-marker paths, including stale-marker and Windows-path variants.- CVE gate in CI —
npm audit --omit=dev --audit-level=criticalin thetoolsjob. - Architecture decision records —
.codearbiter/decisions/with ADR-0001..0004 and a decision log.
Changed
Section titled “Changed”- Plugin storefront (
plugins/ca/README.md) and the README configuration table split so preview opt-ins (prune) sit under Feature Forge, not beside blessed flags. A collapsible README worked-example now shows a real/ca:fix → commit → prflow. - Catalog & routing —
COMMANDS.md,README.md(counts 32→34), and the routing table gain/ca:standupand/ca:watch. - security-controls.md — TLS section rewritten around resolved-URL validation; boundary-crossings
table gains plan.json/
FARM_MUTATION_CMDshell-exec and the loopbackhttp://exception rows. - Babysitter flag resolution is executed, not eyeballed —
_babysitlib.pygains a fail-safe CLI;/ca:prand/ca:watchinvoke it instead of restating spellings in prose. - SH-6 ff-pull gate wired into the live briefing —
assemble_summarycomputesff_pull_eligiblevia the pure helper rather than re-deriving the condition.
- Statusline self-heals across plugin updates — the SessionStart hook refreshes a
codeArbiter-owned pin to the current renderer path each session, persisting only on a real change,
leaving third-party statuslines untouched, and degrading silently on any error. New
refreshaction onwire-statusline.pyandheal_statusline_wiring()insession-start.py, bothunittest-covered. - Cold-install hook test no longer clobbers the developer’s global statusline —
scenario_envnow sandboxesHOME/USERPROFILEso a hook’s~/.claude/settings.jsonwrite cannot escape into real user state. - Pruner robustness — startup self-heal for the write/truncate crash window; rollback no longer
eats a concurrent append;
CODEARBITER_PRUNE_KEEP_RECENTcounts turns as documented. - Audit remediation (pre-tag sweep) — catalog drift in
COMMANDS.md/init.md, the §6 repeat-redirect command list completed,prune.mdWindows interpreter fallback,/sprint→/ca:sprintnormalization;session-start.pybriefing comment/upstream-line/base-branch-namespace fixes; a textual[DEV]statusline badge for where color is stripped.
Security
Section titled “Security”- Validate the resolved API base URL before every fetch —
farm.tsnow checks the resolved base URL (env → plan.meta → default) viaassertSecureBaseUrl(HTTPS-only, documented loopbackhttp://exception, WHATWGURLparsing), closing a path where aFARM_API_BASE_URLoverride could send theAuthorization: Bearerheader over cleartext. Error messages never include the key.
[2.0.1] — 2026-06-10
Section titled “[2.0.1] — 2026-06-10”- Fable pricing in the statusline —
API_PRICESgains the Fable family ($10/$50 per MTok, standard 1.25×/2×/0.1× cache multipliers) so theapi≈cost estimate prices Fable-model tokens correctly instead of falling back to Sonnet rates. - Fable model pill — the statusline model pill recognizes the Fable family and renders it gold, the tier above Opus violet; previously an unrecognized Fable model fell through to the grey unknown-model pill.
[2.0.0] — 2026-06-10 — Native Claude Code plugin
Section titled “[2.0.0] — 2026-06-10 — Native Claude Code plugin”The big one. codeArbiter is rebuilt from a ~13,600-line .agents/ + vendoring framework into a native Claude Code plugin. The soul is intact — orchestration, gates, SMARTS, the audit trail — re-grounded on Claude Code’s plugin primitives and made leaner and more autonomous. Install with /plugin marketplace add arbiterForge/codeArbiter then /plugin install ca@codearbiter; commands are namespaced /ca:<name>. Pre-release, the whole plugin went through an eight-persona adversarial marketplace-readiness review; everything it surfaced is folded in below.
- Native plugin packaging —
.claude-plugin/marketplace.json+ the plugin underplugins/ca/. No clone-into-your-repo, no symlinks, no shims. - Per-repo activation — a
SessionStarthook injects the orchestrator persona only in a repo whose.codearbiter/CONTEXT.mdsetsarbiter: enabled, and exits silently everywhere else. This single mechanism replaces the entireCLAUDE.md → AGENTS.md → _includeschain and the monolith-vs-vendored dual mode. - Root-level
.codearbiter/project state — stage, specs, plans, ADRs, decision log, and the overrides audit trail live at the repo root so they commit with your code and survive uninstalling the plugin. The sole footprint codeArbiter adds to a consumer repo. - Spec-driven
/ca:feature— brainstorm a spec → plan → test-first build → commit → finish. The only path to implementation. - Dynamic-workflow skill layer —
brainstorming,writing-plans,executing-plans,subagent-driven-development,dispatching-parallel-agents,finishing-a-development-branch,using-git-worktrees. /ca:sprint— the flagship autonomy mode: brainstorm a spec (the one interactive gate), then execute the plan deciding “as the user” via SMARTS on every non-hard-gate point, logging each call with a confidence flag to.codearbiter/sprint-log.md. Hard gates — security, crypto/secrets, irreversible ops, merge-to-default — remain true stops./ca:dev//ca:arbiter— maintainer override for editing codeArbiter itself, env-gated behindCODEARBITER_DEV=1with entry/exit logged tooverrides.log. Fully documented; nothing in the plugin is hidden from its operator./ca:choreand/ca:spike— sanctioned lanes for non-behavioral work (docs edits, dependency bumps, reverts — type-scaled gates) and for throwaway exploration (aspike/*branch that can never merge; exits to a findings note or/ca:feature)./ca:featuresmall lane — a logged change-class triage (Step 0): small changes meeting four mechanical criteria skip the brainstorm/plan ceremony and go straight totddafter a one-reply mini-spec confirmation. Every classification is appended to.codearbiter/triage.log, which the hooks guard append-only likeoverrides.log./ca:audit— the promotion packet: assembles commits, overrides (verbatim), triage classifications, ADRs with attribution, sprint auto-decisions, openCONFIRM-NNs, and open checkpoint findings for a window into.codearbiter/audits/<date>.md. Read-only; never overwrites a packet.- Live ADRs — an optional
governs:path-glob field on ADRs; the post-write hook surfaces “this file is governed by ADR-NNNN” on any matching Write/Edit, so accepted decisions push back at edit time instead of waiting for a checkpoint sweep. - SMARTS precedent row — each variance table cites the 1–3 most-similar prior decisions from the project’s own decision log and the observed lens pattern (“Precedent: none on record” on thin history).
- Mechanical hook hardening — every enforcement hook is gated on
arbiter: enabled(the dormancy promise is now mechanically true); hooks match the PowerShell tool as well as Bash; apython3→pythonfallback chain keeps gates alive on stock Windows; UTF-8 stdout guards; Windows backslash-path normalization; git guards tolerate global flags and catchcommit -a,--force-with-lease, forcing refspecs, andgit add --all; the audit logs are protected against truncation, deletion, and non-append edits. - Enforcement layer red-teamed pre-release — six verified bypasses closed: directory/glob/pathspec-magic staging (
git add src/,git add *,-u); audit-log rewrites viatruncate/tee/cp/dd/sed -i; shell-authored ADRs (echo > .codearbiter/decisions/…); pushes whose refspec lands onmain(git push origin HEAD:main); a fail-open UTF-8 decode in the security diff scan; and the 30-minute TOCTOU window in the crypto/secret commit gate — the gate-pass marker is now diff-bound (hooks/security-pass.pyrecords a digest of every sensitive line the gate approved; a pass for one diff cannot launder a different one). Proven by a 62-assertion guard-logic CI matrix on 3 OSes, alongside the 110-assertion cold-install interpreter matrix. /ca:doctor— install health, proven not assumed: interpreter resolution (including the Microsoft Storepython3stub), payload integrity, stale plugin-cache siblings, repo activation state, git identity, statusline wiring — then a live-fire probe (git add --all --dry-runmust come backBLOCKED [H-03]) that catches the silent-dormancy failure the static checks can’t.- Pipeline resume — plans carry a per-task
statuscolumn; acceptance is recorded to the plan file, not just conversation context; an interrupted/ca:featureor/ca:sprintre-enters at the first unaccepted task (never re-brainstorms an approved spec);/ca:statuslists every pipeline with its progress. - Version-bump CI guard — a PR changing the plugin payload on an already-published version fails CI, because
claude plugin updateno-ops on an unchanged version string and installed users would silently keep the old payload. - commit-gate behavioral-proof phase (verification before completion) and a closed reproduce→fix→verify loop in
debug. - Plugin statusline — token/context/cost segment renders everywhere; the four arbiter segments (stage, open tasks, open questions, overrides-since-checkpoint) render only when
arbiter: enabled. Wire it with/ca:statusline.
Changed
Section titled “Changed”AGENTS.md→ORCHESTRATOR.md— terser, high-authority voice, single-source rules,${CLAUDE_PLUGIN_ROOT}paths. Persona is hook-injected, not@import-loaded.- Path model collapsed —
${FRAMEWORK_ROOT}→${CLAUDE_PLUGIN_ROOT};${PROJECT_ROOT}/.agents/projectContext/→.codearbiter/. - SMARTS retained and trimmed — 6 lenses + ADR/decision-log + audit trail kept; the 12-week aging clock and forced challenger dropped.
- Maturity is a single
stagevalue — a rigor knob, not the old 4-stage promotion machinery. - Every skill/command/agent body re-grounded — ~35–40% prose shrink per skill, every hard gate preserved.
- Tone pass on the user-facing surfaces — the off-channel redirect now leads with routing help and a pre-filled command instead of a refusal (“Strike 1/2” is gone); the persona holds the gates without being adversarial toward the operator; a user-facing glossary (stage, gate, phase,
CONFIRM-NN, SMARTS, …) ships inCOMMANDS.md. - Review-stop economics —
tddPhase 1 auto-passes obligations that map one-to-one onto the already-approved spec (user reviews only beyond-spec additions);executing-plansdrops the redundant breakdown acknowledgment; quality review runs once per batch over the combined diff. Roughly 7 interactive stops → 4 for a small feature, with no gate weakened. - Crypto gate tuned — benign
crypto.randomUUID/getRandomValuesno longer trip the commit gate; signing, key-derivation,randomBytes,subtle, and password-hashing changes still do.
Removed
Section titled “Removed”- All portability/vendoring machinery —
.agents/↔.claude/symlinks, per-file@importshims,/init-vendor, the${FRAMEWORK_ROOT}/${PROJECT_ROOT}dual-root scheme, theAGENTS-CODEARBITER-ROOTsentinel,_paths.md, andSELF-EDIT-MODE. - Enterprise ceremony — app-level audit/observability signal emission, the trust-zones doc (folded into
security-controls.md), the 4-stage promotion model, and the commands/hotfix,/rotate,/ticket,/stage,/onboard. Two reviewer agents cut (standards-compliance,scaffold-completeness). - The legacy v1 tree moved to
legacy/for reference.
[2026-05-13] — token efficiency pass, added missing slash commands, added local context caching to decompose
Section titled “[2026-05-13] — token efficiency pass, added missing slash commands, added local context caching to decompose”Meta-review of the framework: a four-workstream pass on the decompose skill, skill↔command coupling, AGENTS.md preamble weight, and a sanctioned self-edit mode. Plus follow-up commits addressing an independent consistency review and a vendor-pollution cleanup.
/decision-variancecommand — entry point to the previously orphandecision-varianceskill. Dispatchesdecision-challenger; requires explicit user attribution for every arbitration choice.${FRAMEWORK_ROOT}/.agents/skills/INDEX.md— skills surface scan with invocation-class annotations (user-invoked / condition-triggered / internal), matching the existing.agents/agents/INDEX.mdpattern.${FRAMEWORK_ROOT}/.agents/SELF-EDIT-MODEsentinel + AGENTS.md §1 Phase 0 detection — a per-developer toggle (gitignored) that suppresses the H-08 bootstrap nag when the framework is being edited as source rather than consumed.session-start.shPhase 0 detection requires SELF-EDIT-MODE + AGENTS-CODEARBITER-ROOT + monolith layout.decomposeskill compaction resilience — new Phase 2.5 init/resume + per-layer disk drafts (${PROJECT_ROOT}/.agents/projectContext/.decompose-draft/layer-N-*.md) + Layer 4 immediateStatus: DRAFTADR writes + Phase 4 disk-rehydrate clause + Phase 6 draft-directory cleanup gate. The interview now survives auto-compaction with no data loss for completed layers.- AGENTS.md §1 Phase 0 — Monolith Self-Edit Detection documenting the suppression clause.
Changed
Section titled “Changed”- AGENTS.md preamble slimmed by ~75 lines. §0.1.1 Path Resolution, §4 Reference Map, and §5 Routing Table extracted to on-demand bodies (
.agents/commands/_paths.md,_reference-map.md,_routing-table.md) following the existing_redirect.mdpattern. Stubs remain in AGENTS.md with bolded “Loaded when:” callouts. - §5 row for
schema-validatorstrengthened to[OPTIONAL PLUGIN]— agent body is consumer-supplied, not framework core. - §5 condition-only skills annotated
(condition-triggered, no command)to disambiguate from user-invoked routes. decomposePhase 1 reduced from a “re-do Pre-Flight checks” duplicate to a lightweight “Pre-Flight passed → announce + log entry” step. Pre-Flight section retained (framework structural standard perskill-author).decomposePhase 5 clarified — DRAFT ADRs written in Layer 4 are now promoted in place toStatus: Acceptedrather than rewritten. Phase 5 source-to-destination mapping notes which files are already on disk from earlier phases.
- HIGH consistency findings from independent review — Phase 2 of decompose was asking the Layer 1 question both in Phase 2 AND Phase 2.5 (now Phase 2.5 only); AGENTS.md §4 stub said “twelve rows” but the body has thirteen (corrected); overrides.log entry from this work cycle contained two factual errors — corrected via an append-only audit-fix entry.
- MEDIUM consistency findings — three places in
decompose/SKILL.mdmisattributed.decompose-draft/detection to Pre-Flight; corrected to Phase 2.5 only. Phase 2 Gate language updated from “No gate; this phase is declarative” to describe the actual gate. - LOW consistency findings — Phase 5 ADR template split into two separate code blocks (DRAFT state, Accepted state) to avoid copy-paste hazard;
skills/INDEX.mdtdd row consolidated touser → /feature, /fix; “Workstream N” self-references in permanent docs replaced with stable language.
Removed
Section titled “Removed”.agents/projectContext/decisions/001-ticketing-design.md— a real ADR about codeArbiter’s own ticketing design was inadvertently shipping in the framework’s projectContext, polluting any vendor consumer’s submodule clone. Removed fromHEAD(still present in git history; vendor consumers don’t see it in their working tree unless they check out an old commit).- Two framework-edit
/overrideentries from.agents/projectContext/overrides.log. Log reset to header-only state with a newFRAMEWORK-SOURCE INTENTblock declaring the framework’s published log is intentionally empty.
[2026-05-13] — copyright standards, /decompose, H-08 hook fix
Section titled “[2026-05-13] — copyright standards, /decompose, H-08 hook fix”/decomposecommand file and registration (#11) — closes a gap where the greenfield-interview skill had no slash-command entry point.- Copyright header enforcement via checkpoint reviewer (#9) — new files must carry the standard
<!-- Copyright ... -->header; checkpoint blocks if missing.
Changed
Section titled “Changed”- Retrofit copyright headers onto all existing framework files (#10).
- Shim file ordering — copyright block moved below the
@pathimport line in every.claude/commands/*.mdshim.
- H-08 source-code check now excludes the vendor tree and framework artifacts (#13) — previously falsed-positive in vendored installs.
[2026-05-12] — ticketing, statusline, perf, expansion
Section titled “[2026-05-12] — ticketing, statusline, perf, expansion”- Ticketing skill (#3) — optional scope-overflow inbox with two variants: lightweight in-repo (
${PROJECT_ROOT}/.agents/projectContext/tickets/) and Plane MCP integration (on-prem only, API-key auth via env vars). Ships disabled (enabled: false); consumers opt in by editingticketing-config.md. - Custom Claude Code statusline (#4) — token-aware status bar surfacing stage / tasks / open questions / git branch / overrides count.
- Project README and MIT LICENSE (#4) — first user-facing documentation surface.
- 5 new skills + 4 new commands (#6) — including
decision-variance,doc-review-gate,observability-emit, and others, with a framework-wide terminology lock (§0.1 invariants onskill/agent/phase/stage/layer/gate/severityand theinvoke/route/dispatchverb triple). /create-contextcommand (#7) — brownfield bootstrap for existing codebases (alongside/decomposefor greenfield).
Changed
Section titled “Changed”- Modular path conventions (#7) — formal
${FRAMEWORK_ROOT}vs${PROJECT_ROOT}split; framework source uses the former, populated project state uses the latter. Vendored-vs-monolith modes documented in AGENTS.md §0.1.1 (later extracted to_paths.md). - Install docs added (#7) —
/init-vendorcommand and submodule install instructions. - ~250 lines cut from AGENTS.md / commands / agents (#5) — token-efficiency pass; surface-scan INDEX files introduced so routing decisions don’t bulk-load
.agents/agents/*.mdor.agents/commands/*.md.
[2026-05-10] — foundation
Section titled “[2026-05-10] — foundation”- codeArbiter v2 foundation — initial commit of
AGENTS.md,${PROJECT_ROOT}/.agents/projectContext/scaffold (templates for CONTEXT, tech-stack, security-controls, audit-spec, coding-standards, secrets-policy, dependency-policy, observability-spec, trust-zones, open-questions, open-tasks, stage, decisions/, decomposition/, tickets/, plugins/, checkpoints/), abstract skills, and the.claude/shim layer. - FUSION
.claude/system — routing-table-driven orchestration: every user intent flows through a slash command that fans out to skills and reviewer agents. - 18 reviewer / author agent definitions —
auth-crypto-reviewer,backend-author,frontend-author,infra-author,migration-reviewer,dependency-reviewer,security-reviewer,trust-zone-reviewer,architecture-drift-reviewer,coverage-auditor,standards-compliance-reviewer,scaffold-completeness-reviewer,audit-emitter,decision-challenger,checkpoint-aggregator,finding-triage,scout,grader. - Command catalog —
/feature,/fix,/refactor,/debug,/commit,/pr,/review,/threat-model,/adr,/adr-status,/checkpoint,/stage,/release,/add-dep,/rotate,/surface-conflict,/ticket,/btw,/status,/init,/override,/hotfix,/onboard,/new-skill,/commands. skill-authorskill — meta-skill enforcing the Skill Structure Standard (Trigger, Pre-Flight, Phases with gates, Failure Modes, Subagents Invoked) for any new skill authored via/new-skill.- Claude Code hook scripts and
settings.json(#2) —pre-bash.sh,pre-edit.sh,pre-write.sh,post-write-edit.sh,session-start.sh,statusline.sh,statusline-tokens.py.
Removed
Section titled “Removed”CODEARBITER_PLAN.mdandCODEARBITER_PROGRESS.md— superseded byAGENTS.mdand the projectContext scaffold once v2 was complete.
Maintenance notes
Section titled “Maintenance notes”- This changelog is updated by the maintainer (or via
/releaseonce that workflow is in regular use), not auto-generated. Each entry should describe an outcome a user might notice, not every commit on the way there. [2.0.0]froze whenv2.0.0was tagged (2026-06-10). New work accumulates in a fresh section above it; any change to the shipped payload (plugins/ca/**) must ride a version bump — CI enforces this against published versions.