Skip to content

Releases: andrewwint/baton

v1.3.5

Choose a tag to compare

@github-actions github-actions released this 16 Oct 22:34
813ecb6

Patch. Two review-lane refinements and a release-doc correction. No change to the frozen 1.0 contract —
the lane's identity and the loop are unchanged, and the new return field is consumed by the manager inside
the skill, not by any external caller.

  • A parity claim is now checked differentially, against the old code, at every consumer. A change that
    claims behavior is unchanged — a refactor, port, registry or config consolidation, a "no functional
    change" cleanup — cannot be verified by exercising the new code: tests written with the change encode the
    new behavior and pass whether or not it matches the old. The code-reviewer lane now runs prior and new
    code on identical inputs at every consumer of the changed seam and compares return value, exception type
    and message, downstream call count and the arguments actually sent, over failure and degenerate inputs
    rather than the happy path alone. Field evidence (field notes, Run 12): on a refactor of 10 model call
    sites promising identical defaults, a well-argued decision to raise on an empty response instead of
    returning an empty string would have changed the outcome at 4 of the 8 call sites sharing the helper —
    three that had returned a fallback would now raise, and at the fourth a case would be judged against a
    placeholder default the old code never produced. No test of the new code alone could have caught it.
  • The parity comparison is a named, always-present return field. parity matrix is now a field the
    code-reviewer lane always fills in — with the comparison, or with an explicit n/a (no parity claim) or
    unverified (prior code could not be run) value — so a skipped comparison is a value someone can read
    rather than an omission indistinguishable from a rule nobody applied. The verify step of SKILL.md gains
    the reading side: n/a or unverified on a change that does claim parity is a finding, not a pass. The
    lane's Constraints also gained a carve-out permitting the prior revision to be materialized outside the
    repository (git archive into a temp directory, or a throwaway clone there), since the read-only rule
    otherwise forbade the comparison the new rule asks for. It deliberately excludes git worktree add, which
    would write .git/worktrees and contradict the lane's read-only guarantee. Honest limit: this is a prose obligation on both sides, not an enforced gate — no hook detects
    a parity claim, nothing in tools/ references the field, and no eval exercises it. An independent cold read
    caught an earlier draft of this entry claiming the absence was "detectable by the manager at integration
    rather than depending on the reviewer remembering the rule," which was false: nothing manager-side had
    changed. The claim now matches what shipped.
  • A run-describing artifact is verified against what was observed. A report, row label, manifest or log
    line is now checked against the observed request or response rather than the configuration meant to
    produce it, since a default that silently overrides an intent makes the two diverge. In the same run, a
    comparison row labeled with its intended sampling had actually sent the defaults (an override equal to the
    default is a no-op), and the false label reached the report, the manifest and the PR text alike.
  • Release-doc fix. AGENTS.md step 1 still told you to bump the version in .claude-plugin/plugin.json
    and .claude-plugin/marketplace.json, both removed in 1.3.4; runtime/package.json is the single source
    of truth, as the same file already said two paragraphs earlier.

v1.3.4

Choose a tag to compare

@github-actions github-actions released this 03 Aug 00:16
c676a76

Patch. Lane-quality refinements and a packaging cleanup. No change to the frozen 1.0 contract.

  • The research lane runs on opus and pins the version it answers for. Research is a silent-failure
    lane: a wrong research answer becomes the contract the implementation and its test are built against,
    so no later review catches it — every downstream artifact inherits the same premise. It is now on the
    strongest tier (like the review lanes), and its Method adds an explicit step — confirm each external
    source applies to the version actually in use in this repo (from the lockfile/manifest), and say so when
    a doc pre- or post-dates it, since sources disagreeing because one is stale is the common case.
  • The review lane attacks the tests by default. A green suite is evidence only if its tests can fail.
    The code-reviewer lane now mutates the source behind new/safety-critical tests and confirms a test
    catches each mutation — reporting which safety properties are actually pinned versus merely green —
    instead of that check depending on the operator remembering to ask for it.
  • Baton is a pure skill. Removed the plugin manifest, which never actually registered the skill (it
    declared no discoverable skills path) and would have forced a /baton:baton command. Baton is
    distributed as a skill — that is how the marketplace syncs it — so one identity, one /baton. Install
    docs corrected, with an explicit note that baton is Claude-Code-specific: its lanes need the Agent tool,
    background tasks, worktree isolation, and plan mode, which do not exist in claude.ai, Claude Desktop, or
    generic MCP clients (it loads there but the lanes do nothing).

v1.3.3

Choose a tag to compare

@github-actions github-actions released this 11 Jul 01:16
2f6e50f

Patch. Closes the run-ledger fidelity gaps an end-to-end verification surfaced (known-count on a real
routed session, not a writer unit pass). No change to the frozen 1.0 contract or the enforcement gate.

  • Every captured lane now carries a stable id. A live probe of the real PostToolUse payload showed
    the spawn id is present at tool_response.agentId (with top-level tool_use_id as a fallback) — the
    earlier null task_id was a wrong-key extraction bug, not a payload limitation, so no new lifecycle hook
    is needed. record_lane_spawn.py and ledger.py now record that id (the same value the Agent tool
    returns and a manager would cite in contract_lane). It stays a secondary signal to non-generic
    subagent_type in the disposition deriver — a model-visible id never becomes the sole certifier of a
    specialist.
  • The ledger de-duplicates a double-fired spawn. When the hook is wired in more than one settings scope
    (project and user-global), one real spawn fires it twice; the ledger now records exactly one lane line
    per spawn via a race-safe first-writer-wins marker keyed on the id (verified under 40-process contention).
    So N routed lanes produce exactly N lane lines even in a multi-wired install.
  • Verified by an observed firing, not a unit pass. On real dispatch (implementer + code-reviewer +
    researcher), the ledger recorded exactly 3 lane lines, each with its real agentId. The de-dup, id
    population, and known-count behavior are exercised by new self-tests gated in CI (nine hook self-tests).

v1.3.2

Choose a tag to compare

@github-actions github-actions released this 10 Jul 15:42
7624d27

Patch. Fixes an enforcement blind spot found on a live interactive /baton run, plus run-trail
consistency. No change to the frozen 1.0 contract.

  • Interactive-path enforcement now engages (the significant fix). The close-out deriver decided whether
    the spawn/triage sidecars were wired by reading only the project .claude/settings.json. But the
    interactive /baton path wires the enforcement hooks in the user-global ~/.claude/settings.json, so
    in an ordinary repo (no project settings) the deriver believed the sidecars were unwired and silently fell
    back to record-only: the completeness gate went silent and the anti-forgery spawn-match no-op'd, even with
    a real independent lane recorded. The wired-check now consults project, project-local, and user-global
    settings, so both the completeness gate and the specialist spawn-match engage on the interactive path.
  • Inline-triaged seams can reach the machine ledger. A new manager-run recorder
    (hooks/record_seam.py) writes a seam identified inline (no triage lane) to the same
    triaged_seams.jsonl the completeness gate reads, arming it — add-only (it records an obligation, never
    clears one). SKILL.md/triage.md: inline triage is for non-seam work; a named seam must be machine-recorded.
  • The run-trail close-out count is single-source. It is now derived only from ledger.py's own recorded
    lane lines (superseding 1.3.1's reconciliation with the sibling ledger), anchored to the lane-line shape,
    so the count can never contradict the lines shown — in either direction. Close-out label clarified to
    "lanes recorded so far" (a per-stop snapshot). task_id is documented as expected-null from Claude Code's
    PostToolUse payload; the specialist match binds by subagent_type, so it is not load-bearing.

v1.3.1

Choose a tag to compare

@github-actions github-actions released this 10 Jul 13:54
c09c2a3

Patch. Fixes a consistency bug in the run trail surfaced by a real integration test: the Stop
close-out could print lanes recorded this session: 0 directly above the lane lines it had just
written. The count read only the sibling machine ledger (lane_spawns.jsonl, written by
record_lane_spawn.py); when that hook had not fired, the count read 0 despite ledger.py having
recorded the spawns itself. The close-out count now derives from ledger.py's own recorded lane
lines, reconciled with the sibling ledger (the higher of the two), so it is never lower than the
lines shown and a sibling-only observation is not lost. Trail-only; no change to any enforcement
verdict, the disposition gate, or the frozen 1.0 contract.

v1.3.0

Choose a tag to compare

@github-actions github-actions released this 10 Jul 13:10
6d88ab5

Minor. Adds a bundled run-trail hook and makes baton's hooks fire on the interactive /baton path
(previously only baton's TypeScript runtime wired them), so the enforcement and trail work without the
runtime. Additive to the frozen 1.0 contract (loop and routing gate, lane map and five bundled agents,
RunRecord shape, MCP-via-.mcp.json), which is unchanged. This entry describes what ships, not what it
achieves — no efficacy claim.

  • The run trail is hook-maintained, not memory-maintained. A bundled dual-event hook
    (hooks/ledger.py, wired on PostToolUse and Stop) keeps a session-scoped trail at
    .agents/runs/ledger.md regardless of whether the model remembers to write one: a line per real lane
    spawn, and an idempotent close-out per stop. It is operability, not part of the security-enforcement
    contract — its absence loses a trail, never a gate — so baton doctor warns (non-gating) when it is not
    wired. Claude Code runs Stop hooks in parallel, so the close-out tolerates a not-yet-stamped verdict
    (unstamped) and self-corrects on the next stop; it never derives or overrides the gate's verdict.
  • An absent disposition record is now explained, not silently missing. On a run where triage names no
    sensitive seam, the close-out records why no disposition.json exists (READY by the no-seam row), so a
    correct no-seam run is distinguishable from a skipped gate.
  • Enforcement wires on the interactive path. A shipped self-installer (hooks/wire_interactive.py)
    wires the enforcement + trail hooks into the user-global ~/.claude/settings.json with absolute paths,
    excluding the SessionStart guard (whose per-project verification-marker model would fail-loud in unrelated
    repos). It is idempotent, preserves existing settings, and runs baton doctor to confirm. The settings
    wirer (wire_settings.py) now ships inside the skill, so an installed-only machine can self-wire with no
    repo checkout — and baton doctor points at that shipped path rather than a file that isn't present.
  • Triage names a deployment seam. An outward-facing cloud deploy that creates an IAM role, exposes a
    public or no-auth endpoint, or routes data to a hosted model is a data-egress/secrets/authz seam
    even when no source line changed; it travels the disposition path, not only the approval gate.
  • Honest labels. The plan step's contract-read checkpoint is labeled guardrail-strength, not
    enforcement-strength — no hook can detect an unfamiliar external tool, so it stays a model-written prompt.
  • CI. The bundled hook self-tests (disposition, contract, doctor, session-start, wiring, self-installer,
    ledger) run in the structural smoke gate, and CI triggers on hooks/**.

v1.2.0

Choose a tag to compare

@github-actions github-actions released this 06 Jul 11:32
2a25e8c

Minor. Adds the bundled close-out enforcement the 1.1.x prose framed as "a later release" — the
disposition record's verdict is now derived and stamped by a hook, and a skipped record is structurally
detectable. Additive to the frozen 1.0 contract (loop and routing gate, lane map and five bundled agents,
RunRecord shape, MCP-via-.mcp.json), which is unchanged. This entry describes what ships, not what it
achieves — no efficacy claim.

  • The verdict is derived, not declared. A bundled Stop hook (hooks/disposition_gate.py, wired in
    settings.json) re-derives the disposition verdict from the record's facts and stamps it; the model's
    own token is kept as an advisory verdict_emitted. Removing the model's authorship of the verdict is the
    design — a model that disagrees can no longer re-emit a non-derivable token.
  • The record's existence is enforced, not asked for. A PostToolUse sidecar
    (hooks/record_triaged_seams.py) records the sensitive seams triage names (the TRIAGE-SEAMS return-format
    contract) to a session-scoped ledger; the close-out completeness gate cross-checks it, so a sensitive seam
    cleared without a disposition.json is stamped MISSING-RECORD instead of passing silently. A
    malformed/unparseable TRIAGE-SEAMS line fails loud to UNVERIFIED-SEAM (seams indeterminate) rather than
    silently shrinking what is owed a disposition.
  • Fabrication is caught at run time, not only post-hoc. A PostToolUse sidecar
    (hooks/record_lane_spawn.py) records real Task/Agent specialist spawns; a claimed specialist
    contract with no recorded spawn is downgraded to UNVERIFIED-SEAM — a signal the model cannot forge by
    narrating. Its trust boundary is stated honestly in the hook: it proves a lane spawned, not that it did
    good work.
  • New verdicts name two honest middles: REVIEWED-CLEAN (a real review lane cleared a sensitive seam
    that recorded no independent specialist — reviewed, nothing found, not READY) and MISSING-RECORD (the
    record was never written). Both are shape-only additions — the vendored disposition-contract predicate and
    its CONTRACT_SHA are unchanged.
  • Install health is checkable. hooks/doctor.py proves the enforcement is wired and firing on the
    machine (with the optional TypeScript runtime absent), and a SessionStart guard fails loud when it is not
    verified. The Python hooks are the standalone floor — enforcement does not depend on the runtime.
  • Coupled-shape documentation. docs/coupled-shape-spec.md (the ratified TRIAGE-SEAMS + disposition
    record shape) and docs/triaged_seams.format.md (the ledger read-surface) ship as synced reference copies
    of the canonical originals; the forge-proof completeness cross-check is runtime-bound, so the shape is
    shared while the gate stays in the runtime.

v1.1.2

Choose a tag to compare

@github-actions github-actions released this 05 Jul 15:34
a9f93d4

Patch. Documentation-only — one SKILL.md sentence, tense only. No schema, hook, or behavior
changes. This entry describes what shipped, not what it achieves — no efficacy claim.

  • The emission-gate prose can no longer be read as a present machine-enforcement claim. The
    disposition section describes a bundled close-out hook that machine-derives and stamps the verdict
    from the record; the sentence was future-framed but its tail ("so the enforcement no longer depends
    on the model remembering") could be misread as a present claim. In a pre-enforcement release that
    reads as an unbacked enforcement claim. The wording is tightened to unambiguous future ("a later
    release will add … so that enforcement will no longer depend on the model remembering").
    1.1.x remains the manager's discipline — model-based derivation from the record, no machine
    enforcement; the close-out hook that machine-stamps the verdict is a later release.

v1.1.1

Choose a tag to compare

@github-actions github-actions released this 05 Jul 14:49
4868ce3

Patch. Documentation-only — SKILL.md prose. The frozen 1.0 contract (the loop and routing gate,
the lane map and five bundled agents, the RunRecord ledger shape, and MCP-via-.mcp.json) is
unchanged, and no runtime behavior changes. This entry describes what shipped, not what it achieves
— no efficacy claim.

  • The data-residency guard now travels with the shipped skill. The MCP-discovery guidance states
    inline that a configured MCP server may be cloud-hosted — its calls send data off the machine — so
    egress should be gated on your data-residency posture, the way you would a deploy. This caveat
    previously lived only in a separate docs/ note that a global or plugin install did not carry; it
    now sits in SKILL.md itself, so every install has it.
  • Resolvable documentation pointers. A SKILL.md reference to docs/research-basis.md used a
    repo-relative path that resolved only inside the source checkout and dangled from a standalone
    (global or plugin) install; it is now an absolute URL. The MCP section's dangling docs/MCP.md
    pointer is removed and its behavioral rules inlined, so the skill carries what it needs to behave
    correctly rather than pointing at a file that may not travel with it.
  • Repo Detection reshaped into capability-triggered discovery. The section is rewritten as a
    short Tool & MCP discovery protocol — lexical by default; configured servers only; manager-only and
    allowlisted by exact name; name a missing capability rather than proceeding silently — replacing a
    hardcoded runtime-manifest list that could not stay current.
  • The recovery bound cites its source. The ~2-attempt recovery bound now names CodeTransOcean's
    DSR@K (arXiv:2310.04951) — automated-repair gains are highest in the first round and plateau by the
    third — in place of an unsourced "evidence-informed" note.

Not in this release: the enforcement build (the close-out disposition gate, doctor, and session-start
guard) and the security-review source-derivation work remain held for a later version. 1.1.1 is
documentation-only and changes no runtime behavior.

v1.1.0

Choose a tag to compare

@github-actions github-actions released this 03 Jul 01:21
0da5727

Minor bump: the frozen 1.0 lane map gains a fifth bundled agent, so this is not a patch. The loop,
the routing gate, the RunRecord ledger shape, and MCP-via-.mcp.json are unchanged. This entry
describes what shipped, not what it achieves — no efficacy claim.

  • Fifth bundled lane — security-review: an independent, read-only security-contract lane the
    verify step consults (as its own subagent_type subagent) on a sensitive seam that has no
    independent contract. It derives the seam's invariants from source and carries no ruleset of its
    own; it may invoke a project /security-review skill for depth. This is the change to the frozen
    lane map that makes this release a minor bump rather than a patch.
  • A disposition discipline for sensitive-seam review: on a sensitive seam class (authorization /
    tenant-isolation, data egress, writes/mutations, auth gates, secrets), the verify step separates
    identifying an exposure from disposing of it — the lane that finds an exposure does not clear
    it; an identified exposure escalates to a named independent party. The manager records the facts
    in .agents/runs/<runId>/disposition.json (seams triaged, each seam's contract source, exposures,
    dispositions) and derives the review verdict from that record rather than declaring it free-hand,
    failing loud (UNVERIFIED-SEAM) on a seam nobody could independently verify. This ships as
    discipline in SKILL.md; a bundled close-out hook that machine-enforces the derivation is
    planned for a later release, not in 1.1.0.
  • Installable as a Claude Code plugin: .claude-plugin/plugin.json and marketplace.json let
    Baton install via /plugin alongside the existing loose-skill install, reusing the nested layout
    through skills/agents path overrides without moving any file from its 1.0 location.

Not in this release: the loop-by-default routing-gate change and the review-lane model reallocation
(update-routing-and-review) are held for a later version pending their own validation — 1.1.0's
routing gate is unchanged from 1.0; and the machine-enforcement close-out hook for the disposition
discipline (above).