# Phase K5 — Freeze Reviewer Contract (Frozen Thinking Outline, K5a) Status: **Frozen contract for K5b (Auto Build). No reviewer CLI implementation in this step. No `governance-sync` agent (that is 9A-5). No consumer-repo migration (that is K6). No live Automation enablement that requires Tier-3 operator action. No `main` merge without review.** This doc is the machine-checkable ground truth K5b implements mechanically against; it refines — and stays compatible with — `docs/OVERSEER-KIT-SPEC.md` §6 (esp. §6.2), and adds no code. ## Freeze-contract declaration (§6.1 schema) ```yaml phase: K5a outputs: - id: k5-freeze-reviewer-contract path: docs/archive/phases/PHASE-K5-FREEZE-REVIEWER-CONTRACT.md frozen: true # K5b treats this as ground truth without re-deriving frozen_inputs: - id: kit-spec-freeze-contract path: docs/OVERSEER-KIT-SPEC.md#6 - id: kit-spec-freeze-reviewer-config path: docs/OVERSEER-KIT-SPEC.md#6.2 - id: kit-vendoring-cli-contract path: docs/archive/phases/PHASE-K4-VENDORING-CLI-CONTRACT.md - id: kit-model-labels path: policy/model-labels.yaml - id: kit-test-tiers path: policy/test-tiers.yaml - id: freeze-review-skill path: cursor/skills/freeze-review/SKILL.md ``` **Downstream edge:** K5b (Auto) → consumes `k5-freeze-reviewer-contract` as ground truth. Per §6, this is a **mandatory reviewed freeze** before K5b builds. Human escalation is required only if a finding hits `security | irreversible | real_money | gates_tier3`. This contract defines the review capability itself (including injection and least-privilege rules) — a `security` finding against this doc **does** trigger human escalation before K5b may build. **Review record (§6.2):** | Round | Reviewer | Verdict | Resolution | | --- | --- | --- | --- | | 1 (2026-07-10) | Independent Freeze-Step Reviewer (Cursor Grok 4.5 Thinking); file+line citations | `blocked` (1 BLOCKER, 5 MAJOR, 3 MINOR) | Not cleared for K5b. No human escalation. Findings F1–F9 listed in round-1 table (historical). | | 2 (2026-07-10) | Independent Freeze-Step Reviewer (Cursor, Thinking); file+line citations | `findings` (1 MAJOR, 2 MINOR) | F1–F9 **all confirmed resolved** (round-1 table). Full regression §K5.1–§K5.12 surfaced 3 new cited findings **N1–N3** (below). None escalating (no `security`/`irreversible`/`real_money`/`gates_tier3`) → **no human escalation**. Not cleared for K5b until N1–N3 resolved → `pass`. | | 2-fix (2026-07-10) | Author fix revision (N1–N3) | — | **N1:** §K5.7 now defines a deterministic **pre-stamp canonical form** (excise `review_stamp` + re-serialize via a round-trip-stable serializer) so re-stamp digests are stable across runs; idempotent-stamp rule + §K5.12 data-integrity case updated. **N2:** §K5.6 citation-hard-rule now points to §K5.2 **step 9**. **N3:** §K5.1 exit-`4` row + §K5.4 refuse note now include the `--checklist` path/read causes (schema failures stay `2`). Awaiting round-3 confirmation. | | 3 (2026-07-10) | Independent Freeze-Step Reviewer (Cursor Grok 4.5 Thinking); file+line citations | **`pass`** | N1–N3 **all confirmed resolved** (table below). Full regression §K5.1–§K5.12 green (F1–F9 hold; ground-truth edge; exits/`precedence`; nested reviewer + legacy; `reviewer_models`; findings/verdicts; fallback:human; §K5.9 one schema; Automation degrade; seven-tier matrix; security/injection/`adapter.status()` only; no K5b leak). **No human escalation.** Cleared for K5b Auto build. | **Round 1 findings (cited) — historical; F1–F9 addressed in the fix revision below:** | ID | Sev | Cat | Citation (at review time) | Resolution in this revision | | --- | --- | --- | --- | --- | | F1 | BLOCKER | completeness | §K5.7 stamp section | **Fixed:** §K5.7 freezes on-disk serialization for Markdown (fenced YAML) and YAML artifacts; machine stamp is `review_stamp:` inside the freeze block — not the narrative Review-record table. | | F2 | MAJOR | consistency | §K5.0 vs §K5.7 locus | **Fixed:** locus pinned to **freeze block** (SPEC §6.2); narrative Review-record markdown table is human/agent-maintained only. | | F3 | MAJOR | completeness | §K5.4 alternate grammar | **Fixed:** non-YAML / HTML-comment / heading-anchored forms dropped from K5b scope; only §6.1 YAML fence/mapping + operator-forced path. | | F4 | MAJOR | completeness | `--checklist` row | **Fixed:** absent → §K5.5; present → **replaces** built-in; YAML `checks:` schema frozen; unit case added. | | F5 | MAJOR | consistency | §K5.8 vs §K5.9 | **Fixed:** one report schema (§K5.9); human/fallback is the same object with escalation fields; human stdout vs `--json` rendering rules frozen. | | F6 | MAJOR | completeness | `artifact_digest` / BOM | **Fixed:** digest uses §K4.7 **Canonical byte rules** items 1–2 by name (UTF-8 no BOM + LF line endings); parse and digest share that canonicalization. | | F7 | MINOR | consistency | shared exit table | **Fixed:** `review --freeze` never emits `3` (DRIFT). | | F8 | MINOR | consistency | exit `4` wording | **Fixed:** `4` causes match §K5.4 refuse list only. | | F9 | MINOR | completeness | conflicting overrides | **Fixed:** `--mode human` + `--provider`/`--model` is ignore (not conflict); true conflicts enumerated. | **Checks that passed in round 1 (no finding):** C1 ground-truth edge to K5b; args table §K5.2; exits `7`/`8` + precedence; nested `reviewer` schema + legacy normalization §K5.3; `reviewer_models` registry rule; findings/verdicts/citations §K5.6; `fallback: human` fail-closed; Automation degrade §K5.10; seven-tier matrix §K5.12; SPEC §6.2 field parity; injection/least-privilege; no K5b implementation leaked. **Round 2 — F1–F9 re-verification (all confirmed RESOLVED):** | ID | Verified at | Confirmation | | --- | --- | --- | | F1 | §K5.7 (locus table + on-disk serialization) | Serialization frozen for all three write paths — Markdown fence, whole-file YAML, and operator-forced `` marker; machine stamp is `review_stamp:` in the freeze block, not the narrative table. **Resolved.** | | F2 | §K5.0 write-column refinement; §K5.7 locus | Stamp locus pinned to the freeze block (= SPEC §6.2); narrative Review-record table is human/agent-maintained, never CLI-written. **Resolved.** | | F3 | §K5.4 (declared form + out-of-scope list) | K5b parses only the §6.1 YAML mapping (whole `.yaml`/`.yml` or first fenced `yaml` block) + operator-forced; HTML-comment/heading/TOML/JSON declaration grammars explicitly out of scope. (The §K5.7 operator-forced *stamp write* marker is an output locus, not a declaration grammar — no conflict.) **Resolved.** | | F4 | §K5.2 `--checklist` row + file schema; §K5.12 unit | Absent → §K5.5 built-in; present → **replace** (no union); `checks:` schema frozen; unit case asserts built-in ids absent from effective list. **Resolved.** | | F5 | §K5.8 field table; §K5.9 one-schema report | Single §K5.9 report object for all outcomes; human/fallback fills escalation fields; `--json` vs human stdout rules frozen. **Resolved.** | | F6 | §K5.7 "Canonical bytes for `artifact_digest`" | Cites §K4.7 **Canonical byte rules items 1 and 2** by name (UTF-8/BOM strip + LF), correctly disambiguated from the aggregate algorithm steps; parse and digest share the canonicalization. **Resolved.** | | F7 | §K5.1 (exit table note + precedence); §K5.12 | `review --freeze` never emits `3`; precedence `2>4>5>8>7>0` omits `3`. **Resolved.** | | F8 | §K5.1 exit-4 row; §K5.4 refuse list | `4` no longer used for verdicts; causes match the refuse semantics. (See N3 for a residual enumeration nit re the `--checklist` file.) **Resolved.** | | F9 | §K5.2 conflicting/ignored override table | `--mode human` + `--provider`/`--model` = ignore (not conflict); true USAGE conflicts enumerated (unknown flag/enum, missing/duplicate `--freeze`). **Resolved.** | **Round 2 findings (cited — new; line numbers at review time):** | ID | Sev | Cat | Citation (at review time) | Finding | | --- | --- | --- | --- | --- | | N1 | MAJOR | consistency / data-integrity | §K5.7 canonical-bytes + idempotent-stamp rules (≈L531–546, L552–555); §K5.1 idempotency (≈L169–172); §K5.12 data-integrity (≈L723) | **Idempotent-stamp digest is non-deterministic for *interleaved* stamps.** `artifact_digest` is defined over "pre-stamp canonical bytes" where canonicalization = **only** §K4.7 rules 1–2 (BOM strip + LF). For a declared-Markdown fence or whole-file YAML the stamp is written **inside** the declaration mapping, so recovering "current pre-stamp canonical bytes" on a second run requires excising `review_stamp` and re-serializing — a transform whose bytes need not equal the original hand-authored pre-stamp bytes hashed on first write. No frozen rule defines that excision, so the recomputed digest can differ run-to-run, defeating the §K5.1 "no-op that does not rewrite the stamp timestamp" guarantee and the §K5.12 "run-twice identical / idempotent same-digest no-op" case. (Operator-forced *appended-block* Markdown is unaffected — its stamp is trailing and byte-recoverable.) **Fix:** freeze the pre-stamp digest as computed over the artifact with any existing `review_stamp` removed via the **same deterministic serializer** used to write it, so first-write and re-run digests agree. | | N2 | MINOR | consistency (citation) | §K5.6 citation-hard-rule (≈L455); §K5.2 steps 8 & 9 (≈L247, L252) | The synthetic-uncited-finding rule is cross-referenced as "§K5.2 **step 8**," but step 8 is provider-reachability; the synthetic-`blocked` rule is **step 9**. Off-by-one citation error — notable because C8 (§K5.5) requires the contract's own review references to keep file+line discipline. **Fix:** change "step 8" → "step 9". | | N3 | MINOR | completeness | §K5.1 exit-4 row (≈L150); §K5.4 refuse list (≈L394); §K5.2 `--checklist` (≈L217, step 5 ≈L242) | F8's resolution states "`4` causes match §K5.4 refuse list only," but `--checklist` path-escape/missing/unreadable → `4` (§K5.2) is a fourth-code cause **absent** from both the §K5.1 exit-4 row and the §K5.4 refuse list (exit-2's row *does* list checklist schema errors; exit-4's does not list checklist path errors). **Fix:** add the checklist-file refuse causes to §K5.1/§K5.4, or drop the word "only". | **Round 3 — N1–N3 re-verification (all confirmed RESOLVED):** | ID | Verified at | Confirmation | | --- | --- | --- | | N1 | §K5.7 pre-stamp canonical form (L565–603); idempotent stamp (L610–614); §K5.1 idempotency (L201–204); §K5.12 data-integrity (L782); §K5.4 parse share (L409–410) vs §K5.7 L601–603 | Pre-stamp form is deterministic and identical for never-stamped vs already-stamped across declared-MD fence, whole-file YAML (interleaved), and operator-forced appended marker (+ operator-forced YAML). Excision is byte-precise (outside-fence / prior bytes verbatim; stamp key deleted then re-serialized). Same round-trip-stable serializer required for write **and** digest. Idempotent no-op: no `reviewed_at` rewrite, no file write when digests match. Data-integrity tests cover re-stamp digest stability + YAML-whitespace invariance. Parse shares only §K4.7 items 1–2 (no contradiction with digest excision). **Resolved.** | | N2 | §K5.6 citation-hard-rule (L487–489); §K5.2 steps 8–9 (L279–286) | Citation hard rule cites §K5.2 **step 9** (synthetic-`blocked`); step 8 remains reachability. Steps 1–12 numbering consistent end-to-end (incl. step-6 cross-refs at L259, L352). **Resolved.** | | N3 | §K5.1 exit-`4` row (L182); §K5.4 refuse note (L426–429); §K5.2 `--checklist` (L248–249) | Exit `4` consolidates artifact **and** `--checklist` path/read refusals; checklist *schema* failures stay `2`. §K5.4 explicitly defers to §K5.1 for the full `4` set (no "§K5.4 only" overstatement in normative text). **Resolved.** | **Freeze status:** **reviewed → `pass` (round 3).** Cleared for the K5b Auto build. **No human escalation** (no finding is `security`/`irreversible`/`real_money`/`gates_tier3`). --- ## Simple summary (no jargon) This freezes exactly how the kit must run an automated check on a "frozen" document before a later step is allowed to treat that document as settled truth. It nails down every switch the `overseer review --freeze` command accepts, every exit number it can return, the shape of each finding (always with a file and line so a human can verify), how a repo picks a local or remote reviewer model (or a human), and what happens when that model is unreachable (always fall back to a human — never skip the review). It also lists the full set of tests the build step must write and pass. Nothing here implements the reviewer — it is the blueprint the next (mechanical) step follows. ## Technical summary K5a freezes the argument contract, exit-code taxonomy, I/O / idempotency / dry-run semantics for `overseer review --freeze`; the extended (spec-compatible, additive) `freeze_contract.reviewer` config schema (`mode`, `model`, `provider`, `fallback`) with legacy-string normalization; the reviewer-model label registry rule (labels only — never vendor slugs; `provider: local` first-class; `fallback: human` fail-closed); the finding / verdict / stamp / escalation contracts; the provider reachability + human-escalation report behavior; the Automation routing degrade path; and the concrete seven-tier test matrix K5b must turn green. The engine remains Python (matching `cli/` + `adapters/`), fronted by the existing POSIX `cli/overseer` shim. Review is read-first; the only optional write is a local review stamp on `pass` (never a VCS commit). No core review capability may be API-only. --- ## §K5.0 — Scope and hard stops (frozen) **In scope for K5b (Auto Build):** implement `overseer review --freeze` exactly to this contract; extend `adapters/config.py` to parse the nested `freeze_contract.reviewer` schema (with legacy string normalization); add the `reviewer_models` registry to `policy/model-labels.yaml` per §K5.3; implement the Freeze-Step Reviewer engine under `tools/freeze_reviewer/` (provider interface + local/api backends + human-escalation report path); emit findings with mandatory file+line citations; verdict → exit-code mapping; optional stamp write on `pass`; Automation **templates** (session-end / on-merge) that invoke the CLI and degrade to slash-command/CLI when Automations are unavailable; the seven-tier tests below. **Explicitly NOT in K5:** | Out of scope | Belongs to | | --- | --- | | `overseer governance-sync` (doc patching, realign, feature-branch commit) | 9A-5 | | Any consumer-repo migration / running `init` against Scooling/Knowtation/MuseHub | K6 | | Dogfood flip to `muse+git-mirror` | K7 | | Live enablement of Cursor Automations that requires operator Tier-3 authorization | operator (templates ship; enablement is not automated by the kit) | | Any `mirror` / `realign` / write to `main` or canonical | Tier 3, human | | Any `main` merge of K5 work without review | governance gate | | Redesign of §6 policy (verdicts, escalation conditions, citation rule) | frozen in SPEC; this doc only refines CLI/config/engine contracts | **Adapter surface K5 may call:** `adapter.status()` only (read-only context in reports). Review never calls `read_head`, `read_canonical_anchor`, `realign`, `commit_feature`, or `mirror`. The optional stamp write is a local filesystem write into the reviewed artifact (Tier 1); committing that stamp is the operator's normal feature-branch step, not the CLI's job. **Refinement of SPEC §5 write column (frozen):** the table row "No (review output only)" means **no VCS writes and no footprint/config/lock writes**. On `pass` without `--dry-run`, the CLI **may** write a `review_stamp` mapping into the artifact's **freeze block** (§K5.7 — same locus as SPEC §6.2). The narrative markdown Review-record table is not written by the CLI. `--dry-run` writes nothing. --- ## §K5.1 — Global conventions (frozen; inherits §K4.1) **Invocation:** `overseer review --freeze [options]`. The published entrypoint remains the POSIX shim `cli/overseer` → Python runtime. No global install required. **Repo/config resolution:** identical to §K4.1 (`--repo` / walk-up / cwd; `--config` override; absolute repo root before any file operation). **Global options:** identical to §K4.1 (`-C/--repo`, `--config`, `--json`, `-q/--quiet`, `-v/--verbose`, `--no-color`, `-h/--help`, `--version`). **Output discipline (frozen):** human/report output → **stdout**; diagnostics/warnings/errors → **stderr**. `--json` prints exactly one JSON object to stdout and nothing else on stdout. No command prints secrets, tokens, credentialed URLs, **absolute machine paths**, or user identity (SPEC §9). **All file references in every stream are repo-relative (POSIX).** Timestamps are ISO-8601 UTC with trailing `Z`. **Shared exit codes (inherited from §K4.1; review-relevant subset):** | Code | Name | Meaning | | --- | --- | --- | | `0` | OK | Success — for review: verdict `pass`. | | `1` | USAGE | Unknown command, bad/conflicting flags, missing required ``. | | `2` | CONFIG | Fail-closed: config missing/unparseable, unknown version, unsupported regime, invalid `freeze_contract` schema, unknown reviewer model label, invalid `--checklist` file, or adapter `ReadError` on a required read. | | `4` | REFUSED | Review refused: `freeze_contract.enabled: false`; artifact `` **or** `--checklist ` escapes repo root; artifact/checklist path missing/unreadable/not a regular file; artifact UTF-8 decode failure (`not-utf8`). (Invalid `--checklist` *schema* is a config error → `2`; a path/read *refusal* on either file is `4`.) | | `5` | IO | Stamp write failed (atomic-replace failure). No half-written artifact. | | `6` | INTEGRITY | Reserved (K4 lock/digest). Review does not emit `6` unless a future flag reuses integrity checks; K5b must not overload `6` for verdicts. | **Not used by `review --freeze`:** exit `3` (DRIFT) remains a §K4.1 `status --exit-code` code only. `review --freeze` **never** emits `3`. **Review-specific exit codes (frozen — additive):** | Code | Name | Meaning | | --- | --- | --- | | `7` | FINDINGS | Verdict `findings` — cited non-escalating findings; no human stop required by config. | | `8` | BLOCKED | Verdict `blocked`, **or** human escalation required (`mode: human`, fallback-to-human after unreachable provider, or a finding whose category intersects `human_escalation`). | **Exit-code precedence for `review --freeze` (frozen):** **`2` (fail-closed) > `4` (refused) > `5` (IO) > `8` (blocked/human) > `7` (findings) > `0` (pass).** The report payload still lists every condition detected (e.g. both findings and an escalation hit), so a non-zero exit never hides a second condition. **Idempotency (frozen):** running `review --freeze` twice on an unchanged artifact with the same config produces the same verdict, the same finding set (stable ordering — §K5.6), and the same exit code. A second successful stamp write on an already-stamped `pass` is a no-op that does not rewrite the stamp timestamp (§K5.7). **Dry-run (frozen):** `--dry-run` runs the full review and prints the report (including the stamp it *would* write) but **writes nothing**. This is the inert-first default (`policy/test-tiers.yaml`). --- ## §K5.2 — `overseer review --freeze` argument contract (frozen) **Purpose:** run the Freeze-Step Reviewer (SPEC §6) on a freeze artifact; emit findings with **mandatory file+line citations**; set exit status by verdict; escalate to human per config. **Synopsis:** ```text overseer review --freeze [options] ``` `` is **required**. It is a repo-relative or absolute path to a single freeze artifact file (Markdown or YAML). After resolution it **must** lie inside the resolved repo root; `..` traversal or any escape → exit `4`. Missing/unreadable file → exit `4`. **Command-specific options:** | Option | Type | Default | Meaning | | --- | --- | --- | --- | | `--freeze ` | path | *(required)* | Artifact to review. The flag form is mandatory (`review` without `--freeze` is USAGE → `1`). | | `--dry-run` | flag | off | Full review report; write nothing (no stamp). | | `--mode ` | enum | *(from config)* | Override `freeze_contract.reviewer.mode` for this invocation only. | | `--provider ` | enum | *(from config)* | Override `freeze_contract.reviewer.provider` for this invocation only. Ignored when effective mode is `human`. | | `--model