# Orchestrator — Verification (lazy-loaded)

Bind this to the parent Pi session only. Load it when the Verification rule fires (a high-risk change) or a delegated writer returns; the small path never needs it.

## Verification rule (normative)

5. **Verification rule** (gentle-pi#661/#662, verify-always-rdd-high S1; normative -- referenced, not restated, in the other orchestrator modules): The bounded writer always runs the exact parent-authorized commands under the delegated task's `## Verification` heading, synchronously and in the foreground, and reports each as `<command>: <observed result>` -- see `gentle-ai-worker`'s Verification contract for the exact rules, including how `## Known environmental failures` (exact pre-existing base failures) differs from any other failing required command, which still forces `status: partial`. Those foreground commands are live work, not silence: while a tool call is in flight the runner's stall watchdog uses `tool_stall_timeout_ms` (default 30 minutes) instead of the `stall_timeout_ms` idle budget. After the writer returns, call `gentle_review` with `{"operation":"assess"}` over the writer's diff and follow the returned plan, whatever the `Receipt-driven development:` line reads (`on`, `off`, or `unknown`), instead of judging non-triviality from the task description: the operation resolves the native risk tier and states exactly who verifies next. When the line reads `on`, the native review is an additional outside view of the change; it never replaces or skips the tier's verification, and the tier's verifier runs before review. Pass `nativeReviewOutcome` when the parent already knows it; ASSESS derives `closed` only from the native `candidate.consumed` fact for this exact candidate (gentle-pi#1175), so a caller-supplied `closed` is not authority and, without that fact, resolves to `unknown`; the outcome only explains the plan, never lowers it. The tier table (stated once, here):

| Tier | Verification (any RDD state) |
|---|---|
| passive | structural readback by the parent; no separate verifier, no tests |
| medium | writer self-verification stands; no separate verifier, whatever model wrote the change |
| high | only through `escalate` naming a Task Size high-risk item: writer self-verification plus one separate `gentle-ai-verify` run |
| native high, unknown, or assess failed | informs only: writer self-verification stands; escalate when a named high-risk item applies |

The independent verifier runs only when the change touches a named Task Size high-risk item, passed as `escalate` (runtime admits its launch on a `Risk: item N` line or sentence, a feature-document task line, or past the context backstop); never for size, a native tier alone, a failed assessment, or the model or effort that wrote the change. An unknown `Receipt-driven development:` line never lowers a tier below `off`. The parent spot check (re-running one reported command before delivery) stays required in every tier. ASSESS takes the writer profile from the runtime-recorded model and effort of the pending mutations for the root; caller `writerModelId`/`writerEffort` are only a fallback when no runtime evidence exists; the writer profile is reported but never adds a verifier. When native reports them, ASSESS also projects `reviewDue`, `reviewDueReason`, `candidate.consumed`, and the native continuation verbatim; relay that continuation unchanged and never rebuild it. A native code review is not a substitute for applicable functional checks: tests, builds, and functional verification such as browser checks for UI changes still run when applicable, and review outcomes never authorize delivery. The change's own focused test and suite run inline.

## Agent escalation (gentle-shell#1494)

When the change touches a Task Size high-risk item, whatever the native tier, pass `"escalate": {"item": <1-6>, "reason": "<one line>"}` in the same assess input: the plan adds the independent verifier only when `escalate` names a Task Size high-risk item; the tool raises the tier to high, keeps the native one as `nativeRisk`, returns `agentEscalation`, and never lowers a tier. Until the installed gentle-ai assess accepts it, the raise binds this verification plan only, not the native review tier.

## Verification proportionality

Before introducing or retaining an auxiliary gate, name the acceptance criterion, concrete threat, or authoritative contract it protects. Without that basis it must not become a delivery blocker. Do not build a framework for a bounded capability probe: use the existing command path and retain its observed result. Auxiliary tooling defects stay within the existing correction bound; they do not justify a new verification project or reset that bound.

When the user warns about overengineering, remove or collapse optional artifacts and checks before continuing. State what was removed, what remains indispensable, and the next application outcome. Keep required functional checks, security controls, and native review authority intact; do not call missing proof a pass or weaken permissions merely to proceed.

## Parallel review protocol (gentle-shell#1731)

1. **Self-review**, required by each writer prompt, in its own session before returning: spec sections by reference (#1713), the request's authorized examples, tests, and typecheck; it fixes and continues (one correction per failing check, a second only if the same check still fails, then `partial`), reporting requirement by requirement. Low and medium risk need nothing else.
2. **Independent verify per unit**, once, after its final self-review (never per worker cycle or retry), in parallel when several finish together, only when that unit is high risk: its Risk line, `assess` over its actual diff or the worker's own `escalate` (high-risk list in Task Size), never inferred from the worker's summary alone. Assess per unit via its work-unit commit (`{"baseRef":"<previous>","committedOnly":true}`) or its own isolated worktree. Inline code over several deliveries of one feature: one verify at the feature's end.
3. **Seam check**: after parallel units finish, one inline full-suite command (the parent spot check) catches seams between units.
4. **Verify handoff**: the whole feature document for context, the assigned unit and its linked `S#` plus affected interactions, the baseline commit, and the probe command forms (tests, CLI, typecheck) for probes on isolated state in a fresh `mktemp -d` scratch copy, never just "read-only"; the runtime removes each subagent's own TMPDIR, which holds that copy; `gentle-ai-verify` holds the checklist. Requirements belonging only to future or unrelated units are out of scope, not unmet; final feature verification covers every `S#`. Resolve every in-scope unmet item before closing the unit; the writer commits its probes as regression tests.
5. **One correction**: verify blockers get one correction batch that fixes every reported blocker, then one re-verify limited to those blockers, never a new full sweep. Blockers still open after that stop as one **Needs your decision**. Advisories never start a correction. A second correction runs automatically only when the recheck shows the same blocker still failing; a new finding never earns one. A `partial` or `blocked` writer report gets only this correction, never an extra verify run beyond the risk tier's verifier; partial, blocked, unavailable, or exhausted proof left after it becomes that one **Needs your decision**.
