---
skill: lfcs-override-capture
version: 1
status: typed-fallback (voice spike Task 0 deferred 2026-05-07)
model: claude-opus-4-7
inputs:
  - bid_record_id (Airtable Bids rec ID)
  - agent_id (e.g. claude-code-opsman)
  - participants (list of names)
  - per-override: bid_line_item_id, original_rate_ex_gst, override_rate_ex_gst,
    reason_codes (list[str] from 9-domain taxonomy), reviewer_type, reviewer_name,
    free_text_rationale
outputs:
  - Bid Line Item Overrides row (LFCS-Operations base)
  - _Internal_Audit_Trail event row
  - _Internal_Session_Logs row (open on entry; closed on exit)
  - Vault md mirror at _Internal/audit-trail/session-{uuid}.md (cross-job source of truth)
  - Per-job _audit/overrides-log-{date}.md (filtered view)
implementation: HQ-Vault/11_OpsMan_LFCS/Codebase/lfcs-pricing-agent/lib/override_capture.py
---

# lfcs-override-capture

Captures one or more rate/qty overrides during a Rocky+Liam (or +Hus) sanity-check
session. Writes structured Override rows + audit trail + session log + vault mirrors.

## When to use

Whenever a sanity-check session produces an override. The skill must be invoked
BEFORE generating the sanitised submission artefact — the feedback path requires
overrides to be captured for the calibration view + Rate Template proposals to fire.

## Voice vs typed

**Voice path:** deferred until Task 0 spike with Rocky + Hus (Stage 5 spec).
The schema already supports voice (`verbal_capture` checkbox, `verbal_transcript_excerpt`
field on the Override row + `capture_mode = voice` on the Session Log row), so adding
voice later requires no schema change.

**Typed path (this version, v1):** caller invokes `OverrideCaptureSession` programmatically
or via a CLI prompt loop. Each override = one `capture_override()` call.

## Reason code taxonomy (9 domains)

`SCOPE-SHIFT` · `RATE-BASIS` · `PRELIM-VISIBILITY` · `STRUCTURAL-ADD` ·
`STRUCTURAL-DEDUCT` · `POSTURE-MISMATCH` · `BOILERPLATE-CARRY` ·
`PRODUCTIVITY-CALIBRATION` · `LOSS-CATEGORY`

Multi-tag is supported (a single override can tag multiple domains, e.g.,
the 2629 CC→Hus $50K composite gap = `RATE-BASIS + PRELIM-VISIBILITY + SCOPE-SHIFT`).

See `construction-methodology/reason-code-taxonomy.md` for full definitions + examples.

## Failure modes + fallback

- **Airtable unreachable:** captures land in
  `_Internal/audit-trail/pending-overrides-{session}.json` for later flush.
  The skill reports `offline=True` in the session log; downstream sanitised-artefact
  generation should refuse to proceed until pending queue is flushed.
- **Validation error** (unknown reason_code, blank rationale, unknown reviewer_type):
  the `capture_override()` call raises `ValueError` immediately. No partial commit.

## Example

```python
from lib.override_capture import OverrideCaptureSession

with OverrideCaptureSession(
    bid_record_id="recXXXXXXXXXXXXXX",
    agent_id="claude-code-opsman",
    participants=["Rocky", "Liam"],
    per_job_audit_dir=Path("Operations/Jobs/Upcoming/2629 - .../  _audit"),
) as session:
    session.capture_override(
        bid_line_item_id="recYYYYYYYYYYYYYY",
        original_rate_ex_gst=11100.0,
        override_rate_ex_gst=12600.0,
        reason_codes=["PRODUCTIVITY-CALIBRATION"],
        reviewer_type="Trades-Internal-Liam",
        reviewer_name="Liam",
        free_text_rationale="Regular rectangle vs irregular pentagon assumption from 2629.",
    )
```

## Related

- `lfcs-sanitise-for-external` (Layer 1 of confidentiality seam — runs after capture)
- `lfcs-sanitisation-verify` (Layer 2 — independent verification)
- `lfcs-feedback-aggregator` (cron-driven; turns captured overrides into Rate Template
  proposals when diversity criteria pass)
