Skip to content

feat(lint): close the run-status write surface (coupling-core Phase A)#463

Merged
proboscis merged 1 commit into
mainfrom
feat/coupling-core-phase-a
Jun 12, 2026
Merged

feat(lint): close the run-status write surface (coupling-core Phase A)#463
proboscis merged 1 commit into
mainfrom
feat/coupling-core-phase-a

Conversation

@proboscis

Copy link
Copy Markdown
Owner

Summary

Phase A of docs/design/coupling-core-roadmap.md: make the run-status write surface machine-checked so that delegated PRs cannot silently add status writers that bypass the step() transition policy.

before                                    after
──────                                    ─────
step() decides transitions,               step() decides transitions,
but 46 sites in 5 files also              exactly 1 sanctioned writer
write status events directly              (Daemon.updateStatus);
→ nothing stops writer #47               46 frozen sites annotated,
                                          writer #47 = CI failure

A1 — semgrep rule run-status-write-surface

  • Bans model.NewStatusEvent / model.NewEvent(EventTypeStatus, …) / Type: "status" literals everywhere in internal/ (except internal/model/).
  • The 46 existing writers (socket.go ×39, proto_handler.go ×4 — now fixed, monitor TUI ×2, cli/repair.go ×1) are frozen with per-line nosemgrep annotations. The whitelist may only shrinkgrep -c 'nosemgrep: run-status-write-surface' is the Phase B progress meter.
  • semgrep test fixtures wired into make lint; CI picks it up via quality.yaml.

A2 — fail-fast on status appends (no-ignored-status-append)

  • The 4 _ = st.AppendEvent(…NewStatusEvent…) master-projection sites in proto_handler.go now propagate append failures with run context.
  • failOpenCodeRunBootstrap (socket.go): error-recording path keeps returning the original bootstrap error, but append failures are now logged instead of swallowed.
  • New rule bans the discard pattern from reappearing.

A3 — routing rules in AGENTS.md

Coupling-core inventory, frontier/delegate routing rule, tripwire checklist for delegate PR review, choice-space gate, and the burn-in loop.

Verification

  • make lint: 0 findings (105 rules), new fixture tests 2/2 pass
  • Synthetic 47th writer trips both new rules (negative test, reverted)
  • go build ./... clean; go test ./internal/daemon ./internal/cli pass
  • internal/monitor TestSessionNameForProject fails identically on main (environment-dependent session-name truncation) — pre-existing, untouched by this PR

🤖 Generated with Claude Code

Run status transitions are decided by the pure step() function but were
still written from 46 sites across 5 files, so nothing stopped a new
writer from bypassing the transition policy. This change makes the write
surface machine-checked:

- Add semgrep rule run-status-write-surface: constructing/appending a run
  status event outside Daemon.updateStatus is an error. The 46 existing
  writers are frozen with per-line nosemgrep annotations (the whitelist
  may only shrink; Phase B consolidates them into step()).
- Add semgrep rule no-ignored-status-append: discarding the error of a
  status append is an error (silent store/in-memory divergence).
- Fix the 4 swallowed status-append errors in proto_handler.go master
  projections (now propagated fail-fast with run context) and the 2 in
  socket.go failOpenCodeRunBootstrap (error-recording path: original
  error preserved, append failures logged).
- Wire `semgrep test .semgrep/run-status-write-surface` into make lint
  with ruleid/ok fixtures; CI (quality.yaml) picks it up via make lint.
- Document coupling cores, change routing, the tripwire checklist, and
  the choice-space gate in AGENTS.md; add the living roadmap/watchlist
  at docs/design/coupling-core-roadmap.md.

Verified: go build ./..., go test (daemon/cli pass; monitor's
TestSessionNameForProject fails identically on main — pre-existing),
make lint passes with 0 findings, and a synthetic 47th writer trips
both rules.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@proboscis proboscis merged commit fb6fa1e into main Jun 12, 2026
3 checks passed
@proboscis proboscis deleted the feat/coupling-core-phase-a branch June 12, 2026 07:56
@proboscis proboscis restored the feat/coupling-core-phase-a branch June 12, 2026 07:57
@proboscis proboscis deleted the feat/coupling-core-phase-a branch June 12, 2026 07:57
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