deftai

deft-directive-build

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.

deftai 31 14 Updated 1w ago
GitHub

Install

npx skillscat add deftai/directive/deft-directive-build

Install via the SkillsCat registry.

SKILL.md

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 full task check (merge chokepoint) once at the end of the batch (or after the last scope), not after every scope.
! 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` § #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`).

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: run full task check (or task check:merge in the framework source repo) once before push/PR and again when CI merge gate runs. 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 task check re-run after a red merge chokepoint task check green Counts toward the implement/quality fix envelope above (do not open a separate unbounded check-retry loop)

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):

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):

task check          # Full gate — format, lint, typecheck, tests, coverage, verify:*
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 task check at PR/merge chokepoint only (#1704)

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 task check at PR/merge chokepoint (#1704)
  • ⊗ 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.

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)

  • ⊗ 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)