Skip to content

Build the hook fail-open promotion-and-surfacing relay (#391)#431

Merged
StarshipSuperjam merged 3 commits into
mainfrom
claude/hook-fail-open-relay-391
Jul 6, 2026
Merged

Build the hook fail-open promotion-and-surfacing relay (#391)#431
StarshipSuperjam merged 3 commits into
mainfrom
claude/hook-fail-open-relay-391

Conversation

@StarshipSuperjam

@StarshipSuperjam StarshipSuperjam commented Jul 6, 2026

Copy link
Copy Markdown
Owner

Closes #391

A green mechanical check below shows this change conforms to the engine's rules — not that it is correct. What covers correctness is the behavioural steps in Review and your own read of the change; a green check is never a substitute for that. Your merge is the binding gate.

Purpose

Make the local safety net honest: when a hook crashes or the tool-runtime is missing, tell the operator instead of going blind and lying.

  • Today a crashed gate (or an unhealthy .engine/.venv) leaves only a transient stderr line nothing consumes — no tracked finding opens, boot never surfaces it, and the one message an operator might glimpse falsely says "this was recorded as a problem to fix" when nothing recorded anything.
  • The enforcement machinery can be dead for many sessions with the operator never told — the exact "advisory theatre from the operator's seat" the fail-open law forbids.

Impact: a safety gate that couldn't run now becomes a durable, tracked, operator-visible finding — and the copy never claims a record that doesn't exist.

Scope

Wire the emit → promote → surface relay, name the absent runtime, and correct the false copy.

  • hooks.py: each fail-open branch promotes the finding to a tracked engine Issue via the existing telemetry.promote_finding (the close.py precedent) — best-effort, telemetry/boot imported lazily off every hook's hot path, TRUST_CRITICAL, source-keyed hooks/fail-open/<event>/<kind> so recurrences collapse to one Issue.
  • The "recorded" copy is now strictly conditional on the promotion landing: promoted → "recorded as a tracked item you'll see at your next start"; offline/degraded → "not durably recorded until the engine next reaches GitHub."
  • hook-runner.sh: when the interpreter never appears, name the absent runtime in plain language on stderr (non-blocking) instead of exiting silently.
  • build-orchestration.md: the PR Validation section surfaces any open fail-open finding as a named line at submit.

Impact: all three operator touchpoints — boot orientation, the merge-time Validation line, and the in-session copy — now actually reach the operator.

Out of scope

The general telemetry triage loop — deliberately left to its lane-siblings.

Impact: #391 is the root emit-side relay; #412 will need light re-scoping once this lands (it claimed some of the same relay).

Risk

It edits two protected hook-wiring files, so it needs your deliberate guardrail-ack. The new write is a hard fail-safe addition.

  • .engine/tools/hooks.py and .engine/tools/hook-runner.sh are guarded → engine-guard goes RED and holds the merge until you apply guardrail-ack. This strengthens the fail-open safety net; the ack is still yours. I have not applied it. boot.py/telemetry.py are only read (lazy import), not edited, so they add no ack.
  • Fail-safety is the load-bearing invariant: promotion is a GitHub write on the failure branch only; any error in it (offline, disk, a misbehaving promoter) is swallowed so recording a crash can never turn the fail-open path fail-closed (the [conformance] Quote the hook script path so a spaced project directory does not fail closed #390-class brick). Guarded by a test that injects a promoter which itself throws.
  • Test-safety: a fail-open firing in any test could otherwise open a real Issue (gh auth token resolves even locally). The promoter is injectable (tests/demo use a fake), and the real one hard-refuses live GitHub under a test harness. (An early build-verification probe that bypassed this backstop did open one spurious Issue, Engine health: msg #430, since closed.)

Impact: the merge stays your conscious decision; a crashed gate can never brick the session.

Validation

Full suite green; the fail-safe, honest-copy, and readout behaviors are all pinned.

  • Full self-tests: Ran 2987 tests … OK — including new tests for the promoted vs offline copy, the fail-safety of a throwing promoter, the coarse marker-safe source_id, the real wiring against a mocked GitHub, the test-harness backstop, and the missing-runtime readout through the real hook-runner.sh.
  • validate.py --suite CI: green except disposition-issue-resolution (environmental — needs a GITHUB_TOKEN CI has; unrelated to hooks). Knowledge graph regenerated.
  • The hooks.py demo self-check was extended to fail unless the crash finding is promoted with the honest copy and the missing-runtime case names its runtime.

Impact: an approver can rely on the automated floor being green in CI; correctness rests on Review + your merge.

Review

Thorough depth: four cold plan lenses reshaped the design before building; four deliverable lenses after. The plan gate caught a real spec violation and half-a-double-build.

  • Plan review (thorough) found my initial plan not buildable as scoped and I revised it with you: (1) my proposed local NDJSON inbox file is forbidden by a locked decision (D-040 / topology law 5 reject a committed or gitignored findings register; the durable home is the GitHub Issue via promote_finding); (2) the consumer/driver/refused-cursor routing is [conformance] Wire telemetry end-to-end: consume the three signals-of-record, drive the triage loop live, and render honestly #403/[conformance] Wire the telemetry self-healing loop into production so fail-open and degraded conditions become durable, auto-closing tracked findings #412's and would double-build; (3) the boot carry is already free; (4) the PR-Validation line has no mechanical renderer — it's a submit-time authoring duty. You approved the tightened scope (emit-side relay + copy + readout + a submit-time guidance line) and the deferrals.
  • Deliverable review (thorough) ran four cold lenses on the built diff. No blocking findings; one serious, now fixed. Spec-conformance: conforms to the agreed scope (all four branches promote with honest conditional copy; in scope — no inbox, no loop, no boot code). Security/governance: safe — adversarially probed the fail-safety (throwing promoter, BaseException, telemetry raising) and confirmed the gate can never go fail-closed; content-injection closed by construction; dedup prevents spam; the test backstop holds and Engine health: msg #430 is closed with no other spurious Issues. Technical-integrity: healthy — hot path imports nothing new, no unbounded hang (bounded timeouts), fail-safety double-wrapped, tests are real falsifications. Usability: the honesty fix lands in all states, but the serious finding was that the operator-runnable demo showed only the promoted copy — fixed by adding a demo case that renders the honest offline "not durably recorded" line (validated; not re-reviewed).
  • Nit dispositions (all judged, none blocking): failure-path latency under degraded connectivity is bounded and on the failure branch only — accepted (matches close.py's immediate-promote); boot.read_state's "owes → telemetry writer" comment is left as-is — the refused-cursor emission it names is genuinely still [conformance] Wire the telemetry self-healing loop into production so fail-open and degraded conditions become durable, auto-closing tracked findings #412's; the block-misuse/decide-misuse copy sharing the crash voice is spec-consistent; the readout's raw .venv path is acceptable (plain language carries the meaning); the local disposition-issue-resolution FAIL is environmental (pre-existing on origin/main, needs a token CI has).
  • spec_referent.py review-steps does not apply — [conformance] Build the hook fail-open promotion-and-surfacing relay #391 is an engine conformance fix with no settled product docs/spec description.
  • Things you can confirm yourself: run uv run --directory .engine -- python tools/hooks.py demo. It drives the real harness: a crashing gate proceeds (non-blocking) and its finding is promoted (against a faked GitHub) with the honest "recorded" copy; a block on a non-eligible event does the same; and the launcher, on an absent interpreter, names the runtime on stderr instead of exiting silently. To see the un-recorded copy, note the offline path says "not durably recorded until the engine next reaches GitHub."

Impact: the engine's own account of the review — your merge is the binding gate.

Files of interest

One harness, one launcher, one runbook line.

  • .engine/tools/hooks.py_promote_fail_open/_do_promote_fail_open (the relay + backstop), _emit_finding (honest conditional copy), the four fail-open sites, and the demo.
  • .engine/tools/hook-runner.sh — the missing-runtime readout.
  • .engine/operations/build-orchestration.md — the submit-time Validation-line guidance.
  • .engine/tools/test_hooks.py — the promotion/copy/fail-safety/readout regression tests.

Impact: the promotion seam and the honest copy are where the operator's trust is won or lost.

Claude involvement

A design the plan gate materially corrected; the wiring follows an existing precedent.

Impact: AI judgment is load-bearing on the spec-conformant scope; the relay is a precedent-following wire, test-pinned.

StarshipSuperjam and others added 2 commits July 6, 2026 14:14
A crashed hook or a missing tool-runtime used to leave only a transient stderr line
nothing consumed — no tracked finding opened, boot never surfaced it, and the one
message an operator might glimpse falsely claimed "this was recorded as a problem to
fix" when nothing recorded anything. This makes the blind safety net honest and
operator-visible.

- hooks.py: each fail-open branch now promotes the finding to a tracked engine Issue
  via telemetry.promote_finding (the close.py "log it" precedent) — best-effort, with
  telemetry/boot imported LAZILY off every hook's hot path, TRUST_CRITICAL, source-keyed
  hooks/fail-open/<event>/<kind> so recurrences collapse to one Issue. FAIL-SAFE: any
  error in the promote path is swallowed, so recording the crash can never re-break the
  fail-open path into a block (the #390-class fail-closed stranding). A test-harness
  backstop refuses to touch live GitHub from any test run.
- The "recorded" copy is now STRICTLY conditional on the promotion landing: promoted ->
  "recorded as a tracked item you'll see at your next start"; offline -> "not durably
  recorded until the engine next reaches GitHub". The old false copy is gone.
- hook-runner.sh: when the venv interpreter never appears, name the absent runtime in
  plain language on stderr (non-blocking) instead of exiting silently.
- build-orchestration.md: the PR Validation section surfaces any open fail-open finding
  as a named line at submit (non-blocking; informs consent, never a new gate).

Boot orientation already carries any promoted finding via open_findings — no new boot
code. The live triage LOOP (production run() driver, ambient capture, refused-cursor and
broken-runtime durable routing, auto-close) stays telemetry's — #403/#412.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…oted one

Deliverable-gate finding (usability): the operator-runnable demo showed only the
promoted 'recorded' copy, leaving the load-bearing offline honesty case — the state
the old code lied about — visible only in tests the operator cannot read. Add a demo
case that injects an offline promoter and renders the honest 'not durably recorded'
line, and make the demo self-check falsify on its absence.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@StarshipSuperjam StarshipSuperjam marked this pull request as ready for review July 6, 2026 21:28
@StarshipSuperjam StarshipSuperjam added the guardrail-ack Deliberately approves a guardrail-weakening change; clears the engine-guard block. label Jul 6, 2026
@StarshipSuperjam StarshipSuperjam merged commit e9cc9a8 into main Jul 6, 2026
7 checks passed
@StarshipSuperjam StarshipSuperjam deleted the claude/hook-fail-open-relay-391 branch July 6, 2026 21:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

guardrail-ack Deliberately approves a guardrail-weakening change; clears the engine-guard block.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[conformance] Build the hook fail-open promotion-and-surfacing relay

1 participant