Skip to content

Releases: andrewwint/baton

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 addso 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).

v1.0.4

Choose a tag to compare

@github-actions github-actions released this 01 Jul 12:22
377c5ca

Additive guidance. The runtime code and the frozen contract (the loop and routing gate, the
lane map and four bundled agents, the RunRecord ledger shape, MCP-via-.mcp.json) are
unchanged. Motivated by a dogfood run where a cosmetic-looking edit to a shared CSV
serializer was triaged direct and, even when reviewed, was checked only against its own diff —
so a pre-existing tenant-scope leak on a sibling endpoint that shared the serializer was
missed. Both gaps are addressed generally, not for that case.

  • Routing gate + triage — serializer/export seams are a risk trigger: a change to a
    shared serializer/formatter or a data-export/response path now counts as a risk trigger, so
    a small-looking output-formatting edit routes through the loop. Such a change crosses the
    data-egress boundary of every endpoint it feeds, even when the edit itself looks cosmetic.
  • Review lane — follow a touched shared seam to its other callers: when a change edits a
    helper with multiple callers (a serializer, formatter, query builder, or auth helper), its
    other callers are in the blast radius, not "unrelated code." The reviewer checks each
    caller of the touched seam against the boundary that seam crosses (e.g. a shared export
    helper feeding several endpoints — verify each endpoint's authorization and tenant/data
    scoping), and a flaw already present on a sibling caller is in scope the moment the change
    touches their shared seam.
  • Default under uncertainty (anti-list-creep): the trigger lists are examples, not
    exhaustive — when you can't tell whether a change touches a risk trigger, it does not
    qualify for direct and routes through the loop. One tie-breaker guards the unlisted tail
    instead of an ever-growing trigger list. (Also aligned the three trigger enumerations — the
    routing gate, the triage disposition, and the triage method step — so the data-egress
    trigger appears in all three.)

v1.0.3

Choose a tag to compare

@github-actions github-actions released this 29 Jun 21:16
9a95f38

Additive guidance. The runtime code and the frozen contract (the loop and routing gate, the
lane map and four bundled agents, the RunRecord ledger shape, MCP-via-.mcp.json) are
unchanged.

  • Plan-step guidance — research the standard first: when work targets an external
    standard, spec, format, or protocol, the plan step now calls for a brief up-front research
    pass to find and read the authoritative source and ground the design in it, rather than
    building against an approximation and reconciling later.
  • Field notes Run 10: a data-science dogfood (compile CDC NHIS into a verified OKF
    bundle + grounded chatbot). The execution-grounded check caught a clean-markdown,
    resolving-links statistic that was wrong when run (3.66% vs the correct survey-weighted
    31.96%) and quarantined it — the "execute the check, don't lint it" pattern carried into a
    non-code domain. The run also surfaced the lesson this release encodes: the OKF format was
    first built to an approximation and only grounded in the published v0.1 spec afterward; the
    fix is the light up-front research step above.