releases#331 **H4**, IR-147 fix candidate **(a)** as ruled by doyle. `0854bbe8` on `c185326b`.

## What
- **One classifier.** `.github/ci/classify-changes.py` now serves both arms (no second copy to drift):
  - **pull_request:** the merge commit's files (`HEAD^1..HEAD`), as before.
  - **push:** the WHOLE push, `github.event.before..github.sha`, after a bounded deepen of the depth-2 checkout (`--deepen=50`, then `--deepen=500`, along `github.sha`).
- **Never `HEAD^1..HEAD` on a push.**
- **Positive docs set:** `traceable-reqs.toml`, repo-root `*.md`, and `docs/**.md` except compiled-in Markdown. `.github/**`, `docs-site/**`, `crates/**`, `releases-repo/**` and every unnamed path are **code**.
  - `docs/ER-SKELETON.md` is `include_str!`'d into an `spt` bin test, so it counts as code.
  - A selftest arm re-derives `COMPILED_MARKDOWN` from every `include_str!`/`include_bytes!` of a `.md` in the tree.
  - The PR arm narrows accordingly: Markdown outside root/`docs/` was docs before and is code now.
- **Conservative by name.** The default is `code=true`. Each of these runs units and logs `CLASSIFY code=true reason=<name>`: `before-zero`, `forced-push`, `before-unreachable`, `before-not-ancestor`, `diff-failed`, `empty-range`, `event-<name>`, `classifier-error:<type>`.
- **The IR-144 reuse helper is untouched.**

## Invariant (verbatim in REQ-CI-PUSH-DOCS-ONLY-THIN, IR-19's status line and GOLDEN-CI)
> main's exact SHA carries unit evidence for its CODE: at that sha via IR-144's exact-PR proof, or inherited from the last code sha when the tip is docs-only; the full-suite authority for an exact sha is the uncancelled golden run.

## Evidence
- **Selftest:** `classify-changes-selftest.py` passes **17/17** offline (fake git). It also runs as a `changes`-job step.
- **Mutation:** switching the push arm to `HEAD^1..HEAD` reds 4 arms. `test_multi_commit_push_reads_the_whole_range_not_head_parent` reds on the real defect (HEAD^1 says docs-only, so `code=false`). The other three red only because their fake tables carry no HEAD^1 entry (`diff-failed`), so they add no discrimination; this is not a one-arm red.
- **Real git, depth-2 shallow clones of this repo:**

  | range | `before` at depth 2 | result |
  |---|---|---|
  | #254 `b4490c4f..c185326b`, 5 commits | absent, reached by the deepen | `code=true reason=code-path:crates/spt-daemon/src/applyhost.rs` (17 files) |
  | H1 `3672c25c..5744839f` | present | `code=false reason=docs-only` |

  **The trap, measured:** `HEAD^1..HEAD` at #254's tip lists only `docs/INFRA-REGISTER.md`.
- **Registry:** `REQ-CI-PUSH-DOCS-ONLY-THIN` (doc/impl/unit). treqs 0.4.1 **951/951**; `[[requirements]]` headers 951 == ids 951.

## Condition 2: consumers asserting "main tip has a green unit run"
- **Predicates:**
  - (1) `/main tip|tip of main|main.s tip|main-tip|green on main|main is green|post-merge|push run|thin run|thin main|push-main|main.s exact|exact sha/i`
  - (2) doyle's `/main.{0,60}(unit|full suite|tested)|unit.{0,60}main tip|golden.{0,40}main|main[- ]tip|green unit run|unit evidence|exact sha|only a .push|run-unit/i`
- **Population:** every tracked `*.md`, `.github/**` and `crates/xtask/**` (`git ls-files`). Sweep (1) returned 87 hits; sweep (2) returned 49 after excluding historical records (INFRA-REGISTER, *-PLAN, GATE-*, RESTORATION-*, RCA-*).
- **Amended in this PR:**
  - `docs/GOLDEN-CI.md` 15-20: "Only a push … may set it to false, through push-main-unit-reuse.py", an exclusive-mechanism claim (doyle's control hit 1). Replaced with the two mechanisms: `code` (IR-147) and `run-unit` (IR-144).
  - `docs/GOLDEN-CI.md` 57-61: acceptance now names the two qualifying classes.
  - `docs/RELEASE-RUNBOOK.md` step 4: the thin-run job list reflects IR-144/IR-147.
  - `traceable-reqs.toml`: the pointer on REQ-CI-DOCS-ONLY-THIN names both senses of "thin" (ci.yml-vs-golden there, lint+unit-skipped here; doyle hit 2). The new REQ's title names its own sense.
- **Read, and survive unamended:**
  - `RELEASE-RUNBOOK` 597-602: box occupancy, not evidence.
  - `RELEASE-RUNBOOK` 111 and ADR-0050 63: golden authority.
  - `golden.yml` 24: "PR classification belongs to ci.yml" is still true; "Main runs thin CI" uses the ci.yml-vs-golden sense.
  - AGENTS.md 42; ci.yml's and the reuse helper's self-references.
  - Other hits (CONTEXT, KNOWN-HAZARDS, INPUT-PROVENANCE, REMOTE-FRICTION, docs-site attachments, the JIT/DRAFT files) are unrelated uses of "main"/"unit".
- **No consumer asserts a main-tip unit run.**

**Acceptance (IR-147):** the next docs-only push to main should show `changes`+`traceability` only, with `unit` not executed on either box. IR-146 (c) is routed to be that push.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

https://claude.ai/code/session_01KR5QdzrHXYGL1djRTBNKEG


[exited with code 0]
