---
skill: lfcs-sanitisation-verify
version: 1
status: live
model: claude-haiku-4-5-20251001
inputs:
  - sanitised artefact (xlsx path, text, or dict record set)
  - expected_author (operator_of_record)
  - expected_company (default "LF Construction Services Pty Ltd")
outputs:
  - VerificationResult (passed: bool, findings: list[VerificationFinding])
  - _Internal_Sanitisation_Log row updated with layer2_pass + layer2_failures
implementation: HQ-Vault/11_OpsMan_LFCS/Codebase/lfcs-pricing-agent/lib/verify.py
---

# lfcs-sanitisation-verify (Layer 2 of two)

Independent verification step that runs AFTER `lfcs-sanitise-for-external` and
blocks output if any internal field / agent-derivation token is detected.

Per Stage 4 § 2.2.4. **CRITICAL INDEPENDENCE PROPERTIES (do not violate):**

1. This module does NOT import from `sanitise.py`.
2. Maintains its own INDEPENDENT regex set, intentionally re-derived from spec
   (not copied from Layer 1). If patterns drift between the two layers, drift is
   detected here.
3. Reads from output artefact bytes / strings, not from any intermediate state.
4. Unconditional — Layer 1 cannot bypass.
5. Fail-closed — caller MUST delete the target artefact + mark
   `verified_by_human=NEVER` if `passed is False`.

## What gets verified

- No field name starting `_internal_` survives in any record / dict
- No sheet name starting `_Internal_` survives in any xlsx
- No agent-attribution token in cell values, cell comments, frontmatter, or md body:
  - `claude-*`, `cowork-*`, `hermes-*`, `openclaw`, `agent confidence`, `agent rate`
  - `friend-vault`, `[source: ...]`, `_internal_`, `_Internal_`
  - `PLACEHOLDER`, `PENDING DERIVE`
- File metadata (`Author`, `LastModifiedBy`, `Company`) matches expected operator-of-record

## Independence test

The L1 + L2 regex sets share semantic intent (both block agent attribution) but
the patterns themselves are written differently. Specifically:

- L1 uses `\bclaude(?:-code|-opus|-sonnet|-haiku)?` (compact); L2 uses
  `claude[\s\-_]?(?:code|opus|sonnet|haiku)` (loose) — catches L1 misses on
  unusual whitespace/separators.
- L1 strips `[source: friend-vault]` specifically + `[source: ...]` generally;
  L2 does general `[source: ...]` AND a separate `friend[\s\-_]?vault` pattern.
- L1 strips `PLACEHOLDER-*`; L2 strips bare `PLACEHOLDER` (catches PLACEHOLDER without
  the `-` suffix that L1 might miss).

Updating either side without updating the other is detected by the test
fixture suite — synthetic-leak fixtures must fail at L2 even if L1 strip-list
is incomplete.

## Worked example

```python
from lib.verify import verify_xlsx

result = verify_xlsx(
    "02a/2629-Tender-Summary-LFCS-submitted.xlsx",
    expected_author="Liam Fitzgerald",
)
if not result.passed:
    # FAIL CLOSED — DELETE the artefact, log layer2_pass=False, notify operator
    os.remove("02a/2629-Tender-Summary-LFCS-submitted.xlsx")
    raise SanitisationLeakDetected(result.findings)
```

## Test fixtures

- Known-good sanitised artefact (must pass)
- Synthetic leak: `_internal_first_pass_rate` field accidentally surviving (must fail)
- Synthetic leak: cell comment "agent confidence 0.71" surviving (must fail)
- Synthetic leak: file Author = "claude-code-opsman" (must fail)
- Historical 2602 / 2629 / HCB Calc Basis text (must pass for Liam-authored phrases;
  must fail for synthetic agent-attribution patterns) — Test T5 fixture

## Related

- `lfcs-sanitise-for-external` (Layer 1 — runs immediately before this)
