@deftai/directive-content 0.109.1 → 0.111.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/.agents/skills/deft-directive-triage/SKILL.md +3 -3
  2. package/SKILL.md +13 -13
  3. package/Taskfile.yml +24 -16
  4. package/commands.md +15 -13
  5. package/contracts/design-critique.md +56 -10
  6. package/contracts/path-write-fence.md +27 -6
  7. package/conventions/machine-generated-banner.md +9 -9
  8. package/conventions/rule-ownership.json +3 -3
  9. package/docs/consumer-issue-label-kit.md +6 -19
  10. package/docs/getting-started.md +1 -1
  11. package/docs/grok-build-subscription-setup.md +146 -0
  12. package/docs/scope-provenance.md +28 -0
  13. package/docs/test-boundary.md +3 -1
  14. package/main.md +22 -22
  15. package/package.json +1 -1
  16. package/packs/rules/rules-pack-0.1.json +1 -1
  17. package/packs/skills/skills-pack-0.1.json +30 -30
  18. package/scm/github.md +1 -1
  19. package/skills/deft-directive-design-critique/SKILL.md +7 -3
  20. package/skills/deft-directive-design-critique/references/motion-shape.md +1 -1
  21. package/skills/deft-directive-portfolio-priority/SKILL.md +2 -2
  22. package/skills/deft-directive-refinement/SKILL.md +3 -3
  23. package/skills/deft-directive-release/SKILL.md +22 -17
  24. package/skills/deft-directive-review-cycle/SKILL.md +45 -12
  25. package/skills/deft-directive-swarm/references/core-phase-0.md +2 -1
  26. package/skills/deft-directive-swarm/references/core-phase-3.md +1 -1
  27. package/skills/deft-directive-swarm/references/host-grok-build.md +17 -1
  28. package/skills/deft-directive-triage/SKILL.md +13 -115
  29. package/tasks/policy.yml +2 -2
  30. package/tasks/scope.yml +16 -25
  31. package/tasks/triage-actions.yml +3 -4
  32. package/tasks/triage-bootstrap.yml +2 -2
  33. package/tasks/triage-bulk.yml +6 -7
  34. package/tasks/triage-classify.yml +13 -3
  35. package/tasks/triage-queue.yml +2 -2
  36. package/tasks/triage-reconcile.yml +2 -2
  37. package/tasks/triage-scope-drift.yml +2 -2
  38. package/tasks/triage-scope.yml +2 -2
  39. package/tasks/triage-smoketest.yml +3 -3
  40. package/tasks/triage-subscribe.yml +2 -2
  41. package/tasks/triage-summary.yml +2 -2
  42. package/tasks/triage-welcome.yml +2 -2
  43. package/tasks/verify.yml +14 -1
  44. package/templates/agent-prompt-preamble.md +4 -1
  45. package/templates/agents-entry.md +7 -7
  46. package/templates/design-critique-brief.md +5 -0
@@ -1,13 +1,9 @@
1
1
  ---
2
2
  name: deft-directive-triage
3
3
  description: >-
4
- Triage-cache hygiene and "what's next?" work selection (ordered plan or
5
- ranked queue) -- the agent-facing playbook for syncing the triage cache,
6
- classifying candidates, presenting a ranked queue or binding to an active
7
- plan-sequence, walking per-item decisions (accept / reject / defer /
8
- needs-ac / mark-duplicate), and auditing the session. Use when the operator
9
- asks what to work on next, wants to build a cohort, work the cache, or run a
10
- triage hygiene pass.
4
+ Withdrawn (#4070). Classify playbook is off. Work selection is
5
+ plan-sequence:current then a read-only triage:queue listing. Replacement
6
+ sieve is #4071. Triggers still match so packs:slice finds this stub.
11
7
  triggers:
12
8
  - triage
13
9
  - triage hygiene
@@ -27,120 +23,22 @@ triggers:
27
23
 
28
24
  # Deft Directive Triage
29
25
 
30
- Triage-cache hygiene + "what's next?" work selection (ordered plan or ranked queue). Operates against the unified `.deft-cache/github-issue/` mirror (#883 Story 2) and the append-only `xbrief/.eval/candidates.jsonl` audit log (#845 Story 2); writes only via the canonical `task triage:*` verbs.
26
+ Withdrawn (#4070). Replacement sieve is #4071. #3579 is transitively withdrawn for the gap.
31
27
 
32
28
  Legend (from RFC2119): !=MUST, ~=SHOULD, ≉=SHOULD NOT, ⊗=MUST NOT, ?=MAY.
33
29
 
34
- ## Platform Requirements
30
+ ## When to Use
35
31
 
36
- ! Requires **GitHub** as the SCM platform and the **GitHub CLI (`gh`)** authenticated against the active project's repo -- the cache surface (`task cache:fetch-all`) and the read-side gate (`task verify:cache-fresh`) both depend on it.
37
-
38
- ## Deterministic Questions Contract
39
-
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
-
42
- ## Work selection fork (#2542 / #2402)
43
-
44
- Directive does not guess your mix: **ordered plan** (`task plan-sequence:*`) when you know the next units in order, or **ranked queue** (`task triage:queue`) when picking from the backlog. Labels bias the queue; they do not override an active plan.
45
-
46
- ! Before Phase 2 on bare "what's next?", run `task plan-sequence:current`. Active sequence → that entry only; exhausted → fail closed. Explicit "what's the queue?" / "build a cohort" → Phase 2. See `commands.md` § Backlog Triage → Two paths.
47
-
48
- ## Phase 0 -- Sync
49
-
50
- ! Probe cache freshness before doing any classification or selection. Stale cache reads produce stale decisions; the gate is the contract.
51
-
52
- 1. ! Run `task verify:cache-fresh` (D5 / #1127). Exit 0 -> proceed to Phase 1. Exit 1 (stale or blocked) -> refresh per the printed remediation. Exit 2 (no bootstrap) -> run `task triage:bootstrap` first. When the cache has zero entries, read paths auto-fetch from GitHub first (#2575).
53
- 2. ~ Refresh path: `task cache:fetch-all -- --source=github-issue --repo OWNER/NAME` for an already-bootstrapped project; `task triage:bootstrap` for a first-time seed.
54
- 3. ~ If `xbrief/active/*.xbrief.json` references are in play, run `task triage:refresh-active` to surface drift before the queue is rendered.
55
- 4. ~ When the session one-liner carries `[scope-drift] N` (D14 / #1133), run `task triage:scope-drift` and choose subscribe / ignore before walking the queue.
56
- 5. ⊗ Walk the queue against a stale cache -- the audit log will record decisions against bodies the operator never actually saw.
57
-
58
- ## Phase 1 -- Classify
59
-
60
- ! Inspect the auto-classification audit log so manually-decided items are not re-walked, and surface anomalies before the queue render.
61
-
62
- 1. ! Run `task triage:classify --list` (D10 / #1129) to render effective rules and hold-markers.
63
- 2. ! Walk recent `xbrief/.eval/candidates.jsonl` entries for anomalies (classifier disagreement, repeated defer, stale needs-ac); surface before Phase 2; do NOT auto-fix.
64
- 3. ~ Scope widen/narrow via `task triage:scope --list` (D12 / #1131); edits belong in PROJECT-DEFINITION.
65
- 4. ~ Label hygiene: recommend repo labels via `gh label list` when unlabeled; do not invent labels or block creation solely for missing labels.
66
- 5. ⊗ Re-classify terminally decided items without operator approval -- supersession is `task triage:reset <N>` only.
67
-
68
- ## Phase 2 -- Present
69
-
70
- ! Apply the Work selection fork gate (#2542): when no ordered-plan is active, render `task triage:queue` before suggesting work (#1149). Active sequence yields to the ordered-plan entry (#2402).
71
-
72
- 1. ! Run `task triage:queue --limit=N` (D11 / #1128) -- default `N=10`. Groups `[RESUME]` -> `[URGENT]` -> untriaged -> other; ranking via `plan.policy.triageRankingLabels[]`, tiebreak `updated_at` desc.
73
- 2. ! For per-item detail, run `task triage:show <N>` (default) or `task triage:show --format=operator <N>` (#2890) -- cached payload, latest decision, audit timeline, active-xBRIEF flag; operator format is the pasteable Phase 3 brief backbone. Exit 0 on hit, 1 on cache miss (re-sync per Phase 0).
74
- 3. ~ Present the ranked **queue listing** verbatim; do NOT silently re-rank, drop, or annotate the listing beyond the canonical renderer. This queue non-annotation rule does **not** forbid Phase 3 per-candidate operator briefs or leans (see Phase 3 / #2890).
75
- 4. ⊗ Recommend a specific issue without `task triage:queue` first, or an issue absent from the queue without `task triage:show` to surface why.
76
-
77
- ## Phase 3 -- Decide
78
-
79
- ! Walk per-item decisions through the canonical `task triage:*` verbs (tasks own audit-log append / schema / `xbrief/proposed/` write).
80
-
81
- ! **Operator brief (same turn as menu) (#2890 / #3116):** Before every per-item decision menu, present an operator brief in the **same operator-visible message/surface** as the menu, containing at least: **URL-first** lead (canonical issue URL as the first line for that item, or `#N title` + URL); labels (or explicit none); **current-state validity** (`still-open` | `partial` | `likely-shipped` | `needs-re-scope`) + one-line evidence (linked closed PR, code path, or "no evidence of fix"); 2–5 line problem/context summary; AC bullets or explicit "thin body / no AC"; agent **lean** + one-line why (Accept / Defer / Reject / Needs-AC / …). ~ Prefer `task triage:show --format=operator <N>` as the brief backbone (URL-first + validity placeholder); agent still owns validity verdict and lean. ⊗ Menu-only or chip-only Phase 3 turns without that brief. ⊗ Brief-only turn followed by a later chip/menu-only turn that does not restate the brief. ⊗ Body-only summary without validity check against current master, closed children, or linked PRs.
82
-
83
- ! **Host structured-question adapter:** On chips / `ask_user` / similar UIs (e.g. OpenClaw `ask_user`), keep the prose brief in chat; structured options are **actions only** (Accept / Defer / Reject / Needs-AC / Mark duplicate / Discuss / Back). Option labels ≉ substitute for the brief.
84
-
85
- For each candidate, render the canonical numbered action menu and dispatch:
86
-
87
- ```
88
- What would you like to do with this candidate?
89
- 1. Accept -- `task triage:accept -- --issue <N> --repo OWNER/NAME`
90
- 2. Reject -- `task triage:reject -- --issue <N> --repo OWNER/NAME`
91
- 3. Defer -- `task triage:defer -- --issue <N> --repo OWNER/NAME [--resume-on <event>]`
92
- 4. Needs-AC -- `task triage:needs-ac -- --issue <N> --repo OWNER/NAME`
93
- 5. Mark duplicate -- `task triage:mark-duplicate -- --issue <N> --of <of-issue> --repo OWNER/NAME`
94
- 6. Discuss
95
- 7. Back
96
- ```
97
-
98
- - ! Map user replies only to the displayed number (`1`-`7`) or exact displayed option text. ⊗ Do NOT infer from alphabetic host affordances or bare letters such as `d` / `b` unless those letters were visibly rendered as choices.
99
- - ! On `Discuss`, halt immediately, prompt `What would you like to discuss?`, resume only on explicit user signal. ⊗ Implicit resumption.
100
- - ! On `Back`, un-buffer prior selection and re-render its action menu only before a `task triage:*` dispatch; after dispatch use `task triage:reset`.
101
- - ~ Bulk: `task triage:bulk-{accept,reject,defer,needs-ac}`; results still flow through the audit log.
102
- - ⊗ Write to `xbrief/proposed/` directly -- only `task triage:accept` is authorised.
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`).
105
-
106
- ## Phase 4 -- Audit
107
-
108
- ! Confirm the session's decisions landed coherently before exiting the skill.
109
-
110
- 1. ! Run `task triage:audit --format=json` (D11 / #1128); optional `#1180` filters `--since` / `--action`. Transform with `jq` -- framework does not compute trends.
111
- 2. ! Run `task triage:summary` (D2 / #1122) -- `[triage] N untriaged · S stale-defer · M in-flight · WIP X/Y [⚠] [· [scope-drift] N]`.
112
- 3. ~ Non-zero `[scope-drift]` → surface `task triage:scope-drift` + subscribe/unsubscribe/ignore remediation; then `task triage:bootstrap -- --resume`.
113
- 4. ~ Stale accept (no active xBRIEF ref) → re-ingest or `task triage:reset`.
114
- 5. ⊗ Skip Phase 4 audit.
115
- 6. ! Umbrella/epic status: REST comments → `## Current shape (as of pass-N)` (#2066 / #1152); never body alone.
116
-
117
- ## Reversibility
118
-
119
- ! Undo via `task triage:reset <N>` (Layer 5; history never deleted). ⊗ Edit/delete `xbrief/.eval/candidates.jsonl` to "undo".
120
-
121
- ## Quarterly closed-entry archive vs TTL prune (#1137)
122
-
123
- Live walkers (`triage:queue`, scope-drift, bootstrap) scan `.deft-cache/github-issue/`. Closed issues can linger forever. Operators may run an **explicit, reversible** archive pass — never auto on bootstrap/session/check.
124
-
125
- | Tool | What it does |
126
- | --- | --- |
127
- | `task triage:cache-archive` | Move **closed** + aged (default 30d) entries → `.deft-cache/archived/github-issue/...` with `archive-meta.json`. Skips open lifecycle scopes. `--dry-run` first. |
128
- | `task triage:archive-list` / `task triage:restore-from-archive` | List / move back to live. |
129
- | `task cache:prune` | **TTL hard-delete** by `expires_at` — **not** reversible; **not** closed-state archive. |
130
-
131
- ! Prefer archive for closed clutter; use prune only for expired TTL / cap eviction. ⊗ Wire archive into session-start or `task check`.
132
-
133
- ## Anti-Patterns
134
-
135
- - ⊗ Recommend work without `task triage:queue` (#1149).
136
- - ⊗ Conclude "nothing to do" from folder scans or live GitHub alone (#2576).
137
- - ⊗ Stale-cache walk; reimplement audit/`proposed/` writes; treat defer/needs-ac as terminal; edit candidates.jsonl; menu-only Phase 3 without operator brief (#2890); body-only brief without URL-first or current-state validity (#3116).
32
+ - Triggers still match so `packs:slice` finds this stub.
33
+ - ⊗ Do not load the old classify / Phase 1-3 playbook.
138
34
 
139
35
  ## EXIT
140
36
 
141
- ! On opt-out: `deft-directive-triage complete -- exiting skill.` Chain: `deft-directive-refinement` (accepted items) · `deft-directive-swarm` (cohort) · `task cache:fetch-all` then re-enter. ⊗ Silent exit.
37
+ ! On any trigger: print `deft-directive-triage withdrawn -- exiting skill.` Point at https://github.com/deftai/directive/issues/4070 and #4071.
38
+
39
+ ! Work selection during the gap: `task plan-sequence:current`, then a read-only `task triage:queue` listing.
142
40
 
143
- ## References
41
+ `task triage:classify -- --mirror` (dry-run or `--apply`).
42
+ ⊗ Treat leftover `triaged` / `triage:*` chips as a decision.
144
43
 
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)
146
- - Siblings: `deft-directive-refinement`, `deft-directive-swarm`, `deft-directive-sync`
44
+ `task triage:accept` / `issue:ingest` stay. Do not close #1423, #3579, #2611, or #3923.
package/tasks/policy.yml CHANGED
@@ -21,8 +21,8 @@ tasks:
21
21
  # --format=text|json -- machine-stable scripting envelope
22
22
  # --changed-only -- drop default-source rows
23
23
  # --field=<name> -- single-field isolation
24
- # The legacy `python -m scripts.policy show` CLI continues to work for
25
- # any scripts that called it directly (back-compat for #746 consumers).
24
+ # Inspect via engine:invoke / packages/cli/dist (policy:show). The
25
+ # retired `python -m scripts.policy` launcher is gone.
26
26
  desc: "Inspect every registered typed-policy field on vbrief/PROJECT-DEFINITION.vbrief.json (#1148 / N8). -- task policy:show [-- --format=json] [--changed-only] [--field=<name>]"
27
27
  dir: '{{.USER_WORKING_DIR}}'
28
28
  deps:
package/tasks/scope.yml CHANGED
@@ -5,33 +5,24 @@ vars:
5
5
 
6
6
  # scope lifecycle tasks.
7
7
  #
8
- # IMPORTANT: every task sets ``dir: '{{.USER_WORKING_DIR}}'`` so the Python
9
- # script's CWD is the consumer project root, NOT ``deft/``. The script path
10
- # is resolved via ``{{.DEFT_ROOT}}/scripts/`` (DEFT_ROOT is defined locally
11
- # in this file's `vars:` block via ``{{joinPath .TASKFILE_DIR ".."}}`` --
12
- # see ../Taskfile.yml for why root-level definition is avoided) so it
13
- # still points at ``deft/scripts/scope_lifecycle.py`` after the dir switch.
14
- # The previous ``{{.TASKFILE_DIR}}/../scripts/`` form broke on Windows
15
- # under `uv --project "{{.DEFT_ROOT}}" run python` (#566) because mixed-separator traversal
16
- # normalizes incorrectly and drops the deft/ prefix.
8
+ # IMPORTANT: every task sets ``dir: '{{.USER_WORKING_DIR}}'`` so
9
+ # engine:invoke CWD is the consumer project root, NOT the framework tree.
10
+ # DEFT_ROOT is defined locally in this file's `vars:` block via
11
+ # ``{{joinPath .TASKFILE_DIR ".."}}`` -- see ../Taskfile.yml for why
12
+ # root-level definition is avoided.
17
13
  #
18
- # CLI_ARGS: passed to the script raw / unquoted. go-task shell-escapes
19
- # CLI_ARGS with single quotes on its own, so wrapping the interpolation
20
- # in Taskfile-level double quotes produces ``"'path'"`` at dispatch time
21
- # on Windows (pwsh/cmd preserve nested quotes verbatim), and Python's
22
- # argv receives a literal single-quote-prefixed filename that fails to
23
- # open (#577). All seven scope:* commands therefore forward
24
- # ``{{.CLI_ARGS}}`` bare -- matching migrate.yml / prd.yml / issue.yml /
25
- # reconcile.yml. ``scope_lifecycle.py`` handles both absolute and
26
- # relative values via ``_resolve_file_path`` + ``resolve_project_root``
27
- # -- the script owns path resolution, the task just forwards
28
- # ``--project-root`` so detection never silently falls back to deft's
29
- # own tree (#535). Relative paths resolve against the consumer root
30
- # thanks to ``--project-root``; absolute paths are used as-is.
14
+ # Handler: packages/cli/src/scope-lifecycle.ts via engine:invoke
15
+ # (packages/cli/dist). Help registry:
16
+ # packages/core/src/triage/help/registry-data.ts (edit in place).
31
17
  #
32
- # ``env: PYTHONUTF8: "1"`` is set per-task as a belt-and-suspenders guard
33
- # for Windows (cp1252 default crashes on -- / -> / x / !); the top-level
34
- # Taskfile.yml also sets this (#540).
18
+ # CLI_ARGS: passed raw / unquoted. go-task shell-escapes CLI_ARGS with
19
+ # single quotes on its own, so wrapping the interpolation in
20
+ # Taskfile-level double quotes produces ``"'path'"`` at dispatch time
21
+ # on Windows (#577). All scope:* commands therefore forward
22
+ # ``{{.CLI_ARGS}}`` bare -- matching migrate.yml / prd.yml / issue.yml /
23
+ # reconcile.yml. The TypeScript handler owns path resolution; the task
24
+ # forwards ``--project-root`` so detection never silently falls back to
25
+ # the framework tree (#535).
35
26
 
36
27
  tasks:
37
28
 
@@ -20,10 +20,9 @@ version: '3'
20
20
  # (#74), `task pr:check-protected-issues` (#702), and `task verify:encoding`
21
21
  # (#798).
22
22
  #
23
- # Companion script: scripts/triage_actions.py
24
- # Companion tests: tests/test_triage_actions.py
25
- # Upstream contracts (frozen): scripts/candidates_log.py (#845 Story 2 audit log),
26
- # scripts/cache.py (#883 Story 2 unified cache).
23
+ # Handler: packages/cli/src/triage-actions.ts via engine:invoke (packages/cli/dist).
24
+ # Help registry: packages/core/src/triage/help/registry-data.ts (edit in place).
25
+ # Audit/cache contracts live in packages/core (candidates log + unified cache).
27
26
 
28
27
  vars:
29
28
  DEFT_ROOT: '{{joinPath .TASKFILE_DIR ".."}}'
@@ -15,8 +15,8 @@ version: '3'
15
15
  # tasks/triage-bulk.yml (Story 4 -- bulk ops + freshness)
16
16
  # tasks/triage-bootstrap.yml (Story 6 -- this file)
17
17
  #
18
- # Companion script: scripts/triage_bootstrap.py
19
- # Companion test: tests/test_triage_bootstrap.py
18
+ # Handler: packages/cli/src/triage-bootstrap.ts via engine:invoke (packages/cli/dist).
19
+ # Help registry: packages/core/src/triage/help/registry-data.ts (edit in place).
20
20
  #
21
21
  # Per `conventions/task-caching.md` (#574): NO `sources:` / `generates:`
22
22
  # declarations on this task because user-facing recovery flags
@@ -11,13 +11,12 @@ version: '3'
11
11
  # are hidden from `task -l`.
12
12
  #
13
13
  # The disable-gate `cmds:` blocks introduced by PR #916 (#915 hot-fix) were
14
- # REVERSED once scripts/triage_bulk.py was rewritten to walk the local
15
- # cache instead of live `gh issue list`. As of #883 Story 3 the cache walk
16
- # consumes the unified `cache:get` surface
17
- # (`.deft-cache/github-issue/<owner>/<repo>/<N>/`); the four `bulk-*`
18
- # targets continue to invoke triage_bulk.py directly. The cache-empty
19
- # hard-fail (exit 2) and Tier-2 audit-log short-circuit are enforced
20
- # inside triage_bulk.py itself (#915 fix).
14
+ # reversed once bulk ops walked the local cache instead of live `gh issue
15
+ # list`. As of #883 Story 3 the cache walk consumes the unified `cache:get`
16
+ # surface (`.deft-cache/github-issue/<owner>/<repo>/<N>/`); the four
17
+ # `bulk-*` targets invoke packages/cli/src/triage-bulk.ts via engine:invoke.
18
+ # The cache-empty hard-fail (exit 2) and Tier-2 audit-log short-circuit are
19
+ # enforced inside that handler (#915 fix).
21
20
  #
22
21
  # Per `conventions/task-caching.md` (#574): every target here accepts user
23
22
  # flags via `{{.CLI_ARGS}}` (--label, --author, --age-days, --cluster,
@@ -13,8 +13,8 @@ version: '3'
13
13
  # `--validate`, `--project-root`) are forwarded via {{.CLI_ARGS}} and
14
14
  # go-task's incremental-build cache layer would silently swallow them.
15
15
  #
16
- # Companion script: scripts/triage_classify.py (+ scripts/_triage_classify_cli.py)
17
- # Companion tests: tests/test_triage_classify.py
16
+ # Handler: packages/cli/src/triage-classify.ts via engine:invoke (packages/cli/dist).
17
+ # Help registry: packages/core/src/triage/help/registry-data.ts (edit in place).
18
18
  # Current Shape: https://github.com/deftai/directive/issues/1129#issuecomment-4471901622
19
19
 
20
20
  vars:
@@ -22,7 +22,7 @@ vars:
22
22
 
23
23
  tasks:
24
24
  classify:
25
- desc: "Inspect / validate triageAutoClassify + triageLabelMirror; Tier-1 SCM label mirror (#1129 / #1423). -- task triage:classify -- [--list | --validate | --mirror [--apply]]"
25
+ desc: "Inspect / validate triageAutoClassify + triageLabelMirror. --mirror is withdrawn (#4070)."
26
26
  internal: true
27
27
  deps: [":engine:_ts-build"]
28
28
  dir: '{{.USER_WORKING_DIR}}'
@@ -30,3 +30,13 @@ tasks:
30
30
  - task: :engine:invoke
31
31
  vars:
32
32
  ENGINE_CMD: 'triage-classify --project-root "{{.USER_WORKING_DIR}}" {{.CLI_ARGS}}'
33
+
34
+ strip-withdrawn-chips:
35
+ desc: "Remaining-set strip of withdrawn triaged / triage:* chips (#4070). Dry-run default; --apply writes. --emit-digest prints shadowed vs faithful classify rows for #4071."
36
+ internal: true
37
+ deps: [":engine:_ts-build"]
38
+ dir: '{{.USER_WORKING_DIR}}'
39
+ cmds:
40
+ - task: :engine:invoke
41
+ vars:
42
+ ENGINE_CMD: 'triage-strip-withdrawn --project-root "{{.USER_WORKING_DIR}}" {{.CLI_ARGS}}'
@@ -17,8 +17,8 @@ version: '3'
17
17
  # `--project-root`, `--cache-root`, `--audit-log`) via {{.CLI_ARGS}} and
18
18
  # go-task's incremental-build cache layer would silently swallow them.
19
19
  #
20
- # Companion script: scripts/triage_queue.py (+ scripts/_triage_queue_cli.py)
21
- # Companion tests: tests/test_triage_queue.py
20
+ # Handler: packages/cli/src/triage-queue.ts via engine:invoke (packages/cli/dist).
21
+ # Help registry: packages/core/src/triage/help/registry-data.ts (edit in place).
22
22
  # Current Shape: https://github.com/deftai/directive/issues/1128#issuecomment-4471272093
23
23
 
24
24
  vars:
@@ -12,8 +12,8 @@ version: '3'
12
12
  # `--project-root`) are forwarded via {{.CLI_ARGS}} and go-task's
13
13
  # incremental-build cache layer would silently swallow them.
14
14
  #
15
- # Companion script: scripts/triage_reconcile.py
16
- # Companion tests: tests/test_triage_reconcile.py
15
+ # Handler: packages/cli/src/triage-reconcile.ts via engine:invoke (packages/cli/dist).
16
+ # Help registry: packages/core/src/triage/help/registry-data.ts (edit in place).
17
17
  # Pattern reference: tasks/triage-bootstrap.yml (#845 Story 6).
18
18
 
19
19
  vars:
@@ -13,8 +13,8 @@ version: '3'
13
13
  # {{.CLI_ARGS}} and go-task's incremental-build cache layer would silently
14
14
  # swallow them.
15
15
  #
16
- # Companion script: scripts/triage_scope_drift.py (+ shims).
17
- # Companion tests: tests/test_triage_scope_drift.py.
16
+ # Handler: packages/cli/src/triage-scope-drift.ts via engine:invoke (packages/cli/dist).
17
+ # Help registry: packages/core/src/triage/help/registry-data.ts (edit in place).
18
18
 
19
19
  vars:
20
20
  DEFT_ROOT: '{{joinPath .TASKFILE_DIR ".."}}'
@@ -14,8 +14,8 @@ version: '3'
14
14
  # via {{.CLI_ARGS}} and go-task's incremental-build cache layer would
15
15
  # silently swallow them.
16
16
  #
17
- # Companion script: scripts/triage_scope.py (+ scripts/_triage_scope_cli.py)
18
- # Companion tests: tests/test_triage_scope.py
17
+ # Handler: packages/cli/src/triage-scope.ts via engine:invoke (packages/cli/dist).
18
+ # Help registry: packages/core/src/triage/help/registry-data.ts (edit in place).
19
19
  # Current Shape: https://github.com/deftai/directive/issues/1131#issuecomment-4471901494
20
20
 
21
21
  vars:
@@ -13,9 +13,9 @@ version: '3'
13
13
  # `--cache-only`, `--fixture`) are forwarded via {{.CLI_ARGS}} and
14
14
  # go-task's incremental-build cache layer would silently swallow them.
15
15
  #
16
- # Companion script: scripts/triage_smoketest.py (+ scripts/_triage_smoketest_stages.py)
17
- # Companion fixture: tests/fixtures/triage_smoketest/
18
- # Companion tests: tests/test_triage_smoketest.py + tests/test_triage_smoketest_fixture.py
16
+ # Handler: packages/cli/src/triage-smoketest.ts via engine:invoke (packages/cli/dist).
17
+ # Help registry: packages/core/src/triage/help/registry-data.ts (edit in place).
18
+ # Fixture: tests/fixtures/triage_smoketest/
19
19
  # Pattern reference: tasks/triage-summary.yml (D2 / #1122).
20
20
 
21
21
  vars:
@@ -12,8 +12,8 @@ version: '3'
12
12
  # declarations -- user-facing flags (`--label`, `--milestone`, `--issue`,
13
13
  # `--issue-note`, `--actor`) are forwarded via {{.CLI_ARGS}}.
14
14
  #
15
- # Companion script: scripts/triage_subscribe.py (+ shim).
16
- # Companion tests: tests/test_triage_subscribe.py.
15
+ # Handler: packages/cli/src/triage-subscribe.ts via engine:invoke (packages/cli/dist).
16
+ # Help registry: packages/core/src/triage/help/registry-data.ts (edit in place).
17
17
 
18
18
  vars:
19
19
  DEFT_ROOT: '{{joinPath .TASKFILE_DIR ".."}}'
@@ -12,8 +12,8 @@ version: '3'
12
12
  # `--no-history`, `--json`) are forwarded via {{.CLI_ARGS}} and go-task's
13
13
  # incremental-build cache layer would silently swallow them.
14
14
  #
15
- # Companion script: scripts/triage_summary.py
16
- # Companion tests: tests/test_triage_summary.py
15
+ # Handler: packages/cli/src/triage-summary.ts via engine:invoke (packages/cli/dist).
16
+ # Help registry: packages/core/src/triage/help/registry-data.ts (edit in place).
17
17
  # Pattern reference: tasks/triage-scope.yml (D12 / #1131 / merged via #1190).
18
18
 
19
19
  vars:
@@ -13,8 +13,8 @@ version: '3'
13
13
  # `--no-subprocess`) are forwarded via {{.CLI_ARGS}} and go-task's
14
14
  # incremental-build cache layer would silently swallow them.
15
15
  #
16
- # Companion script: scripts/triage_welcome.py (+ scripts/_triage_welcome_cli.py)
17
- # Companion tests: tests/test_triage_welcome.py
16
+ # Handler: packages/cli/src/triage-welcome.ts via engine:invoke (packages/cli/dist).
17
+ # Help registry: packages/core/src/triage/help/registry-data.ts (edit in place).
18
18
  # Pattern reference: tasks/triage-summary.yml (D2 / #1122).
19
19
 
20
20
  vars:
package/tasks/verify.yml CHANGED
@@ -369,6 +369,19 @@ tasks:
369
369
  vars:
370
370
  ENGINE_CMD: 'codebase-map-fresh --project-root "{{.USER_WORKING_DIR}}" {{.CLI_ARGS}}'
371
371
 
372
+
373
+ spec-prd-fresh:
374
+ desc: "Fail-closed SPECIFICATION.md / PRD.md render-freshness gate (#4086). Re-renders to a buffer and fails on banner or projection diff. Banner canon and full projection freshness are separate assertions. Modeled on verify:codebase-map-fresh."
375
+ dir: '{{.USER_WORKING_DIR}}'
376
+ deps:
377
+ - task: :engine:_ts-build
378
+ # Per conventions/task-caching.md: no sources/generates because this gate
379
+ # forwards project-root through CLI_ARGS.
380
+ cmds:
381
+ - task: :engine:invoke
382
+ vars:
383
+ ENGINE_CMD: 'verify:spec-prd-fresh --project-root "{{.USER_WORKING_DIR}}" {{.CLI_ARGS}}'
384
+
372
385
  session-ritual:
373
386
  desc: "Fail-closed session ritual verifier (#1348). Flags: --tier quick|gated / --json. Set DEFT_SESSION_RITUAL_SKIP=1 for headless workers and CI."
374
387
  dir: '{{.USER_WORKING_DIR}}'
@@ -401,7 +414,7 @@ tasks:
401
414
  ENGINE_CMD: 'verify:tools {{.CLI_ARGS}}'
402
415
 
403
416
  scm-boundary:
404
- desc: "Detection-bound gate against raw `gh` / `ghx` subprocess calls outside `scripts/scm.py` (#1145 / N5). Scans verb-layer Python files (`scripts/triage_*.py`, `scripts/scope_*.py`, `scripts/slice_*.py`, `scripts/_triage_*.py`, `scripts/_scope_*.py`, `scripts/resume_conditions.py`, `scripts/issue_ingest.py`) and fails loud when any of them invoke `gh` directly instead of going through `scm.call(source, verb, args)`. Three-state exit (0 clean / 1 violations / 2 config error). Document an exception via `--allow-list <path>` (file with newline-separated glob patterns)."
417
+ desc: "Detection-bound gate against raw `gh` / `ghx` subprocess calls (#1145 / N5). TypeScript verbs route through packages/core/src/scm/call.ts. The scanner still globs retired scripts/triage_*.py paths (vacuous; owner packages/core/src/verify-source/scm-boundary.ts SCOPE_GLOBS). Three-state exit (0 clean / 1 violations / 2 config error). Document an exception via `--allow-list <path>`."
405
418
  dir: '{{.USER_WORKING_DIR}}'
406
419
  deps:
407
420
  - task: :engine:_ts-build
@@ -97,6 +97,7 @@ Populate `selected_backend` OR `routing_policy` (or both when the operator sets
97
97
  **Role-boundary expectations (all providers):** the same boundaries apply whether the worker runs on Composer, Grok Build, Cursor/cloud, Claude Code, OpenClaw, or a future adapter:
98
98
 
99
99
  - ! `leaf-implementation` workers implement scoped xBRIEF work in their assigned worktree only -- gates (`task check`, file-scope audit, Greptile review cycle) are model-agnostic and MUST still pass.
100
+ - ! **Spawned mutating workers take their own worktree (#4066).** Implement-class spawn must carry `isolation=worktree` or a linked `worktree_path`/`cwd` before occupancy claim. Sharing the primary checkout with a live occupant is refuse, not `occupancy:grant` across hosts. Master/primary occupancy is the exception (`release-cut`, `policy-restore`, operator-directed default-branch work). `--read-only` never claims. On DONE/terminal the dispatcher compare-and-releases the recorded child tree (incarnation + parent-id); do not steal the parent's lease to recover. Grok `spawn_subagent` cannot rewrite PreToolUse input -- pass cwd to the reserved worktree.
100
101
  - ! `orchestrator`, `review-monitor`, and `merge-release` roles MUST run on strong or review-capable agents; dispatchers MUST NOT route these roles to cheap leaf backends.
101
102
  - ⊗ Route a cheap leaf backend onto the merge cascade, Phase 5->6 release gate, conflict-resolution rebase, or review-cycle merge-ready decision -- these are irreversible-damage surfaces that stay on the strong tier regardless of provider.
102
103
 
@@ -486,10 +487,12 @@ These rules bind **orchestrators** dispatching implementation, fix, or review-cy
486
487
 
487
488
  **Worker-owns-lifecycle (Gap C):**
488
489
 
489
- - ! When dispatching an implementation worker, the dispatch envelope MUST declare the unit-of-work boundary explicitly: `stop-at: pr-open` (worker opens PR and exits) OR `drive-to: merge-ready` (worker owns PR + Greptile review cycle + fix batches through merge-ready as ONE unit of work, spawning its own review poller per `skills/deft-directive-review-cycle/SKILL.md` monitoring tiers). Default for story implementation dispatches is `drive-to: merge-ready`.
490
+ - ! When dispatching an implementation worker, the dispatch envelope MUST declare the unit-of-work boundary explicitly: `stop-at: pr-open` (worker opens PR and exits) OR `drive-to: merge-ready` (worker owns PR + Greptile review cycle + fix batches through merge-ready as ONE unit of work, following `skills/deft-directive-review-cycle/SKILL.md` monitoring tiers). On hosts whose leaves cannot nest a review-monitor (Cursor #2797, Claude Code #3134, Grok Build #4130), merge-ready means blocking `pr:watch` in **this** process -- not spawning a child poller. Default for story implementation dispatches is `drive-to: merge-ready`.
490
491
  - ! **Envelope selection SLA (#3153):** Choose the boundary before spawn using the swarm decision tree (`skills/deft-directive-swarm/references/core-phase-0.md` — capacity stall, conf-only residual, wall-clock budget, large multi-gate, host nest limits). Happy-path default remains `drive-to: merge-ready`. A **deliberate** `stop-at: pr-open` is valid only with an immediate partner merge-path owner per `skills/deft-directive-review-cycle/SKILL.md` § Partner merge-path (babysit / Approach 1 lease / parent-retained — not freestyle global babysit). Under human-merge policy, that owner (or an explicit handoff recipient) remains responsible through merge + `scope:complete` — do not stand down at CLEAN alone. Consumer pin: `templates/agents-entry.md` § Envelope selection SLA. Silent PR-open handback for a worker already scoped merge-ready remains **forbidden**.
491
492
  - ! **Cursor Task ownership split (#2797 / #2814):** A Cursor `Task` implementation leaf MUST NOT spawn another Cursor `Task` review-monitor: nested Task (leaf spawning leaf) is unsupported/unreliable. A Cursor `drive-to: merge-ready` leaf instead owns a blocking `task pr:watch -- <N>` in its own process. To use an Approach 1 monitor, scope the leaf `stop-at: pr-open`; the orchestrator that owns the Task primitive then launches the sibling monitor and runs `task review-monitor:register -- --pr <N> --monitor-agent-id <id> --platform-primitive cursor-task` (GitHub sticky `<!-- deft:review-owner -->` lease — not local JSON).
492
493
  - ⊗ Let a Cursor leaf background `task pr:watch` and claim review monitoring is active. The process dies with the leaf and has no GitHub review-owner lease; treat that claim as a regression/eval failure and let `task verify:review-monitor -- --pr <N>` fail closed.
494
+ - ! **Grok Build ownership split (#4130 / #2797 analogue):** A `spawn_subagent` implementation leaf MUST NOT nested-spawn a review-monitor or any other `spawn_subagent`. Nested spawn does not report to the parent, and the parent cannot re-prompt a live child (`resume_from` requires terminal). A Grok Build `drive-to: merge-ready` leaf instead owns a blocking `deft pr:watch <N>` (or `task deft:pr:watch -- <N>`) in its own process, then `pr:merge-ready` / merge in the same loop. To use an Approach 1 monitor, scope the leaf `stop-at: pr-open`; the orchestrator that owns `spawn_subagent` then launches the sibling monitor and registers `--platform-primitive spawn_subagent`. If the leaf needs another agent, it stops and reports `BLOCKED`.
495
+ - ⊗ Tell a grok-build leaf to spawn its own review poller, or let it nested-spawn `spawn_subagent` and claim monitoring is active.
493
496
  - ! **Post-merge scope lifecycle (#2321 / Gap C / #3429 / #3476):** Workers scoped `stop-at: pr-open` MUST NOT run `task scope:complete` before exit — their activation checkpoint rides into master on merge. The **orchestrator** (or Phase 6 `task swarm:finalize-cohort` / `task swarm:complete-cohort` on the headless path) MUST run `task scope:complete` or `task scope:cancel` for each shipped story xBRIEF after its PR merges. Workers scoped `drive-to: merge-ready` (or `drive-to: merge`) MUST include `task scope:complete` on their active xBRIEF as part of the same unit of work (after merge when appropriate). After merge (or observing merge) of issue `#N`, run `task verify:orphan-active -- --issue N`. Exit `0` is required before `DONE`. Exit `1` shipped → run the printed `task scope:complete -- <path>`. Exit `1` unresolved lookup → retry / emit `BLOCKED`; ⊗ complete unfinished scope. After `scope:complete`, `task verify:completed-tracked -- --issue N` MUST be exit `0` against `origin/<deliveryBranch>` (not feature-worktree HEAD) before `DONE` (#3476). Exit `1` missing tracked artifact → not DONE; remediate with `task swarm:finalize-cohort` or a lifecycle PR. `scope:complete` stays filesystem-only — ⊗ teach every leaf to commit on master.
494
497
  - ! Workers scoped `drive-to: merge-ready` MUST drive to merge-ready in their own tool loop — pre-PR, push, PR open, review-cycle poll/fix loop, and the #1259 Step 6 fail-closed exit — without handing back at PR-open for the orchestrator to re-dispatch separate leaf agents for review or fixes.
495
498
  - ⊗ Re-dispatch a separate review-monitor or fix agent after an implementation worker exits at PR-open when the original envelope scoped `drive-to: merge-ready` — that split recreates cross-agent state-handoff hazards and terminal lifecycle gaps (#1878 / Gap C).
@@ -17,11 +17,11 @@ Deft is installed in .deft/core/. Full guidelines: .deft/core/main.md
17
17
 
18
18
  ## Session routing (#2176)
19
19
 
20
- ! **Read-only default** until mutation intent: load AGENTS.md / main.md / USER.md / `xbrief/PROJECT-DEFINITION.xbrief.json`; resolve USER.md via `deft session:start` (`USER.md resolved …`; win32 `%APPDATA%\deft\USER.md`; unix `~/.config/deft/USER.md`; ⊗ invent `~/.config/deft` on Windows #2544); confirm Deft alignment + addressing-name; ⊗ no mutable `deft session:start` / triage welcome / sync / branch-policy unless asked or implementation-ready (#2176) — `.deft/core/commands.md` § Session routing. Bootstrap: cold-start → README § Cold-start (#2273) ⊗ never `.deft/core/`; pre-cutover → setup Pre-Cutover (#2068); missing USER.md / PROJECT-DEFINITION → setup Phase 1/2 (#1813) ⊗ before answering; else main → USER → PROJECT-DEFINITION; ~ sync. Mutation → `deft session:start` then `deft verify:session-ritual -- --tier=gated` (#1149). Occupancy (#3433/#3611/#3755): bearer-id, not auth/lineage; `occupancy:grant` → `commands.md`. ? `deft session:start -- --read-only` (#2176).
20
+ ! **Read-only default** until mutation intent: load AGENTS.md / main.md / USER.md / `xbrief/PROJECT-DEFINITION.xbrief.json`; resolve USER.md via `deft session:start` (`USER.md resolved …`; win32 `%APPDATA%\deft\USER.md`; unix `~/.config/deft/USER.md`; ⊗ invent `~/.config/deft` on Windows #2544); confirm Deft alignment + addressing-name; ⊗ no mutable `deft session:start` / triage welcome / sync / branch-policy unless asked or implementation-ready (#2176) — `.deft/core/commands.md` § Session routing. Bootstrap: cold-start → README § Cold-start (#2273) ⊗ never `.deft/core/`; pre-cutover → setup Pre-Cutover (#2068); missing USER.md / PROJECT-DEFINITION → setup Phase 1/2 (#1813) ⊗ before answering; else main → USER → PROJECT-DEFINITION; ~ sync. Mutation → `deft session:start` then `deft verify:session-ritual -- --tier=gated` (#1149). Occupancy (#3433/#3611/#3755/#3926): bearer-id, not auth/lineage; `occupancy:grant` → `commands.md`. ? `deft session:start -- --read-only` (#2176).
21
21
 
22
22
  ## Session-start ritual (#1149)
23
23
 
24
- ! On **mutation** session start, run `deft session:start`; before code-writing or `start_agent` dispatch run `deft verify:session-ritual -- --tier=gated` (stale after `plan.policy.sessionRitualStalenessHours`; records `deft verify:tools` / `deft doctor` / `deft verify:cache-fresh` / `deft agents:refresh` / `npm i -g @deftai/directive@latest`; #1149 / #1348) — `.deft/core/commands.md` § Session-start ritual. Recovery: `deft session:ready` (one-shot: start + gated ritual + cache recovery; #2993). ! SCM mirror tip (#3124): restate existence + get-the-most user-visible when tip fires (depth `commands.md`). Absorb tip without restating.
24
+ ! On **mutation** session start, run `deft session:start`; before code-writing or `start_agent` dispatch run `deft verify:session-ritual -- --tier=gated` (stale after `plan.policy.sessionRitualStalenessHours`; records `deft verify:tools` / `deft doctor` / `deft verify:cache-fresh` / `deft agents:refresh` / `npm i -g @deftai/directive@latest`; #1149 / #1348) — `.deft/core/commands.md` § Session-start ritual. Recovery: `deft session:ready` (one-shot: start + gated ritual + cache recovery; #2993). The #3124 SCM mirror tip does not fire (`triage:classify --mirror` withdrawn, #4070).
25
25
 
26
26
  ## WIP cap
27
27
 
@@ -29,9 +29,9 @@ Deft is installed in .deft/core/. Full guidelines: .deft/core/main.md
29
29
 
30
30
  ## xBRIEF layout (#2034 / #2110)
31
31
 
32
- Legacy `vbrief/`; `deft migrate:xbrief` (v0.6→v0.8). New writes `"version": "0.8"`. Depth: `main.md` (#3600).
33
- ! Completed xBRIEFs are record of *what is*, zero authority over *what to build next* (#3383). Current contract = active xBRIEF + human operator live instruction. Depth: `main.md` Persistence; build skill declare-the-contract / halt-and-ask.
34
- ⊗ Treat a completed xBRIEF as the next-build contract.
32
+ ! Writes: `./xbrief/` (`PROJECT-DEFINITION.xbrief.json`, `plan.xbrief.json`, `specification.xbrief.json`) as `"xBRIEFInfo"` `"version": "0.8"`. Legacy `vbrief/`; `deft migrate:xbrief`.
33
+ ! Completed xBRIEFs are record of *what is*, zero authority over *what to build next* (#3383). Current contract = active xBRIEF + human operator live instruction.
34
+ ⊗ Treat a completed xBRIEF as the next-build contract. ⊗ Emit `"version": "0.6"` on new writes.
35
35
 
36
36
  ## Unmanaged project header (#2065)
37
37
 
@@ -39,7 +39,7 @@ Legacy `vbrief/`; `deft migrate:xbrief` (v0.6→v0.8). New writes `"version": "0
39
39
 
40
40
  ## Cache-as-authoritative work selection (#1149)
41
41
 
42
- ! "what next?" → two work-selection modes (#2402): **ordered plan** (`deft plan-sequence:*`) or **ranked queue** (`deft triage:queue`) — `commands.md` § Backlog Triage → Two paths. ordered-plan first; else `deft-directive-triage` + `deft triage:queue --limit=10` (D11). Empty cache auto-populates from GitHub (#2575).
42
+ ! "what next?" → two work-selection modes (#2402 / #1149): **ordered-plan first** (`deft plan-sequence:current`), then a read-only `deft triage:queue --limit=10` listing (D11) — `commands.md` § Backlog Triage → Two paths. `deft-directive-triage` classify withdrawn (#4070 / #4071). Empty cache auto-populates from GitHub (#2575).
43
43
 
44
44
  ⊗ Recommend work without queue/plan consult; ⊗ widen past an exhausted plan; ⊗ conclude "nothing to do" from `xbrief/{pending,active}` folder scans or GitHub-only reads without `deft triage:queue` (#2576).
45
45
 
@@ -92,7 +92,7 @@ Legacy `vbrief/`; `deft migrate:xbrief` (v0.6→v0.8). New writes `"version": "0
92
92
 
93
93
  ## Envelope selection SLA (#3153)
94
94
 
95
- ! Default story / through-merge unit of work is `drive-to: merge-ready`. Deliberate `stop-at: pr-open` is allowed only when a **partner merge-path owner** is planned (review-cycle babysit / Approach 1 lease / parent-retained) for Greptile + CI + post-merge `scope:complete` — triggers: capacity stall, wall-clock budget, large multi-gate, host nest limits (swarm Phase 0 decision tree). Depth: `deft-directive-swarm` + `deft-directive-review-cycle` partner merge-path.
95
+ ! Default story / through-merge unit of work is `drive-to: merge-ready`. Deliberate `stop-at: pr-open` is allowed only when a **partner merge-path owner** is planned (review-cycle babysit / Approach 1 lease / parent-retained) for Greptile + CI + post-merge `scope:complete` — triggers: capacity stall, wall-clock budget, large multi-gate, host nest limits (Cursor / Claude Code / Grok Build #4130; swarm Phase 0 decision tree). Depth: `deft-directive-swarm` + `deft-directive-review-cycle` partner merge-path.
96
96
  ! Under human-merge policy, a **durable** owner (parent/monitor sticky lease or Phase 6 closer) MUST remain for post-merge `scope:complete` — CLEAN alone is not lifecycle complete; ⊗ stand down at CLEAN with no reachable owner.
97
97
  ⊗ Silent PR-open handback for a worker already scoped `drive-to: merge-ready`.
98
98
  ⊗ `stop-at: pr-open` without a named babysit / merge-path owner, or dual review-monitor leases on recovery (#3044 / #2261).
@@ -12,8 +12,11 @@ Dispatch envelope skeleton for one critic or synthesis pass. Fill the fields. Re
12
12
  - Critic role (fresh | resume):
13
13
  - Id ceiling (GitHub comment id, inclusive):
14
14
  - SHA at dispatch:
15
+ - Run posture (`arc-mode: direct` | `arc-mode: checkout`):
15
16
  - Target (work issue or umbrella):
16
17
  - Audit targets (marker ids, comma-separated, or `none`; ids only, no parent rationale):
18
+ - Seat families (N≥3: three claimed families before spawn):
19
+ - Launcher (spawn_subagent | grok | claude | codex | paste-ready):
17
20
 
18
21
  ## Forbidden inputs
19
22
 
@@ -36,10 +39,12 @@ Read, do not restate:
36
39
  |---|---|
37
40
  | Gate (ADR-005) | Stop 1 — Gate |
38
41
  | Stop 1 `refutation-target:` | Stop 1 — Gate |
42
+ | Run posture `arc-mode:` | Stop 1 — Gate |
39
43
  | Variant selection | Stop 2 — Variant selection |
40
44
  | Parent-facing dispatch rules | Parent-facing dispatch rules |
41
45
  | Critic method | Critic method |
42
46
  | Envelope and ceiling | Envelope and ceiling |
47
+ | Seat families / Grok Build launcher | Envelope and ceiling |
43
48
  | Comment lead (model then role) | Stop 3 — Critic envelope |
44
49
  | Fresh reiteration | Stop 4 — Residual reiteration |
45
50
  | Operator-gated loop | Operator-gated loop |