Skip to content

release: baton 1.3.2 — interactive-path enforcement engages; single-source run-trail count#35

Merged
andrewwint merged 1 commit into
mainfrom
fix/1.3.2-ledger-count-inline-seam
Jul 10, 2026
Merged

release: baton 1.3.2 — interactive-path enforcement engages; single-source run-trail count#35
andrewwint merged 1 commit into
mainfrom
fix/1.3.2-ledger-count-inline-seam

Conversation

@andrewwint

Copy link
Copy Markdown
Owner

Patch release (1.3.1 → 1.3.2). Version bump + CHANGELOG ## 1.3.2 + the fixes below. Pushing the v1.3.2 tag after merge triggers release.yml.

The significant fix — interactive-path enforcement now engages

The close-out deriver decided whether the spawn/triage sidecars were wired by reading only the project .claude/settings.json. 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 (observed live: _sidecar_diag.enforcement_active: false with a real security-review spawn in lane_spawns.jsonl). The wired-check now consults project + project-local + user-global settings, so both gates engage on the interactive path. Verified live: sidecar_enforcement_active() / triage_sidecar_active() return True from a bare cwd where they were False.

Other fixes

  • Inline-triaged seams reach the machine ledger: new hooks/record_seam.py (manager-run) writes an inline-named seam to the same triaged_seams.jsonl the completeness gate reads (add-only). SKILL.md/triage.md: inline triage is for non-seam work; a named seam must be machine-recorded.
  • Single-source run-trail count: derived only from ledger.py's own lane lines (supersedes 1.3.1's max() reconciliation), anchored to the lane-line shape — the count can't contradict the visible lines in either direction. Close-out relabel "this session" → "so far". task_id documented expected-null (specialist match binds by subagent_type).
  • Spawn-match binding: contract_lane format documented (cite subagent_type; binds by type; per-instance is the post-hoc scorer's job).
  • No close-out inline-seam WARN — a reliable transcript scan is impossible (skill's own seam examples + TRIAGE-SEAMS: none live in the transcript); removed per review, post-hoc scorer is the authority.
  • doctor intentional-decoupling comment hardened (do not add ledger to the green condition).
  • CI: record_seam_test.py gated; hooks-e2e runs with a hermetic HOME so "unwired" scenarios don't read the dev's real global config.
  • OpenSpec: add-infra-seam-taxonomy change (ratifies the deployment-surface-seam rule; validates --strict).

Verified: full smoke green (8 hook self-tests, hooks-e2e 22, mcp/conformance/fault-catch); fresh N-lane acceptance; interactive-path enforcement selftest; two independent cold-read review rounds (findings resolved). No change to the frozen 1.0 contract.

🤖 Generated with Claude Code

…dger/seam fixes (candidate)

Live interactive /baton findings, fixed forward. HELD — no version bump/push.

ROOT-CAUSE FIX (biggest): disposition_gate read only the PROJECT .claude/settings.json to decide
whether the spawn/triage sidecars were wired — but the INTERACTIVE path wires them in the USER-GLOBAL
~/.claude/settings.json. In an ordinary repo (no project settings), the deriver therefore 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 (observed live as _sidecar_diag.enforcement_active:false with a real
security-review spawn in lane_spawns.jsonl). Now sidecar_enforcement_active / triage_sidecar_active
consult project + project-local + user-global settings, so both gates engage on the interactive path.
Tests pass explicit paths (checked alone); a new selftest drives the global-only scenario; hooks-e2e
runs with a hermetic HOME so "unwired" cases don't read the dev's real global config.
- The reconciliation binds a claimed specialist by subagent_type NAME (token-equality), so a genuine
  lane matches and a claimed specialist with no real spawn of that type fails to UNVERIFIED-SEAM;
  task_id null is not the blocker. SKILL.md documents the contract_lane format (cite subagent_type;
  binds by type; per-instance binding is the post-hoc scorer's job).

1.3.2 ledger/seam fixes:
- ledger count: OWN lines only (supersedes 1.3.1 max), anchored to the lane-line shape — count can't
  contradict visible lines in either direction.
- record_seam.py (new): manager-run recorder for an inline-triaged seam -> arms the completeness gate
  (add-only). SKILL.md/triage.md: inline triage is for non-seam work; a named seam MUST be recorded.
- NO close-out WARN: a reliable transcript-scan is impossible (skill's own seam examples + TRIAGE-SEAMS:
  none are in the transcript) -> removed per review; post-hoc scorer is the authority.
- close-out relabel "this session" -> "so far"; task_id documented expected-null; doctor decouple
  comment hardened; record_seam_test gated in CI; openspec add-infra-seam-taxonomy (validates --strict).

Verified: full smoke green (8 hook self-tests, hooks-e2e 22); fresh N-lane acceptance; interactive-path
enforcement selftest; independent cold-read review (3 findings resolved).

Co-Authored-By: Claude Opus 4.8 <[email protected]>
@andrewwint
andrewwint merged commit 7624d27 into main Jul 10, 2026
2 checks passed
@andrewwint
andrewwint deleted the fix/1.3.2-ledger-count-inline-seam branch July 10, 2026 15:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant