---
name: lfcs-pre-grill
description: Phase 0 mandatory grill — runs every LFCS bid through pricing-checklist.md before any pricing starts. Output written to Pre-Pricing-Grill-{date}.md in the job's 02b folder. Pricing aborts on any "TBC" answer.
status: live
created: 2026-05-06
created_by: claude-code-opsman
related:
  - "[[lfcs-standards/pricing-checklist]]"
  - "[[Operations/skills/lfcs-bid-prep-doc/SKILL]]"
  - "[[Operations/skills/lfcs-boq-parse/SKILL]]"
  - "[[_Brain/AB-Test-Tracker]]"
user_invocable: true
---

# SKILL — lfcs-pre-grill

## Purpose

Codifies the Phase 0 Pre-Pricing Exclusion Grill from `lfcs-standards/pricing-checklist.md`. Mandatory before ANY pricing skill (`lfcs-bid-prep-doc`, `lfcs-boq-parse` final write) runs. Captures Rocky's answers to supply-boundary questions, scope-conflict questions, and rate-card-specific questions BEFORE the agent invents assumptions.

Lessons from 2626 (5 revisions) and 2602 (4 A/B rounds): every miss on the grill costs LFCS a revision. Run the grill, get the answers, then price.

## Trigger

- "Build pre-pricing grill for [job#]" / "Run Phase 0 for [job#]" / "Pre-grill [job#]"
- Auto-triggered by `lfcs-project-init` orchestrator after BoQ parse completes
- Auto-triggered by `lfcs-bid-prep-doc` if grill output is missing or incomplete (aborts with redirect to this skill)

## Inputs

- **Job ID** (e.g. `2629`) — required
- **Job folder path** (auto-resolved from job ID via `Jobs/Upcoming/<job>*` glob) — required
- BoQ parsed JSON output from `lfcs-boq-parse` — required (skill aborts if missing)
- 00-brief.md + 00-Bid-Prep.md from job folder — required for context

## Behaviour

1. Resolve job folder. If multiple matches, ask user to disambiguate.
2. Read in order: `00-brief.md`, `00-Bid-Prep.md`, parsed BoQ JSON, RFQ email under `06 - Correspondence/06a - Emails/`.
3. Cross-reference each BoQ line with `lfcs-standards/element-taxonomy.md` to identify any non-canonical elements — flag.
4. Run Phase 0 grill questions from `lfcs-standards/pricing-checklist.md` § Phase 0:
   - Q1 — Supply boundaries per major material (concrete, reo, sand, backfill, pit fixtures, step irons, ERSED, pipe, formwork ply, bituthene, etc.)
   - Q2 — Scope boundary (FRP-install-only vs full-supply-and-install)
   - Q3 — Cranage (LFCS or head contractor)
   - Q4 — Pumping (LFCS or head contractor)
   - Q5 — Survey + setout (LFCS or head contractor)
   - Q6 — ITPs and inspection-hold-points (LFCS-prepared or HC template)
   - Q7 — Working hours (contract window vs LFCS estimating choice — reference §"working-hours" lesson)
   - Q8 — RFQ-vs-BoQ conflicts (list each conflict, get Rocky's call)
5. Each "I don't know" / "TBC" answer is a SHOWSTOPPER. Skill aborts with the list of unanswered Qs and tells caller to surface them in the QS call (see `lfcs-precall-questions`).
6. Write output to:
   ```
   Jobs/Upcoming/<job>/02 - Scope and Pricing/02b - BOQ and Rate Schedules/Pre-Pricing-Grill-{YYYY-MM-DD}.md
   ```
7. Frontmatter: `job`, `date`, `created_by`, `purpose`, `status: signed-off-{date}` once all Qs answered (else `status: open-{date}`).
8. Final step: emit log-event:
   ```bash
   bash scripts/log-event.sh "<agent-id>" "skill_run" "lfcs-pre-grill" "<ok|fail>" "<job> grill {signed-off|open-with-N-tbc}"
   ```
9. Final step: call `lfcs-airtable-sync` (programmatic) with table=Bids, primary=job_id, fields={grill_status, grill_date, grill_path}. Failure non-blocking per LFCS adapter convention.

## Output format

Body structure (template — adapt per job):

```markdown
# Phase 0 — Pre-Pricing Grill — <job> <client>

**Rule:** Pricing does NOT start until every Q below has Rocky's answer.

**Today:** YYYY-MM-DD. **Bid due:** YYYY-MM-DD. **QS call:** YYYY-MM-DD.

**Source baseline:**
- BoQ <filename> — N priceable rows
- RFQ <source> — pasted/linked
- Brief 00-brief.md + Bid Prep 00-Bid-Prep.md + Drawing Index

**RFQ email vs BoQ conflicts already flagged:**
N. <conflict>: <description>. Q-XN below.

## Q1 — Supply boundaries (per major material)
[ ] Concrete: <answer>
[ ] Reinforcement: <answer>
... (full list per pricing-checklist.md)

## Q2 — Scope boundary
- FRP-install-only OR supply-and-install? <answer>

## Q3 — Cranage / Q4 — Pumping / Q5 — Survey / Q6 — ITPs / Q7 — Working hours
... (one section each)

## Q8 — RFQ-vs-BoQ conflicts
- <each conflict + Rocky's answer>

## Sign-off
- Date answered: YYYY-MM-DD
- All Qs answered? [yes|no — list unanswered]
- Signed off by Rocky? [yes|no]
```

## Hard rules

- **No "I'll figure it out" answers.** Each Q gets a literal Rocky answer or it stays TBC and the bid stalls.
- **Don't infer from RFQ literal text alone.** RFQ §1+§3 reading missed Rocky's company convention on 2626; ask explicitly.
- **No fabrication.** If Rocky hasn't answered, write `TBC` literal — never plausible-sounding fiction.
- **Append-only on `_Log.md` and daily note** per AI Team Protocol.
- **Vault markdown is source of truth.** Airtable sync failures don't block grill completion.
- **Regression fixtures:** 2602, 2626, 2629 all have signed-off grill outputs. Compare new grill structure against these fixtures; structural drift = blocking issue.
- **Skill abort condition:** if BoQ parse output missing, abort with: "Run lfcs-boq-parse first."
- **Lesson from B16:** Q7 (working hours) — for `type: price` jobs, "contract working hours" = permitted window NOT obligation. Don't draft "we owe you 1.8× hours" framing.

## Dependencies

- `lfcs-standards/pricing-checklist.md` (canonical Q list — UPDATE this file when a new lesson lands; this skill follows it)
- `lfcs-standards/element-taxonomy.md` (canonical element vocab)
- `lfcs-standards/folder-spec.md` (output destination)
- 2602 / 2626 / 2629 Pre-Pricing-Grill outputs (regression fixtures)
- `lfcs-boq-parse` SKILL output (mandatory upstream)

## Failure modes

| Failure | Detection | Recovery |
|---|---|---|
| BoQ parse missing | Pre-check for parsed JSON | Abort, redirect to `lfcs-boq-parse` |
| Job folder ambiguous | Glob match returns > 1 | Ask user to specify |
| Rocky unavailable to answer | Skill detects no answers after N prompts | Write grill with all TBC, status `open-{date}`, abort caller |
| Output file already exists | Pre-check destination path | Ask: "Regenerate or merge with existing?" — never silently overwrite |
| Element-taxonomy mismatch | Cross-ref BoQ rows | Surface as warning in grill output, don't block |

## Airtable behaviour

| Operation | Field | Notes |
|---|---|---|
| Read | Bids.job_id | Look up existing grill row |
| Write | Bids.grill_status | Set to `signed-off` or `open` |
| Write | Bids.grill_date | YYYY-MM-DD |
| Write | Bids.grill_path | Vault-relative path to grill MD |

Failure: non-blocking. Write to `_System/Conflicts.md` and continue.

## Idempotency

Re-running on same job + same date detects existing output and prompts before overwrite. Re-running on same job + new date creates a new dated file (versioned trail). Multiple grills per job are normal — pre-bid + post-QS-call refinement.
