@deftai/directive-content 0.106.0 → 0.108.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.
Files changed (46) hide show
  1. package/Taskfile.yml +14 -1
  2. package/UPGRADING.md +24 -5
  3. package/commands.md +29 -4
  4. package/contracts/design-critique.md +369 -14
  5. package/contracts/issue-eval.md +77 -0
  6. package/contracts/path-write-fence.md +126 -1
  7. package/contracts/runtime-authority.md +2 -0
  8. package/contracts/scm-readiness.md +2 -2
  9. package/docs/delivery-attempt.md +2 -1
  10. package/docs/freshness-contract.md +6 -1
  11. package/docs/getting-started.md +10 -11
  12. package/docs/hook-runtime-unavailable.md +54 -0
  13. package/docs/orphan-active-verdict-basis.md +166 -0
  14. package/docs/scope-provenance.md +1 -1
  15. package/package.json +1 -1
  16. package/packs/skills/skills-pack-0.1.json +24 -10
  17. package/scm/github.md +65 -2
  18. package/skills/deft-directive-build/SKILL.md +2 -2
  19. package/skills/deft-directive-cost/SKILL.md +7 -11
  20. package/skills/deft-directive-design-critique/SKILL.md +22 -6
  21. package/skills/deft-directive-design-critique/references/motion-shape.md +19 -0
  22. package/skills/deft-directive-feedback/SKILL.md +11 -2
  23. package/skills/deft-directive-interview/SKILL.md +10 -10
  24. package/skills/deft-directive-issue-eval/SKILL.md +48 -0
  25. package/skills/deft-directive-release/SKILL.md +10 -6
  26. package/skills/deft-directive-review-cycle/SKILL.md +33 -0
  27. package/skills/deft-directive-setup/SKILL.md +53 -22
  28. package/skills/deft-directive-swarm/references/core-ops.md +4 -0
  29. package/skills/deft-directive-swarm/references/core-phase-1-2.md +1 -1
  30. package/skills/deft-directive-swarm/references/core-phase-3.md +3 -1
  31. package/skills/deft-directive-swarm/references/core-phase-4.md +11 -8
  32. package/skills/deft-directive-swarm/references/host-cursor.md +1 -0
  33. package/skills/deft-directive-swarm/references/host-grok-build.md +1 -0
  34. package/skills/deft-directive-triage/SKILL.md +3 -2
  35. package/tasks/engine.yml +4 -0
  36. package/tasks/feedback.yml +1 -1
  37. package/tasks/occupancy.yml +34 -1
  38. package/tasks/prd.yml +4 -5
  39. package/tasks/scm.yml +14 -2
  40. package/tasks/session.yml +13 -2
  41. package/tasks/toolchain.yml +2 -2
  42. package/tasks/triage-evaluate.yml +22 -0
  43. package/tasks/verify.yml +21 -1
  44. package/templates/agent-prompt-preamble.md +28 -4
  45. package/templates/agents-entry.md +10 -5
  46. package/templates/design-critique-brief.md +19 -5
@@ -127,6 +127,8 @@ When guiding an operator through migration on the pinned release, mention the mi
127
127
  - ! If `$DEFT_USER_PATH` is set, it takes precedence on any platform
128
128
  - ! Create parent directories as needed when writing USER.md
129
129
  - ~ `$DEFT_PROJECT_PATH` overrides the default project config path (`./xbrief/PROJECT-DEFINITION.xbrief.json`) if set
130
+ - ! Resolve `<policy-project-root>` to the user's working directory at skill entry. When `$DEFT_PROJECT_PATH` is set, resolve it relative to that root and preserve the environment variable for every Phase 2 command; the public policy writer, inspector, lock, and conformance gate honor the configured file even when it is outside the canonical `xbrief/` path.
131
+ - ! Pass `--project-root <policy-project-root>` to every Phase 2 policy inspector, writer, and conformance command. Do not unset or rewrite `$DEFT_PROJECT_PATH`, and do not let those commands fall back to a different working directory.
130
132
 
131
133
  ## Agent Behavior
132
134
 
@@ -418,6 +420,15 @@ for project-scoped settings (strategy, coverage).
418
420
  - ~ Skip if `./xbrief/PROJECT-DEFINITION.xbrief.json` exists (or `$DEFT_PROJECT_PATH` if set) and user doesn't want to replace
419
421
  - ⊗ Count `./deft/PROJECT-DEFINITION.xbrief.json` or `./deft/core/project.md` as the user's project config — those are framework-internal
420
422
 
423
+ ### Re-entry shadow guard (#3609)
424
+
425
+ ! Before any Phase 2 confirmation or file mutation when PROJECT-DEFINITION already exists, run `deft policy:show --field=plan.policy.allowDirectCommitsToMaster --project-root <policy-project-root>` and inspect **stderr as well as the exit code**. The inspector intentionally exits 0 when it can still read the namespaced value, so a warning that bare `plan.policy` coexists with `plan["x-directive/policy"]` is a hard stop even when the command succeeds.
426
+
427
+ ! On that warning, do not regenerate, overwrite, or run a policy writer. Inventory the keys in both blocks; fold every bare-only key into `plan["x-directive/policy"]`; resolve every collision explicitly; delete bare `plan.policy`; then rerun the inspector. Preserve all unrelated PROJECT-DEFINITION content. Resume only when exactly one policy block remains.
428
+
429
+ ⊗ Treat matching `allowDirectCommitsToMaster` values as safe while other keys may still be stranded in the shadowed block
430
+ ⊗ Copy arbitrary policy values into a diagnostic or silently choose one side of a collision
431
+
421
432
  ### Inference
422
433
 
423
434
  - ! Before asking, infer from codebase — look for `package.json`, `go.mod`, `requirements.txt`, `Cargo.toml`, `pyproject.toml`, `*.csproj`
@@ -491,21 +502,21 @@ apply here too. Do not combine questions. See `skills/deft-directive-interview/S
491
502
  ! **Capability-cost disclosure (#746):** When the user picks option 2 (trunk-based), the agent MUST present the capability-cost disclosure verbatim BEFORE writing the typed flag, then re-prompt for explicit confirmation:
492
503
 
493
504
  > "Capability-cost disclosure -- enabling direct commits to the default branch turns OFF the deft branch-protection policy. The pre-commit + pre-push hooks will no longer block default-branch commits, `task verify:branch` will pass on the default branch, and the skill-level guards in deft-directive-{swarm,review-cycle,pre-pr,release} will not halt for default-branch work. The change is reversible (`task policy:enforce-branches`) and is recorded to meta/policy-changes.log for auditability. The CI sanity check (head_ref != base_ref) remains independent and will continue to flag master->master PRs. Are you sure?"
494
- > 1. Yes, opt out -- write `plan.policy.allowDirectCommitsToMaster = true`
495
- > 2. No, keep branch-protection enforced -- write `plan.policy.allowDirectCommitsToMaster = false`
505
+ > 1. Yes, opt out -- persist `allowDirectCommitsToMaster=true` through the policy writer
506
+ > 2. No, keep branch-protection enforced -- persist `allowDirectCommitsToMaster=false` through the policy writer
496
507
  > 3. Discuss
497
508
  > 4. Back
498
509
 
499
510
  ! Default to option 2 (enforce). Explicit affirmative on option 1 is required to opt out -- a broad `proceed` does NOT satisfy this gate. The same affirmative-only rule applies as in `/deft:change` (`yes`, `confirmed`, `approve`).
500
511
 
501
- ! Write the answer to `plan.policy.allowDirectCommitsToMaster` (typed boolean) on the PROJECT-DEFINITION xBRIEF. Default `false` (enforce branches) when the user picks option 2 OR omits the question entirely. Writing this typed surface is what the framework reads going forward; agents MUST NOT write the legacy free-form `Allow direct commits to master:` narrative key (#746 part A migrates the legacy narrative away).
512
+ ! Record the answer as the logical field `plan.policy.allowDirectCommitsToMaster`, but do not hand-write either policy block. The common Output Path gate below invokes the only writer and stores the boolean under `plan["x-directive/policy"].allowDirectCommitsToMaster`. Default `false` (enforce branches) when the user picks option 2 OR omits the question entirely. Agents MUST NOT write bare `plan.policy` or the legacy free-form `Allow direct commits to master:` narrative key.
502
513
 
503
- ! **Re-running the interview detects the existing flag (#746 part G2):** If `xbrief/PROJECT-DEFINITION.xbrief.json` already exists and has `plan.policy.allowDirectCommitsToMaster` set, the interview MUST surface the current value (e.g. "Current setting: `allowDirectCommitsToMaster=false` (branch-protection ON)") and ask whether to keep it or change it before re-prompting. Do not silently overwrite an existing typed value.
514
+ ! **Re-running the interview detects the existing flag (#746 part G2):** After the Re-entry shadow guard passes, surface the resolved current value (e.g. "Current setting: `allowDirectCommitsToMaster=false` (branch-protection ON)") and ask whether to keep it or change it before re-prompting. A keep choice still runs the selected writer so legacy-only storage is migrated; an already-namespaced match is a no-op with no audit append. On Track 2 or 3, preserve an existing resolved boolean by default without asking a new branching question. Never replace an existing `true` with the greenfield `false` default unless the operator explicitly chooses the Track 1 change flow.
504
515
 
505
- ! **Slash-command alternatives (#746 part G2):** Once the project is set up, the typed flag can also be flipped via slash commands wrapping `task policy:*`:
506
- - `/deft:policy:show` -- display the current resolved policy and source
507
- - `/deft:policy:enforce-branches` -- set `allowDirectCommitsToMaster=false`
508
- - `/deft:policy:allow-direct-commits` -- set `allowDirectCommitsToMaster=true` (requires `--confirm` to apply)
516
+ ! **Consumer command alternatives (#746 part G2):** Once the project is set up, use the public CLI directly:
517
+ - `deft policy:show --field=plan.policy.allowDirectCommitsToMaster --project-root <policy-project-root>` -- display the current resolved policy and source
518
+ - `deft policy:enforce-branches --actor agent:deft-directive-setup --project-root <policy-project-root>` -- set `allowDirectCommitsToMaster=false`
519
+ - `deft policy:allow-direct-commits --confirm --actor agent:deft-directive-setup --project-root <policy-project-root>` -- set `allowDirectCommitsToMaster=true`
509
520
 
510
521
  Each transition is recorded to `meta/policy-changes.log` for auditability.
511
522
 
@@ -515,14 +526,30 @@ apply here too. Do not combine questions. See `skills/deft-directive-interview/S
515
526
  - Step 3: Ask languages (show detected, confirm or adjust; if none detected, infer from type and ask)
516
527
  - Step 4: Ask strategy (default to USER.md Defaults; ask if this project needs different — show Available Strategies numbered list with descriptions and recommended marker)
517
528
  - Default coverage to USER.md Defaults without asking
529
+ - ! Do not ask a branching question. For greenfield or absent policy, the common Output Path gate persists `allowDirectCommitsToMaster=false`. On re-entry it preserves the resolved existing boolean, including `true`; change it only through the Track 1 disclosure gate.
518
530
 
519
531
  **Track 3 (non-technical) — 1 step:**
520
532
  - Step 1: Present summary of inferences: "Based on your project: {name} ({type}), built with {stack}. Look right?"
521
533
  - ⊗ Ask about strategy or coverage — use Phase 1 defaults
534
+ - ! Do not ask a branching question. For greenfield or absent policy, the common Output Path gate persists `allowDirectCommitsToMaster=false`. On re-entry it preserves the resolved existing boolean, including `true`; change it only through the Track 1 disclosure gate.
522
535
 
523
536
  ### Output Path
524
537
 
525
- `./xbrief/PROJECT-DEFINITION.xbrief.json` (or `$DEFT_PROJECT_PATH` if set). Create `./xbrief/` directory and lifecycle subfolders (`proposed/`, `pending/`, `active/`, `completed/`, `cancelled/`) if they don't exist.
538
+ `./xbrief/PROJECT-DEFINITION.xbrief.json` (or the resolved `$DEFT_PROJECT_PATH` if set). Create `<policy-project-root>/xbrief/` and its lifecycle subfolders (`proposed/`, `pending/`, `active/`, `completed/`, `cancelled/`) if they don't exist. A configured PROJECT-DEFINITION may live elsewhere; the lifecycle root remains under `<policy-project-root>`.
539
+
540
+ ### Branch-policy persistence gate (#3609)
541
+
542
+ ! This gate applies to **every track**, including default/greenfield and keep/re-entry paths. For greenfield setup, first write the confirmed PROJECT-DEFINITION base without any hand-authored policy block. On re-entry, merge base changes while preserving the existing policy block byte-for-byte: keep a legacy-only bare `plan.policy` intact until the shared writer migrates the whole block, and keep a namespaced block intact until that writer updates it. Never delete or reconstruct a legacy-only block before the writer because it may contain unrelated keys such as `wipCap`. Then invoke exactly one public writer:
543
+
544
+ - Branch-based/greenfield-default/keep-false: `deft policy:enforce-branches --actor agent:deft-directive-setup --project-root <policy-project-root>`
545
+ - Explicitly confirmed trunk-based/keep-true/Track 2 or 3 existing-true: `deft policy:allow-direct-commits --confirm --actor agent:deft-directive-setup --project-root <policy-project-root>`
546
+
547
+ ! A nonzero writer exit halts Phase 2 immediately. Do not print a completion claim and do not retry by hand-editing JSON. Resolve the reported configuration problem, rerun the Re-entry shadow guard, and invoke the writer again.
548
+
549
+ ! Before Phase 2 can complete, re-read PROJECT-DEFINITION and verify all three postconditions: `plan["x-directive/policy"].allowDirectCommitsToMaster` is the selected boolean; bare `plan.policy` is absent; and `deft verify:vbrief-conformance --project-root <policy-project-root>` exits 0. Also run `deft policy:show --field=plan.policy.allowDirectCommitsToMaster --project-root <policy-project-root>` and confirm its resolved value matches the selection. Any mismatch is a hard stop.
550
+
551
+ ⊗ Finish Phase 2 after writing only the narrative template
552
+ ⊗ Add a setup-specific policy writer or weaken conformance to permit bare `plan.policy`
526
553
 
527
554
  ### GitHub PR Template Scaffolding (#531)
528
555
 
@@ -579,7 +606,7 @@ omit = [
579
606
  "Strategy": "Use {strategy name} for this project",
580
607
  "Quality": "Run task check before every commit. Achieve >= {coverage}% coverage overall + per-module. Store secrets in secrets/ dir.",
581
608
  "ProjectRules": "{Any rules the user specified, or 'No project-specific rules defined.'}",
582
- "Branching": "{If trunk-based: 'Allow direct commits to master: true', else omit or 'Branch-based workflow (default)'}",
609
+ "Branching": "{If confirmed trunk-based: 'Trunk-based workflow', otherwise 'Branch-based workflow (default)'}",
583
610
  "DeftVersion": "0.20.0"
584
611
  },
585
612
  "items": []
@@ -614,7 +641,7 @@ omit = [
614
641
  ! **Path Resolution Anchor**: Same rule as Phase 2 -- resolve ALL paths relative to the user's pwd at skill entry, never relative to the skill file, AGENTS.md, or any framework directory.
615
642
 
616
643
  - ~ Skip if user already has scope xBRIEFs in `./xbrief/` they're happy with
617
- - ! Check `./xbrief/specification.xbrief.json` or `./xbrief/proposed/` for existing scope xBRIEFs
644
+ - ! Check `./xbrief/PROJECT-DEFINITION.xbrief.json` and `./xbrief/proposed/` for existing greenfield authority; treat `./xbrief/specification.xbrief.json` as a full-spec compatibility artifact only
618
645
  - ⊗ Count ANY file inside `./deft/` as the project's spec — those are framework-internal
619
646
  (e.g. `deft/PROJECT.md`, `deft/specs/`, `deft/templates/`, `deft/core/project.md`
620
647
  are all part of the framework, NOT the user's project)
@@ -682,8 +709,10 @@ project complexity per [strategies/interview.md](../../strategies/interview.md#s
682
709
  - ⊗ Combine the sizing proposal with the first interview question
683
710
  - ⊗ Proceed to interview questions before the user has confirmed the path
684
711
 
685
- **Light** (small/medium): Interview → `specification.xbrief.json` with slim narratives (Overview + Architecture) → scope xBRIEFs in `xbrief/proposed/`.
686
- **Full** (large/complex): Interview → rich narratives in `specification.xbrief.json` (user approval) → scope xBRIEFs with traceability.
712
+ **Light** (small/medium): Interview → slim narratives (Overview + Architecture) in `PROJECT-DEFINITION.xbrief.json` → scope xBRIEFs in `xbrief/proposed/`.
713
+ **Full** (large/complex): Interview → rich PROJECT-DEFINITION narratives for user approval → scope xBRIEFs with traceability.
714
+
715
+ ! Neither greenfield path creates `xbrief/specification.xbrief.json`; that file remains a full-spec compatibility artifact.
687
716
 
688
717
  ### Interview Process (interview strategy)
689
718
 
@@ -715,7 +744,7 @@ Per [strategies/interview.md](../../strategies/interview.md#interview-rules-shar
715
744
 
716
745
  ### Output — Light Path
717
746
 
718
- 1. ! Write `./xbrief/specification.xbrief.json` with `"xBRIEFInfo": { "version": "0.8" }`, `status: draft`, and slim narratives:
747
+ 1. ! Merge the confirmed slim narratives into `./xbrief/PROJECT-DEFINITION.xbrief.json`:
719
748
  - `Overview`: Brief project summary
720
749
  - `Architecture`: System design description
721
750
  2. ! Create scope xBRIEFs in `./xbrief/proposed/` for each identified work item
@@ -733,8 +762,8 @@ Per [strategies/interview.md](../../strategies/interview.md#interview-rules-shar
733
762
  }
734
763
  ]
735
764
  ```
736
- 3. ! Summarize decisions, ask user to review the xBRIEF narratives
737
- 4. ! On approval, update `specification.xbrief.json` status to `approved`
765
+ 3. ! Summarize decisions and ask the user to approve the PROJECT-DEFINITION narratives and proposed scope set
766
+ 4. ! Record approval in the setup session; do not manufacture or require `specification.xbrief.json`
738
767
  - ⊗ Create a separate PRD.md on the Light path
739
768
  - ⊗ Generate an authoritative PRD.md — if needed, users run `task prd:render`
740
769
 
@@ -747,7 +776,7 @@ Per [strategies/interview.md](../../strategies/interview.md#interview-rules-shar
747
776
 
748
777
  ### Output — Full Path
749
778
 
750
- 1. ! Write rich narratives to `./xbrief/specification.xbrief.json` with `"xBRIEFInfo": { "version": "0.8" }`, `plan.status: draft`, and these narrative keys:
779
+ 1. ! Merge these rich narratives into `./xbrief/PROJECT-DEFINITION.xbrief.json` for review:
751
780
  - `ProblemStatement`: What problem this project solves
752
781
  - `Goals`: High-level project goals
753
782
  - `UserStories`: User stories in standard format
@@ -755,8 +784,8 @@ Per [strategies/interview.md](../../strategies/interview.md#interview-rules-shar
755
784
  - `SuccessMetrics`: Measurable success criteria
756
785
  - `Architecture`: System design and technical architecture
757
786
  - `Overview`: Brief project summary
758
- 2. ! **Human approval gate**: Present the xBRIEF draft narratives to the user for review — reviewing the `specification.xbrief.json` narratives IS the approval step (replaces the former PRD.md review). The user may request changes before approving.
759
- 3. ! On approval, update `status` to `approved` and proceed to downstream generation
787
+ 2. ! **Human approval gate**: Present the PROJECT-DEFINITION narratives and proposed scope plan to the user for review. The user may request changes before approving.
788
+ 3. ! Record approval in the setup session and proceed to downstream generation; do not manufacture or require `specification.xbrief.json`
760
789
  4. ! Create scope xBRIEFs in `./xbrief/proposed/` with traceability to requirement IDs from the narratives
761
790
  - ! Scope xBRIEFs MUST trace tasks back to requirement IDs (FR-1, NFR-1) from the `Requirements` narrative
762
791
  - ⊗ Generate an authoritative PRD.md — if needed, users run `task prd:render`
@@ -813,8 +842,9 @@ Per [strategies/interview.md](../../strategies/interview.md#interview-rules-shar
813
842
 
814
843
  ### Handoff to deft-directive-build
815
844
 
816
- - ! Emit a structured-tool question asking whether to continue to the build phase only when the host preserves numeric labels; otherwise emit the deterministic numbered menu in chat. Options: `1. Yes (continue)`, `2. Not now (exit setup)`, `3. Discuss`, `4. Back (revisit previous phase)`. The numeric labels MUST remain visible and be returned as numeric selections or exact displayed option text.
817
- - ~ If platform supports skill invocation and the user picks Yes, invoke `skills/deft-directive-build/SKILL.md`
845
+ - ! Emit a structured-tool question asking whether to continue toward the build phase only when the host preserves numeric labels; otherwise emit the deterministic numbered menu in chat. Options: `1. Yes (run cost phase)`, `2. Not now (exit setup)`, `3. Discuss`, `4. Back (revisit previous phase)`. The numeric labels MUST remain visible and be returned as numeric selections or exact displayed option text.
846
+ - ! If the user picks Yes, invoke `skills/deft-directive-cost/SKILL.md`; only a recorded Build or Skip decision from that skill may hand off to `skills/deft-directive-build/SKILL.md`
847
+ - ⊗ Invoke the build skill directly from setup and bypass the required cost decision
818
848
  - ⊗ Leave user with a dead end -- always offer the next step via the structured-tool phase-transition question
819
849
  - ⊗ Ask the handoff-to-build question as unnumbered conversational prose or through a structured UI that hides the canonical numeric labels -- it is a deterministic menu and MUST preserve visible numbers (#478, #1563).
820
850
 
@@ -832,7 +862,8 @@ Per [strategies/interview.md](../../strategies/interview.md#interview-rules-shar
832
862
  4. ! If the user says `no`: re-display the values and ask which ones to correct, then re-confirm before writing
833
863
  5. ! If any value appears to be auto-generated filler (e.g. repeated default text, placeholder strings, or values that echo the question prompt), warn the user explicitly: "Some values look like they may have been auto-filled rather than provided by you. Please review carefully."
834
864
 
835
- ⊗ Write USER.md, PROJECT-DEFINITION.xbrief.json, specification.xbrief.json, or any other deft-directive-setup artifact without first displaying captured values and receiving explicit user confirmation.
865
+ ⊗ Write USER.md, PROJECT-DEFINITION.xbrief.json, lifecycle scope xBRIEFs, or any other deft-directive-setup artifact without first displaying captured values and receiving explicit user confirmation.
866
+ ⊗ Create `specification.xbrief.json` on a greenfield Light or Full path solely to satisfy export, cost, or build handoff.
836
867
  ⊗ Treat a broad "proceed" or "continue" as confirmation to write files -- the user must explicitly confirm the displayed values.
837
868
 
838
869
  ? **Yolo strategy carve-out**: When the user's chosen strategy is `yolo` (auto-pilot), the confirmation gate still applies but the agent (Johnbot) may self-confirm on the user's behalf by displaying the summary and immediately proceeding -- the user has already opted into auto-pilot by selecting yolo. The summary must still be displayed so the user can interrupt if values look wrong.
@@ -61,6 +61,8 @@ Task B (xBRIEF: [filename], issue #[N]): [one-paragraph description with specifi
61
61
  STEP 3 — Validate: Use iteration fast lane during commits (affected/static gates). Run full task check once before push/PR (#1704). Fix any failures.
62
62
 
63
63
  STEP 4 — Commit: Add CHANGELOG.md entries under [Unreleased].
64
+ Commit early: as soon as a coherent unit exists (source + tests that compile), then at checkpoints.
65
+ A host-kill must not leave the only copy unversioned (#3730).
64
66
  Commit with message: [type]([scope]): [description] — with bullet-point body.
65
67
 
66
68
  STEP 5 — Push and PR: Push branch to origin. Create PR targeting <configured-base-branch> using gh CLI.
@@ -77,6 +79,8 @@ CONSTRAINTS:
77
79
  - Iteration commits: affected/static fast lane only; full task check required before push (#1704)
78
80
  - Never force-push
79
81
  - Dual stop (#2442): multi-iteration fix/repair loops need success + failure/budget stop (build defaults: max 5 quality-fix iters or 3 identical no-progress; pre-PR: max 3 polish passes). On halt: operator-visible report (tried / missing / human decision). Single-turn work is exempt. Delivery/acceptance mechanical ledger is #3143 (`packages/core/src/delivery-attempt/` / `docs/delivery-attempt.md`).
82
+ - Heartbeat (#1365 / #3730): write `.deft-scratch/subagent-status/<agent-id>.json` immediately on start (`phase: starting`) and every 2-3 minutes. See `docs/subagent-heartbeat.md`.
83
+ - Commit early (#3730): first coherent unit, then checkpoints. Do not hold a complete correct diff uncommitted until PR time.
80
84
  ```
81
85
 
82
86
  ### Template Rules
@@ -37,7 +37,7 @@
37
37
  #### Mode A -- Pre-created worktree map (C3, headless via `--worktree-map`)
38
38
 
39
39
  - ! When `task swarm:launch -- ... --worktree-map <path>` supplied a **pre-created worktree map** (**C3**), Phase 2 CONSUMES it instead of running `git worktree add` per agent. The C3 map is a JSON array of `{ "story_id": str, "worktree_path": str, "base_branch": str }`.
40
- - ! The launch engine resolves the worktree map via `resolveWorktreeMap` (`packages/core/src/swarm/worktrees.ts`), which validates normalized C3 records and RAISES on same-path collisions or base-branch mismatches. The monitor MUST surface any such raise verbatim and HALT setup -- a same-path collision means two agents would share one worktree (the Duplicate-Agent Failure Mode in Phase 4).
40
+ - ! The launch engine resolves the worktree map via `resolveWorktreeMap` (`packages/core/src/swarm/worktrees.ts`), which validates normalized C3 records and RAISES on same-path collisions, base-branch mismatches, or a registered path whose HEAD OID differs from the requested base OID. The HEAD check is a snapshot at resolution time -- `swarm:launch` emits a manifest and stops, so HEAD can still move before spawn. The monitor MUST surface any such raise verbatim and HALT setup -- a same-path collision means two agents would share one worktree (the Duplicate-Agent Failure Mode in Phase 4).
41
41
  - ! Each resolved record's `worktree_path` and `base_branch` feed straight into Phase 3 dispatch and MUST match the **C2** launch-manifest's `worktree_path` / `branch` fields for the same `story_id`.
42
42
 
43
43
  #### Mode B -- Monitor-created worktrees (interactive path)
@@ -100,7 +100,9 @@ Cross-references: `packages/core/src/platform/platform-capabilities.ts` (#1557a)
100
100
 
101
101
  ! **Supported backend examples (none mandatory):** Composer-class coding agents, Grok Build `spawn_subagent` workers, Cursor/cloud agents, and future adapters are all first-class examples. No single backend is required — Grok Build is one implementation of provider-neutral routing, not the only target.
102
102
 
103
- ! **Implement-leaf pre-dispatch (#3228):** Before the actual spawn primitive for an implement leaf (and before any re-dispatch), run `task swarm:pre-dispatch -- --scope-id <id> --target-id <worktree-or-branch>` — exit **0** only means spawn is allowed; exit **1** is `DENY_DUPLICATE_ACTIVE` (do not spawn). Depth + takeover: [`core-phase-4.md`](core-phase-4.md) Pre-dispatch deny gate; library #3143.
103
+ ! **Implement-leaf pre-dispatch (#3228 / #3730):** Before the actual spawn primitive for an implement leaf (and before any re-dispatch), run `task swarm:pre-dispatch -- --scope-id <id> --target-id <worktree-or-branch>` — exit **0** only means spawn is allowed; exit **1** is `DENY_DUPLICATE_ACTIVE` (do not spawn). Begin on a filesystem worktree target also mkdirs `.deft-scratch/subagent-status/` so `verify:subagent-alive --require-agent` can return REDISPATCH_OK instead of exit 2. Depth + takeover: [`core-phase-4.md`](core-phase-4.md) Pre-dispatch deny gate; library #3143.
104
+
105
+ ! **Arm the heartbeat path at dispatch (#3730):** Create the worker worktree's `.deft-scratch/subagent-status/` before spawn (mechanical on `swarm:launch` worktree-map and `swarm:pre-dispatch` begin). Instruct the worker to heartbeat per `templates/agent-prompt-preamble.md` § 10.5 and to commit early. Monitors MUST pass `--require-agent <agent-id>` on `task verify:subagent-alive`. ⊗ Put liveness on the C2 launch manifest or in `occupancy.json`.
104
106
 
105
107
  ! **Operator model routing (#1739):** the concrete per-role model lives in the gitignored, per-machine `.deft/routing.local.json`, keyed by `(dispatch_provider, worker_role)`. Record a decision with `task swarm:routing-set -- --role <role> (--model <slug> | --harness-default)`. `task swarm:launch` resolves the active provider's route and stamps `resolved_model` + `model_source` into each C2 manifest record. When `resolved_model` is non-null, the monitor MUST pass it as the **model argument of the actual dispatch primitive** (e.g. the Task tool's `model` field for a Cursor sub-agent) — stamping the manifest is prep; a recorded model that never reaches the spawn call is the bug #1739 closes. Run `task verify:routing` before dispatching a cohort (pre-dispatch hard gate; fails when a dispatched role is undecided) and `task verify:routing -- --advise` at session start (non-blocking disclosure). For harness-bound providers (e.g. `grok`) only `--harness-default` is recordable and `resolved_model` stays null.
106
108
 
@@ -11,16 +11,17 @@
11
11
 
12
12
  ! On the Grok Build hybrid path (`spawn_subagent` dispatch, no native lifecycle channel back to the monitor), worktree git state alone is INSUFFICIENT to distinguish a healthy mid-poll sub-agent from a stalled one. Long-running review-cycle pollers spend most of their wall-clock waiting on Greptile and emit no commits during that wait -- the #1166 swarm session is the recurrence record (two of three dispatched pollers went silent with zero observable signals; the monitor could not tell).
13
13
 
14
- ! The canonical alive-check on the Grok Build hybrid path is the heartbeat contract documented in `docs/subagent-heartbeat.md`. Every long-running sub-agent (pollers, watchdogs, implementation agents whose tool loop exceeds ~3 min) writes a JSON heartbeat to `.deft-scratch/subagent-status/<agent-id>.json` per the canonical poller template + agent preamble; the monitor reads those records via `task agent:monitor` (three-state exit 0 ok / 1 stale-or-malformed / 2 config error). Default threshold is 30 minutes; `--threshold-minutes` overrides.
14
+ ! The canonical alive-check on the Grok Build hybrid path is the heartbeat contract documented in `docs/subagent-heartbeat.md`. Every long-running sub-agent (pollers, watchdogs, implementation agents whose tool loop exceeds ~3 min) writes a JSON heartbeat to `.deft-scratch/subagent-status/<agent-id>.json` per the canonical poller template + agent preamble. Default threshold is 30 minutes; `--threshold-minutes` overrides.
15
+
16
+ ! Monitors MUST poll with `task verify:subagent-alive -- --require-agent <agent-id> [--scratch-dir <worktree>/.deft-scratch/subagent-status]` so a missing required record is exit `1` + `REDISPATCH_OK`, not a raw sweep that treats an empty dir as OK. `task agent:monitor` remains the raw sweep.
15
17
 
16
18
  ```
17
- # Scan all worktrees in the cohort
18
- task agent:monitor -- \
19
- --scratch-dir <worktree-1>/.deft-scratch/subagent-status \
20
- --scratch-dir <worktree-2>/.deft-scratch/subagent-status
19
+ task verify:subagent-alive -- \
20
+ --require-agent <agent-id> \
21
+ --scratch-dir <worktree>/.deft-scratch/subagent-status
21
22
  ```
22
23
 
23
- ! Run the heartbeat sweep alongside the worktree git checks at every monitor polling iteration (~2-3 min). When a record is reported STALE (mid-flight, terminal_state unpopulated, age > threshold), treat it as a candidate for the Takeover Triggers below; when it is reported MALFORMED, surface the diagnostics to the user and re-dispatch the agent with a fresh prompt that re-establishes the heartbeat contract. A TERMINAL record (terminal_state set) is NEVER stale -- the agent reached its exit on its own terms.
24
+ ! Run the liveness gate alongside the worktree git checks at every monitor polling iteration (~2-3 min). When a record is reported STALE (mid-flight, terminal_state unpopulated, age > threshold), treat it as a candidate for the Takeover Triggers below; when it is reported MALFORMED, surface the diagnostics to the user and re-dispatch the agent with a fresh prompt that re-establishes the heartbeat contract. A TERMINAL record (terminal_state set) is NEVER stale -- the agent reached its exit on its own terms.
24
25
 
25
26
  ~ The heartbeat is filesystem-only by design; a network partition or rate-limit ceiling cannot mask agent liveness. Pair the on-disk sweep with the worktree git checks (`git status --short`, `git log --oneline -3`) and the per-PR readiness gate (`task pr:merge-ready`) for the full alive + progressing + clean picture.
26
27
 
@@ -144,12 +145,14 @@ task swarm:pre-dispatch -- \
144
145
  --scope-id <id> --target-id <target> \
145
146
  --action complete --status succeeded|failed|cancelled|blocked
146
147
 
147
- # Takeover: cancel prior attempt, THEN pre-dispatch begin again (never dual active)
148
+ # Takeover after REDISPATCH_OK: cancel prior attempt, THEN pre-dispatch begin again (never dual active)
148
149
  task swarm:pre-dispatch -- --scope-id <id> --target-id <target> --action cancel
149
150
  task swarm:pre-dispatch -- --scope-id <id> --target-id <target> # begin
151
+ # If verify:session-ritual --tier=gated fails first:
152
+ task session:start --rearm --session-id=<same>
150
153
  ```
151
154
 
152
- ! Gate authority is **#3143** `DENY_DUPLICATE_ACTIVE` (`maxActiveAttempts: 1`) on the delivery-attempt unit ledger (`scopeId` + `targetId` + `workflowId`, default workflow `drive-to:merge-ready`). CLI is authoritative; this section is a pointer only.
155
+ ! Gate authority is **#3143** `DENY_DUPLICATE_ACTIVE` (`maxActiveAttempts: 1`) on the delivery-attempt unit ledger (`scopeId` + `targetId` + `workflowId`, default workflow `drive-to:merge-ready`). A killed worker stays `queued`/`running` until cancel; `REDISPATCH_OK` does not lift the deny (#3730). CLI is authoritative; this section is a pointer only.
153
156
  ⊗ Spawn a second implement leaf while pre-dispatch exits 1 (active attempt exists).
154
157
  ⊗ Treat "resume failed" / host false-alive as license to skip the gate.
155
158
  ⊗ Lift DENY by concurrent dual active — escape hatch is cancel-then-begin, not override-while-both-run.
@@ -11,6 +11,7 @@ Load this file only after detect selects Cursor. Do not load other host adapters
11
11
  ### Step 2e: Cursor Launch (Task tool available) — #1877
12
12
 
13
13
  ! When the platform descriptor is `cursor-composer` or `cursor-cloud-agent` (Cursor `Task` tool detected with Cursor signals, no `start_agent`, no `WARP_*`, no Claude Code classification, no OpenClaw `sessions_spawn`, no `spawn_subagent`), dispatch each worker via the Cursor `Task` tool with:
14
+ 0. Create `<worktree>/.deft-scratch/subagent-status/` before spawn if `swarm:launch` / `swarm:pre-dispatch` did not already (#3730). Include preamble § 10.5 (heartbeat + commit early) and poll with `task verify:subagent-alive -- --require-agent <agent-id>`.
14
15
  1. The canonical `templates/agent-prompt-preamble.md` content as the preamble (AGENTS.md read mandate, #810 xBRIEF gate, #798 PowerShell UTF-8, pre-PR + review-cycle mandates).
15
16
  2. The standard worktree prompt (STEP 1-6 from the Prompt Template below).
16
17
  3. The worktree path set to the agent's isolated git worktree.
@@ -24,6 +24,7 @@ This path became first-class in #1342 (platform adapter slices 1-3) and is fully
24
24
  ### Step 2d: Grok Build Launch (spawn_subagent available)
25
25
 
26
26
  ! When the platform descriptor is `grok-build` (spawn_subagent detected, no start_agent, no WARP_*, no Cursor `Task`, no OpenClaw `sessions_spawn`), dispatch each worker via `spawn_subagent` with:
27
+ 0. Create `<worktree>/.deft-scratch/subagent-status/` before spawn if launch/pre-dispatch did not already, and instruct the worker to heartbeat + commit early (#3730).
27
28
  1. The canonical `templates/agent-prompt-preamble.md` content as the preamble
28
29
  2. The standard worktree prompt (STEP 1-6 from the Prompt Template below), adapted to use `get_command_or_subagent_output` for polling rather than `start_agent` lifecycle events
29
30
  3. The worktree path set to the agent's isolated git worktree
@@ -37,7 +37,7 @@ Legend (from RFC2119): !=MUST, ~=SHOULD, ≉=SHOULD NOT, ⊗=MUST NOT, ?=MAY.
37
37
 
38
38
  ## Deterministic Questions Contract
39
39
 
40
- ! Every numbered-menu prompt rendered in this skill (Phase 2 candidate selection, Phase 3 per-item decision walk) ! MUST follow [`../../contracts/deterministic-questions.md`](../../contracts/deterministic-questions.md): render the canonical numbered menu in chat unless the host UI visibly preserves numeric option labels and returns numeric selections or exact displayed option text. The final two numbered options are `Discuss` and `Back`, in that order, and the Discuss-pause semantic from the contract applies verbatim -- on `Discuss` the agent halts the in-progress sequence and resumes only on an explicit user signal.
40
+ ! Every numbered-menu prompt rendered in this skill (Phase 2 candidate selection, Phase 3 per-item decision walk, post-Accept offer) ! MUST follow [`../../contracts/deterministic-questions.md`](../../contracts/deterministic-questions.md): render the canonical numbered menu in chat unless the host UI visibly preserves numeric option labels and returns numeric selections or exact displayed option text. The final two numbered options are `Discuss` and `Back`, in that order, and the Discuss-pause semantic from the contract applies verbatim -- on `Discuss` the agent halts the in-progress sequence and resumes only on an explicit user signal.
41
41
 
42
42
  ## Work selection fork (#2542 / #2402)
43
43
 
@@ -101,6 +101,7 @@ What would you like to do with this candidate?
101
101
  - ~ Bulk: `task triage:bulk-{accept,reject,defer,needs-ac}`; results still flow through the audit log.
102
102
  - ⊗ Write to `xbrief/proposed/` directly -- only `task triage:accept` is authorised.
103
103
  - ~ **Accept → pending chain (#1136):** `task triage:accept` ingests into **`proposed/`**. To stage into WIP (`pending/`) in one operator action: `task triage:accept -- --issue <N> --repo OWNER/NAME --auto-promote` (WIP cap still enforced; use `--force` on the accept command for WIP override). Separately, promote an already-accepted proposed scope by issue: `task scope:promote -- --from-issue=<N> [--repo OWNER/NAME]` (gates on latest `candidates.jsonl` decision = `accept`; non-accept refuses unless `--force-no-cache`; no decision soft-warns, `--strict` fails). Path-based `task scope:promote -- <file>` remains ungated for refinement scaffolds.
104
+ - ? **After Accept (#3708):** offer `deft-directive-design-critique`. Optional; same after `--auto-promote` (promote already happened). Decline writes nothing. Menu: 1. Run critique (existing ADR-005 path) 2. Skip 3. Discuss 4. Back. Back = Skip (do not re-open Accept; undo is `task triage:reset`).
104
105
 
105
106
  ## Phase 4 -- Audit
106
107
 
@@ -141,5 +142,5 @@ Live walkers (`triage:queue`, scope-drift, bootstrap) scan `.deft-cache/github-i
141
142
 
142
143
  ## References
143
144
 
144
- - #1119 D6; #1128 D11 (`triage:queue` / `show` / `audit`); #2890 Phase 3 operator brief; #3116 validity + URL-first; #1122 / #1123 / #1127 / #1129 / #1131; #1136 (`scope:promote --from-issue` / `triage:accept --auto-promote`)
145
+ - #1119 D6; #1128 D11 (`triage:queue` / `show` / `audit`); #2890 Phase 3 operator brief; #3116 validity + URL-first; #1122 / #1123 / #1127 / #1129 / #1131; #1136 (`scope:promote --from-issue` / `triage:accept --auto-promote`); #3708 (post-Accept design-critique offer)
145
146
  - Siblings: `deft-directive-refinement`, `deft-directive-swarm`, `deft-directive-sync`
package/tasks/engine.yml CHANGED
@@ -102,6 +102,10 @@ tasks:
102
102
  " session:start "|" session-start "|\
103
103
  " session:ready "|" session-ready "|\
104
104
  " occupancy:steal "|" occupancy-steal "|\
105
+ " occupancy:release "|" occupancy-release "|\
106
+ " occupancy:heartbeat "|" occupancy-heartbeat "|\
107
+ " occupancy:grant "|" occupancy-grant "|\
108
+ " session:end "|" session-end "|\
105
109
  " lifecycle:event "|" lifecycle-event "|\
106
110
  " verify:session-ritual "|" verify-session-ritual "|\
107
111
  " verify:tools "|" verify-tools "|\
@@ -5,7 +5,7 @@ vars:
5
5
 
6
6
  tasks:
7
7
  file:
8
- desc: "Draft or file a deduped framework-gap issue upstream (#1709). -- task feedback:file -- [--summary TEXT | positional] [--context ...] [--confirm] [--dry-run] [--json]"
8
+ desc: "Draft or file a deduped framework-gap issue upstream (#1709 / #3713). -- task feedback:file -- [--summary TEXT | positional] [--context ...] [--blocker] [--confirm] [--dry-run] [--json]"
9
9
  deps:
10
10
  - task: :engine:_ts-build
11
11
  cmds:
@@ -7,7 +7,7 @@ vars:
7
7
 
8
8
  tasks:
9
9
  steal:
10
- desc: "Supersede a live worktree occupancy lease (#3433). Flags: --confirm --occupant <id>"
10
+ desc: "Lease-only confirmed steal (#3433/#3611). Flags: --confirm --occupant <reported-session-id>; manual/Grok owner: --session-id <your-session-id> or DEFT_SESSION_ID. If ritual differs, align that ID with eligible re-arm or cold session:start. Prefer session:start --steal."
11
11
  dir: '{{.USER_WORKING_DIR}}'
12
12
  env:
13
13
  PYTHONUTF8: "1"
@@ -15,3 +15,36 @@ tasks:
15
15
  - task: :engine:invoke
16
16
  vars:
17
17
  ENGINE_CMD: 'occupancy:steal --project-root "{{.USER_WORKING_DIR}}" {{.CLI_ARGS}}'
18
+
19
+ release:
20
+ desc: "Release this worktree occupancy lease (#3604/#3611). Manual/Grok owner: --session-id <id> or DEFT_SESSION_ID. Owner live or expired residue; non-owner live denied."
21
+ dir: '{{.USER_WORKING_DIR}}'
22
+ # Runtime/session dispatch: no engine:_ts-build / pnpm build (#2181).
23
+ env:
24
+ PYTHONUTF8: "1"
25
+ cmds:
26
+ - task: :engine:invoke
27
+ vars:
28
+ ENGINE_CMD: 'occupancy:release --project-root "{{.USER_WORKING_DIR}}" {{.CLI_ARGS}}'
29
+
30
+ heartbeat:
31
+ desc: "Refresh your own live lease during long quiet stretches (#3599). Manual/Grok owner: --session-id <id> or DEFT_SESSION_ID. Gated writes refresh automatically; this never claims."
32
+ dir: '{{.USER_WORKING_DIR}}'
33
+ # Runtime/session dispatch: no engine:_ts-build / pnpm build (#2181).
34
+ env:
35
+ PYTHONUTF8: "1"
36
+ cmds:
37
+ - task: :engine:invoke
38
+ vars:
39
+ ENGINE_CMD: 'occupancy:heartbeat --project-root "{{.USER_WORKING_DIR}}" {{.CLI_ARGS}}'
40
+
41
+ grant:
42
+ desc: "Admit a dispatched child to your lease for writes (#3755). Owner-only: --session-id <id> or DEFT_SESSION_ID, plus --child-session-id <id> --role <worker-role> [--ttl-minutes N] [--revoke]. Grants admit writes, never administration."
43
+ dir: '{{.USER_WORKING_DIR}}'
44
+ # Runtime/session dispatch: no engine:_ts-build / pnpm build (#2181).
45
+ env:
46
+ PYTHONUTF8: "1"
47
+ cmds:
48
+ - task: :engine:invoke
49
+ vars:
50
+ ENGINE_CMD: 'occupancy:grant --project-root "{{.USER_WORKING_DIR}}" {{.CLI_ARGS}}'
package/tasks/prd.yml CHANGED
@@ -21,12 +21,11 @@ tasks:
21
21
  # would cause go-task to short-circuit before `cmds:` runs, dropping
22
22
  # CLI_ARGS and silently breaking the #539 recovery path (#573, #574).
23
23
  # See deft/conventions/task-caching.md for the full rule.
24
- desc: Export plan.narratives from the specification artifact to a read-only PRD.md
24
+ desc: Export resolved project narratives to a read-only PRD.md
25
25
  summary: |
26
- Reads the specification artifact (xbrief/specification.xbrief.json on migrated
27
- trees, vbrief/specification.vbrief.json on legacy trees) and extracts
28
- plan.narratives into a human-readable PRD.md for stakeholder export. PRD.md is
29
- never authoritative -- the xBRIEF is the source of truth.
26
+ Resolves full-spec or greenfield authority from the project root and extracts
27
+ stakeholder-safe narratives into a human-readable PRD.md. Explicit --spec remains
28
+ supported. PRD.md is never authoritative -- the resolved xBRIEF is the source of truth.
30
29
  dir: '{{.USER_WORKING_DIR}}'
31
30
  deps:
32
31
  - task: :engine:_ts-build
package/tasks/scm.yml CHANGED
@@ -13,6 +13,7 @@ version: '3'
13
13
  # - scm:issue:view (thin wrapper over `ghx|gh issue view`)
14
14
  # - scm:issue:close (thin wrapper over `ghx|gh issue close`)
15
15
  # - scm:issue:edit (thin wrapper over `ghx|gh issue edit`)
16
+ # - scm:issue:design-critique-chip (#3642 closed catalog remaining-set)
16
17
  # - scm:body:* (#1555 safe Markdown body posting via github-body TS CLI)
17
18
  #
18
19
  # Each command is a thin pass-through to `ghx <verb>` (when ghx is on PATH)
@@ -34,8 +35,9 @@ version: '3'
34
35
  # stub deliberately does not re-implement; #881 owns the full surface.
35
36
  #
36
37
  # Forward-compat marker: v1 was issue:* plus #1555 body-posting. #3391
37
- # adds scm:sync-default (dest-targeted staged sync PRs). Other PR verbs
38
- # remain #881.
38
+ # adds scm:sync-default (dest-targeted staged sync PRs). #3642 adds
39
+ # scm:issue:design-critique-chip (closed catalog remaining-set). Other PR
40
+ # verbs remain #881.
39
41
  # ---------------------------------------------------------------------------
40
42
 
41
43
  vars:
@@ -89,6 +91,16 @@ tasks:
89
91
  vars:
90
92
  ENGINE_CMD: 'scm issue edit {{.CLI_ARGS}}'
91
93
 
94
+ issue:design-critique-chip:
95
+ desc: "[#3642] Exclusive design-critique catalog chip -- task scm:issue:design-critique-chip -- --issue N --chip triage-ready|mechanism-shaped [--repo OWNER/NAME]"
96
+ dir: '{{.USER_WORKING_DIR}}'
97
+ deps:
98
+ - task: :engine:_ts-build
99
+ cmds:
100
+ - task: :engine:invoke
101
+ vars:
102
+ ENGINE_CMD: 'scm issue design-critique-chip {{.CLI_ARGS}}'
103
+
92
104
  body:issue:create:
93
105
  desc: "[#1555] Safely create an issue body from --body-file without shell Markdown interpolation"
94
106
  dir: '{{.USER_WORKING_DIR}}'
package/tasks/session.yml CHANGED
@@ -10,7 +10,7 @@ vars:
10
10
 
11
11
  tasks:
12
12
  start:
13
- desc: "Run quick-tier session-start ritual and write .deft/ritual-state.json (#1348). Flags: --defer step=reason / --json"
13
+ desc: "Claim occupancy and run the quick-tier ritual for one owner (#1348/#3611). Flags: --session-id <id> / --steal --confirm --occupant <current-id> / --defer step=reason / --json"
14
14
  dir: '{{.USER_WORKING_DIR}}'
15
15
  # Runtime/session dispatch: no engine:_ts-build / pnpm build (#2181).
16
16
  env:
@@ -21,7 +21,7 @@ tasks:
21
21
  ENGINE_CMD: 'session:start --project-root "{{.USER_WORKING_DIR}}" {{.CLI_ARGS}}'
22
22
 
23
23
  ready:
24
- desc: "One-shot mutation recovery to gated write-ready (#2993). Composes session:start + verify:session-ritual --tier=gated + cache fetch-all when needed. Flags: --json / --repo OWNER/NAME / --with-network"
24
+ desc: "One-shot mutation recovery to gated write-ready (#2993/#3611). Composes session:start + verify:session-ritual --tier=gated + cache fetch-all when needed. Flags: --session-id <id> / --json / --repo OWNER/NAME / --with-network"
25
25
  dir: '{{.USER_WORKING_DIR}}'
26
26
  # Runtime/session dispatch: no engine:_ts-build / pnpm build (#2181).
27
27
  env:
@@ -30,3 +30,14 @@ tasks:
30
30
  - task: :engine:invoke
31
31
  vars:
32
32
  ENGINE_CMD: 'session:ready --project-root "{{.USER_WORKING_DIR}}" {{.CLI_ARGS}}'
33
+
34
+ end:
35
+ desc: "End this mutation session by releasing occupancy (#3604/#3611). Manual/Grok owner: --session-id <id> or DEFT_SESSION_ID. Same as occupancy:release."
36
+ dir: '{{.USER_WORKING_DIR}}'
37
+ # Runtime/session dispatch: no engine:_ts-build / pnpm build (#2181).
38
+ env:
39
+ PYTHONUTF8: "1"
40
+ cmds:
41
+ - task: :engine:invoke
42
+ vars:
43
+ ENGINE_CMD: 'session:end --project-root "{{.USER_WORKING_DIR}}" {{.CLI_ARGS}}'
@@ -14,10 +14,10 @@ tasks:
14
14
  ENGINE_CMD: 'toolchain-check'
15
15
 
16
16
  check-consumer:
17
- desc: Verify required consumer toolchain is installed (git, gh, node, pnpm, task) without Python/go/uv (#2022 Phase 3).
17
+ desc: Verify git, gh, node, and the consumer's selected npm or pnpm; this gate does not probe go-task/Python/go/uv (#3610/#3335).
18
18
  deps:
19
19
  - task: :engine:_ts-build
20
20
  cmds:
21
21
  - task: :engine:invoke
22
22
  vars:
23
- ENGINE_CMD: 'toolchain-check --consumer'
23
+ ENGINE_CMD: 'toolchain-check --consumer --project-root "{{.USER_WORKING_DIR}}"'
@@ -0,0 +1,22 @@
1
+ version: '3'
2
+
3
+ # tasks/triage-evaluate.yml -- Stage A isolated issue-eval (#3648).
4
+ #
5
+ # Wired into Taskfile.yml under include key `triage-evaluate`. Inner task
6
+ # `evaluate` is exposed as `task triage:evaluate`.
7
+ #
8
+ # Per conventions/task-caching.md: NO sources/generates -- user-facing flags.
9
+
10
+ vars:
11
+ DEFT_ROOT: '{{joinPath .TASKFILE_DIR ".."}}'
12
+
13
+ tasks:
14
+ evaluate:
15
+ desc: "Evaluate issues off origin/master (validity + parent WIP + value). -- task triage:evaluate -- <N...> [--concurrency N] [--repo OWNER/NAME] [--json]"
16
+ internal: true
17
+ deps: [":engine:_ts-build"]
18
+ dir: '{{.USER_WORKING_DIR}}'
19
+ cmds:
20
+ - task: :engine:invoke
21
+ vars:
22
+ ENGINE_CMD: 'triage-evaluate --project-root "{{.USER_WORKING_DIR}}" {{.CLI_ARGS}}'
package/tasks/verify.yml CHANGED
@@ -503,7 +503,7 @@ tasks:
503
503
  ENGINE_CMD: 'verify:lifecycle-visible --project-root "{{.USER_WORKING_DIR}}" {{.CLI_ARGS}}'
504
504
 
505
505
  orphan-active:
506
- desc: "Fail-closed orphan-active guard (#2321 / #3429). Detects xbrief/active/ briefs with plan.status==running whose referenced GitHub issues are all closed and/or whose linked PR is merged — the stop-at:pr-open lifecycle leak. Confirmed shipped remediates with task scope:complete / scope:cancel or swarm finalize. Unresolved GitHub lookup still exits 1 but prints a retry, not scope:complete. Three-state exit (0 clean / 1 orphan / 2 config). Pass --issue N to scan one origin after merge; --skip-gh to rely on triage cache only."
506
+ desc: "Fail-closed orphan-active guard (#2321 / #3429). Detects xbrief/active/ briefs with plan.status==running whose referenced GitHub issues are all closed and/or whose linked PR is merged — the stop-at:pr-open lifecycle leak. Confirmed shipped remediates with task scope:complete / scope:cancel or swarm finalize. Unresolved GitHub lookup still exits 1 but prints a retry, not scope:complete. Three-state exit (0 clean / 1 orphan / 2 config). Pass --issue N to scan one origin after merge; --skip-gh to rely on triage cache only. Issue state resolves by query shape (#3767): scoped --issue N takes an authoritative read and stays fail-closed on unknown; the unscoped sweep uses one complete open-issue inventory and stays fail-open on unknown. A cache hit counts only within 15 minutes, and every run prints the basis of its verdict — see content/docs/orphan-active-verdict-basis.md."
507
507
  dir: '{{.USER_WORKING_DIR}}'
508
508
  deps:
509
509
  - task: :engine:_ts-build
@@ -512,6 +512,26 @@ tasks:
512
512
  vars:
513
513
  ENGINE_CMD: 'verify:orphan-active --project-root "{{.USER_WORKING_DIR}}" {{.CLI_ARGS}}'
514
514
 
515
+ pr-closeout-attestable:
516
+ desc: "Fail-closed merge-time closeout gate (#3781). Refuses a merge when the PR's structured closing references name an issue whose brief is still running in xbrief/active/ with acceptance criteria carrying neither x-directive/evidence nor x-directive/disposition. The trigger is the closing reference, not the branch diff — CI runs before the merge and the issue closes on it, so a diff-keyed gate can never fail the PR that creates the orphan. Reuses evaluateAcceptanceEvidenceGate, the same rule scope:complete enforces. A PR that leaves an unattested brief WITHOUT closing its issue is unaffected. Three-state exit (0 attestable or closes nothing / 1 unattested closeout / 2 config or closing-reference lookup error). -- task verify:pr-closeout-attestable -- --pr N [--repo OWNER/REPO]"
517
+ dir: '{{.USER_WORKING_DIR}}'
518
+ deps:
519
+ - task: :engine:_ts-build
520
+ cmds:
521
+ - task: :engine:invoke
522
+ vars:
523
+ ENGINE_CMD: 'verify:pr-closeout-attestable --project-root "{{.USER_WORKING_DIR}}" {{.CLI_ARGS}}'
524
+
525
+ completed-write-guard:
526
+ desc: "Fail-closed completed/ write guard (#3679). Newly added xbrief/completed/ (or vbrief/completed/) artifacts must have been written by scope:complete / scope:fail. Historical corpus is advisory via doctor. Remediation names the leftover land PR (#3476). Three-state exit (0 clean / 1 unguarded add / 2 config). Does not change verify:completed-tracked."
527
+ dir: '{{.USER_WORKING_DIR}}'
528
+ deps:
529
+ - task: :engine:_ts-build
530
+ cmds:
531
+ - task: :engine:invoke
532
+ vars:
533
+ ENGINE_CMD: 'verify:completed-write-guard --project-root "{{.USER_WORKING_DIR}}" {{.CLI_ARGS}}'
534
+
515
535
  completed-tracked:
516
536
  desc: "Fail-closed completed-tracked land guard (#3264 / #1358 / #3476). Closed scoped GitHub issues with a known lifecycle xBRIEF origin must have a tracked xbrief/completed/ or xbrief/cancelled/ artifact on the delivery tip. --issue N is the drive-to DONE form. Remediation: task swarm:finalize-cohort or a lifecycle PR. Three-state exit (0 clean / 1 missing land / 2 config). Pass --skip-gh to rely on triage cache only; --tip to override delivery tip."
517
537
  dir: '{{.USER_WORKING_DIR}}'