# Stage-5 grounding audit -- SCOPE (2026-07-27)

STATUS: this file is the audit's own charter and plan. It carries NO status
claims about the cloud (GA-R1 -- `docs/CURRENT-STATE.md` is the only status
authority). It is committed BEFORE any agent is spawned so that a session
that dies mid-run still leaves the plan behind.

Branch: `dc-dc-stage5-grounding-audit`, off post-merge `main` at `71519a2`
(Stage 4 CLOSED + merged as `6f5701d`, branch retired).

## 1. Why this audit exists

Operator direction, 2026-07-27 (verbatim intent, not a ruling): Stage 4 took
multiple sessions with "real gaps in process, data, scripts, and procedures".
Before Stage 5 opens, the operator asked for a full reconciliation and
grounding from a fresh session -- a committee review of current status, the
changes required to reach the current as-built, the configuration as compared
to the overall goal of the project, and the stability and readiness to move
into the next stage error-free; then a review of the UPCOMING stages to fix
problems before the deployment process finds them.

The operator is away for the duration. The run is autonomous. Rulings are
QUEUED, never adopted (GA-R5: one decision per operator exchange; an
ambiguous or reconstructed ruling rules NOTHING).

## 2. Deliverables (three files, fixed up front)

1. `docs/audit/stage5-readiness-20260727.md` -- THE ORDERED STAGE-5
   PRECONDITION CHECKLIST. This is what gets read first. One row per
   precondition, in execution order, each carrying:
   status (DONE / MECHANICAL / NEEDS-RULING / UNMEASURED), evidence
   (path:line or quoted command output), and what breaks if it is skipped.
2. `docs/audit/stage5-grounding-committee-20260727.md` -- the committee
   record: every lens, its findings, and the adversarial verification verdict
   on each finding that claims to block Stage 5.
3. `docs/audit/queued-rulings-20260727.md` -- the questions, GA-R5 shaped:
   N SEPARATE questions, each with options and a blank operator-utterance
   line. Split into STAGE-5 BLOCKING vs STANDING/DEFERRED so the blocking
   few are not lost among the items already pinned past this deployment
   (D-068 Q2, D-131 sub-4, D-132, D-136).

## 3. The seven lenses (read-only, parallel)

| # | Lens | Bounded to |
|---|------|-----------|
| 1 | Record integrity / status reconciliation | ONLY status claims that would change a Stage-5 decision or that CONTRADICT a RULED decision. See the GA-F06 bound below. |
| 2 | As-built vs live measurement | Does the doc match the cloud? Measured, not read. |
| 3 | Deploy-artifact conformance | bundle.yaml + overlays vs the governing D-numbers; VIP legality; validator behaviour. |
| 4 | Gate / checker integrity | "A checker that cannot fail is not a gate." Attempt to construct a false green for each gate Stage 5 will close on. |
| 5 | Stage-5 pre-mortem | phase-4 runbook line-by-line vs measured reality; what fails on first run. |
| 6 | Stages 6-7 pre-mortem | phase-5/6 runbooks + the workflow-doc gap register; DOCFIX-200/204-class defects. |
| 7 | Roosevelt-delta / goal alignment | Does the current configuration serve MINIMIZE DELTA TO ROOSEVELT? Which VR1 choices are rehearsal-only and correctly flagged, vs silently divergent? |

### GA-F06 bound (mandatory, lens 1 especially)

The skill names record-churn-presenting-as-progress as this project's
measured failure mode, with a circuit-breaker. A record-integrity lens turned
loose on this corpus will produce fifty findings and drown the three that
gate the deploy. Therefore: a record defect is only a FINDING if it would
change a Stage-5 decision or contradicts a RULED decision. Already-recorded
staleness (CURRENT-STATE section 4 HIGH, the G14 row title count, the phase-4
"no designate" line) is CLEANUP, not a finding.

## 4. The mechanical-vs-ruling discriminator

One question decides disposition: **does the fix require a choice?**

- NO  -> MECHANICAL. Execute it under gating. A line contradicting a ruled
  decision is DOCFIX-class (the DOCFIX-200 / DOCFIX-204 precedent); a checker
  that cannot fail is a gate defect. Any script touch ships with its
  `tests/<name>/run-tests.sh` green, gauntlet ALL GREEN, repo-lint 0-fail,
  and a session-changelog entry carrying a per-item revert. This set is kept
  deliberately small and chosen, never opportunistic.
- YES -> QUEUE IT. Present options; do not pick. PROPOSED means present
  options (hard rule 1 + GA-R5).

## 5. Subagent contract (verbatim in every lens prompt)

1. READ-ONLY. No subagent attempts a mutating shape -- nobody is present to
   answer a permission prompt, and hard rule 3 is not relaxed by absence.
2. Required per-finding schema:
   `claim / evidence (path:line or quoted command output) / blocks-Stage-5
   (yes|no) / disposition (DOCFIX | ruling | log-only)`.
3. Never an inferred value (hard rule 2). If a value would be inferred, the
   finding is UNMEASURED, not asserted.
4. **Any denied or prompted tool call is reported as UNMEASURED with the
   exact command, and is NEVER folded into a negative finding.** "Could not
   look" is never "nothing there" -- the rule that turned `/root/maas-secrets`
   from "does not exist" into UNREADABLE on 2026-07-26.
5. A known-findings exclusion list is supplied; do not restate the last three
   sessions' closed work as new.

## 6. Session permission posture (operator-granted 2026-07-27)

The operator offered a broad exception; a SCOPED READ-ONLY expansion was
taken instead, on the grounds that the task is read-only by construction and
the `ask` rules ARE the enforcement of hard rule 3 (CLAUDE.md). Design:
the allow list enumerates READ verbs, the ask list enumerates MUTATING verbs,
and anything matching neither falls through and FAILS SAFE -- logged as
UNMEASURED, never assumed absent. Added: read-only shell tooling, read-only
`virsh`, `maas admin ... read`, the per-DC artifact checkers, `docs/**`
writes, commit/push, and upstream doc fetch. Operator additionally granted
the tier-2 `--privileged` credential sweep (remote `sudo -n stat`, metadata
only, never file content). NOT granted and not requested: jumphost `sudo`,
`tofu apply|destroy|import|state rm`, any `maas admin` write, `juju
deploy|add-model|bootstrap`, `opnsense-api.sh POST`, `scripts/* apply|install`,
`*--commit*`, `rm *`. `Edit(.claude/settings*.json)` deliberately stays `ask`
so the session cannot widen its own permissions unattended. The deny list and
the PreToolUse guard are untouched.

REMOVE the session-scoped allow block at session close.

## 7. Standing measurements this audit must capture

Named here so they are not skipped; each to its own dated capture file.

- Three `tofu plan` captures: the outer root on vcloud, and BOTH inner roots
  on voffice1 (their tfstate lives there -- D-128 Plane 2). ZERO DIFF is the
  standing expectation (CURRENT-STATE section 5) and ANY diff is a STOP.
  This is the strongest single as-built test available.
- Gauntlet `bash scripts/run-tests-all.sh` -- ALL GREEN (81) expected.
- `bash scripts/repo-lint.sh` -- 0 fail, 1 warn (the L1 legacy carve-out).
- `bash scripts/preflight.sh` -- it is ALREADY red. The useful result is
  whether the red reasons are EXACTLY the known set (P4 octavia overlay
  absent, MAAS unreachable from the jumphost, P5 credential findings) and
  nothing new has joined them.
- Per-DC artifact path: `dc-mirror.sh check dc0` (full mirror) and
  `dc-cache-proxy.sh check dc1` (proxy). They DIFFER BY RULING (D-135
  amendment) -- checking dc1 as a mirror fails by design.
- `site-baseleg.sh check office1`; live MAAS + `virsh` as-built sweep;
  `creds-matrix.py --all` and the privileged tier-2 sweep.

## 8. Boundary

`docs/CURRENT-STATE.md` is NOT edited from this audit branch except where a
FRESH MEASUREMENT corrects it -- that is GA-R1 amendment C2, and it belongs
in the capture's own commit. All findings live in the three audit files above.
