@deftai/directive-content 0.89.0 → 0.91.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/coding/coding.md +8 -0
- package/commands.md +70 -5
- package/contracts/host-lifecycle-duties.md +10 -0
- package/contracts/scm-readiness.md +78 -0
- package/docs/inter-run-learning.md +27 -0
- package/docs/openclaw-agent-host.md +43 -3
- package/events/README.md +1 -1
- package/events/registry.json +36 -0
- package/package.json +1 -1
- package/packs/lessons/lessons-pack-0.1.json +1 -1
- package/packs/patterns/patterns-pack-0.1.json +13 -1
- package/packs/rules/rules-pack-0.1.json +114 -82
- package/packs/skills/skills-pack-0.1.json +2 -2
- package/patterns/in-band-signaling.md +124 -0
- package/patterns/tool-call-taxonomy.md +73 -0
- package/scm/github.md +47 -0
- package/skills/deft-directive-build/SKILL.md +44 -1
- package/skills/deft-directive-pre-pr/SKILL.md +4 -2
- package/skills/deft-directive-swarm/references/core-phase-4.md +20 -0
- package/skills/deft-directive-swarm/references/host-openclaw.md +4 -0
- package/tasks/engine.yml +1 -0
- package/tasks/lifecycle.yml +14 -1
- package/tasks/pr.yml +7 -8
- package/tasks/roadmap.yml +1 -1
- package/tasks/scope.yml +4 -1
- package/tasks/session.yml +11 -0
- package/tasks/spec.yml +5 -2
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
],
|
|
30
30
|
"path": "skills/deft-directive-build/SKILL.md",
|
|
31
31
|
"version": "0.1",
|
|
32
|
-
"body": "# Deft Directive Build\n\nImplements a project from its scope xBRIEFs following Deft Directive standards.\n\nLegend (from RFC2119): !=MUST, ~=SHOULD, ≉=SHOULD NOT, ⊗=MUST NOT, ?=MAY.\n\n## When to Use\n\n- After `deft-directive-setup` completes and generates `PROJECT-DEFINITION.xbrief.json`\n- User says \"build this\", \"implement the spec\", or \"start building\"\n- Resuming a partially-built project that has story xBRIEFs in `xbrief/active/`\n\n## Ordered-plan / cohort exhaustion (#2402)\n\n! 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.\n\n## Step 0 -- Implementation Preflight (#810)\n\n- ! Before starting any new implementation story or switching from one story to another, MUST run `git status --short --branch`.\n- ! 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.\n- ⊗ Begin a new story while unrelated dirty work is present without explicit operator approval.\n- ! 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.\n- ! Batching multiple stories in one branch/PR requires explicit operator approval and a short rationale recorded in the handoff.\n- ! **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.\n- ! **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.\n- ! **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.\n- ! If the target story is in `xbrief/proposed/`, run `task scope:promote -- <path>` first; if it is in `xbrief/pending/`, run `task scope:activate -- <path>`. After activation, update the path to the active-file location before preflight.\n- ! 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; wraps `scripts/preflight_implementation.py` so the same invocation works whether deft is the project root or installed as a `deft/` subdirectory).\n\nThe 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>`.\n\n- ! 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.\n- ! 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.\n- ⊗ 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).\n- ⊗ 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.\n\n## Platform Detection\n\n! Before resolving any config paths, detect the host OS from your environment context:\n\n| Platform | USER.md default path |\n|--------------------|-------------------------------------------------------------------|\n| Windows | `%APPDATA%\\deft\\USER.md` (e.g. `C:\\Users\\{user}\\AppData\\Roaming\\deft\\USER.md`) |\n| Unix (macOS/Linux) | `~/.config/deft/USER.md` |\n\n- ! If `$DEFT_USER_PATH` is set, it takes precedence on any platform\n\n## Pre-Cutover Detection Guard\n\n! 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.\n\n### Detection Criteria\n\nA project is **pre-cutover** if ANY of the following are true. This prose mirrors the executable helper in `scripts/_precutover.py`; when in doubt, the helper is canonical.\n\n1. `SPECIFICATION.md` exists and is neither a deprecation redirect nor a current generated spec export. A current generated spec export contains `<!-- Purpose: rendered specification -->` and `<!-- Source of truth: xbrief/specification.xbrief.json -->`, and `xbrief/specification.xbrief.json` plus all five lifecycle folders exist.\n2. `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)\n3. `xbrief/specification.xbrief.json` exists but the lifecycle folders (`xbrief/proposed/`, `xbrief/pending/`, `xbrief/active/`, `xbrief/completed/`, `xbrief/cancelled/`) do NOT exist\n4. Strategy output shape violations (run `task verify-strategy-output` -- the canonical gate -- or the direct form `python .deft/core/scripts/validate_strategy_output.py --project-root <path>` after `deft` install):\n - 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`).\n - `xbrief/PROJECT-DEFINITION.xbrief.json` is missing.\n - `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`.\n\n### Action on Detection\n\n! If pre-cutover or strategy-nonconformant state is detected, **stop immediately** and display an actionable message that cites the exact validator:\n\n> \"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) or `python .deft/core/scripts/validate_strategy_output.py --project-root .`. 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.\"\n\n! Include specific details about what was detected (the validator output is authoritative):\n\n- 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\"\n- 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`\"\n- Missing `PROJECT-DEFINITION.xbrief.json`: \"Run `task project:render` to generate the project definition\"\n- `SPECIFICATION.md` / `PROJECT.md` without sentinel: the classic pre-cutover messages\n- Scope xBRIEF in wrong folder: \"Status is '{status}' but file is in {folder}/ -- run `task scope:activate <file>` to fix\"\n\n! After the validator reports clean, re-run this guard before continuing.\n\n⊗ 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.\n⊗ Silently ignore these artifacts or guess at fixes -- the validator (wired into `task check` and this guard) is the deterministic gate.\n\n## USER.md Gate\n\n! Before proceeding, verify USER.md exists at the platform-appropriate path\n(resolved via Platform Detection above, or `$DEFT_USER_PATH` if set).\n\n- ! If USER.md is not found: inform the user and redirect to `deft-directive-setup`\n Phase 1 before continuing -- do not proceed without user preferences\n- ! Once USER.md exists, continue with the Cost Phase Gate below\n\n## Cost Phase Gate (#739)\n\n! Before proceeding to File Reading, verify the project has gone through the\npre-build cost & budget transparency phase from `skills/deft-directive-cost/SKILL.md`.\nThis closes the adoption-blocker surfaced by issue #739 (refs #151 umbrella) where\nusers finished the spec flow and stopped at build because deft offered no cost\nsignal.\n\n### Detection\n\n- ! Check for `COST-ESTIMATE.md` in the project root.\n- ! Check that the file contains a recorded decision (the **Decision recorded**\n block populated with one of: `build`, `rescope`, `no-build`, `skip`).\n- ! For `skip`, `rescope`, or `no-build` decisions: the **Reason** field MUST be\n populated (one or two sentences in plain language). A skip with no reason\n recorded is treated the same as no decision.\n\n### Action\n\n- ! If `COST-ESTIMATE.md` is missing OR the **Decision recorded** block is\n unpopulated OR a `skip`/`rescope`/`no-build` decision has no reason recorded:\n stop immediately and redirect the user:\n\n > \"This project has not gone through the pre-build cost & budget transparency\n > phase. Run `skills/deft-directive-cost/SKILL.md` to produce a plain-English\n > `COST-ESTIMATE.md`, then re-run the build skill once the user has chosen\n > build / rescope / no-build / skip(+reason).\"\n\n- ! On a `build` or `skip` decision: continue with File Reading below.\n- ! On a `rescope` decision: stop and redirect the user back to spec edits\n (chain to `skills/deft-directive-refinement/SKILL.md` to pull spec scope\n back, or the interview), then re-run `skills/deft-directive-cost/SKILL.md`\n before re-attempting build.\n- ! On a `no-build` decision: stop and exit; do NOT proceed to File Reading.\n The user has explicitly stopped the project at the cost phase.\n- ⊗ Proceed to File Reading or any subsequent phase when `COST-ESTIMATE.md` is\n missing, when the decision is unpopulated, or when a skip / rescope / no-build\n decision has no reason recorded.\n- ⊗ Treat a `rescope` or `no-build` decision as if it were a `build` -- the\n build skill MUST honor the recorded decision.\n\n## File Reading\n\n- ! Read in order, lazy load:\n 1. `./xbrief/active/` -- scope xBRIEFs for work items to build (required)\n 2. `./xbrief/PROJECT-DEFINITION.xbrief.json` -- project identity, tech stack, architecture\n 3. `./.planning/codebase/MAP.md` -- generated codebase orientation projection, if present (advisory)\n 4. USER.md at the platform-appropriate path (see Platform Detection) -- Personal section is highest precedence; Defaults are fallback\n 5. `deft/main.md` -- framework guidelines\n 6. `deft/coding/coding.md` -- coding standards\n 7. `deft/coding/testing.md` -- testing requirements\n 8. `deft/coding/toolchain.md` -- toolchain validation rules\n 9. `deft/languages/{language}.md` -- only for languages this project uses\n- ~ 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.\n- ! Treat `plan.architecture.codeStructure` and selected provider artifacts as authoritative. The MAP is a generated projection.\n- ⊗ Read all language/interface/tool files upfront\n- ⊗ Hand-edit `.planning/codebase/MAP.md` or block unrelated implementation solely because the MAP is stale or absent\n\n## Rule Precedence\n\n```\nUSER.md Personal <- HIGHEST (name, custom rules -- always wins)\nPROJECT-DEFINITION.xbrief.json <- Project-specific (tech stack, architecture, config)\nUSER.md Defaults <- Fallback defaults (used when PROJECT-DEFINITION doesn't specify)\n{language}.md <- Language standards\ncoding.md <- General coding\nmain.md <- Framework defaults\nScope xBRIEFs <- LOWEST\n```\n\n- ! USER.md Personal section always wins over any other file\n- ! For project-scoped settings, PROJECT-DEFINITION.xbrief.json overrides USER.md Defaults\n\n## Change Lifecycle Gate\n\n! Before any implementation that touches 3+ files, verify that a `/deft:change <name>` proposal exists and has been confirmed by the user:\n\n- ! Check `history/changes/` for an active `proposal.xbrief.json` matching this work\n- ! If no proposal exists: propose `/deft:change <name>` and present the change name for explicit confirmation (e.g. \"Confirm? yes/no\")\n- ! The user must reply with an affirmative (`yes`, `confirmed`, `approve`) — a general 'proceed', 'do it', or 'go ahead' does NOT satisfy this gate\n- ? 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\n- ⊗ Skip this gate because the user has already said \"proceed\" or \"go ahead\"\n\n## Build Process\n\nAll xBRIEFs (including those read from `xbrief/active/` and any new xBRIEFs this skill emits) MUST use `\"xBRIEFInfo\": { \"version\": \"0.6\" }`. The validator rejects any other version (see [`../../conventions/references.md`](../../conventions/references.md)).\n\n### Step 1: Understand the Scope\n\n- ! Read story xBRIEFs from `xbrief/active/` and `PROJECT-DEFINITION.xbrief.json`\n- ! Identify phases, dependencies, starting point from scope xBRIEF acceptance criteria\n- ~ 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.\n- ! 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\n- ⊗ Begin implementation against an averaged blend of two contradicting patterns -- \"average code that satisfies both rules is the worst code\" (#1005)\n- ! Present brief summary to user:\n\n> \"Here's what I see: {N} story xBRIEFs in active/. I'll start with {name}. Ready?\"\n\n### Step 2: Verify Toolchain\n\n- ! Before any implementation, verify all tools required by this project are installed and functional — see `deft/coding/toolchain.md` for full rules\n- ! At minimum: confirm task runner (`task --version`), language compiler/runtime, and platform SDK (if applicable) are available\n- ! If any required tool is missing, stop and report — do not proceed to Step 3\n- ⊗ Assume tools are available because the spec references them\n\n### Gate throughput — iteration fast lane vs merge chokepoint (#1704)\n\n> **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.\n\n- ! **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.\n- ! **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.\n- ! **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).\n- ~ **In-engine incrementality (#1713):** content-hash task cache and runner-delegated affected selection are sibling work — not required for this policy face.\n- ⊗ Run full `task check` on every iteration commit when a cheaper proxy suffices — reserve the full gate for PR/merge (#1704).\n- ⊗ Skip the merge chokepoint because the iteration lane passed — the fast lane is convenience only.\n\n**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.\n\n## Step 3: Build Phase by Phase\n\nFor each phase:\n\n1. ! **Scaffold** — file structure, dependencies, config\n2. ! **Test first** — write tests before implementation (TDD)\n3. ! **Implement** — make tests pass, following deft coding standards\n4. ! **Verify (iteration lane)** — run affected/static gates per `#1704` fast lane above; fix failures before checkpoint commits\n5. ! **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)\n6. ! **Checkpoint** — tell user what's done, what's next\n\n- ⊗ Move to next phase until current phase passes all checks\n\n### Step 4: Quality Gates\n\nAfter EVERY phase (iteration lane — #1704):\n\n```bash\nvitest run --coverage <changed-paths> # or project test runner on touched modules\ntask coverage:hotspots # branch headroom before merge\ntask verify:forward-coverage # new-source coverage (#1310)\n```\n\nBefore PR / phase handoff (merge chokepoint):\n\n```bash\ntask check # Full gate — format, lint, typecheck, tests, coverage, verify:*\ntask test:coverage # >=85% or PROJECT-DEFINITION.xbrief.json override\n```\n\n- ! Phase checkpoint commits MAY use the iteration lane; phase is NOT done for PR handoff until full `task check` passes at the merge chokepoint\n- ⊗ Skip quality gates or claim they passed without running\n- ⊗ Treat iteration-lane green as merge-ready without full `task check`\n\n## Coding Standards (Summary)\n\nRead full files when you need detail:\n\n- ! TDD: write tests first — implementation incomplete without passing tests\n- ! Coverage: ≥85% lines, functions, branches, statements\n- ~ Files: <300 lines ideal, <500 recommended, ! <1000 max\n- ~ Naming: hyphens for filenames unless language idiom dictates otherwise\n- ! Contracts first: define interfaces/types before implementation\n- ! Secrets: in `secrets/` dir with `.example` templates; ⊗ secrets in code\n- ! Commits: Conventional Commits format; ! use iteration fast lane before checkpoint commits; ! run full `task check` at PR/merge chokepoint only (#1704)\n\nSee `deft/coding/coding.md` and `deft/coding/testing.md` for full rules.\n\n## Pre-Commit File Review\n\n! Before every commit, re-read ALL modified files and explicitly check for:\n\n1. ! **Encoding errors** -- em-dashes corrupted to replacement characters, BOM artifacts, mojibake from round-trip read/write\n2. ! **Unintended duplication** -- accidental double entries in CHANGELOG.md, scope xBRIEF files, or structured data files\n3. ! **Structural issues** -- malformed CHANGELOG entries, broken table rows, mismatched index entries, invalid JSON/YAML\n4. ! **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)\n5. ! **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\n6. ! **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\n7. ! **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\n\n⊗ Commit without re-reading all modified files first.\n\n## Commit Strategy\n\n- ! Default to one story per branch/PR. Batching multiple stories in one branch requires explicit operator approval and a short rationale.\n- ! Create a checkpoint commit after each completed story before beginning another story.\n- ! Use iteration fast lane before checkpoint commits; run full `task check` at PR/merge chokepoint (#1704)\n- ⊗ Claim checks passed without running them\n\n```\nfeat(phase-1): scaffold project structure\nfeat(phase-1): implement core data models with tests\nfeat(phase-2): add REST API endpoints with integration tests\n```\n\n## Error Recovery\n\n- ! Tests fail → fix them; ⊗ skip or weaken assertions\n- ! Coverage drops → write more tests; ⊗ exclude files\n- ! Lint/type errors → fix them; ≉ add ignore comments without documented reason\n- ! Scope xBRIEF ambiguous -> ask user; ⊗ guess\n- ! Scope needs changes -> propose, get approval, update the scope xBRIEF first\n\n## Completion\n\n- ! When all phases pass and `task check` is green, complete each implemented story via `task scope:complete -- <active-story-path>` before final PR handoff.\n\n> \"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.\"\n\n## Anti-Patterns\n\n- ⊗ Skip tests or write them after implementation\n- ⊗ Ignore `task check` failures\n- ⊗ Implement things not in scope xBRIEF without asking\n- ⊗ Read every deft file upfront\n- ⊗ Move to next phase before current passes checks\n- ⊗ Make commits without running iteration-lane validation; ⊗ skip full `task check` at PR/merge chokepoint (#1704)\n- ⊗ Proceed without USER.md -- always run the USER.md Gate first\n- ⊗ Spawn an implementation agent or invoke a code-writing tool against a xBRIEF that has not passed `task xbrief:preflight` (which wraps `scripts/preflight_implementation.py`) -- always run the Step 0 Implementation Preflight (#810) first; satisfy via `task xbrief:activate <path>`\n- ⊗ Proceed without `COST-ESTIMATE.md` and a recorded build / rescope / no-build / skip(+reason) decision -- always run the Cost Phase Gate (#739) first\n- ⊗ Proceed with implementation when the build or test toolchain is unavailable -- always run the Toolchain Gate (Step 2) first\n- ⊗ Proceed to next task or phase without tests passing -- testing is a hard gate, not a cleanup step\n- ⊗ Skip the Change Lifecycle Gate because the user said \"proceed\" -- broad approval does not satisfy the confirmation gate\n- ⊗ 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`\n- ⊗ Add a prohibition (`!` or `⊗`) without scanning the same file for conflicting softer-strength rules (`~`, `≉`) that reference the same term\n",
|
|
32
|
+
"body": "# Deft Directive Build\n\nImplements a project from its scope xBRIEFs following Deft Directive standards.\n\nLegend (from RFC2119): !=MUST, ~=SHOULD, ≉=SHOULD NOT, ⊗=MUST NOT, ?=MAY.\n\n## When to Use\n\n- After `deft-directive-setup` completes and generates `PROJECT-DEFINITION.xbrief.json`\n- User says \"build this\", \"implement the spec\", or \"start building\"\n- Resuming a partially-built project that has story xBRIEFs in `xbrief/active/`\n\n## Ordered-plan / cohort exhaustion (#2402)\n\n## Multi-scope turn/cache budget (epic #3009)\n\nMulti-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.\n\n### Offline seed vs implement phase (#3010)\n\n! 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**.\n\n! When seed + session ritual are already complete for the engagement:\n- ⊗ Run `directive init` again\n- ⊗ Run full cold `session:start` unless hooks deny writes and recovery is required\n- ⊗ Run `directive migrate` or re-copy scopes already present\n- ! Prefer recovery via `session:ready` (or re-arm) when PreToolUse denies — not full re-init\n- ! Documented consumer/harness contract: seed is done once; implement agents only activate+implement\n\n### Batch promote; one active implement (#3011)\n\n! For a multi-scope pin, batch-stage scopes with `task scope:promote -- --batch` (all `proposed/`) or `task scope:promote -- --batch <path>…`.\n! Implement path remains **one** `scope:activate` + implement at a time — no multi-active write fence.\n! When pin order is known, do **not** re-list the entire lifecycle tree every scope; walk the known ordered list.\n⊗ Activate all scopes at once or drop the one-active-scope / story-ready stack.\n\n### Quality check once at end of multi-scope batch (#3012)\n\n! 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.\n! Exception: if the last full check **failed**, fix loops MAY re-run check until green.\n! Pre-PR / merge-ready gates remain end-of-unit — this does not weaken them.\n! Iteration lane (affected tests / `verify:forward-coverage` / `coverage:hotspots`) still applies **per scope** during implementation (#1704).\n⊗ Spam full `directive check` / `task check` after every scope when the batch is still mid-flight and the last merge-chokepoint check was green.\n\n### One-shot project:render (#3013)\n\n! 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.\n⊗ Invent project identity across many turns when seed already stamped the skeleton.\n\n\n! 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.\n\n## Step 0 -- Implementation Preflight (#810)\n\n- ! Before starting any new implementation story or switching from one story to another, MUST run `git status --short --branch`.\n- ! 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.\n- ⊗ Begin a new story while unrelated dirty work is present without explicit operator approval.\n- ! 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.\n- ! Batching multiple stories in one branch/PR requires explicit operator approval and a short rationale recorded in the handoff.\n- ! **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.\n- ! **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.\n- ! **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.\n- ! 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.\n- ! 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; wraps `scripts/preflight_implementation.py` so the same invocation works whether deft is the project root or installed as a `deft/` subdirectory).\n\nThe 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>`.\n\n- ! 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.\n- ! 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.\n- ⊗ 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).\n- ⊗ 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.\n\n## Platform Detection\n\n! Before resolving any config paths, detect the host OS from your environment context:\n\n| Platform | USER.md default path |\n|--------------------|-------------------------------------------------------------------|\n| Windows | `%APPDATA%\\deft\\USER.md` (e.g. `C:\\Users\\{user}\\AppData\\Roaming\\deft\\USER.md`) |\n| Unix (macOS/Linux) | `~/.config/deft/USER.md` |\n\n- ! If `$DEFT_USER_PATH` is set, it takes precedence on any platform\n\n## Pre-Cutover Detection Guard\n\n! 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.\n\n### Detection Criteria\n\nA project is **pre-cutover** if ANY of the following are true. This prose mirrors the executable helper in `scripts/_precutover.py`; when in doubt, the helper is canonical.\n\n1. `SPECIFICATION.md` exists and is neither a deprecation redirect nor a current generated spec export. A current generated spec export contains `<!-- Purpose: rendered specification -->` and `<!-- Source of truth: xbrief/specification.xbrief.json -->`, and `xbrief/specification.xbrief.json` plus all five lifecycle folders exist.\n2. `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)\n3. `xbrief/specification.xbrief.json` exists but the lifecycle folders (`xbrief/proposed/`, `xbrief/pending/`, `xbrief/active/`, `xbrief/completed/`, `xbrief/cancelled/`) do NOT exist\n4. Strategy output shape violations (run `task verify-strategy-output` -- the canonical gate -- or the direct form `python .deft/core/scripts/validate_strategy_output.py --project-root <path>` after `deft` install):\n - 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`).\n - `xbrief/PROJECT-DEFINITION.xbrief.json` is missing.\n - `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`.\n\n### Action on Detection\n\n! If pre-cutover or strategy-nonconformant state is detected, **stop immediately** and display an actionable message that cites the exact validator:\n\n> \"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) or `python .deft/core/scripts/validate_strategy_output.py --project-root .`. 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.\"\n\n! Include specific details about what was detected (the validator output is authoritative):\n\n- 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\"\n- 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`\"\n- Missing `PROJECT-DEFINITION.xbrief.json`: \"Run `task project:render` to generate the project definition\"\n- `SPECIFICATION.md` / `PROJECT.md` without sentinel: the classic pre-cutover messages\n- Scope xBRIEF in wrong folder: \"Status is '{status}' but file is in {folder}/ -- run `task scope:activate <file>` to fix\"\n\n! After the validator reports clean, re-run this guard before continuing.\n\n⊗ 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.\n⊗ Silently ignore these artifacts or guess at fixes -- the validator (wired into `task check` and this guard) is the deterministic gate.\n\n## USER.md Gate\n\n! Before proceeding, verify USER.md exists at the platform-appropriate path\n(resolved via Platform Detection above, or `$DEFT_USER_PATH` if set).\n\n- ! If USER.md is not found: inform the user and redirect to `deft-directive-setup`\n Phase 1 before continuing -- do not proceed without user preferences\n- ! Once USER.md exists, continue with the Cost Phase Gate below\n\n## Cost Phase Gate (#739)\n\n! Before proceeding to File Reading, verify the project has gone through the\npre-build cost & budget transparency phase from `skills/deft-directive-cost/SKILL.md`.\nThis closes the adoption-blocker surfaced by issue #739 (refs #151 umbrella) where\nusers finished the spec flow and stopped at build because deft offered no cost\nsignal.\n\n### Detection\n\n- ! Check for `COST-ESTIMATE.md` in the project root.\n- ! Check that the file contains a recorded decision (the **Decision recorded**\n block populated with one of: `build`, `rescope`, `no-build`, `skip`).\n- ! For `skip`, `rescope`, or `no-build` decisions: the **Reason** field MUST be\n populated (one or two sentences in plain language). A skip with no reason\n recorded is treated the same as no decision.\n\n### Action\n\n- ! If `COST-ESTIMATE.md` is missing OR the **Decision recorded** block is\n unpopulated OR a `skip`/`rescope`/`no-build` decision has no reason recorded:\n stop immediately and redirect the user:\n\n > \"This project has not gone through the pre-build cost & budget transparency\n > phase. Run `skills/deft-directive-cost/SKILL.md` to produce a plain-English\n > `COST-ESTIMATE.md`, then re-run the build skill once the user has chosen\n > build / rescope / no-build / skip(+reason).\"\n\n- ! On a `build` or `skip` decision: continue with File Reading below.\n- ! On a `rescope` decision: stop and redirect the user back to spec edits\n (chain to `skills/deft-directive-refinement/SKILL.md` to pull spec scope\n back, or the interview), then re-run `skills/deft-directive-cost/SKILL.md`\n before re-attempting build.\n- ! On a `no-build` decision: stop and exit; do NOT proceed to File Reading.\n The user has explicitly stopped the project at the cost phase.\n- ⊗ Proceed to File Reading or any subsequent phase when `COST-ESTIMATE.md` is\n missing, when the decision is unpopulated, or when a skip / rescope / no-build\n decision has no reason recorded.\n- ⊗ Treat a `rescope` or `no-build` decision as if it were a `build` -- the\n build skill MUST honor the recorded decision.\n\n## File Reading\n\n- ! Read in order, lazy load:\n 1. `./xbrief/active/` -- scope xBRIEFs for work items to build (required)\n 2. `./xbrief/PROJECT-DEFINITION.xbrief.json` -- project identity, tech stack, architecture\n 3. `./.planning/codebase/MAP.md` -- generated codebase orientation projection, if present (advisory)\n 4. USER.md at the platform-appropriate path (see Platform Detection) -- Personal section is highest precedence; Defaults are fallback\n 5. `deft/main.md` -- framework guidelines\n 6. `deft/coding/coding.md` -- coding standards\n 7. `deft/coding/testing.md` -- testing requirements\n 8. `deft/coding/toolchain.md` -- toolchain validation rules\n 9. `deft/languages/{language}.md` -- only for languages this project uses\n- ~ 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.\n- ! Treat `plan.architecture.codeStructure` and selected provider artifacts as authoritative. The MAP is a generated projection.\n- ⊗ Read all language/interface/tool files upfront\n- ⊗ Hand-edit `.planning/codebase/MAP.md` or block unrelated implementation solely because the MAP is stale or absent\n\n## Rule Precedence\n\n```\nUSER.md Personal <- HIGHEST (name, custom rules -- always wins)\nPROJECT-DEFINITION.xbrief.json <- Project-specific (tech stack, architecture, config)\nUSER.md Defaults <- Fallback defaults (used when PROJECT-DEFINITION doesn't specify)\n{language}.md <- Language standards\ncoding.md <- General coding\nmain.md <- Framework defaults\nScope xBRIEFs <- LOWEST\n```\n\n- ! USER.md Personal section always wins over any other file\n- ! For project-scoped settings, PROJECT-DEFINITION.xbrief.json overrides USER.md Defaults\n\n## Change Lifecycle Gate\n\n! Before any implementation that touches 3+ files, verify that a `/deft:change <name>` proposal exists and has been confirmed by the user:\n\n- ! Check `history/changes/` for an active `proposal.xbrief.json` matching this work\n- ! If no proposal exists: propose `/deft:change <name>` and present the change name for explicit confirmation (e.g. \"Confirm? yes/no\")\n- ! The user must reply with an affirmative (`yes`, `confirmed`, `approve`) — a general 'proceed', 'do it', or 'go ahead' does NOT satisfy this gate\n- ? 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\n- ⊗ Skip this gate because the user has already said \"proceed\" or \"go ahead\"\n\n## Build Process\n\nAll xBRIEFs (including those read from `xbrief/active/` and any new xBRIEFs this skill emits) MUST use `\"xBRIEFInfo\": { \"version\": \"0.6\" }`. The validator rejects any other version (see [`../../conventions/references.md`](../../conventions/references.md)).\n\n### Step 1: Understand the Scope\n\n- ! Read story xBRIEFs from `xbrief/active/` and `PROJECT-DEFINITION.xbrief.json`\n- ! Identify phases, dependencies, starting point from scope xBRIEF acceptance criteria\n- ~ 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.\n- ! 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\n- ⊗ Begin implementation against an averaged blend of two contradicting patterns -- \"average code that satisfies both rules is the worst code\" (#1005)\n- ! Present brief summary to user:\n\n> \"Here's what I see: {N} story xBRIEFs in active/. I'll start with {name}. Ready?\"\n\n### Step 2: Verify Toolchain\n\n- ! Before any implementation, verify all tools required by this project are installed and functional — see `deft/coding/toolchain.md` for full rules\n- ! At minimum: confirm task runner (`task --version`), language compiler/runtime, and platform SDK (if applicable) are available\n- ! If any required tool is missing, stop and report — do not proceed to Step 3\n- ⊗ Assume tools are available because the spec references them\n\n### Gate throughput — iteration fast lane vs merge chokepoint (#1704)\n\n> **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.\n\n- ! **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.\n- ! **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.\n- ! **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).\n- ~ **In-engine incrementality (#1713):** content-hash task cache and runner-delegated affected selection are sibling work — not required for this policy face.\n- ⊗ Run full `task check` on every iteration commit when a cheaper proxy suffices — reserve the full gate for PR/merge (#1704).\n- ⊗ Skip the merge chokepoint because the iteration lane passed — the fast lane is convenience only.\n\n**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.\n\n## Step 3: Build Phase by Phase\n\nFor each phase:\n\n1. ! **Scaffold** — file structure, dependencies, config\n2. ! **Test first** — write tests before implementation (TDD)\n3. ! **Implement** — make tests pass, following deft coding standards\n4. ! **Verify (iteration lane)** — run affected/static gates per `#1704` fast lane above; fix failures before checkpoint commits\n5. ! **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)\n6. ! **Checkpoint** — tell user what's done, what's next\n\n- ⊗ Move to next phase until current phase passes all checks\n\n### Step 4: Quality Gates\n\nAfter EVERY phase (iteration lane — #1704):\n\n```bash\nvitest run --coverage <changed-paths> # or project test runner on touched modules\ntask coverage:hotspots # branch headroom before merge\ntask verify:forward-coverage # new-source coverage (#1310)\n```\n\nBefore PR / phase handoff (merge chokepoint):\n\n```bash\ntask check # Full gate — format, lint, typecheck, tests, coverage, verify:*\ntask test:coverage # >=85% or PROJECT-DEFINITION.xbrief.json override\n```\n\n- ! Phase checkpoint commits MAY use the iteration lane; phase is NOT done for PR handoff until full `task check` passes at the merge chokepoint\n- ⊗ Skip quality gates or claim they passed without running\n- ⊗ Treat iteration-lane green as merge-ready without full `task check`\n- ! **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.\n- ⊗ Re-run full install/session ceremony after offline seed when ritual is already complete (#3010) — use `session:ready` for recovery only.\n\n\n## Coding Standards (Summary)\n\nRead full files when you need detail:\n\n- ! TDD: write tests first — implementation incomplete without passing tests\n- ! Coverage: ≥85% lines, functions, branches, statements\n- ~ Files: <300 lines ideal, <500 recommended, ! <1000 max\n- ~ Naming: hyphens for filenames unless language idiom dictates otherwise\n- ! Contracts first: define interfaces/types before implementation\n- ! Secrets: in `secrets/` dir with `.example` templates; ⊗ secrets in code\n- ! Commits: Conventional Commits format; ! use iteration fast lane before checkpoint commits; ! run full `task check` at PR/merge chokepoint only (#1704)\n\nSee `deft/coding/coding.md` and `deft/coding/testing.md` for full rules.\n\n## Pre-Commit File Review\n\n! Before every commit, re-read ALL modified files and explicitly check for:\n\n1. ! **Encoding errors** -- em-dashes corrupted to replacement characters, BOM artifacts, mojibake from round-trip read/write\n2. ! **Unintended duplication** -- accidental double entries in CHANGELOG.md, scope xBRIEF files, or structured data files\n3. ! **Structural issues** -- malformed CHANGELOG entries, broken table rows, mismatched index entries, invalid JSON/YAML\n4. ! **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)\n5. ! **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\n6. ! **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\n7. ! **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\n\n⊗ Commit without re-reading all modified files first.\n\n## Commit Strategy\n\n- ! Default to one story per branch/PR. Batching multiple stories in one branch requires explicit operator approval and a short rationale.\n- ! Create a checkpoint commit after each completed story before beginning another story.\n- ! Use iteration fast lane before checkpoint commits; run full `task check` at PR/merge chokepoint (#1704)\n- ⊗ Claim checks passed without running them\n\n```\nfeat(phase-1): scaffold project structure\nfeat(phase-1): implement core data models with tests\nfeat(phase-2): add REST API endpoints with integration tests\n```\n\n## Error Recovery\n\n- ! Tests fail → fix them; ⊗ skip or weaken assertions\n- ! Coverage drops → write more tests; ⊗ exclude files\n- ! Lint/type errors → fix them; ≉ add ignore comments without documented reason\n- ! Scope xBRIEF ambiguous -> ask user; ⊗ guess\n- ! Scope needs changes -> propose, get approval, update the scope xBRIEF first\n\n## Completion\n\n- ! When all phases pass and `task check` is green, complete each implemented story via `task scope:complete -- <active-story-path>` before final PR handoff.\n\n> \"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.\"\n\n## Anti-Patterns\n\n- ⊗ Skip tests or write them after implementation\n- ⊗ Ignore `task check` failures\n- ⊗ Implement things not in scope xBRIEF without asking\n- ⊗ Read every deft file upfront\n- ⊗ Move to next phase before current passes checks\n- ⊗ Make commits without running iteration-lane validation; ⊗ skip full `task check` at PR/merge chokepoint (#1704)\n- ⊗ Proceed without USER.md -- always run the USER.md Gate first\n- ⊗ Re-run `directive init`, cold `session:start`, migrate, or re-copy pin scopes after offline seed when ritual is already complete (#3010)\n- ⊗ Run full `task check` after every intermediate scope of an approved multi-scope batch when the last merge-chokepoint check was green (#3012)\n- ⊗ Promote scopes one-by-one for a known multi-scope pin when `scope:promote --batch` would stage them in one turn (#3011)\n\n- ⊗ Spawn an implementation agent or invoke a code-writing tool against a xBRIEF that has not passed `task xbrief:preflight` (which wraps `scripts/preflight_implementation.py`) -- always run the Step 0 Implementation Preflight (#810) first; satisfy via `task xbrief:activate <path>`\n- ⊗ Proceed without `COST-ESTIMATE.md` and a recorded build / rescope / no-build / skip(+reason) decision -- always run the Cost Phase Gate (#739) first\n- ⊗ Proceed with implementation when the build or test toolchain is unavailable -- always run the Toolchain Gate (Step 2) first\n- ⊗ Proceed to next task or phase without tests passing -- testing is a hard gate, not a cleanup step\n- ⊗ Skip the Change Lifecycle Gate because the user said \"proceed\" -- broad approval does not satisfy the confirmation gate\n- ⊗ 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`\n- ⊗ Add a prohibition (`!` or `⊗`) without scanning the same file for conflicting softer-strength rules (`~`, `≉`) that reference the same term\n",
|
|
33
33
|
"frontmatter_extra": null
|
|
34
34
|
},
|
|
35
35
|
{
|
|
@@ -158,7 +158,7 @@
|
|
|
158
158
|
],
|
|
159
159
|
"path": "skills/deft-directive-pre-pr/SKILL.md",
|
|
160
160
|
"version": "0.1",
|
|
161
|
-
"body": "# Deft Directive Pre-PR -- Read, Write, Lint, Diff, Loop\n\nStructured self-review loop agents run before submitting a PR. Catches inconsistencies, missing enforcement markers, incomplete acceptance criteria, scope creep, and unintended changes before they reach the reviewer.\n\nLegend (from RFC2119): !=MUST, ~=SHOULD, ≉=SHOULD NOT, ⊗=MUST NOT, ?=MAY.\n\n**See also**: [deft-directive-review-cycle](../deft-directive-review-cycle/SKILL.md) | [deft-directive-build](../deft-directive-build/SKILL.md) | [RWLDL tool](../../tools/RWLDL.md)\n\n> **Formerly `deft-rwldl`** -- renamed to clearly communicate the skill's purpose (iterative pre-PR quality loop).\n\n## Branch-Protection Policy Guard\n\n! Before entering Phase 1 (Read), run the skill-level branch-policy guard documented in `scripts/policy.py` / `scripts/preflight_branch.py` (#746 / #747). Halt before any state mutation (the Phase 2 Write phase, the Phase 3 Lint phase that may touch files) when the policy is unresolvable AND no env-var bypass is active:\n\n```\nuv run python scripts/preflight_branch.py --project-root . --quiet || exit 1\n```\n\nor invoke `task verify:branch`. Pre-PR is the last gate before push, so a stale / unresolvable policy here is the highest-leverage place to catch the bug before it reaches the bot reviewer.\n\n## Deterministic Questions Contract\n\n! Every numbered-menu prompt rendered in this skill (per-finding decision menus in Phase 4 Diff, the Phase 5 Loop restart-vs-exit gate) MUST follow [`../../contracts/deterministic-questions.md`](../../contracts/deterministic-questions.md): the final two numbered options MUST be `Discuss` and `Back`, in that order. The Discuss-pause semantic is documented verbatim there -- implicit resumption is forbidden.\n\n\n## Ordered-plan target gate (#2402)\n\n! Before opening or pushing a PR, when an ordered-plan sequence may be active, verify the work unit matches the current authorized entry:\n\n1. Resolve the current entry kind and id:\n\n```\ntask plan-sequence:current\n```\n\n Use `task plan-sequence:current -- --json` when you need machine-readable `kind` / `id` fields from the current entry.\n\n2. Verify with the **entry kind** (not hardcoded `pr` — `story` / `issue` entries are common):\n\n```\ntask verify:plan-sequence -- --target-kind <entry-kind> --target <entry-id>\n```\n\n- ! Exit non-zero → fail closed; do not open an unauthorized PR.\n- ! Exit 0 with \"skipped (no active ordered-plan sequence)\" → proceed under normal pre-PR rules.\n- ⊗ Hardcode `--target-kind pr` when the current entry is `kind=story` or `kind=issue` — the verifier matches entry kind exactly (#2662).\n- ! After the PR's review cycle completes successfully, run `task plan-sequence:advance` so \"next\" resolves to the following entry (or exhausted).\n- ⊗ Treat skill-chaining or \"what's next?\" as permission to open a PR outside the current sequence entry.\n\n## Gate throughput — iteration fast lane vs merge chokepoint (#1704)\n\n> **Invariant:** every change MUST pass the full gate at least once before merge. Pre-PR is the merge chokepoint — NOT every iteration commit.\n\n- ! **Iteration lane (Phases 2–3 loop):** use affected/static gates on changed paths — `vitest run --coverage <paths>`, relevant `verify:*` on touched files, `task coverage:hotspots` — instead of full `task check` on every RWLDL iteration.\n- ! **Merge chokepoint (Phase 3 Lint exit + final confirm):** run full `task check` once before push/PR; Phase 3c targeted coverage precedes but does not replace the full gate.\n- ! **Escape-rate safety (#1703 Tier-1):** before recommending fleet-wide fast-lane tightening, cite `#1703` Tier-1 telemetry (`helped/crud-metrics.jsonl`) and `task eval:health` — do NOT invent a separate escape-rate surface.\n- ~ **In-engine incrementality (#1713):** content-hash cache + runner-delegated affected selection are sibling work (#1713).\n- ⊗ Treat Phase 3c targeted coverage alone as PR-ready without full `task check` at the merge chokepoint.\n\n## When to Use\n\n- ! Before pushing a branch for PR creation\n- ! After completing implementation but before the final merge-chokepoint `task check` (#1704)\n- ~ After addressing bot reviewer findings (run one RWLDL pass before pushing the fix batch)\n- ? During mid-implementation checkpoints on large changes\n\n## Loop Phases\n\nEach iteration proceeds through all phases in order. Do NOT skip phases or reorder them.\n\n### Phase 1 -- Read\n\n! Re-read each changed file end-to-end (`git diff master --name-only` to get the list).\n\n- ! Read every changed file in full -- do not skim or skip sections\n- ! Compare each file against its scope xBRIEF acceptance criteria in `xbrief/active/`\n- ~ If changed files include `xbrief/PROJECT-DEFINITION.xbrief.json`, a configured `codebase-map` provider artifact, or `.planning/codebase/MAP.md`, read the MAP and canonical metadata together. The MAP is orientation; `plan.architecture.codeStructure` and provider artifacts remain authoritative.\n- ! 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\n- ! When strengthening a rule (e.g. upgrading `~` to `!`), grep for the term in the full file and verify no weaker-strength duplicate remains\n- ~ Note any inconsistencies, missing RFC2119 markers, stale cross-references, or incomplete sections\n- ~ Check that CHANGELOG.md entries match the actual changes made\n\n### Phase 2 -- Write\n\n! Fix any issues found in the Read phase.\n\n- ! Fix inconsistencies, add missing RFC2119 enforcement markers (`!`, `~`, `⊗`)\n- ! Complete any incomplete acceptance criteria or missing content\n- ! Update stale cross-references\n- ~ Improve clarity where intent is ambiguous\n- ⊗ Make changes beyond the scope of the current task -- if you notice unrelated issues, file them as ideas or future work, do not fix them now\n\n### Phase 3 -- Lint\n\n! Run the merge-chokepoint gate and fix any failures (#1704).\n\n- ! Run full `task check` (fmt + lint + typecheck + tests + coverage + verify:*) — the merge chokepoint, not every RWLDL iteration\n- ! Fix all failures before proceeding to Phase 3b\n- ~ If a lint fix requires changing a file, that counts as a change for the Loop phase\n\n~ **Windows + Grok Build (#1353):** Avoid `|`, `>`, or `2>&1` in `run_terminal_command` strings -- use Python `pathlib`/`subprocess` or plain task commands instead.\n\n### Phase 3c -- Coverage headroom (#2683)\n\n! Before the full `task check` coverage gate, run targeted coverage on changed modules and verify headroom above the project floor.\n\n- ! Run targeted coverage first: `vitest run --coverage <changed-paths>` (or language equivalent) — not only full `task check`.\n- ! Exercise both sides of new branches (ternary / early-return / catch / default switch / `||` / `??`).\n- ! Treat barely ≥ floor as insufficient — aim for ≥ floor + 0.3–0.5pp headroom on the branch metric relative to **your project's** vitest/coverage floor (may differ from 85%).\n- ! Run `task coverage:hotspots` / `deft coverage:hotspots` to locate uncovered branches before opening a PR; complements `deft verify:forward-coverage` (#1310) and `--allow-coverage-debt=#N` (#2573).\n\n### Phase 3b -- Auto-Render Exports\n\n! If `xbrief/specification.xbrief.json` exists, refresh rendered exports before the diff check:\n\n- ! Run `task prd:render` if `PRD.md` already exists in the project root\n- ! Run `task spec:render` if `SPECIFICATION.md` already exists and does not contain `<!-- deft:deprecated-redirect -->`\n- ! If `plan.architecture.codeStructure`, a configured `codebase-map` provider artifact, or `.planning/codebase/MAP.md` changed, run `task codebase:map` and `task verify:codebase-map-fresh` so the generated orientation projection matches its canonical inputs.\n- ⊗ Create export files that don't already exist -- only refresh existing ones\n- ⊗ Hand-edit `.planning/codebase/MAP.md` to satisfy review; update canonical metadata or provider artifacts, then regenerate it\n\n### Phase 4 -- Diff\n\n! Review the full diff against the base branch for unintended changes.\n\n```\ngit --no-pager diff master\n```\n\n- ! Verify no files outside the task scope were modified\n- ! Check for scope creep -- changes that go beyond the spec task acceptance criteria\n- ! Verify no debug code, TODO comments, or temporary scaffolding remains\n- ! Confirm no unintended whitespace-only changes or formatting drift\n- ! **Run `task pr:check-closing-keywords -- --pr <N>` (or pass `--body-file` / `--commits-file` for offline checking) before opening the PR; refuse to push if findings (#737)**. The lint scans both the PR body AND every commit message for closing-keyword tokens (`close|closes|closed|fix|fixes|fixed|resolve|resolves|resolved`) followed by `#\\d+` in negation / quotation / example / code-block contexts. The recurrence record is the Layer 1 / Layer 2 / Layer 3 stack: #167 (post-merge close-verify), #697 / #698 (negation-context substring match), #401 / #700 (persistent `closingIssuesReferences` link), #735 (squash body containing `DOES NOT CLOSE #734` auto-closed #734). When the lint surfaces a known-safe occurrence (e.g. test fixtures that legitimately exercise the trigger token), pass `--allow-known-false-positives <issue-numbers>` to suppress -- DO NOT silently delete the lint invocation\n- ~ Verify the diff tells a coherent story -- a reviewer reading it top-to-bottom should understand the change\n- ~ If the PR adds or moves any documentation, verify each new doc is reachable from the AGENTS.md reference chain -- an orphan doc is discovered <10% of the time yet still costs context when found (the reference-chain contract, #644 / #647). Add a pointer or fold it in rather than leaving it stranded.\n\n### Phase 5 -- Loop\n\n! Decide whether to restart or exit.\n\n- ! If ANY fixes were made in Phase 2 (Write) or Phase 3 (Lint): restart from Phase 1 (Read)\n- ~ Phase 3b auto-renders are intentional output refreshes; they do NOT trigger a loop restart\n- ! If a full Read-Write-Lint-Diff cycle produced zero changes: exit the loop\n- ~ Track iteration count -- if you exceed 3 iterations, pause and assess whether you are oscillating between competing fixes\n\n## Exit Condition\n\n! Exit when a complete Read-Write-Lint-Diff cycle produces **zero changes** -- no file edits in Write, no lint fixes in Lint, and no scope issues in Diff.\n\nAfter exiting:\n- ! Run `task check` one final time to confirm clean state\n- ~ The branch is now ready for push and PR creation\n\n## Anti-Patterns\n\n- ⊗ Submit a PR without running the RWLDL loop -- every PR branch should pass at least one full cycle\n- ⊗ Exit the loop after the Lint phase without completing the Diff phase -- Diff catches scope creep and unintended changes that Lint cannot detect\n- ⊗ Skip the Read phase and jump directly to Lint -- Read catches semantic issues (missing content, wrong RFC2119 markers, incomplete acceptance criteria) that linters do not check\n- ⊗ Make out-of-scope fixes during Write -- this introduces scope creep that Diff will flag, forcing another iteration\n- ⊗ Ignore the iteration count -- more than 3 iterations usually indicates oscillating fixes or an unclear spec task\n- ⊗ Add a prohibition (`!` or `⊗`) without scanning the same file for conflicting softer-strength rules (`~`, `≉`) that reference the same term\n- ⊗ Skip `task pr:check-closing-keywords` (#737) before pushing a PR. The negation-context substring match is the Layer 0 (prevention) gate that prevents the recurring auto-close of umbrella / staying-OPEN issues observed in #697 (closed #642), #401 (closed #642), #700 (closed #233), and #735 (closed #734) -- each incident required manual reopen and downstream cleanup. The lint's three-state exit (0 clean / 1 hits found / 2 config error) MUST be treated as a hard refusal: rewrite the PR body / commit messages until clean, OR pass `--allow-known-false-positives` ONLY for legitimately-quoted occurrences (test fixtures, documentation that discusses the trigger token literally). See `skills/deft-directive-swarm/SKILL.md` Phase 6 Step 1 for the corresponding Layer 3 (recovery) `pr:check-protected-issues` rule (#701)\n",
|
|
161
|
+
"body": "# Deft Directive Pre-PR -- Read, Write, Lint, Diff, Loop\n\nStructured self-review loop agents run before submitting a PR. Catches inconsistencies, missing enforcement markers, incomplete acceptance criteria, scope creep, and unintended changes before they reach the reviewer.\n\nLegend (from RFC2119): !=MUST, ~=SHOULD, ≉=SHOULD NOT, ⊗=MUST NOT, ?=MAY.\n\n**See also**: [deft-directive-review-cycle](../deft-directive-review-cycle/SKILL.md) | [deft-directive-build](../deft-directive-build/SKILL.md) | [RWLDL tool](../../tools/RWLDL.md)\n\n> **Formerly `deft-rwldl`** -- renamed to clearly communicate the skill's purpose (iterative pre-PR quality loop).\n\n## Branch-Protection Policy Guard\n\n! Before entering Phase 1 (Read), run the skill-level branch-policy guard documented in `scripts/policy.py` / `scripts/preflight_branch.py` (#746 / #747). Halt before any state mutation (the Phase 2 Write phase, the Phase 3 Lint phase that may touch files) when the policy is unresolvable AND no env-var bypass is active:\n\n```\nuv run python scripts/preflight_branch.py --project-root . --quiet || exit 1\n```\n\nor invoke `task verify:branch`. Pre-PR is the last gate before push, so a stale / unresolvable policy here is the highest-leverage place to catch the bug before it reaches the bot reviewer.\n\n## Deterministic Questions Contract\n\n! Every numbered-menu prompt rendered in this skill (per-finding decision menus in Phase 4 Diff, the Phase 5 Loop restart-vs-exit gate) MUST follow [`../../contracts/deterministic-questions.md`](../../contracts/deterministic-questions.md): the final two numbered options MUST be `Discuss` and `Back`, in that order. The Discuss-pause semantic is documented verbatim there -- implicit resumption is forbidden.\n\n\n## Ordered-plan target gate (#2402)\n\n! Before opening or pushing a PR, when an ordered-plan sequence may be active, verify the work unit matches the current authorized entry:\n\n1. Resolve the current entry kind and id:\n\n```\ntask plan-sequence:current\n```\n\n Use `task plan-sequence:current -- --json` when you need machine-readable `kind` / `id` fields from the current entry.\n\n2. Verify with the **entry kind** (not hardcoded `pr` — `story` / `issue` entries are common):\n\n```\ntask verify:plan-sequence -- --target-kind <entry-kind> --target <entry-id>\n```\n\n- ! Exit non-zero → fail closed; do not open an unauthorized PR.\n- ! Exit 0 with \"skipped (no active ordered-plan sequence)\" → proceed under normal pre-PR rules.\n- ⊗ Hardcode `--target-kind pr` when the current entry is `kind=story` or `kind=issue` — the verifier matches entry kind exactly (#2662).\n- ! After the PR's review cycle completes successfully, run `task plan-sequence:advance` so \"next\" resolves to the following entry (or exhausted).\n- ⊗ Treat skill-chaining or \"what's next?\" as permission to open a PR outside the current sequence entry.\n\n## Gate throughput — iteration fast lane vs merge chokepoint (#1704)\n\n> **Invariant:** every change MUST pass the full gate at least once before merge. Pre-PR is the merge chokepoint — NOT every iteration commit.\n\n- ! **Iteration lane (Phases 2–3 loop):** use affected/static gates on changed paths — `vitest run --coverage <paths>`, relevant `verify:*` on touched files, `task coverage:hotspots` — instead of full `task check` on every RWLDL iteration.\n- ! **Merge chokepoint (Phase 3 Lint exit + final confirm):** run full `task check` once before push/PR; Phase 3c targeted coverage precedes but does not replace the full gate.\n- ! **Escape-rate safety (#1703 Tier-1):** before recommending fleet-wide fast-lane tightening, cite `#1703` Tier-1 telemetry (`helped/crud-metrics.jsonl`) and `task eval:health` — do NOT invent a separate escape-rate surface.\n- ~ **In-engine incrementality (#1713):** content-hash cache + runner-delegated affected selection are sibling work (#1713).\n- ⊗ Treat Phase 3c targeted coverage alone as PR-ready without full `task check` at the merge chokepoint.\n\n## When to Use\n\n- ! Before pushing a branch for PR creation\n- ! After completing implementation but before the final merge-chokepoint `task check` (#1704)\n- ~ After addressing bot reviewer findings (run one RWLDL pass before pushing the fix batch)\n- ? During mid-implementation checkpoints on large changes\n\n## Loop Phases\n\nEach iteration proceeds through all phases in order. Do NOT skip phases or reorder them.\n\n### Phase 1 -- Read\n\n! Re-read each changed file end-to-end (`git diff master --name-only` to get the list).\n\n- ! Read every changed file in full -- do not skim or skip sections\n- ! Compare each file against its scope xBRIEF acceptance criteria in `xbrief/active/`\n- ~ If changed files include `xbrief/PROJECT-DEFINITION.xbrief.json`, a configured `codebase-map` provider artifact, or `.planning/codebase/MAP.md`, read the MAP and canonical metadata together. The MAP is orientation; `plan.architecture.codeStructure` and provider artifacts remain authoritative.\n- ! 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\n- ! When strengthening a rule (e.g. upgrading `~` to `!`), grep for the term in the full file and verify no weaker-strength duplicate remains\n- ~ Note any inconsistencies, missing RFC2119 markers, stale cross-references, or incomplete sections\n- ~ Check that CHANGELOG.md entries match the actual changes made\n\n### Phase 2 -- Write\n\n! Fix any issues found in the Read phase.\n\n- ! Fix inconsistencies, add missing RFC2119 enforcement markers (`!`, `~`, `⊗`)\n- ! Complete any incomplete acceptance criteria or missing content\n- ! Update stale cross-references\n- ~ Improve clarity where intent is ambiguous\n- ⊗ Make changes beyond the scope of the current task -- if you notice unrelated issues, file them as ideas or future work, do not fix them now\n\n### Phase 3 -- Lint\n\n! Run the merge-chokepoint gate and fix any failures (#1704).\n\n- ! Run full `task check` (fmt + lint + typecheck + tests + coverage + verify:*) — the merge chokepoint, not every RWLDL iteration\n- ! Fix all failures before proceeding to Phase 3b\n- ~ If a lint fix requires changing a file, that counts as a change for the Loop phase\n\n~ **Windows + Grok Build (#1353):** Avoid `|`, `>`, or `2>&1` in `run_terminal_command` strings -- use Python `pathlib`/`subprocess` or plain task commands instead.\n\n### Phase 3c -- Coverage headroom (#2683)\n\n! Before the full `task check` coverage gate, run targeted coverage on changed modules and verify headroom above the project floor.\n\n- ! Run targeted coverage first: `vitest run --coverage <changed-paths>` (or language equivalent) — not only full `task check`.\n- ! Exercise both sides of new branches (ternary / early-return / catch / default switch / `||` / `??`).\n- ! Treat barely ≥ floor as insufficient — aim for ≥ floor + 0.3–0.5pp headroom on the branch metric relative to **your project's** vitest/coverage floor (may differ from 85%).\n- ! Run `task coverage:hotspots` / `deft coverage:hotspots` to locate uncovered branches before opening a PR; complements `deft verify:forward-coverage` (#1310) and `--allow-coverage-debt=#N` (#2573).\n\n### Phase 3b -- Auto-Render Exports\n\n! If `xbrief/specification.xbrief.json` exists, refresh rendered exports before the diff check:\n\n- ! Run `task prd:render` if `PRD.md` already exists in the project root\n- ! Run `task spec:render` if `SPECIFICATION.md` already exists and does not contain `<!-- deft:deprecated-redirect -->`\n- ! If `plan.architecture.codeStructure`, a configured `codebase-map` provider artifact, or `.planning/codebase/MAP.md` changed, run `task codebase:map` and `task verify:codebase-map-fresh` so the generated orientation projection matches its canonical inputs.\n- ⊗ Create export files that don't already exist -- only refresh existing ones\n- ⊗ Hand-edit `.planning/codebase/MAP.md` to satisfy review; update canonical metadata or provider artifacts, then regenerate it\n\n### Phase 4 -- Diff\n\n! Review the full diff against the base branch for unintended changes.\n\n```\ngit --no-pager diff master\n```\n\n- ! Verify no files outside the task scope were modified\n- ! Check for scope creep -- changes that go beyond the spec task acceptance criteria\n- ! Verify no debug code, TODO comments, or temporary scaffolding remains\n- ! Confirm no unintended whitespace-only changes or formatting drift\n- ! **Closing-keyword policy (#3015 class D / #737 Layer 0):** Default PR body uses `Tracking: #N` / `Related: #N` / `Refs #N` only. Use `Closes` / `Fixes` / `Resolves #N` only when the **full issue DoD** is met (not Phase A partial / multi-phase mid-stream).\n- ⊗ Write `Closes #N Phase A`, `only if`, `partial`, or other conditional English around a real closing keyword — GitHub ignores the condition and auto-closes (#3015 enterprize#29).\n- ! **Run `task pr:check-closing-keywords` before opening the PR (default mode `both` = FP #737 + intent #3015).** Offline: `--body-file` / `--commits-file`. Scans body and commits for closing-keyword tokens in negation / quotation / example / code-block contexts (FP) and for any unallowlisted real close (intent). When full DoD close is intentional, pass `--allow-close <N,M>` (CLI allowlist only — body trailers are not an authorization path). FP-only: `--mode fp`. Known-safe quoted tokens: `--allow-known-false-positives`. Recurrence stack: #167, #697 / #698, #401 / #700, #735 (class A), #3015 (class D enterprize#29).\n- ~ Verify the diff tells a coherent story -- a reviewer reading it top-to-bottom should understand the change\n- ~ If the PR adds or moves any documentation, verify each new doc is reachable from the AGENTS.md reference chain -- an orphan doc is discovered <10% of the time yet still costs context when found (the reference-chain contract, #644 / #647). Add a pointer or fold it in rather than leaving it stranded.\n\n### Phase 5 -- Loop\n\n! Decide whether to restart or exit.\n\n- ! If ANY fixes were made in Phase 2 (Write) or Phase 3 (Lint): restart from Phase 1 (Read)\n- ~ Phase 3b auto-renders are intentional output refreshes; they do NOT trigger a loop restart\n- ! If a full Read-Write-Lint-Diff cycle produced zero changes: exit the loop\n- ~ Track iteration count -- if you exceed 3 iterations, pause and assess whether you are oscillating between competing fixes\n\n## Exit Condition\n\n! Exit when a complete Read-Write-Lint-Diff cycle produces **zero changes** -- no file edits in Write, no lint fixes in Lint, and no scope issues in Diff.\n\nAfter exiting:\n- ! Run `task check` one final time to confirm clean state\n- ~ The branch is now ready for push and PR creation\n\n## Anti-Patterns\n\n- ⊗ Submit a PR without running the RWLDL loop -- every PR branch should pass at least one full cycle\n- ⊗ Exit the loop after the Lint phase without completing the Diff phase -- Diff catches scope creep and unintended changes that Lint cannot detect\n- ⊗ Skip the Read phase and jump directly to Lint -- Read catches semantic issues (missing content, wrong RFC2119 markers, incomplete acceptance criteria) that linters do not check\n- ⊗ Make out-of-scope fixes during Write -- this introduces scope creep that Diff will flag, forcing another iteration\n- ⊗ Ignore the iteration count -- more than 3 iterations usually indicates oscillating fixes or an unclear spec task\n- ⊗ Add a prohibition (`!` or `⊗`) without scanning the same file for conflicting softer-strength rules (`~`, `≉`) that reference the same term\n- ⊗ Skip `task pr:check-closing-keywords` (#737) before pushing a PR. Intent mode (#3015) also refuses bare/conditional real `Closes #N` without `--allow-close`. The negation-context substring match is the Layer 0 (prevention) gate that prevents the recurring auto-close of umbrella / staying-OPEN issues observed in #697 (closed #642), #401 (closed #642), #700 (closed #233), and #735 (closed #734) -- each incident required manual reopen and downstream cleanup. The lint's three-state exit (0 clean / 1 hits found / 2 config error) MUST be treated as a hard refusal: rewrite the PR body / commit messages until clean, OR pass `--allow-known-false-positives` ONLY for legitimately-quoted occurrences (test fixtures, documentation that discusses the trigger token literally). See `skills/deft-directive-swarm/SKILL.md` Phase 6 Step 1 for the corresponding Layer 3 (recovery) `pr:check-protected-issues` rule (#701)\n",
|
|
162
162
|
"frontmatter_extra": null
|
|
163
163
|
},
|
|
164
164
|
{
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
# No in-band signaling / absence is not a decision (#1695)
|
|
2
|
+
|
|
3
|
+
Coding-standards pattern: do not overload one field (or its
|
|
4
|
+
presence/absence) to carry two orthogonal facts. Separate **value** from
|
|
5
|
+
**decision-provenance**. Triggered by the wipCap onboarding contradiction
|
|
6
|
+
(#1694).
|
|
7
|
+
|
|
8
|
+
Legend (from RFC2119): !=MUST, ~=SHOULD, ≉=SHOULD NOT, ⊗=MUST NOT, ?=MAY.
|
|
9
|
+
|
|
10
|
+
**Load when:** modeling a config/policy field, or any onboarding /
|
|
11
|
+
decision / lifecycle state that might be inferred from whether a value
|
|
12
|
+
is present.
|
|
13
|
+
|
|
14
|
+
**⚠️ See also**:
|
|
15
|
+
- [../coding/coding.md](../coding/coding.md) — always-loaded Design
|
|
16
|
+
Principles floor (`**State & Data Modeling (#1695)**`)
|
|
17
|
+
- [../coding/coding.md](../coding/coding.md) — resolver `source`
|
|
18
|
+
provenance (typed | default | default-on-error) for *value*-provenance
|
|
19
|
+
|
|
20
|
+
## The pattern
|
|
21
|
+
|
|
22
|
+
**In-band signaling** smuggles control or metadata through the data
|
|
23
|
+
channel. **Out-of-band signaling** gives the control signal its own
|
|
24
|
+
field.
|
|
25
|
+
|
|
26
|
+
The cautionary prior art is the blue-box / 2600 Hz tone: phone systems
|
|
27
|
+
shared the control signal with the voice channel, so a tone on the data
|
|
28
|
+
path could seize trunk control. The same footgun appears under several
|
|
29
|
+
names:
|
|
30
|
+
|
|
31
|
+
- Overloaded NULL / sentinel values (SQL NULL meaning "unknown" *and*
|
|
32
|
+
"not applicable" *and* "use default")
|
|
33
|
+
- Connascence of Meaning (Page-Jones) — components silently agreeing
|
|
34
|
+
what a magic value or absence *means*
|
|
35
|
+
- "Make illegal states unrepresentable" — an ambiguous
|
|
36
|
+
"absent-but-decided vs absent-and-undecided" state should not be
|
|
37
|
+
expressible in one field
|
|
38
|
+
- Single Responsibility applied to data — one field, one reason to
|
|
39
|
+
change
|
|
40
|
+
|
|
41
|
+
- ! MUST encode exactly one fact per field
|
|
42
|
+
- ! MUST record decision / onboarding / lifecycle state in an explicit
|
|
43
|
+
out-of-band marker when a workflow needs to know a human chose
|
|
44
|
+
- ⊗ MUST NOT infer decision-state from whether a value field is present
|
|
45
|
+
- ⊗ MUST NOT treat field absence as "incomplete" when omission is a
|
|
46
|
+
deliberate valid default
|
|
47
|
+
|
|
48
|
+
## The orthogonality test
|
|
49
|
+
|
|
50
|
+
Ask: can fact A and fact B vary independently?
|
|
51
|
+
|
|
52
|
+
| Fact A (value) | Fact B (decided?) | Independent? |
|
|
53
|
+
| --- | --- | --- |
|
|
54
|
+
| value == default | decided = true (accepted default) | yes |
|
|
55
|
+
| value == default | decided = false (never considered) | yes |
|
|
56
|
+
| value == override | decided = true | yes |
|
|
57
|
+
| value == override | decided = false | usually illegal |
|
|
58
|
+
|
|
59
|
+
If two facts can vary independently, they MUST live in separate slots.
|
|
60
|
+
If one fact strictly implies the other, sharing a slot is fine:
|
|
61
|
+
|
|
62
|
+
- **True `Optional<T>`** — absence means "no value" and there is no
|
|
63
|
+
second "was this considered?" question
|
|
64
|
+
- **Tombstones** — a dedicated deleted/absent sentinel that only means
|
|
65
|
+
lifecycle, not a configured value
|
|
66
|
+
- **Value-provenance `source`** — once a resolved value exists, source
|
|
67
|
+
∈ {typed, default, default-on-error} is a property *of that resolve*,
|
|
68
|
+
not a second independent human decision
|
|
69
|
+
|
|
70
|
+
Worked examples:
|
|
71
|
+
|
|
72
|
+
1. **WIP cap onboarding (#1694)** — `plan.policy.wipCap` value vs "did
|
|
73
|
+
the operator consider a cap?" Independent; use
|
|
74
|
+
`x-directive/onboarding.wipCapDecided`.
|
|
75
|
+
2. **Feature flag default** — `enabled: false` may mean "deliberately
|
|
76
|
+
off" or "never configured." If product needs the distinction, store
|
|
77
|
+
an explicit decided marker.
|
|
78
|
+
3. **Optional timeout** — absence of `timeoutMs` means "use library
|
|
79
|
+
default" and no workflow asks whether a human considered it. One
|
|
80
|
+
fact; one field is fine.
|
|
81
|
+
|
|
82
|
+
## Three kinds of provenance in directive
|
|
83
|
+
|
|
84
|
+
Directive already separates two of three facts for policy resolution:
|
|
85
|
+
|
|
86
|
+
| Kind | What it answers | Modeled? |
|
|
87
|
+
| --- | --- | --- |
|
|
88
|
+
| **Effective value** | What int/string do we use right now? | yes (the field or default) |
|
|
89
|
+
| **Value-provenance** | Override vs framework default vs error-fallback? | yes (`source` on resolvers / `PolicyField`) |
|
|
90
|
+
| **Decision-provenance** | Did a human choose this (including accepting default)? | **must be modeled out-of-band** |
|
|
91
|
+
|
|
92
|
+
- ! MUST generalize the `source` discipline to decision-provenance:
|
|
93
|
+
never fake "operator decided" from field presence
|
|
94
|
+
- ! MUST leave value fields to mean exactly one thing (e.g.
|
|
95
|
+
`plan.policy.wipCap` = deliberate non-default override only)
|
|
96
|
+
- ~ SHOULD keep decision markers under an `x-directive/` namespaced
|
|
97
|
+
block when the value lives on PROJECT-DEFINITION
|
|
98
|
+
|
|
99
|
+
## Canonical worked example — wipCap onboarding (#1694)
|
|
100
|
+
|
|
101
|
+
**Before:** `_classify_onboarding` / `classifyOnboarding` treated
|
|
102
|
+
absent `plan.policy.wipCap` as incomplete onboarding. Accepting the
|
|
103
|
+
framework default (omit-by-design, #1186 D1 / #1250) left the field
|
|
104
|
+
absent forever, so the nudge never cleared. Setting a non-default
|
|
105
|
+
cleared the nudge but broke `test_policy_omits_wip_cap`. The nudge was
|
|
106
|
+
structurally unsatisfiable on deft's own repo.
|
|
107
|
+
|
|
108
|
+
**Root cause:** one field carried two orthogonal facts — configured
|
|
109
|
+
value *and* decision-made.
|
|
110
|
+
|
|
111
|
+
**After (#1694 direction 2):**
|
|
112
|
+
|
|
113
|
+
- `plan.policy.wipCap` (or `x-directive/policy.wipCap`) means only a
|
|
114
|
+
deliberate non-default override
|
|
115
|
+
- `plan["x-directive/onboarding"].wipCapDecided` records that the
|
|
116
|
+
operator considered WIP cap (including accepting the default)
|
|
117
|
+
- `writeWipCapDecision` / `writeWipCap` (default path) set the marker
|
|
118
|
+
without materializing the value field
|
|
119
|
+
- `classifyOnboarding` reads decision-provenance, not field presence
|
|
120
|
+
|
|
121
|
+
Greenfield consumers still get prompted until they run
|
|
122
|
+
`deft triage:welcome --onboard` (or otherwise record the decision).
|
|
123
|
+
Deft's own repo commits the marker with `acceptedDefault: true` and
|
|
124
|
+
stays omit-by-design green.
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
# Tool-call taxonomy — explore / commit / verify (#2967)
|
|
2
|
+
|
|
3
|
+
Deterministic activity buckets for swarm and review-cycle operators. Use
|
|
4
|
+
this taxonomy when skimming tool logs, monitor status lines, or batch
|
|
5
|
+
briefs so “ran N tools” becomes a structured mix.
|
|
6
|
+
|
|
7
|
+
Legend (from RFC2119): !=MUST, ~=SHOULD, ≉=SHOULD NOT, ⊗=MUST NOT, ?=MAY.
|
|
8
|
+
|
|
9
|
+
**Load when:** writing swarm monitor status, review-cycle batch briefs,
|
|
10
|
+
PR evidence one-liners, usage metrics that group tool events, or any
|
|
11
|
+
harness surface that aggregates agent tool calls.
|
|
12
|
+
|
|
13
|
+
**Implementation:** pure rule-first API in
|
|
14
|
+
`packages/core/src/tool-events/` (`classifyToolEvent`,
|
|
15
|
+
`summarizeToolEvents`). No LLM per event.
|
|
16
|
+
|
|
17
|
+
**Related but distinct:**
|
|
18
|
+
- `packages/core/src/hooks/classify/` (#2950) — PreToolUse write-intent
|
|
19
|
+
and host payload identity. Share vocabulary only; do not merge.
|
|
20
|
+
- Causal graph work (#2966) may consume these buckets as node kinds.
|
|
21
|
+
|
|
22
|
+
**⚠️ See also**:
|
|
23
|
+
- [../swarm/swarm.md](../swarm/swarm.md) — multi-agent coordination
|
|
24
|
+
- [../skills/deft-directive-swarm/references/core-phase-4.md](../skills/deft-directive-swarm/references/core-phase-4.md) — monitor status line consumer
|
|
25
|
+
- [../skills/deft-directive-review-cycle/SKILL.md](../skills/deft-directive-review-cycle/SKILL.md) — review batch surfaces
|
|
26
|
+
|
|
27
|
+
## Buckets
|
|
28
|
+
|
|
29
|
+
| Bucket | Meaning | Typical tools / commands |
|
|
30
|
+
|--------|---------|---------------------------|
|
|
31
|
+
| `explore` | Read / search / fetch-for-analysis | `Read`, `Grep`, `Glob`, `list_dir`, `SemanticSearch`, `web_search`, `git status`/`log`/`diff`, `gh … view`/`list`, `rg`, `ghx` |
|
|
32
|
+
| `commit` | Mutate product or SCM state | `Write`, `Edit`, `StrReplace`, `ApplyPatch`, `Delete`, `git add`/`commit`/`push`, `gh pr create`, mutating `gh api -X POST` |
|
|
33
|
+
| `verify` | Run a **proven** gate or test | `vitest`, `pytest`, `go test`, `cargo test`, `npm test`, `task check`, `task verify:*`, `tsc`, `biome`, `eslint`, `task pr:watch` |
|
|
34
|
+
| `coordinate` | Session / swarm / handoff | `Task`, `spawn_subagent`, `start_agent`, `sessions_spawn`, `TodoWrite`, `AskQuestion`, `task swarm:*`, `task scope:*` |
|
|
35
|
+
| `unknown` | Explicit residual | Missing name, shell without command, ambiguous names, unlisted bins |
|
|
36
|
+
|
|
37
|
+
## Misclassification policy
|
|
38
|
+
|
|
39
|
+
- ! MUST prefer `unknown` over a wrong `verify`. False-positive verify
|
|
40
|
+
hides “shipped without gates”; residual unknown is recoverable.
|
|
41
|
+
- ! MUST classify as `verify` only when the tool name or shell command
|
|
42
|
+
**honestly proves** a test/lint/typecheck/doctor/check/watch gate.
|
|
43
|
+
- ⊗ MUST NOT map bare names that merely contain `test` / `lint` /
|
|
44
|
+
`check` (e.g. `TestHelper`, `npm run build`, `make install`, custom
|
|
45
|
+
scripts) to `verify`.
|
|
46
|
+
- ~ SHOULD leave novel MCP server tools as `unknown` until a nested
|
|
47
|
+
segment matches a known name (`mcp__host__Read` → explore).
|
|
48
|
+
|
|
49
|
+
## Anomalies (derived from counts)
|
|
50
|
+
|
|
51
|
+
`summarizeToolEvents` derives conservative anomaly codes:
|
|
52
|
+
|
|
53
|
+
| Code | When |
|
|
54
|
+
|------|------|
|
|
55
|
+
| `commit-without-explore` | `commit > 0` and `explore === 0` |
|
|
56
|
+
| `verify-skipped` | `commit > 0` and `verify === 0` |
|
|
57
|
+
| `explore-only` | `explore > 0`, `commit === 0`, `verify === 0`, and total events ≥ 3 |
|
|
58
|
+
|
|
59
|
+
## Status line format
|
|
60
|
+
|
|
61
|
+
```
|
|
62
|
+
tools: explore=N commit=N verify=N coordinate=N unknown=N
|
|
63
|
+
tools: explore=0 commit=2 verify=0 coordinate=0 unknown=0 | anomalies: commit-without-explore,verify-skipped
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
Produced by `formatToolEventStatusLine` / `summarizeToolEvents`.statusLine.
|
|
67
|
+
|
|
68
|
+
## Non-goals
|
|
69
|
+
|
|
70
|
+
- ⊗ LLM classification per tool event (cost/drift kills ROI)
|
|
71
|
+
- ⊗ Proving a verify command was the *correct* test suite
|
|
72
|
+
- ⊗ Semantic code understanding of what was written
|
|
73
|
+
- ⊗ Replacing hooks write-path / authz classifiers (#2950 / #2944)
|
package/scm/github.md
CHANGED
|
@@ -290,6 +290,53 @@ Rationale: `docs/analysis/2026-07-02-agents-md-incident-rule-rationale.md` § SC
|
|
|
290
290
|
|
|
291
291
|
See also § ghx cache proxy (#884) for install surfaces and read-only vs mutation rules.
|
|
292
292
|
|
|
293
|
+
## Mismatched/headless SCM readiness (#2275)
|
|
294
|
+
|
|
295
|
+
Follow-up to adoption epic #2203 (Decision 7). Framework-local gates
|
|
296
|
+
(`session:start`, `verify:*`, `xbrief:preflight`, `doctor`, `scope:*`,
|
|
297
|
+
local `cache-fresh` checks) run with zero SCM tooling. SCM-dependent gates
|
|
298
|
+
need `gh`/`ghx` **in the execution env** (not only on the install host) plus
|
|
299
|
+
auth.
|
|
300
|
+
|
|
301
|
+
### Probe contract
|
|
302
|
+
|
|
303
|
+
- ! `session:start` (read-only, cold, and re-arm) reports SCM readiness via
|
|
304
|
+
`[deft scm]` lines and a `scm` object in `--json`. Shallow by default
|
|
305
|
+
(PATH + token presence + short `gh auth status`); deep API validation when
|
|
306
|
+
`--with-network` / `DEFT_SESSION_START_NETWORK=1`.
|
|
307
|
+
- ! `deft scm:status` (alias `scm:readiness`) is the explicit probe verb:
|
|
308
|
+
exit `0` ready / `1` not ready / `2` config. Flags: `--json`,
|
|
309
|
+
`--deep` / `--shallow` / `--depth shallow|deep`.
|
|
310
|
+
- ! When not ready, diagnostics MUST name the reason
|
|
311
|
+
(`binary-absent` | `missing-token` | `unauthenticated` | ...) and list
|
|
312
|
+
skipped gates (`triage:queue`, `issue:ingest`, `pr:*`, `reconcile:issues`,
|
|
313
|
+
`cache:fetch-all`, `scm:*`, ...). Never fail opaquely on a missing binary.
|
|
314
|
+
- ! Session-start itself MUST NOT hard-block when SCM is unavailable
|
|
315
|
+
(framework-local orientation still succeeds).
|
|
316
|
+
- ! SCM-dependent verbs that actually need the network MUST fail loud with
|
|
317
|
+
the #2275 diagnostic (exit non-zero / `ScmStubError`) rather than hang on
|
|
318
|
+
auth prompts or emit an unhelpful spawn error.
|
|
319
|
+
- ⊗ Echo `GH_TOKEN` / `GITHUB_TOKEN` / `GH_ENTERPRISE_TOKEN` values into
|
|
320
|
+
prompts, transcripts, logs, or `--json` payloads -- report presence only
|
|
321
|
+
(`injected_token_present`).
|
|
322
|
+
|
|
323
|
+
### Making SCM gates runnable in a mismatched env
|
|
324
|
+
|
|
325
|
+
1. **Host-gh (local / unsandboxed):** install GitHub CLI (or `task setup:ghx`)
|
|
326
|
+
in the *execution* environment, then `gh auth login`. Host credential
|
|
327
|
+
stores are not shared into agent sandboxes.
|
|
328
|
+
2. **Injected-token (cloud / headless):** set `GH_TOKEN`, `GITHUB_TOKEN`, or
|
|
329
|
+
`GH_ENTERPRISE_TOKEN` in the execution env via host secrets. Runtime mode
|
|
330
|
+
`cloud-headless` infers `github_auth_mode=injected-token` (#1557).
|
|
331
|
+
3. **Run SCM elsewhere:** keep framework-local work in the sandbox; run
|
|
332
|
+
`triage:*` / `pr:*` / `issue:ingest` from a matched authenticated shell.
|
|
333
|
+
4. **Deep check:** `deft scm:status --deep` or
|
|
334
|
+
`deft github-auth-modes --json` validates API reachability and optional
|
|
335
|
+
repo access.
|
|
336
|
+
|
|
337
|
+
Contract file: `content/contracts/scm-readiness.md`. Implementation:
|
|
338
|
+
`packages/core/src/scm/readiness.ts`.
|
|
339
|
+
|
|
293
340
|
## Windows / ASCII Conventions for Machine-Editable Sections
|
|
294
341
|
|
|
295
342
|
Agent `edit_files` operations can fail when structured file sections contain Unicode characters that do not round-trip cleanly through Windows toolchains (xref warpdotdev/warp#9022). The following rules apply to **machine-editable structured sections**: ROADMAP.md phase bodies, CHANGELOG.md entries, and Open Issues Index rows.
|
|
@@ -27,6 +27,42 @@ Legend (from RFC2119): !=MUST, ~=SHOULD, ≉=SHOULD NOT, ⊗=MUST NOT, ?=MAY.
|
|
|
27
27
|
|
|
28
28
|
## Ordered-plan / cohort exhaustion (#2402)
|
|
29
29
|
|
|
30
|
+
## Multi-scope turn/cache budget (epic #3009)
|
|
31
|
+
|
|
32
|
+
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.
|
|
33
|
+
|
|
34
|
+
### Offline seed vs implement phase (#3010)
|
|
35
|
+
|
|
36
|
+
! 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**.
|
|
37
|
+
|
|
38
|
+
! When seed + session ritual are already complete for the engagement:
|
|
39
|
+
- ⊗ Run `directive init` again
|
|
40
|
+
- ⊗ Run full cold `session:start` unless hooks deny writes and recovery is required
|
|
41
|
+
- ⊗ Run `directive migrate` or re-copy scopes already present
|
|
42
|
+
- ! Prefer recovery via `session:ready` (or re-arm) when PreToolUse denies — not full re-init
|
|
43
|
+
- ! Documented consumer/harness contract: seed is done once; implement agents only activate+implement
|
|
44
|
+
|
|
45
|
+
### Batch promote; one active implement (#3011)
|
|
46
|
+
|
|
47
|
+
! For a multi-scope pin, batch-stage scopes with `task scope:promote -- --batch` (all `proposed/`) or `task scope:promote -- --batch <path>…`.
|
|
48
|
+
! Implement path remains **one** `scope:activate` + implement at a time — no multi-active write fence.
|
|
49
|
+
! When pin order is known, do **not** re-list the entire lifecycle tree every scope; walk the known ordered list.
|
|
50
|
+
⊗ Activate all scopes at once or drop the one-active-scope / story-ready stack.
|
|
51
|
+
|
|
52
|
+
### Quality check once at end of multi-scope batch (#3012)
|
|
53
|
+
|
|
54
|
+
! 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.
|
|
55
|
+
! Exception: if the last full check **failed**, fix loops MAY re-run check until green.
|
|
56
|
+
! Pre-PR / merge-ready gates remain end-of-unit — this does not weaken them.
|
|
57
|
+
! Iteration lane (affected tests / `verify:forward-coverage` / `coverage:hotspots`) still applies **per scope** during implementation (#1704).
|
|
58
|
+
⊗ Spam full `directive check` / `task check` after every scope when the batch is still mid-flight and the last merge-chokepoint check was green.
|
|
59
|
+
|
|
60
|
+
### One-shot project:render (#3013)
|
|
61
|
+
|
|
62
|
+
! 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.
|
|
63
|
+
⊗ Invent project identity across many turns when seed already stamped the skeleton.
|
|
64
|
+
|
|
65
|
+
|
|
30
66
|
! 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.
|
|
31
67
|
|
|
32
68
|
## Step 0 -- Implementation Preflight (#810)
|
|
@@ -39,7 +75,7 @@ Legend (from RFC2119): !=MUST, ~=SHOULD, ≉=SHOULD NOT, ⊗=MUST NOT, ?=MAY.
|
|
|
39
75
|
- ! **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.
|
|
40
76
|
- ! **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.
|
|
41
77
|
- ! **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.
|
|
42
|
-
- ! If the target story is in `xbrief/proposed/`, run `task scope:promote -- <path>` first; if it is in `xbrief/pending/`, run `task scope:activate -- <path>`. After activation, update the path to the active-file location before preflight.
|
|
78
|
+
- ! 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.
|
|
43
79
|
- ! 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; wraps `scripts/preflight_implementation.py` so the same invocation works whether deft is the project root or installed as a `deft/` subdirectory).
|
|
44
80
|
|
|
45
81
|
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>`.
|
|
@@ -255,6 +291,9 @@ task test:coverage # >=85% or PROJECT-DEFINITION.xbrief.json override
|
|
|
255
291
|
- ! Phase checkpoint commits MAY use the iteration lane; phase is NOT done for PR handoff until full `task check` passes at the merge chokepoint
|
|
256
292
|
- ⊗ Skip quality gates or claim they passed without running
|
|
257
293
|
- ⊗ Treat iteration-lane green as merge-ready without full `task check`
|
|
294
|
+
- ! **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.
|
|
295
|
+
- ⊗ Re-run full install/session ceremony after offline seed when ritual is already complete (#3010) — use `session:ready` for recovery only.
|
|
296
|
+
|
|
258
297
|
|
|
259
298
|
## Coding Standards (Summary)
|
|
260
299
|
|
|
@@ -320,6 +359,10 @@ feat(phase-2): add REST API endpoints with integration tests
|
|
|
320
359
|
- ⊗ Move to next phase before current passes checks
|
|
321
360
|
- ⊗ Make commits without running iteration-lane validation; ⊗ skip full `task check` at PR/merge chokepoint (#1704)
|
|
322
361
|
- ⊗ Proceed without USER.md -- always run the USER.md Gate first
|
|
362
|
+
- ⊗ Re-run `directive init`, cold `session:start`, migrate, or re-copy pin scopes after offline seed when ritual is already complete (#3010)
|
|
363
|
+
- ⊗ Run full `task check` after every intermediate scope of an approved multi-scope batch when the last merge-chokepoint check was green (#3012)
|
|
364
|
+
- ⊗ Promote scopes one-by-one for a known multi-scope pin when `scope:promote --batch` would stage them in one turn (#3011)
|
|
365
|
+
|
|
323
366
|
- ⊗ Spawn an implementation agent or invoke a code-writing tool against a xBRIEF that has not passed `task xbrief:preflight` (which wraps `scripts/preflight_implementation.py`) -- always run the Step 0 Implementation Preflight (#810) first; satisfy via `task xbrief:activate <path>`
|
|
324
367
|
- ⊗ Proceed without `COST-ESTIMATE.md` and a recorded build / rescope / no-build / skip(+reason) decision -- always run the Cost Phase Gate (#739) first
|
|
325
368
|
- ⊗ Proceed with implementation when the build or test toolchain is unavailable -- always run the Toolchain Gate (Step 2) first
|
|
@@ -144,7 +144,9 @@ git --no-pager diff master
|
|
|
144
144
|
- ! Check for scope creep -- changes that go beyond the spec task acceptance criteria
|
|
145
145
|
- ! Verify no debug code, TODO comments, or temporary scaffolding remains
|
|
146
146
|
- ! Confirm no unintended whitespace-only changes or formatting drift
|
|
147
|
-
- ! **
|
|
147
|
+
- ! **Closing-keyword policy (#3015 class D / #737 Layer 0):** Default PR body uses `Tracking: #N` / `Related: #N` / `Refs #N` only. Use `Closes` / `Fixes` / `Resolves #N` only when the **full issue DoD** is met (not Phase A partial / multi-phase mid-stream).
|
|
148
|
+
- ⊗ Write `Closes #N Phase A`, `only if`, `partial`, or other conditional English around a real closing keyword — GitHub ignores the condition and auto-closes (#3015 enterprize#29).
|
|
149
|
+
- ! **Run `task pr:check-closing-keywords` before opening the PR (default mode `both` = FP #737 + intent #3015).** Offline: `--body-file` / `--commits-file`. Scans body and commits for closing-keyword tokens in negation / quotation / example / code-block contexts (FP) and for any unallowlisted real close (intent). When full DoD close is intentional, pass `--allow-close <N,M>` (CLI allowlist only — body trailers are not an authorization path). FP-only: `--mode fp`. Known-safe quoted tokens: `--allow-known-false-positives`. Recurrence stack: #167, #697 / #698, #401 / #700, #735 (class A), #3015 (class D enterprize#29).
|
|
148
150
|
- ~ Verify the diff tells a coherent story -- a reviewer reading it top-to-bottom should understand the change
|
|
149
151
|
- ~ If the PR adds or moves any documentation, verify each new doc is reachable from the AGENTS.md reference chain -- an orphan doc is discovered <10% of the time yet still costs context when found (the reference-chain contract, #644 / #647). Add a pointer or fold it in rather than leaving it stranded.
|
|
150
152
|
|
|
@@ -173,4 +175,4 @@ After exiting:
|
|
|
173
175
|
- ⊗ Make out-of-scope fixes during Write -- this introduces scope creep that Diff will flag, forcing another iteration
|
|
174
176
|
- ⊗ Ignore the iteration count -- more than 3 iterations usually indicates oscillating fixes or an unclear spec task
|
|
175
177
|
- ⊗ Add a prohibition (`!` or `⊗`) without scanning the same file for conflicting softer-strength rules (`~`, `≉`) that reference the same term
|
|
176
|
-
- ⊗ Skip `task pr:check-closing-keywords` (#737) before pushing a PR. The negation-context substring match is the Layer 0 (prevention) gate that prevents the recurring auto-close of umbrella / staying-OPEN issues observed in #697 (closed #642), #401 (closed #642), #700 (closed #233), and #735 (closed #734) -- each incident required manual reopen and downstream cleanup. The lint's three-state exit (0 clean / 1 hits found / 2 config error) MUST be treated as a hard refusal: rewrite the PR body / commit messages until clean, OR pass `--allow-known-false-positives` ONLY for legitimately-quoted occurrences (test fixtures, documentation that discusses the trigger token literally). See `skills/deft-directive-swarm/SKILL.md` Phase 6 Step 1 for the corresponding Layer 3 (recovery) `pr:check-protected-issues` rule (#701)
|
|
178
|
+
- ⊗ Skip `task pr:check-closing-keywords` (#737) before pushing a PR. Intent mode (#3015) also refuses bare/conditional real `Closes #N` without `--allow-close`. The negation-context substring match is the Layer 0 (prevention) gate that prevents the recurring auto-close of umbrella / staying-OPEN issues observed in #697 (closed #642), #401 (closed #642), #700 (closed #233), and #735 (closed #734) -- each incident required manual reopen and downstream cleanup. The lint's three-state exit (0 clean / 1 hits found / 2 config error) MUST be treated as a hard refusal: rewrite the PR body / commit messages until clean, OR pass `--allow-known-false-positives` ONLY for legitimately-quoted occurrences (test fixtures, documentation that discusses the trigger token literally). See `skills/deft-directive-swarm/SKILL.md` Phase 6 Step 1 for the corresponding Layer 3 (recovery) `pr:check-protected-issues` rule (#701)
|
|
@@ -40,6 +40,26 @@ Track each agent through these stages:
|
|
|
40
40
|
6. **PR Created** — PR visible via `gh pr list --head <branch>`
|
|
41
41
|
7. **Review Cycling** — additional commits after PR creation (Greptile fix rounds)
|
|
42
42
|
|
|
43
|
+
### Tool-event mix status line (#2967)
|
|
44
|
+
|
|
45
|
+
! When the monitor has a sequence of tool names (and optional shell commands) for a leaf — host transcript, heartbeat sidecar, or operator-supplied log — classify with the pure `#2967` taxonomy and include the status line in the **next monitor status** (chat heartbeat or sticky cohort note). Do not invent counts; only report when events are available.
|
|
46
|
+
|
|
47
|
+
Buckets: `explore` | `commit` | `verify` | `coordinate` | `unknown`. Misclassification policy: prefer `unknown` over wrong `verify`. Canonical docs: [`content/patterns/tool-call-taxonomy.md`](../../../patterns/tool-call-taxonomy.md). API: `@deftai/directive-core/tool-events` (`classifyToolEvent`, `summarizeToolEvents`).
|
|
48
|
+
|
|
49
|
+
```
|
|
50
|
+
# Status line shape (from summarizeToolEvents(...).statusLine)
|
|
51
|
+
tools: explore=12 commit=4 verify=2 coordinate=1 unknown=0
|
|
52
|
+
tools: explore=0 commit=3 verify=0 coordinate=0 unknown=1 | anomalies: commit-without-explore,verify-skipped
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
! Surface anomalies when present:
|
|
56
|
+
- `commit-without-explore` — mutators without any explore events (possible blind edit)
|
|
57
|
+
- `verify-skipped` — commit events with zero verify gates (ship without check/test)
|
|
58
|
+
- `explore-only` — thrash signal (explore-only, no commit/verify, ≥3 events)
|
|
59
|
+
|
|
60
|
+
~ Pair the status line with worktree git checks and `task pr:merge-ready` so operators see progress **and** tool mix without reading raw tool logs.
|
|
61
|
+
⊗ Treat raw “ran N tools” as a structured mix — always bucket when events are available (#2967).
|
|
62
|
+
|
|
43
63
|
### Takeover Triggers
|
|
44
64
|
|
|
45
65
|
! **Pre-spawn verification:** Before spawning a replacement agent, verify the original is truly unresponsive by waiting for an idle/blocked lifecycle event — verified via worktree state (`git status`, `git log --oneline -3`) and sub-agent lifecycle signals showing no in-flight work (for grok-build / spawn_subagent agents: polling is via worktree state + `get_command_or_subagent_output` rather than tab observation; for openclaw / sessions_spawn agents: worktree state + parent completion announce / heartbeat records, not Grok Build poll output). Do NOT spawn a replacement based solely on message timing, absence of recent commits, or a perceived delay — original agents (Warp tabs, spawn_subagent processes, or OpenClaw sessions) can resume after apparent failure, and spawning a new agent creates two concurrent agents on the same worktree (see Duplicate-Tab Failure Mode below).
|
|
@@ -31,6 +31,10 @@ Live miss: operator said “use review skill” + URL; agent stayed on host free
|
|
|
31
31
|
⊗ Answer Deft-shaped intent with freestyle tools only when a Directive skill is indexed for that intent.
|
|
32
32
|
⊗ Skip project-root resolution and improvise from workspace home outside the target checkout.
|
|
33
33
|
|
|
34
|
+
### Pin wire into OpenClaw workspace skills (#3001)
|
|
35
|
+
|
|
36
|
+
Package install alone does not put always-pins into `~/.openclaw/workspace/skills`. Operators / agents SHOULD run `deft doctor` (detect) and `deft doctor --fix` (symlink or copy the four pins) when main-workspace pins are missing. Multi-seat only with `--openclaw-all-agents`. Operator steps: [`../../docs/openclaw-agent-host.md`](../../docs/openclaw-agent-host.md) § Wire skills into OpenClaw workspace.
|
|
37
|
+
|
|
34
38
|
## Hard isolation before spawn (#2929)
|
|
35
39
|
|
|
36
40
|
! For **parallel** OpenClaw leaves (cohort size > 1):
|
package/tasks/engine.yml
CHANGED
|
@@ -97,6 +97,7 @@ tasks:
|
|
|
97
97
|
is_runtime_verb=0
|
|
98
98
|
case " ${first_token} " in
|
|
99
99
|
" session:start "|" session-start "|\
|
|
100
|
+
" session:ready "|" session-ready "|\
|
|
100
101
|
" lifecycle:event "|" lifecycle-event "|\
|
|
101
102
|
" verify:session-ritual "|" verify-session-ritual "|\
|
|
102
103
|
" verify:tools "|" verify-tools "|\
|