# Caliber C112 — Four-Gate Prune-Boundary Isolation (contract excerpt)

_Source: `system/caliber/lib/c112-four-gate-prune-isolation.mjs` (header) and
`system/caliber/docs/CRITERIA.md § Criterion 112` (~L4003). C112 is the mechanical enforcement that
keeps the four-gate isolation installed. No redaction required — scanner logic, no secrets or customer
data._

**Family:** Engineering · **Severity:** Critical · **Points:** 2 · **Bootstrap grace:** NONE ·
**Kill switch:** NONE (Critical-severity criteria do not get the `CALIBER_C{N}=0` bypass; the constant
is defined for structural completeness only and is never checked at runtime — the scanner always runs).

C112 audits the four-gate doctrine's prune-isolation boundary invariants I75–I78 (from the owner plan
`2026-05-13-promote-session-resilience-push-before-prune.md`). Its stated root cause: "cc1fc8a canary
commit loss — submodule on non-main branch; close-time detection skipped push; old inline prune ran on
SUCCESS; worktree removed; sha became unreachable in origin."

## Five audit dimensions (A–E)

- **Dim A — boundary isolation.** `promote-session.mjs` contains **zero** matches for `worktree\s+remove`
  or `branch\s+-d` on executable (non-pure-comment) lines. Any match → FAIL. Mirrors I50's Vercel-token
  boundary on `deploy-session.mjs`.
- **Dim B — prune structural shape.** `prune-session.mjs` exists, imports
  `detectSessionTouchedSubmodulesFromGitlinkDiff` from the canonical library, references exit codes
  30/31/32/33, and declares an `async function` entrypoint (`runPrune` or `main`).
- **Dim C — exit-code registry.** `EXIT_CODES.md` has a documented table row for each of 30, 31, 32,
  and 33.
- **Dim D — detection single-source.** `close-session-promote.mjs`'s detection body **delegates** to the
  shared library (contains a call to `detectSessionTouchedSubmodulesFromGitlinkDiff`) rather than
  re-implementing an inline `git diff` — so every site that classifies a session-touched submodule uses
  one algorithm.
- **Dim E — no best-effort framing.** `prune-session.mjs` contains **zero** `non-fatal`, `best-effort`,
  `Manual cleanup`, or `WARN:` strings inside `process.stdout.write(` contexts. Any match → FAIL (an I77
  violation — this is the exact framing the incident's buried prune used).

**Pass:** all five dimensions PASS. **Fail:** any dimension FAIL → BLOCKED (Critical; no grace). The
report names which dimension failed, the matched line or missing pattern, and the specific invariant
violated (I75–I78).

## What C112 does and does not own

C112 owns **only** the boundary-isolation invariants: are destructive prune tokens absent from
promote-session, does prune-session have the correct structural shape, are all failure modes
fail-closed, and does close-session delegate rather than re-implement detection. It does **not** audit
the full promote-pipeline shape (that is C71, the higher-level close-session pipeline integrity
criterion) or the push-reachability artifact schema (C83). The scanner ships with a `--self-test`
covering all five dims plus synthetic-absence negatives; that self-test must exit PASS.
