---
name: lfo-sanity-check-driver
description: Invoke when Phase 3 is sealed (bottom-up first-pass priced take-off complete) AND Rocky says "starting sanity-check" / "open sanity-check" OR autonomous-daemon advances state from `phase-3-sealed` to `phase-4-sanity`. Owns Phase 4 — unquarantines the reverse-engineered envelope from Phase 3.5, computes delta vs bottom-up midpoint, writes the comparison file with one of three outcome flags (inside ±15% / below >15% / above >15%), drafts the OverrideCaptureSession prompt for the worker per `lfcs-pricing` §4.2, monitors override capture for completeness, queues methodology proposals to `_Internal/lessons-learned/proposals-pending.md` per CLAUDE.md §3.3.
model: claude-sonnet-4-6
phase: 4
invoked_by: state transition `phase-3-sealed → phase-4-sanity` OR Rocky-typed trigger
preconditions:
  - Phase 3 sealed (bottom-up priced take-off written + total ex GST captured)
  - Phase 3.5 envelope file exists at `_Internal/quarantined/budget-envelope-{job-id}.md` (OR low-confidence flag logged in session)
  - assumptions log present at `_Internal/assumptions-log-{job-id}.md`
inputs:
  - job_no
  - bottom_up_total_ex_gst (from Phase 3 sealed total)
  - envelope_path (default `_Internal/quarantined/budget-envelope-{job-id}.md`)
  - participants (Rocky + Liam | Rocky + Hus | Rocky-only — drives the override-capture session)
  - capture_mode (typed | voice | mixed)
outputs:
  - `_Internal/budget-envelope-comparison-{job-id}.md` — delta computation + outcome flag
  - drafted OverrideCaptureSession prompt block ready for handoff bus
  - methodology proposals queued in `proposals-pending.md` (Rate Template adjustments / new Common Misses / new Rate Buildup notes)
  - session log appended with override count + net delta_dollars
side_effects:
  - unquarantines envelope file (removes from pricer's path-exclusion patterns)
  - writes to handoff bus (next prompt to worker)
  - never auto-applies methodology proposals
authored_by: claude-code-orchestrator
created: 2026-05-10
---

# lfo-sanity-check-driver

Phase 4 owner. Currently Phase 4 is an orphan — only inlined in `lfo-bid-lifecycle` SKILL.md:104-111. This skill encapsulates it as a standalone unit so Phase 4 has a clear contract, single source of truth, and reusable invocation.

## Why this exists

Phase 4 has three distinct responsibilities — each non-trivial:
1. **Envelope reveal + comparison** — unquarantine the Phase 3.5 envelope, compute delta vs bottom-up, classify outcome
2. **Override-capture session orchestration** — draft the worker prompt, monitor responses
3. **Methodology proposal queueing** — pull patterns from override reasons, queue for Rocky triage

Without a dedicated skill, the lfo-bid-lifecycle inline version (a) duplicates content if Phase 4 is invoked outside lifecycle, (b) lacks the granular procedure for envelope-comparison classification logic, (c) doesn't formalise the override → proposal pipeline.

## Procedure

### 1. Verify envelope state

Read session log for Phase 3.5 outcome:
- If `envelope_confidence < 60` was logged → skip envelope reveal; sanity-check proceeds without comparison signal. Surface to Rocky: "Phase 3.5 returned confidence <60; sanity-check opens without envelope comparison."
- If envelope file exists at `_Internal/quarantined/budget-envelope-{job-id}.md` → proceed to step 2.
- If envelope file missing AND no low-confidence flag → STOP. Surface to Rocky: "Phase 3.5 didn't run. Run before Phase 4."

### 2. Unquarantine envelope

Remove `_Internal/quarantined/budget-envelope-{job-id}.md` from pricer's path-exclusion patterns. The envelope is now readable in this orchestrator session (still NOT readable to worker until step 4 explicit relay).

### 3. Compute delta + classify outcome

Read envelope file frontmatter:
- `envelope_low_aud`, `envelope_high_aud`, `confidence`

Read bottom-up total from session log or Bid record `_internal_first_pass_total_ex_gst`.

Compute:
```
envelope_mid = (envelope_low + envelope_high) / 2
delta_pct = (bottom_up - envelope_mid) / envelope_mid * 100
delta_aud = bottom_up - envelope_mid
```

Classify outcome:

| Delta range | Outcome flag | Recommendation |
|---|---|---|
| `\|delta_pct\| ≤ 15` | **Inside envelope** | Confident submission. Bottom-up consistent with reverse-engineered HC allocation post-deductions. |
| `delta_pct < -15` | **Bottom-up below envelope (under)** | Potential underprice OR HC margin pad larger than assumed. Review labour rates, productivity assumptions, exclusion deductions before submission. |
| `delta_pct > +15` | **Bottom-up above envelope (over)** | Potential overprice OR HC has under-allocated to FRP package. Review scope assumptions, complexity factors, contingency. |

### 4. Write comparison file

`_Internal/budget-envelope-comparison-{job-id}.md`:

```markdown
---
job_no: {job-id}
session_id: {orchestrator-session}
created: {iso-now}
agent: lfcs-orchestrator (lfo-sanity-check-driver)
purpose: Phase 4 envelope reveal + delta classification
---

# Envelope Comparison — Job {job-id}

## Inputs
- Bottom-up sealed total: ${bottom_up:,.0f} ex GST (from Phase 3 sealed)
- Envelope (from Phase 3.5): ${envelope_low:,.0f} – ${envelope_high:,.0f} ex GST
- Envelope mid: ${envelope_mid:,.0f}
- Envelope confidence: {N}%

## Delta
- delta_pct: {±N}%
- delta_aud: ${delta_aud:,.0f}

## Outcome
**{outcome_flag}**

{recommendation prose}

## Drill-down (for sanity-check session)
- Largest line items by direct $: {top-5 from bottom-up}
- Largest exclusion deductions in envelope: {top-3 from envelope file}
- Methodology rows that drove top-3 lines: {list with confidence}
```

### 5. Surface to Rocky

Use `AskUserQuestion` with summary:
> "Sanity-check open. Bottom-up ${bottom_up:,.0f}; envelope ${envelope_low:,.0f}–${envelope_high:,.0f}; delta {±N}%. Outcome: {flag}. Open envelope-comparison file + start override-capture session?"

Allow Rocky to: proceed (run override capture) | hold (review comparison first) | abort (envelope is wrong; re-run Phase 3.5).

### 6. Draft OverrideCaptureSession worker prompt

If Rocky proceeds, invoke `lfo-prompt-pricing` with `step=sanity-check-open`. The prompt template (per `lfcs-pricing` §4.2) includes:

```markdown
{INTAKE-ENVELOPE — re-used from sealed Phase 1}

Open OverrideCaptureSession with:
- bid_record_id: {id}
- agent_id: lfcs-pricing
- participants: {Rocky + Liam OR Rocky + Hus OR Rocky-only}
- capture_mode: {typed | voice | mixed}

Display the bid line items table side-by-side. Per line: original_rate_ex_gst, qty, unit, complexity_factors, source_methodology_template, original_qty.

Capture every override via `session.capture_override(...)`:
- bid_line_item_id, original_rate, override_rate
- reason_codes (1-3 from 9 domains)
- reviewer_type (Trades-Internal-Rocky / Trades-Internal-Liam / Trades-Internal-Hasibul)
- reviewer_name
- free_text_rationale (1-3 sentences — REQUIRED)

Each capture writes Bid Line Item Overrides + _Internal_Audit_Trail + session-{uuid}.md + per-job _audit/overrides-log-{date}.md.

On session close: stamp ended_at + write transcript_summary.
```

Relay via `lfo-handoff-watcher` write-mode to `orch-to-pricer.md`.

### 7. Monitor override capture

While the worker runs the override session:

- Every pricer-to-orch.md update with new override row → run `lfo-gap-watch` G5 ("override missing reason_codes") on the row
- If G5 fires → re-prompt the worker (correction inline)
- Track running totals: override_count, net delta_dollars

### 8. On worker session close

- Worker writes `transcript_summary` to BCS row + session log
- Orchestrator reads the summary
- Drafts a one-paragraph session summary in `_Internal/orchestrator-sessions/session-{uuid}.md` under `## Phase 4 — sanity-check + overrides`
- Captures: override_count, net_delta_dollars, top-3 reason_codes, any Rate Template adjustment proposals, any new Common Misses Patterns

### 9. Queue methodology proposals

For each pattern in the override capture:

- **Rate Template adjustment proposal:** if a row was overridden with the same direction (up/down) by 2+ reviewers OR delta exceeded 25% → append to `_Internal/lessons-learned/proposals-pending.md` under `## Methodology proposals`:
  ```markdown
  ### Rate-Template-{template_id} adjustment ({date})
  **Source:** session {uuid}, bid {job_no}, line {item_id}
  **Current base_rate_aud:** ${X}
  **Proposed adjustment:** ${X} → ${Y} (override evidence)
  **Reason codes:** {list}
  **Reviewer:** {names}
  **Free-text rationale:** {snippet}
  **Status:** pending
  ```

- **New Common Misses Pattern:** if a reason_code combination repeats across 2+ overrides on the same line type → propose new pattern. Same proposal format.

Per CLAUDE.md §3.3 — proposals stay as proposals. Rocky triages.

### 10. Set state

`state.json.current_phase = phase-4-sanity-complete`. Phase 5 (blind comparison) opens if applicable; otherwise Phase 6 (submission gate) opens.

## Failure modes

- **Worker override session never completes (silent or errors):** surface to Rocky after 5 min; capture partial overrides; flag in session log.
- **Override row count is zero:** surface to Rocky — either the worker didn't capture (skill error) or Rocky team accepted bottom-up as-is (legitimate). Don't auto-classify.
- **Envelope unquarantine fails (file deleted by user):** STOP, surface, ask Rocky to re-run Phase 3.5 OR proceed without envelope.
- **Methodology proposal queue >20 unresolved (per CLAUDE.md §10):** STOP queueing. Surface to Rocky for triage.

## Notes

- Phase 4 is where pricing methodology learns. Most lessons emerge here. The proposal queue is the long-term system memory.
- The 15% inside-band threshold is calibrated; review after 5 bids per `lesson-2026-05-08-bid-lifecycle.md` calibration to-do.
- Override-capture transcript_summary is the single most important artefact for `lfo-gap-analyse` standing-context completeness audit. Keep it complete.
