---
name: deft-directive-build
description: >-
  Build a project from scope xBRIEFs following Deft Directive framework
  standards. Use after deft-directive-setup has generated the project
  definition, or when the user has story xBRIEFs in xbrief/active/ ready to
  implement. Handles scaffolding, implementation, testing, and quality checks
  phase by phase.
---
<!-- AUTO-GENERATED by task packs:render -- DO NOT EDIT MANUALLY -->
<!-- Purpose: rendered skill -->
<!-- Source of truth: packs/skills/skills-pack-0.1.json -->
<!-- Regenerate with: task packs:render -->
<!-- Edit the source, not this file. Slice instead of loading every SKILL.md: task packs:slice skills by-trigger --trigger <kw> (or list) -->

# Deft Directive Build

Implements a project from its scope xBRIEFs following Deft Directive standards.

Legend (from RFC2119): !=MUST, ~=SHOULD, ≉=SHOULD NOT, ⊗=MUST NOT, ?=MAY.

## When to Use

- After `deft-directive-setup` completes and generates `PROJECT-DEFINITION.xbrief.json`
- User says "build this", "implement the spec", or "start building"
- Resuming a partially-built project that has story xBRIEFs in `xbrief/active/`

## Ordered-plan / cohort exhaustion (#2402)

## Multi-scope turn/cache budget (epic #3009)

Multi-scope greenfield (app-bank pins, N story scopes) multiplies agent turns when ceremony, promote, check, and render are re-run per scope. Apply the following after offline seed.

### Offline seed vs implement phase (#3010)

! Distinguish **offline seed** (operator or harness already ran `directive init` / deposit, pin-copied scopes into `xbrief/proposed/`, and recorded session ritual) from the **agent implement phase**.

! When seed + session ritual are already complete for the engagement:
- ⊗ Run `directive init` again
- ⊗ Run full cold `session:start` unless hooks deny writes and recovery is required
- ⊗ Run `directive migrate` or re-copy scopes already present
- ! Prefer recovery via `session:ready` (or re-arm) when PreToolUse denies — not full re-init
- ! Documented consumer/harness contract: seed is done once; implement agents only activate+implement

### Batch promote; one active implement (#3011)

! For a multi-scope pin, batch-stage scopes with `task scope:promote -- --batch` (all `proposed/`) or `task scope:promote -- --batch <path>…`.
! Implement path remains **one** `scope:activate` + implement at a time — no multi-active write fence.
! When pin order is known, do **not** re-list the entire lifecycle tree every scope; walk the known ordered list.
⊗ Activate all scopes at once or drop the one-active-scope / story-ready stack.

### Quality check once at end of multi-scope batch (#3012)

! On an approved multi-scope batch (operator-approved multi-story branch, swarm cohort, or pin walk): run the merge chokepoint **once at the end of the batch** (or after the last scope), not after every scope — prefer `deft check`; if the CLI is missing, use the tree-correct task form (`task deft:check` on include-only consumers; `task check` in framework source). Do not run both.
! Exception: if the last full check **failed**, fix loops MAY re-run check until green.
! Pre-PR / merge-ready gates remain end-of-unit — this does not weaken them.
! Iteration lane (affected tests / `verify:forward-coverage` / `coverage:hotspots`) still applies **per scope** during implementation (#1704).
⊗ Spam full `directive check` / `task check` after every scope when the batch is still mid-flight and the last merge-chokepoint check was green.

### One-shot project:render (#3013)

! Greenfield init seeds a minimal render-ready `PROJECT-DEFINITION`. Treat `task project:render` as a **refresh of items from lifecycle folders**, not multi-turn identity research.
⊗ Invent project identity across many turns when seed already stamped the skeleton.


! When processing an approved multi-story cohort or an active ordered-plan sequence, stop after the final approved entry. Do not promote or dispatch adjacent stories from queue intuition. Continuation language advances only within the approved order; skill-chaining is non-authorizing.

## Step 0 -- Implementation Preflight (#810)

- ! Before starting any new implementation story or switching from one story to another, MUST run `git status --short --branch`.
- ! If the working tree is dirty, MUST stop and summarize the current branch, modified/untracked files, and whether the changes appear related to the target story. Ask the operator to choose one path: commit existing work, stash existing work, include existing work in the current story, or stop.
- ⊗ Begin a new story while unrelated dirty work is present without explicit operator approval.
- ! Resolve exactly one target story xBRIEF path by default. One story is the default implementation unit for this skill; if the user asks for a phase/epic, decompose or ask which story to start.
- ! Batching multiple stories in one branch/PR requires explicit operator approval and a short rationale recorded in the handoff.
- ! **Swarm-cohort dispatch carve-out**: when this skill is invoked as part of a swarm cohort allocated by `skills/deft-directive-swarm/SKILL.md`, the approved Phase 5 allocation plan satisfies the "explicit operator approval and short rationale recorded in the handoff" requirement above -- the dispatched xBRIEF paths and allocation rationale ARE the consent token. Process each assigned story sequentially under the checkpoint-commit + `task scope:complete` discipline below. Do NOT re-prompt the parent for batching approval mid-cohort -- the all-or-nothing dispatch envelope rule (`AGENTS.md` `## Multi-agent orchestration discipline (#954)`) forbids mid-scope user-approval gates.
- ! **Structured consent-token recognition (#1378)**: the canonical recognition path for the carve-out above is the structured `## Allocation context` section of the dispatch envelope (the frozen schema in `templates/agent-prompt-preamble.md`, Story A of #1378). When that section reports `dispatch_kind: swarm-cohort` with a non-null `allocation_plan_id` AND a non-null `batching_rationale`, the consent token is satisfied mechanically -- read `cohort_vbriefs` as the authoritative file boundary and process each entry sequentially under the checkpoint-commit + `task scope:complete` discipline below, without re-prompting the parent for batching approval mid-cohort. When the `## Allocation context` section is ABSENT (pre-#1378 dispatches, solo-interactive sessions), fall back to the #1371 prose carve-out immediately above -- the prose carve-out remains the recognition path of record for un-elevated envelopes.
- ! **Within a cohort, between stories**: the working tree MUST be clean after each story's checkpoint commit + `task scope:complete`. If `git status --short` shows uncommitted state between stories (e.g. a missed `task scope:complete` move, an unstaged file from the prior story), checkpoint-commit it and proceed -- do NOT pause to ask the operator. The dirty-tree "ask the operator" branch above applies only at the FIRST story-start of a fresh branch, where uncommitted operator work might legitimately exist.
- ! If the target story is in `xbrief/proposed/`, run `task scope:promote -- <path>` first (or `task scope:promote -- --batch` for a multi-scope pin — #3011); if it is in `xbrief/pending/`, run `task scope:activate -- <path>`. After activation, update the path to the active-file location before preflight.
- ! **Effort estimate gate (#1581):** before `task scope:activate` / `task vbrief:activate`, scan `plan.items` (including nested `items` / `subItems`) for `effort`. Time anchors: `S` <2h, `M` half-day (2-4h), `L` 1-2 days, `XL` needs breakdown. The activate path fails closed while any item still has `effort: "XL"` — break XL work into S/M/L items (or re-estimate) first. Omitted `effort` remains valid (field is optional). Plan-item effort is **post-planning** authority (confirms/corrects intake estimates); it is **not** session-start ritual input — ceremony depth (#3214) uses two-stage rapid→escalate, not a required plan-item read at cold start. Headless: no operator confirm. Depth: `vbrief/vbrief.md` § Effort estimate.
- ⊗ Activate a scope that still carries plan items with `effort: "XL"` — XL means "not ready to start" until broken down (#1581).
- ⊗ Require plan-item `effort` to choose session-start ritual depth — estimates do not exist until after planning (#1581 / #3214).
- ! Before any code-writing tool call -- the first scaffold edit, the first `task` invocation that mutates files, or any `start_agent` dispatch that will implement scope -- MUST run `task xbrief:preflight -- <active-story-path>` (the structural intent gate; the same invocation works whether deft is the project root or installed as a `deft/` subdirectory).

The gate exits 0 only when the candidate xBRIEF lives in `xbrief/active/` AND `plan.status == "running"`. Any other state (pending/, proposed/, completed/, active/-with-non-running-status, malformed JSON, missing keys) exits 1 with an actionable redirect to `task xbrief:activate <path>`.

- ! A non-zero exit MUST halt the skill. Surface the helper's stderr message verbatim to the user; do NOT proceed to USER.md Gate, File Reading, or any later phase.
- ! Use canonical lifecycle tasks to satisfy this gate: `task scope:promote -- <path>` for proposed stories, `task scope:activate -- <path>` for pending stories, and the helper's idempotent companion `task xbrief:activate <path>` only when following the preflight redirect directly. Manual lifecycle moves bypass the activation contract -- use the task.
- ⊗ Infer implementation intent from lifecycle vocabulary ("do the full PR process", "start the work", "poller agents"), branching language, or workflow shape. Workflow-shape vocabulary is NOT authorization to spawn an implementation agent (#810 surfacing event).
- ⊗ Skip this preflight because the user said "yes", "go", or "proceed" -- affirmative continuation phrases are NOT implementation authorization unless the prior turn explicitly proposed implementation. When intent is ambiguous, ask one targeted question before invoking the gate.

## Platform Detection

! Before resolving any config paths, detect the host OS from your environment context:

| Platform           | USER.md default path                                              |
|--------------------|-------------------------------------------------------------------|
| Windows            | `%APPDATA%\deft\USER.md` (e.g. `C:\Users\{user}\AppData\Roaming\deft\USER.md`) |
| Unix (macOS/Linux) | `~/.config/deft/USER.md`                                          |

- ! If `$DEFT_USER_PATH` is set, it takes precedence on any platform

## Pre-Cutover Detection Guard

! Before proceeding with any build step, detect whether the project uses the pre-v0.20 document model **or was generated by a strategy that emitted non-conformant v0.20 output shape** (the root cause of most "build fails immediately after spec" complaints in #1166). Redirect or block with the precise remediation.

### Detection Criteria

A project is **pre-cutover** if ANY of the following are true. This prose mirrors the executable helper in `task migrate:preflight`; when in doubt, the helper is canonical.

1. `SPECIFICATION.md` exists and is neither a deprecation redirect nor a current generated spec export. A current generated spec export contains `<!-- Purpose: rendered specification -->`, all five lifecycle folders exist, and its `<!-- Source of truth: ... -->` marker names an authority artifact that exists: either `xbrief/specification.xbrief.json` for full-spec compatibility or `xbrief/PROJECT-DEFINITION.xbrief.json` for greenfield authority (legacy `vbrief/...` aliases remain read-compatible).
2. `PROJECT.md` exists and contains neither the legacy `<!-- deft:deprecated-redirect -->` sentinel NOR the current `Purpose: deprecation redirect` canonical-banner marker (real content, not a deprecation redirect)
3. `xbrief/specification.xbrief.json` exists but the lifecycle folders (`xbrief/proposed/`, `xbrief/pending/`, `xbrief/active/`, `xbrief/completed/`, `xbrief/cancelled/`) do NOT exist
4. Strategy output shape violations (run `task verify-strategy-output` -- the canonical gate for source and consumer installs):
   - Any scope xBRIEF under `xbrief/proposed/` (or other lifecycle dirs) lacks the required `YYYY-MM-DD-` date prefix in its filename (e.g. bare `scaffold.xbrief.json`).
   - `xbrief/PROJECT-DEFINITION.xbrief.json` is missing.
   - `xbrief/specification.xbrief.json` exists as a legacy dual-write in a user-generated project. This is tolerated only for the framework source tree or a complete post-cutover full-spec consumer where all lifecycle folders exist and `SPECIFICATION.md` is rendered from `xbrief/specification.xbrief.json`.

### Action on Detection

! If pre-cutover or strategy-nonconformant state is detected, **stop immediately** and display an actionable message that cites the exact validator:

> "This project was generated with pre-v0.20 or non-conformant strategy output. Run the deterministic validator and follow its remediation: `task verify-strategy-output` (works in source and after `deft` package install). For document-model migration, follow UPGRADING.md § Frozen pre-v0.20 document-model migration (#2068): pin v0.59.0, then run `task migrate:vbrief` from that payload. Otherwise `task project:render` / strategy re-run as indicated."

! Include specific details about what was detected (the validator output is authoritative):

- Legacy specification.xbrief.json or missing lifecycle folders: "Follow the frozen v0.59.0 migrator path (#2068) or run `task migrate:preflight` for current-release guidance"
- Non-date-prefixed xBRIEFs: "Re-run the emitting strategy after the v0.20 migrations (#1166 s1+s2+...) or manually rename files to `YYYY-MM-DD-<slug>.xbrief.json` and `task scope:promote`"
- Missing `PROJECT-DEFINITION.xbrief.json`: "Run `task project:render` to generate the project definition"
- `SPECIFICATION.md` / `PROJECT.md` without sentinel: the classic pre-cutover messages
- Scope xBRIEF in wrong folder: "Status is '{status}' but file is in {folder}/ -- run `task scope:activate <file>` to fix"

! After the validator reports clean, re-run this guard before continuing.

⊗ Proceed with build when pre-cutover or strategy-nonconformant artifacts are detected -- always redirect to the frozen migration path first (or run the validator) and surface the exact remediation.
⊗ Silently ignore these artifacts or guess at fixes -- the validator (wired into `task check` and this guard) is the deterministic gate.

## USER.md Gate

! Before proceeding, verify USER.md exists at the platform-appropriate path
(resolved via Platform Detection above, or `$DEFT_USER_PATH` if set).

- ! If USER.md is not found: inform the user and redirect to `deft-directive-setup`
  Phase 1 before continuing -- do not proceed without user preferences
- ! Once USER.md exists, continue with the Cost Phase Gate below

### Forge-outage drop-back (#3422)

! On attributed platform outage or repeated REST 429/502/503 during YOLO / through-merge implement: drop GitHub I/O, report once to the human in chat, and re-probe on `plan.policy.forgeOutageRetryMinutes` (default **30**; USER.md Personal wins; min 5; `task policy:show --field=forgeOutageRetryMinutes`). Local edit/test/commit MAY continue. Depth: [`scm/github.md`](../../scm/github.md) § #3180 / #3422. Complements #3167 / #3180.

⊗ Tight retry, empty-commit thrash, or sending the human to github.com as the only remediation.

## Cost Phase Gate (#739)

! Before proceeding to File Reading, verify the project has gone through the
pre-build cost & budget transparency phase from `skills/deft-directive-cost/SKILL.md`.
This closes the adoption-blocker surfaced by issue #739 (refs #151 umbrella) where
users finished the spec flow and stopped at build because deft offered no cost
signal.

### Detection

- ! Check for `COST-ESTIMATE.md` in the project root.
- ! Check that the file contains a recorded decision (the **Decision recorded**
  block populated with one of: `build`, `rescope`, `no-build`, `skip`).
- ! For `skip`, `rescope`, or `no-build` decisions: the **Reason** field MUST be
  populated (one or two sentences in plain language). A skip with no reason
  recorded is treated the same as no decision.

### Action

- ! If `COST-ESTIMATE.md` is missing OR the **Decision recorded** block is
  unpopulated OR a `skip`/`rescope`/`no-build` decision has no reason recorded:
  stop immediately and redirect the user:

  > "This project has not gone through the pre-build cost & budget transparency
  > phase. Run `skills/deft-directive-cost/SKILL.md` to produce a plain-English
  > `COST-ESTIMATE.md`, then re-run the build skill once the user has chosen
  > build / rescope / no-build / skip(+reason)."

- ! On a `build` or `skip` decision: continue with File Reading below.
- ! On a `rescope` decision: stop and redirect the user back to spec edits
  (chain to `skills/deft-directive-refinement/SKILL.md` to pull spec scope
  back, or the interview), then re-run `skills/deft-directive-cost/SKILL.md`
  before re-attempting build.
- ! On a `no-build` decision: stop and exit; do NOT proceed to File Reading.
  The user has explicitly stopped the project at the cost phase.
- ⊗ Proceed to File Reading or any subsequent phase when `COST-ESTIMATE.md` is
  missing, when the decision is unpopulated, or when a skip / rescope / no-build
  decision has no reason recorded.
- ⊗ Treat a `rescope` or `no-build` decision as if it were a `build` -- the
  build skill MUST honor the recorded decision.

## File Reading

- ! Read in order, lazy load:
  1. `./xbrief/active/` -- scope xBRIEFs for work items to build (required)
  2. `./xbrief/PROJECT-DEFINITION.xbrief.json` -- project identity, tech stack, architecture
  3. `./.planning/codebase/MAP.md` -- generated codebase orientation projection, if present (advisory)
  4. USER.md at the platform-appropriate path (see Platform Detection) -- Personal section is highest precedence; Defaults are fallback
  5. `deft/main.md` -- framework guidelines
  6. `deft/coding/coding.md` -- coding standards
  7. `deft/coding/testing.md` -- testing requirements
  8. `deft/coding/toolchain.md` -- toolchain validation rules
  9. `deft/languages/{language}.md` -- only for languages this project uses
- ~ If the MAP is absent or may be stale and the current scope needs broad codebase orientation, run `task codebase:map` and `task verify:codebase-map-fresh` when those commands resolve. Treat absence/staleness as advisory unless the task edits `plan.architecture.codeStructure`, a configured provider artifact, or the generated MAP itself.
- ! Treat `plan.architecture.codeStructure` and selected provider artifacts as authoritative. The MAP is a generated projection.
- ⊗ Read all language/interface/tool files upfront
- ⊗ Hand-edit `.planning/codebase/MAP.md` or block unrelated implementation solely because the MAP is stale or absent

## Rule Precedence

```
USER.md Personal                  <- HIGHEST (name, custom rules -- always wins)
PROJECT-DEFINITION.xbrief.json   <- Project-specific (tech stack, architecture, config)
USER.md Defaults                  <- Fallback defaults (used when PROJECT-DEFINITION doesn't specify)
{language}.md                     <- Language standards
coding.md                         <- General coding
main.md                           <- Framework defaults
Scope xBRIEFs                     <- LOWEST
```

- ! USER.md Personal section always wins over any other file
- ! For project-scoped settings, PROJECT-DEFINITION.xbrief.json overrides USER.md Defaults

## Change Lifecycle Gate

! Before any implementation that touches 3+ files, verify that a `/deft:change <name>` proposal exists and has been confirmed by the user:

- ! Check `history/changes/` for an active `proposal.xbrief.json` matching this work
- ! If no proposal exists: propose `/deft:change <name>` and present the change name for explicit confirmation (e.g. "Confirm? yes/no")
- ! The user must reply with an affirmative (`yes`, `confirmed`, `approve`) — a general 'proceed', 'do it', or 'go ahead' does NOT satisfy this gate
- ? For solo projects: this gate is RECOMMENDED but not mandatory for changes fully covered by `task check`; it remains mandatory for cross-cutting, architectural, or high-risk changes
- ⊗ Skip this gate because the user has already said "proceed" or "go ahead"

## Build Process

All xBRIEFs (including those read from `xbrief/active/` and any new xBRIEFs this skill emits) MUST use `"xBRIEFInfo": { "version": "0.8" }`. Legacy 0.6 is read-accepted until `deft migrate:xbrief`. The validator accepts both; new writes are 0.8 only (see [`../../conventions/references.md`](../../conventions/references.md)).

### Step 1: Understand the Scope

- ! Read story xBRIEFs from `xbrief/active/` and `PROJECT-DEFINITION.xbrief.json`
- ! Identify phases, dependencies, starting point from scope xBRIEF acceptance criteria
- ~ Use `.planning/codebase/MAP.md`, when present, to orient broad codebase scanning. If the MAP conflicts with current code or canonical metadata, surface the drift and trust `plan.architecture.codeStructure` / provider artifacts plus the working tree over generated prose.
- ! When scanning the existing codebase during scope understanding, MUST surface any contradicting patterns (two error-handling shapes, two state-management approaches, two naming conventions, etc.) before implementation begins -- apply `coding/hygiene.md` `## Surface Conflicts: Pick One, Explain, Flag the Other (#1005)` and choose ONE pattern (more recent OR more tested), explain the choice in the scope summary, and flag the other for cleanup
- ⊗ Begin implementation against an averaged blend of two contradicting patterns -- "average code that satisfies both rules is the worst code" (#1005)
- ! Present brief summary to user:

> "Here's what I see: {N} story xBRIEFs in active/. I'll start with {name}. Ready?"

### Step 2: Verify Toolchain

- ! Before any implementation, verify all tools required by this project are installed and functional — see `deft/coding/toolchain.md` for full rules
- ! At minimum: confirm task runner (`task --version`), language compiler/runtime, and platform SDK (if applicable) are available
- ! If any required tool is missing, stop and report — do not proceed to Step 3
- ⊗ Assume tools are available because the spec references them

### Gate throughput — iteration fast lane vs merge chokepoint (#1704)

> **Invariant:** every change MUST pass the full gate at least once before merge. Iteration MAY use a cheaper proxy; the merge chokepoint MUST NOT be skipped.

- ! **Iteration lane (agents + humans):** during implementation commits, use affected/static gates — targeted tests on changed paths (`vitest run --coverage <paths>` or project equivalent), static `verify:*` gates relevant to touched files, and `task coverage:hotspots` / `task verify:forward-coverage` — NOT full `task check` on every commit.
- ! **Merge chokepoint:** prefer `deft check` once before push/PR (and again when CI merge gate runs). If the CLI is missing, use the tree-correct task form (`task deft:check` on include-only consumers; `task check` / `task check:merge` in framework source). These are one gate, not two sequential runs. Do not add a fourth probe (#2893 / #4379). A bare `task check` miss on an include-only consumer is not "gate unavailable". Pre-PR skill exit and review-cycle fix batches still require a green full gate.
- ! **Escape-rate safety (#1703 Tier-1):** before tightening fast-lane defaults fleet-wide, consult `#1703` measurement — `task eval:health` (Tier 0) and Tier-1 session telemetry (`helped/crud-metrics.jsonl` via instrumented CRUD / workflow metrics). Do NOT invent a separate fast-lane escape-rate surface (#1704 LockedDecisions).
- ~ **In-engine incrementality (#1713):** content-hash task cache and runner-delegated affected selection are sibling work — not required for this policy face.
- ⊗ Run full `task check` on every iteration commit when a cheaper proxy suffices — reserve the full gate for PR/merge (#1704).
- ⊗ Skip the merge chokepoint because the iteration lane passed — the fast lane is convenience only.

**Cost model (swarm-heavy path):** moves from roughly `O(commits × full-gate)` toward `O(merges × full-gate) + O(iterations × cheap-proxy)` when workers iterate with affected/static gates and run full `task check` only at PR/merge.

### Dual stop — multi-iteration implement and pre-PR loops (#2442)

Multi-iteration implement-fix and pre-PR polish loops MUST carry **both** a success stop and a failure/budget stop (`main.md` `## Dual Stop Rule (#2442)`). Single-turn edits and one-shot probes are exempt.

**Defaults for this skill (override only with an explicit operator envelope or xBRIEF field):**

| Loop class | Success stop | Default failure stop |
|------------|--------------|----------------------|
| Implement / quality fix (tests, lint, typecheck, coverage, AC) | Affected/static gates green for the change; AC met | **max 5** fix iterations **or** **3** consecutive identical outcomes (same failing command + same primary error class) with no material code/config change |
| Pre-PR polish (`deft-directive-pre-pr` Read-Write-Lint-Diff) | Full pass with zero further edits | **max 3** polish passes **or** **2** consecutive no-diff / same-diff outcomes |
| Full `deft check` re-run | tree-correct full gate green after a red merge chokepoint or a new commit | Counts toward the implement/quality fix envelope above (do not open a separate unbounded check-retry loop) |

- ! Re-run the full gate (prefer `deft check`; else the tree-correct task form) only after a red merge chokepoint or a new commit. Do not run both.

**On failure stop:**

- ! Halt the loop. Surface an **operator-visible halt report** with: (1) iterations attempted and which stop fired (max-iter / no-progress / budget), (2) commands and primary failure fingerprints tried, (3) what is still red or missing, (4) the human decision needed (unblock dependency, rescope AC, waive with audit, abandon).
- ! Prefer a structured `BLOCKED:` terminal (preamble §11 / #2843) when exiting a drive-to:merge-ready or parent-dispatched unit early because the envelope is exhausted.
- ⊗ Continue "one more fix" after the envelope is exhausted.
- ⊗ Reset the counter by opening a new commit, rewording the same change, or swapping workers while the same failure class remains.


### Budget-aware effort - bank the pass before deepening (#3266)

When a hard turn or cost budget is detectable (session:start `effort_budget` / env `DEFT_MAX_TURNS` / `DEFT_MAX_BUDGET` / host descriptor #1461), size effort to the **stated** acceptance bar first. This is the success-side analog of dual-stop (#2442): dual-stop stops thrash on failure; bank-the-pass stops budget exhaustion on over-deepening.

- ! At implement start, read the session effort-budget signal (`task session:start` lines or JSON `effort_budget`, or env). When `posture=hard-capped`, treat the run as budget-constrained.
- ! **Bank the pass first:** satisfy stated acceptance criteria (xBRIEF items / issue AC / official checker) and produce the passing artifact **before** any self-imposed deeper verification suite that exceeds the stated bar.
- ! Only with **remaining** budget after the stated pass, extend verification depth. Never deepen past the point where a found defect could not also be fixed within budget (default reserve: enough turns/cost for one fix batch).
- ! Self-verification scope scales with remaining budget - prefer the official/stated checks under a tight cap.
- ! When deepening is skipped for budget, MUST say so in the run summary / handoff (`deepening_skipped=true` + reason) - fail-loud (#1006). Use `formatDeepeningSkippedNote` semantics from `packages/core/src/session/effort-budget.ts`.
- ~ When no hard budget is detected (`posture=unbounded`), normal dual-stop defaults still apply; bank-the-pass is optional discipline, not a license to skip stated AC.
- ⊗ Exhaust the turn/cost budget on self-imposed gold-plating after the stated bar is already within reach (#3266).
- ⊗ Silently skip deepening without naming it, or silently gold-plate under a hard cap (#1006 / #3266).
- ⊗ Treat bank-the-pass as permission to ship without meeting stated AC - stated AC remains the success stop.

Core helper: `packages/core/src/session/effort-budget.ts` (`detectHardEffortBudget`, `recommendVerificationDepth`). Composes #2442, #1581, #3214, #1006.
**Enforcement note:** skill defaults are behavioral. Durable delivery/acceptance circuit-breaker: **#3143** `packages/core/src/delivery-attempt/` (`evaluatePreDispatch`, `.deft/delivery-attempts/`). Docs: `docs/delivery-attempt.md`. Route delivery/acceptance automatic retries through that gate; do not invent a parallel ledger in this skill.

### AC-pass banking checkpoint - finalize on green (#3285)

Sharpens #3266: the **first** moment stated/official acceptance criteria pass is a **banking checkpoint**, not a license to keep spending the turn budget on self-imposed depth.

- ! When stated acceptance criteria first pass (`task verify:ac` / product-first done-gate #3284 / official checker), the **next** action is **FINALIZE**: checkpoint-commit the green state and record the bank (durable under `.deft/cache/ac-pass-banks/`; optional run-summary line when `DEFT_RUN_SUMMARY_PATH` is set).
- ! **Deepening after the bank requires surplus budget.** Self-imposed extra verification, refactors, or polish are permitted only when remaining budget meets `plan.policy.acPassBanking.surplusThreshold` (default **0.2** = 20% of max turns/cost still remaining) **and** the absolute reserve from #3266. Env override: `DEFT_AC_PASS_SURPLUS_THRESHOLD`.
- ! Deepening, when allowed, happens **on top of** the committed checkpoint so a failed experiment can revert to banked green.
- ! **Post-bank discoveries are reported, not chased** when surplus is insufficient: file a note/issue in the deliverable for out-of-scope defects unless they **regress stated AC** (then fix-regression). Finding beyond the bar is a win; thrashing a dying budget into a zero is the failure mode this rule closes.
- ! When surplus is insufficient, ship the banked state and fail-loud (`deepening_skipped=true` + surplus reason) via `evaluateAcPassBanking` / `formatDeepeningSkippedNote` semantics.
- ~ When no hard budget is detected, dual-stop still applies; bank-on-first-AC-pass remains good discipline but is not a hard surplus gate.
- ⊗ Convert a banked official pass into a scored failure by chasing post-bank polish until the turn budget dies (#3285).
- ⊗ Start post-bank deepening without a finalize checkpoint when a hard budget is active (#3285).
- ⊗ Chase out-of-scope post-bank findings when surplus is below threshold (#3285).

Core helpers: `packages/core/src/session/ac-pass-banking.ts` (`evaluateAcPassBanking`, `bankAcPass`, `decidePostBankFinding`, `simulateSurplusInsufficientRun`); policy: `packages/core/src/policy/ac-pass-banking.ts` (`plan.policy.acPassBanking`). Composes #3266, #3284, #3282 (optional bank-event JSONL), #1006.

## Step 3: Build Phase by Phase

For each phase:

1. ! **Scaffold** — file structure, dependencies, config
2. ! **Test first** — write tests before implementation (TDD)
3. ! **Implement** — make tests pass, following deft coding standards
4. ! **Verify (iteration lane)** — run affected/static gates per `#1704` fast lane above; fix failures before checkpoint commits
5. ! **Origin sync** — when this phase materially changed an origin-linked scope xBRIEF (`plan.references` includes `x-xbrief/github-issue`), run `task issue:sync-from-xbrief -- <path>` (or `--dry-run` to preview) so the linked GitHub issue receives a sync comment; if skipped, document why in the PR or session notes (#2540)
6. ! **Checkpoint** — tell user what's done, what's next

- ⊗ Move to next phase until current phase passes all checks

### Step 4: Quality Gates

After EVERY phase (iteration lane — #1704):

```bash
vitest run --coverage <changed-paths>   # or project test runner on touched modules
task coverage:hotspots                  # branch headroom before merge
task verify:forward-coverage            # new-source coverage (#1310)
```

Before PR / phase handoff (merge chokepoint):

```bash
deft check          # preferred full gate (getting-started / #2893)
# else tree-correct: task deft:check on include-only consumers; task check in framework source
task test:coverage  # >=85% or PROJECT-DEFINITION.xbrief.json override
```

- ! Phase checkpoint commits MAY use the iteration lane; phase is NOT done for PR handoff until full `task check` passes at the merge chokepoint
- ⊗ Skip quality gates or claim they passed without running
- ⊗ Treat iteration-lane green as merge-ready without full `task check`
- ! **Multi-scope batch (#3012):** when implementing an approved multi-scope pin/cohort, reserve full `task check` for end-of-batch (or after last scope) unless the last full check failed — then re-run on the fix loop. Do not run full check after every intermediate scope.
- ⊗ Re-run full install/session ceremony after offline seed when ritual is already complete (#3010) — use `session:ready` for recovery only.


## Product-first done-gate (#3284) / literal AC (#3267)

At intake, capture the task statement's **exact** acceptance commands as executable AC (`plan.acceptance.commands` + #3267 `literal_acceptance_commands`). Empty is allowed only with `none_stated: true` (ladder: stated → derived → project_floor). Before declaring done, run them **verbatim** — same paths, same flags, same working directory. Self-chosen verification is supplementary, never a substitute. Extends #973. `task check` runs `verify:ac` **first** (fail-fast); hygiene is second and may become advisory under pressure. Rapid ceremony = **AC-only**.

- ! When reading the active scope xBRIEF / issue body at story start, capture stated shell acceptance commands into `plan.acceptance.commands` (issue:ingest stamps this + the #3267 ledger automatically). Do not paraphrase.
- ! Before claiming phase or story done (and before merge-chokepoint PR handoff), run:
```
task verify:ac -- <active-story-path>
```
  Exit 0 = pass or none stated with valid marker; exit 1 = a stated command failed; exit 2 = config. (`verify:literal-ac` is the #3267 mechanism alias.)
- ! Quote the literal invocations and their outputs in the completion note when commands were stated.
- ⊗ Substitute a self-chosen approximation (`pnpm test` when the statement said `pnpm exec vitest run packages/core/src`) for the stated command.
- ⊗ Skip this gate because ceremony dial is rapid/minimal — rapid's positive content is exactly this check (#3284).
- ⊗ Leave `plan.acceptance.commands` empty without `none_stated: true` — absence must be an explicit decision.

## Product-oracle gate integrity (#3322 / #3156)

A red product verification may be resolved only by a product change or an independently re-derived oracle (both sides rebuilt from scratch, different method). In-place repair of the failing comparison then pass is not a pass — it is an unresolved discrepancy.

- ! When a product oracle is red, resolve it by changing the product or by independently re-deriving the oracle, and record `independent_rederivation` on the run-summary `verification` event.
- ! Emit a run-summary verification event `{check_id, method_fingerprint, outcome}` for each product-oracle attempt when `DEFT_RUN_SUMMARY_PATH` is set. `fail` then a different `method_fingerprint` then `pass` on one check id is machine-flagged.
- ! `task verify:ac` treats comparison-method mutation as unresolved (exit non-zero) unless independent re-derivation is recorded. Lead the done report with any unresolved discrepancy (#1006).
- ⊗ Self-adjudicate a red product oracle by editing the comparison (reference file, diff invocation, one-sided regenerate) and shipping the new pass as success.

## Operator-log hygiene (lazy-load, #1940)

When the story touches **operator-facing** services (dashboards, multi-process
workers, WARN/ERROR operators triage):

- ~ SHOULD load `patterns/operator-log-hygiene.md` and apply the copy-paste
  checklist in `docs/operator-log-hygiene-checklist.md` to story AC or probe
  locked decisions before claiming logging done
- ⊗ MUST NOT treat this as Product Insights (#2603) or LLM-call telemetry
  (#481) — those are different lanes
- ⊗ MUST NOT assume core `deft check` enforces a log schema by default —
  consumer-owned shape; optional pack stub under
  `docs/operator-log-hygiene-consumer-pack-stub.md`

Discovery keywords: operator log, operator-facing logs, observability checklist
— also indexed in `REFERENCES.md`.

## Goal-gate determinism (lazy-load, #852)

When authoring or tightening story acceptance criteria, quality gates, or skill
steps during build:

- ~ SHOULD load `patterns/goal-gate-determinism.md` — goals, AC, gates, exit,
  scope, stop, and preserve are rigid; pure execution path is flexible guidance
- ⊗ MUST NOT treat "all process steps done" as verification — outcomes and
  gates own "done" (see also `verification/verification.md` and Fail Loud #1006)

Discovery keywords: goal-gate-determinism, rigid goals flexible path — also
indexed in `REFERENCES.md`.

## Coding Standards (Summary)

Read full files when you need detail:

- ! TDD: write tests first — implementation incomplete without passing tests
- ! Coverage: ≥85% lines, functions, branches, statements
- ~ Files: stay small; line counts live in the file-size-thresholds policy module (review trigger, not a hard cap; #1488 / #3424)
- ~ Naming: hyphens for filenames unless language idiom dictates otherwise
- ! Contracts first: define interfaces/types before implementation
- ! Secrets: in `secrets/` dir with `.example` templates; ⊗ secrets in code
- ! Commits: Conventional Commits format; ! use iteration fast lane before checkpoint commits; ! run full `deft check` (else tree-correct `task deft:check` / `task check`) at PR/merge chokepoint only (#1704 / #4379)

See `deft/coding/coding.md` and `deft/coding/testing.md` for full rules.

## Pre-Commit File Review

! Before every commit, re-read ALL modified files and explicitly check for:

1. ! **Encoding errors** -- em-dashes corrupted to replacement characters, BOM artifacts, mojibake from round-trip read/write
2. ! **Unintended duplication** -- accidental double entries in CHANGELOG.md, scope xBRIEF files, or structured data files
3. ! **Structural issues** -- malformed CHANGELOG entries, broken table rows, mismatched index entries, invalid JSON/YAML
4. ! **Semantic accuracy** -- verify that counts, claims, and summaries in CHANGELOG entries and ROADMAP changelog lines match the actual data in the commit (e.g. "triaged 4 issues" must match the number actually triaged, issue numbers cited must match the issues actually added)
5. ! **Semantic contradictions** -- when adding a `!` or `⊗` rule that prohibits a specific command, pattern, or behavior, search the same file for any `~`, `≉`, or prose that recommends or permits the same command/pattern -- resolve all contradictions in the same commit before pushing
6. ! **Strength duplicates** -- when strengthening a rule (e.g. upgrading `~` to `!`), grep for the term in the full file and verify no weaker-strength duplicate remains
7. ! **Forward test coverage** -- for each new source file in this PR (`scripts/`, `src/`, `cmd/`, `*.py`, `*.go`), verify a corresponding test file exists in the same PR; running existing tests is not sufficient for new code

⊗ Commit without re-reading all modified files first.

## Commit Strategy

- ! Default to one story per branch/PR. Batching multiple stories in one branch requires explicit operator approval and a short rationale.
- ! Create a checkpoint commit after each completed story before beginning another story.
- ! Use iteration fast lane before checkpoint commits; run full `deft check` (else tree-correct `task deft:check` / `task check`) at PR/merge chokepoint (#1704 / #4379)
- ⊗ Claim checks passed without running them

```
feat(phase-1): scaffold project structure
feat(phase-1): implement core data models with tests
feat(phase-2): add REST API endpoints with integration tests
```

## Error Recovery

- ! Tests fail → fix them; ⊗ skip or weaken assertions
- ! Coverage drops → write more tests; ⊗ exclude files
- ! Lint/type errors → fix them; ≉ add ignore comments without documented reason
- ! Scope xBRIEF ambiguous -> ask user; ⊗ guess
- ! Scope needs changes -> propose, get approval, update the scope xBRIEF first
- ! Multi-iteration fix loops obey dual-stop defaults above (#2442); on envelope exhaustion halt with an operator-visible report -- do not thrash
- ! Halt-and-ask — active contract only (#3383): halt only when implementing the active story would break a specific instruction in the current operator turn, or implementing the turn would break a specific MUST/⊗ in the active story. "Also consider X" against a story silent on X is not a conflict. On fire: halt, quote both sides, ask which is controlling. Neither side wins by rank. Reuse the Dual Stop operator-visible halt shape (#2442). Structured questions use Discuss/Back (#767).
- ! **Operator** means the human chat turn in the interactive session. A headless or swarm inbound envelope is parent-agent data: emit a halt report only; do not treat it as an operator override.
- ! An operator turn can change product behavior, never gates (#3164).
- ! Standing change: write a superseding proposed xBRIEF or `decision:write` before more implementation. Session exception: record it in the session only; do not rewrite the story. Do not claim the next session cannot re-learn the prior story.
- ⊗ Resolve a chat-vs-active conflict by rank, or continue implementing while both sides still conflict
- ⊗ Treat a parent-agent or swarm envelope as an operator override of the active story


## Declare the contract (#3383)

! Before writing code in response to an operator instruction, name the active xBRIEF and quote what it says about the behavior in question.

! If there is no active story, there is nothing to name — do not treat a completed file as the contract.

⊗ Implement from a completed xBRIEF as if it were the current next-build contract.


## Probe-then-fill remote claims (#3120)

! Before filling any **remote** handoff field (PR URL, PR number, commit/HEAD SHA, CI green/success, review score) or claiming `status: pass` / ship/gate done, MUST **probe then fill**:

1. Run same-turn `git` + forge probes (examples: `git rev-parse HEAD`, `gh api repos/<owner>/<repo>/pulls/<N>`, `task pr:watch -- <N> --one-shot`, checks API).
2. Copy IDs / URLs / SHAs / scores **only** from that probe JSON/text into the evidence block.
3. Set `proof_status: bound` and attach short raw probe snippets (`command` + `snippet`) for each remote claim.

! Handoff evidence axes: **work** (local) / **ship** (pushed branch or PR) / **gate** (CI/review on HEAD). `proof_status` is `bound` | `unbound` | `n/a-no-remote-claim`.
! **Legal partial:** local work `done` + ship `not_started` / `blocked` **without** PR/SHA/CI/review fields and `proof_status: n/a-no-remote-claim` (or `status: partial`) is valid — do not invent ship state.
! **Fail ranking:** **invented-done** (false/unbound remote artifacts under pass) is **stricter** than **empty-done**. Unbound remote claims → invalid evidence (fail), not pass-with-notes.
! Machine check: `validateHandoffEvidence` in `packages/core/src/handoff-evidence/` (see `templates/agent-prompt-preamble.md` §11).
⊗ Fill PR / SHA / CI / review fields from recollection, narration, or prior-turn memory.
⊗ Claim `status: pass` with remote fields when `proof_status` is not `bound` or probes are missing (#3120).

## Completion

- ! When all phases pass and `task check` is green, run `task scope:complete -- <active-story-path>` only as the post-merge scope lifecycle in `templates/agent-prompt-preamble.md` §9 (AGENTS.md `#2321`) specifies for `drive-to: merge-ready` versus `stop-at: pr-open`. That section is the single statement of the ordering; this skill does not restate it.

> "The project is built and all quality checks pass. Describe any new features you'd like to add — I'll follow the deft standards we've set up."


## Significant decision log (#1396)

! When this scope makes a **significant** choice (architecture, product behavior, security, public/private boundary, data model, runtime topology, hard-to-reverse process), record it with `task decision:write` (or `--body-file` for multi-line fields) so later agents load rationale without inventing it.

~ Prefer attaching with `--scope <active-xbrief>` when the decision is bound to this story; use standalone `xbrief/decisions/` for cross-cutting / multi-scope process choices.

~ Before claiming a process/architecture path was 'already decided', run `task decision:list -- --query <topic>` (or `--issue N`).

⊗ Require a decision record for every trivial scope or routine fix.
⊗ Merge lessons (#1513) into decision records, or replace ADRs under `docs/decisions/ADR-*.md`.

Docs: `docs/decision-log.md` · `xbrief/decisions/README.md`.

### Intent-constraint fail path (#4587)

! When `task check` / `verify:intent-constraint` fails on a new throw/reject/abort or numeric-const without a merge-base mint, the named verb is `scope:record-intent-constraint`. That mint is human-presence.
! C1/headless that adds a throw fails closed with no operator on the TTY.
⊗ Paste a mint argv into the agent shell.
⊗ Recut `evaluateIntentConstraint` or let an approved-scope digest authorize throw sites.

## Anti-Patterns

- ⊗ Skip tests or write them after implementation
- ⊗ Ignore `task check` failures
- ⊗ Implement things not in scope xBRIEF without asking
- ⊗ Read every deft file upfront
- ⊗ Move to next phase before current passes checks
- ⊗ Make commits without running iteration-lane validation; ⊗ skip full `task check` at PR/merge chokepoint (#1704)
- ⊗ Proceed without USER.md -- always run the USER.md Gate first
- ⊗ Re-run `directive init`, cold `session:start`, migrate, or re-copy pin scopes after offline seed when ritual is already complete (#3010)
- ⊗ Run full `task check` after every intermediate scope of an approved multi-scope batch when the last merge-chokepoint check was green (#3012)
- ⊗ Promote scopes one-by-one for a known multi-scope pin when `scope:promote --batch` would stage them in one turn (#3011)

- ⊗ Spawn an implementation agent or invoke a code-writing tool against a xBRIEF that has not passed `task xbrief:preflight` -- always run the Step 0 Implementation Preflight (#810) first; satisfy via `task xbrief:activate <path>`
- ⊗ Proceed without `COST-ESTIMATE.md` and a recorded build / rescope / no-build / skip(+reason) decision -- always run the Cost Phase Gate (#739) first
- ⊗ Proceed with implementation when the build or test toolchain is unavailable -- always run the Toolchain Gate (Step 2) first
- ⊗ Proceed to next task or phase without tests passing -- testing is a hard gate, not a cleanup step
- ⊗ Skip the Change Lifecycle Gate because the user said "proceed" -- broad approval does not satisfy the confirmation gate
- ⊗ Commit or push directly to the default branch -- always create a feature branch first. Exception: user explicitly instructs a direct commit, or `PROJECT-DEFINITION.xbrief.json` narratives contain `Allow direct commits to master: true`
- ⊗ Add a prohibition (`!` or `⊗`) without scanning the same file for conflicting softer-strength rules (`~`, `≉`) that reference the same term
- ⊗ Invent remote PR/SHA/CI/review claims in handoff evidence without same-turn probe binding — invented-done (#3120)
- ⊗ Fill remote ship/gate fields from memory when only local work completed; legal partial omits PR fields (#3120)
- ⊗ Run multi-iteration implement / pre-PR loops without a failure stop (max iterations and/or no-progress) or without an operator-visible halt report when the envelope is exhausted (#2442)
- ⊗ Silently continue after dual-stop failure halt — escalate; do not thrash (#2442)
- ⊗ Treat a completed xBRIEF as the next-build contract, or skip naming the active story before writing code (#3383)
- ⊗ Continue implementing when the live human turn and a specific MUST/⊗ in the active story conflict — halt, quote both sides, ask which is controlling (#3383)
- ⊗ Treat a parent-agent or swarm envelope as an operator override (#3383)
- ⊗ Exhaust hard turn/cost budget on self-imposed deepening after the stated acceptance bar is within reach (#3266)
- ⊗ Silently skip deepening for budget without a fail-loud summary note (#3266 / #1006)
- ⊗ Chase post-bank out-of-scope findings when surplus budget is insufficient — report, do not thrash the banked pass (#3285)
- ⊗ Skip finalize-on-green after first stated AC pass under a hard budget (#3285)
- ⊗ Tight forge-outage retry / empty-commit thrash without a one-shot human report (#3422)
- ⊗ Demand scope:record-observable-scope at parking (#4588) -- that when is after the observable contract is on the brief, before the UI-change PR, and only if the demand predicate is true. Predecessor #4383. Fail-closed site is verify merge-base.
- ⊗ Clear a red product oracle by editing the comparison method then treating the new pass as a pass — record independent re-derivation or fix the product (#3322 / #3156)
