@deftai/directive-content 0.71.1 → 0.73.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.
@@ -6,6 +6,11 @@ description: >-
6
6
  deftai/directive, and files upstream only after explicit operator
7
7
  confirmation. Gated on plan.policy.valueFeedback upstreamPrompt.
8
8
  ---
9
+ <!-- AUTO-GENERATED by task packs:render -- DO NOT EDIT MANUALLY -->
10
+ <!-- Purpose: rendered skill -->
11
+ <!-- Source of truth: packs/skills/skills-pack-0.1.json -->
12
+ <!-- Regenerate with: task packs:render -->
13
+ <!-- Edit the source, not this file. Slice instead of loading every SKILL.md: task packs:slice skills by-trigger --trigger <kw> (or list) -->
9
14
 
10
15
  # Deft Directive Feedback -- gap escalation to upstream
11
16
 
@@ -107,7 +107,7 @@ Present designs sequentially, then compare in prose. Give your own recommendatio
107
107
  - ! Create a refactor RFC immediately using `gh issue create` with the template below
108
108
  - ~ Issue-label hygiene: before filing, inspect the target repo's existing labels with `gh label list` or the labels API; choose one or more suitable existing labels when practical, or explicitly note that no label was applied. This is a recommendation, not a gate -- do not block issue creation solely because no label fits, and do not invent ad hoc labels outside the repo's existing label set.
109
109
  - ! After creating, print the issue URL
110
- - ! When the RFC is filed as an umbrella with companion child issues (e.g. an interface-extraction RFC plus one child per migrating caller), record the cohort in `xbrief/.eval/slices.jsonl` via `scripts/slice_record.py::write_slice(...)` with `actor="skill:gh-arch"` -- this is the durable production-side record consumed by `task triage:audit --orphans` (#1132 / D13). Same usage pattern as `skills/deft-directive-gh-slice/SKILL.md` Step 6; idempotent on retry. Skip when the RFC is a single-issue "file and forget" with no child cohort.
110
+ - ! When the RFC is filed as an umbrella with companion child issues (e.g. an interface-extraction RFC plus one child per migrating caller), record the cohort via `task slice:record -- --actor skill:gh-arch` -- this is the durable production-side record consumed by `task triage:audit --orphans` (#1132 / D13). Same usage pattern as `skills/deft-directive-gh-slice/SKILL.md` Step 6; idempotent on retry. Skip when the RFC is a single-issue "file and forget" with no child cohort.
111
111
  - ! Confirm skill exit: "deft-directive-gh-arch complete — RFC filed at <url>."
112
112
  - ~ Suggest next steps: run `deft-directive-refinement` to slot the RFC into the xBRIEF lifecycle, or assign the issue for swarm pickup.
113
113
 
@@ -29,13 +29,13 @@ Legend (from RFC2119): !=MUST, ~=SHOULD, ≉=SHOULD NOT, ⊗=MUST NOT, ?=MAY.
29
29
 
30
30
  ## Branch-Protection Policy Guard
31
31
 
32
- ! Before entering the review/fix loop, run the skill-level branch-policy guard documented in `scripts/policy.py` / `scripts/preflight_branch.py` (#746 / #747). Halt before any state mutation if the project's `plan.policy.allowDirectCommitsToMaster` is unresolvable AND the operator has not set `DEFT_ALLOW_DEFAULT_BRANCH_COMMIT=1`. Concretely:
32
+ ! Before entering the review/fix loop, run the skill-level branch-policy guard (#746 / #747). Halt before any state mutation if the project's `plan.policy.allowDirectCommitsToMaster` is unresolvable AND the operator has not set `DEFT_ALLOW_DEFAULT_BRANCH_COMMIT=1`. Concretely:
33
33
 
34
34
  ```
35
- uv run python scripts/preflight_branch.py --project-root . --quiet || exit 1
35
+ task verify:branch || exit 1
36
36
  ```
37
37
 
38
- or invoke `task verify:branch`. The skill MUST NOT modify files, push, or comment on the PR until the guard passes -- this catches the case where a malformed PROJECT-DEFINITION quietly disabled the policy and the agent would have committed directly to master mid-review.
38
+ The skill MUST NOT modify files, push, or comment on the PR until the guard passes -- this catches the case where a malformed PROJECT-DEFINITION quietly disabled the policy and the agent would have committed directly to master mid-review.
39
39
 
40
40
  ## Deterministic Questions Contract
41
41
 
@@ -311,7 +311,7 @@ If the exit predicate is not met (any field `unknown`), go back to Step 2.
311
311
 
312
312
  Greptile can post a **separate** informal clean reply that says prior issues are resolved and the current diff is clean while omitting the canonical rolling-summary fields Directive merge gates require: `Last reviewed commit:` and `Confidence Score: X/5`. `task pr:merge-ready` and `task swarm:verify-review-clean` correctly refuse merge-ready in this state -- prose alone cannot prove review currency or confidence.
313
313
 
314
- ! When the latest Greptile bot comment is found, reports P0=0 and P1=0, but BOTH canonical fields are unparsed, classify the state as **`informal-clean missing-canonical-fields`** (see `scripts/pr_merge_readiness.py`) instead of treating it as "review still writing" or silently polling.
314
+ ! When the latest Greptile bot comment is found, reports P0=0 and P1=0, but BOTH canonical fields are unparsed, classify the state as **`informal-clean missing-canonical-fields`** (see `task pr:merge-ready` diagnostic output) instead of treating it as "review still writing" or silently polling.
315
315
 
316
316
  ! Recovery for informal-clean missing canonical fields -- route to ONE of these operator actions; do NOT keep polling:
317
317
 
@@ -348,10 +348,10 @@ Choose whichever minimizes steps and maximizes clarity for the given task.
348
348
 
349
349
  ## Framework Events Emitted Here
350
350
 
351
- ! When the user replies `yes` / `confirmed` / `approve` on a ready-to-merge PR thread (Phase 5 -> 6 gate per the canonical #642 workflow comment), emit a `plan:approved` framework event via `scripts/_events.py` so the approval is captured as a structural artifact rather than prose-only:
351
+ ! When the user replies `yes` / `confirmed` / `approve` on a ready-to-merge PR thread (Phase 5 -> 6 gate per the canonical #642 workflow comment), emit a `plan:approved` framework event via `task lifecycle:event` so the approval is captured as a structural artifact rather than prose-only:
352
352
 
353
353
  ```
354
- python -m scripts._events emit plan:approved \
354
+ task lifecycle:event -- emit plan:approved \
355
355
  --plan-ref https://github.com/<owner>/<repo>/pull/<N> \
356
356
  --approver <github-login> \
357
357
  --approval-phrase <yes|confirmed|approve> \
@@ -30,7 +30,7 @@ Legend (from RFC2119): !=MUST, ~=SHOULD, ≉=SHOULD NOT, ⊗=MUST NOT, ?=MAY.
30
30
 
31
31
  ### Detection Criteria
32
32
 
33
- A project is **pre-cutover** if ANY of the following are true. This prose mirrors the executable helper in `scripts/_precutover.py`; when in doubt, the helper is canonical.
33
+ A project is **pre-cutover** if ANY of the following are true. When in doubt, run `task verify:pre-cutover` (the deterministic helper).
34
34
 
35
35
  1. `SPECIFICATION.md` exists and is neither a deprecation redirect nor a current generated spec export. A current generated spec export contains `<!-- Purpose: rendered specification -->` and `<!-- Source of truth: xbrief/specification.xbrief.json -->`, and `xbrief/specification.xbrief.json` plus all five lifecycle folders exist.
36
36
  2. `PROJECT.md` exists and contains neither the legacy `<!-- deft:deprecated-redirect -->` sentinel NOR the current `Purpose: deprecation redirect` canonical-banner marker (same one-release-cycle grace window).
@@ -625,7 +625,7 @@ Per [strategies/interview.md](../../strategies/interview.md#interview-rules-shar
625
625
 
626
626
  - **If the next step is `skills/deft-directive-swarm/SKILL.md`**: the swarm skill's Phase 0 Step 0.5 (Lifecycle Bridge -- Promote and Activate Proposed Scope xBRIEFs) is the canonical bridge. The monitor will scan `xbrief/proposed/` and `xbrief/pending/`, present in-scope candidates, and run `task scope:promote -- <path>` then `task scope:activate -- <path>` on explicit user approval. No manual operator action is required ahead of the swarm invocation.
627
627
  - **If the next step is `skills/deft-directive-refinement/SKILL.md`**: the refinement skill's Phase 4 (Promote/Demote) owns the same `task scope:promote` / `task scope:activate` surface and runs the bridge as part of the refinement loop. The refinement skill MAY leave xBRIEFs in `pending/` deliberately when they are queued for prioritisation rather than immediate dispatch.
628
- - **If the user wants to invoke an implementation agent directly via `skills/deft-directive-build/SKILL.md` or `start_agent`**: the bridge MUST be run manually before dispatch -- `task scope:promote -- xbrief/proposed/<file>` then `task scope:activate -- xbrief/pending/<file>`. Both commands are idempotent and exit 0 on no-op (see `scripts/scope_lifecycle.py`). The #810 preflight gate (`task xbrief:preflight -- <active-path>`) will exit 0 only after the activate step.
628
+ - **If the user wants to invoke an implementation agent directly via `skills/deft-directive-build/SKILL.md` or `start_agent`**: the bridge MUST be run manually before dispatch -- `task scope:promote -- xbrief/proposed/<file>` then `task scope:activate -- xbrief/pending/<file>`. Both commands are idempotent and exit 0 on no-op. The #810 preflight gate (`task xbrief:preflight -- <active-path>`) will exit 0 only after the activate step.
629
629
 
630
630
  ⊗ Auto-run `task scope:promote` or `task scope:activate` from the setup skill on the Phase 3 outputs. The lifecycle commitment belongs to the user ("I am ready to swarm/build on this scope"), not the setup interview; silent promotion would clear the #810 implementation-intent gate without explicit user authorisation and bypass the deterministic-questions contract that protects every other Phase 3 transition.
631
631
 
@@ -26,13 +26,13 @@ Legend (from RFC2119): !=MUST, ~=SHOULD, ≉=SHOULD NOT, ⊗=MUST NOT, ?=MAY.
26
26
 
27
27
  ## Branch-Protection Policy Guard
28
28
 
29
- ! Before any state mutation (creating worktrees, dispatching sub-agents, opening PRs), run the skill-level branch-policy guard documented in `scripts/policy.py` / `scripts/preflight_branch.py` (#746 / #747). Halt with the actionable disclosure message when the project's `plan.policy.allowDirectCommitsToMaster` is unresolvable AND `DEFT_ALLOW_DEFAULT_BRANCH_COMMIT` is unset:
29
+ ! Before any state mutation (creating worktrees, dispatching sub-agents, opening PRs), run the skill-level branch-policy guard (#746 / #747). Halt with the actionable disclosure message when the project's `plan.policy.allowDirectCommitsToMaster` is unresolvable AND `DEFT_ALLOW_DEFAULT_BRANCH_COMMIT` is unset:
30
30
 
31
31
  ```
32
- uv run python scripts/preflight_branch.py --project-root . --quiet || exit 1
32
+ task verify:branch || exit 1
33
33
  ```
34
34
 
35
- or invoke `task verify:branch`. The swarm skill creates branches per agent so the guard is mostly informational here, but a malformed PROJECT-DEFINITION (missing `plan.policy` block AND no legacy narrative) is a fail-closed signal worth surfacing before the swarm spawns N agents.
35
+ The swarm skill creates branches per agent so the guard is mostly informational here, but a malformed PROJECT-DEFINITION (missing `plan.policy` block AND no legacy narrative) is a fail-closed signal worth surfacing before the swarm spawns N agents.
36
36
 
37
37
  ## Deterministic Questions Contract
38
38
 
@@ -190,7 +190,7 @@ Loop body, per candidate (top-of-queue first):
190
190
  - For candidates in `xbrief/proposed/`: `task scope:promote -- <path>` (moves to `pending/`, status `pending`), THEN `task scope:activate -- <path-in-pending>` (moves to `active/`, status `running`).
191
191
  - For candidates already in `xbrief/pending/`: `task scope:activate -- <path>` alone (moves to `active/`, status `running`).
192
192
 
193
- Both commands are idempotent: a same-folder move with matching status is a no-op (see `scripts/scope_lifecycle.py`). If either command exits non-zero, surface the exit message verbatim, do NOT attempt to allocate against the failed candidate, and ask the user how to route.
193
+ Both commands are idempotent: a same-folder move with matching status is a no-op. If either command exits non-zero, surface the exit message verbatim, do NOT attempt to allocate against the failed candidate, and ask the user how to route.
194
194
 
195
195
  ! **Verify**: re-run the scan and confirm each approved candidate now lives in `xbrief/active/` with `plan.status == "running"`. Only candidates that pass this verification advance to Step 1 (Read Project State); the rest stay surfaced as preflight rejections.
196
196
 
@@ -203,19 +203,19 @@ Loop body, per candidate (top-of-queue first):
203
203
  Cross-references:
204
204
  - Setup-side deposit point: `skills/deft-directive-setup/SKILL.md` Phase 3 Output -- Light Path / Output -- Full Path (scope xBRIEFs land in `xbrief/proposed/`).
205
205
  - Refinement-side deposit point: `skills/deft-directive-refinement/SKILL.md` Phase 4 -- Promote/Demote (lifecycle transitions via the same `task scope:promote` / `task scope:activate` surface).
206
- - Underlying CLI: `scripts/scope_lifecycle.py` (the deterministic state machine; idempotent on same-folder moves; three-state exit 0 / 1 / 2).
206
+ - Underlying CLI: `task scope:promote` / `task scope:activate` (the deterministic state machine; idempotent on same-folder moves; three-state exit 0 / 1 / 2).
207
207
  - Recurrence record: issue #1025 (2026-05-10 first-session consumer tic-tac-toe swarm; monitor hit `Invalid transition: 'activate' requires file in pending/` on all four candidate xBRIEFs because they were still in `proposed/`).
208
208
 
209
209
  ### Step 1: Read Project State and Readiness Report
210
210
 
211
211
  - ! Scan `xbrief/active/` for candidate xBRIEFs (files matching `*.xbrief.json`)
212
- - ! For each candidate xBRIEF, MUST run `task xbrief:preflight -- <path>` (the structural intent gate, #810; wraps `scripts/preflight_implementation.py` so the same invocation works whether deft is the project root or installed as a `deft/` subdirectory) to validate lifecycle eligibility before allocation work. Skip any xBRIEF that exits non-zero -- the helper's stderr message is the actionable redirect (`task xbrief:activate <path>`). Surface the exit message in the Phase 0 Step 4 analysis so the user can route the lifecycle move; do NOT attempt to allocate, dispatch, or implement against a xBRIEF that fails the preflight.
212
+ - ! For each candidate xBRIEF, MUST run `task xbrief:preflight -- <path>` (the structural intent gate, #810) to validate lifecycle eligibility before allocation work. Skip any xBRIEF that exits non-zero -- the helper's stderr message is the actionable redirect (`task xbrief:activate <path>`). Surface the exit message in the Phase 0 Step 4 analysis so the user can route the lifecycle move; do NOT attempt to allocate, dispatch, or implement against a xBRIEF that fails the preflight.
213
213
  - ! Run `task swarm:readiness -- xbrief/active/*.xbrief.json` before any agent allocation. This deterministic report is the allocator's source of truth for ready stories, blocked stories, decomposition-needed epics/phases, dependency waves, conflict groups, file overlap matrix, and missing fields.
214
214
  - ! Treat `plan.metadata.kind = "epic"` and `plan.metadata.kind = "phase"` as **needs decomposition**, not merely incomplete. Route broad scopes to `skills/deft-directive-decompose/SKILL.md` instead of assigning them to workers.
215
215
  - ! Read only readiness-approved story fields for allocation: `plan.title`, `plan.status`, non-empty `plan.items`, `planRef`, `references`, `plan.metadata.kind`, and `plan.metadata.swarm`.
216
216
  - ! Read `xbrief/PROJECT-DEFINITION.xbrief.json` for project-wide context (narratives, scope registry)
217
217
  - ! Determine the base branch: ask the user which branch to target for worktree creation, PR targets, and rebase cascade (default: `master`). Record this as the **configured base branch** for all subsequent phases.
218
- - ⊗ Spawn an implementation agent (via `start_agent`, `oz agent run`, Warp tab dispatch, or any other path) for a xBRIEF that has not passed `task xbrief:preflight` (which wraps `scripts/preflight_implementation.py`) -- the gate is the only authorization signal; affirmative continuation phrases and workflow-shape vocabulary are NOT (#810).
218
+ - ⊗ Spawn an implementation agent (via `start_agent`, `oz agent run`, Warp tab dispatch, or any other path) for a xBRIEF that has not passed `task xbrief:preflight` -- the gate is the only authorization signal; affirmative continuation phrases and workflow-shape vocabulary are NOT (#810).
219
219
  - ⊗ Allocate concurrent workers unless candidates are swarm-ready `kind=story` xBRIEFs with non-empty executable `plan.items` and `task swarm:readiness` exits 0.
220
220
  - ⊗ Use manual file-overlap reasoning as the only safety check; use the readiness report first, then explain any additional human judgment.
221
221
 
@@ -243,7 +243,7 @@ Cross-references:
243
243
 
244
244
  - **Candidate xBRIEFs**: story-level xBRIEFs eligible for assignment (with titles, statuses, and origin references)
245
245
  - **Readiness report**: ready stories, blocked stories, decomposition-needed epics/phases, dependency waves, conflict groups, file overlap matrix, and missing fields from `task swarm:readiness`.
246
- - **Preflight rejections (#810)**: any xBRIEFs that failed `task xbrief:preflight` (wraps `scripts/preflight_implementation.py`) in Step 1 -- include the file path AND the helper's exit message verbatim so the user can route the appropriate `task xbrief:activate <path>` move. These xBRIEFs MUST NOT be allocated until they pass the preflight on a re-run.
246
+ - **Preflight rejections (#810)**: any xBRIEFs that failed `task xbrief:preflight` in Step 1 -- include the file path AND the helper's exit message verbatim so the user can route the appropriate `task xbrief:activate <path>` move. These xBRIEFs MUST NOT be allocated until they pass the preflight on a re-run.
247
247
  - **Blockers found**: blocked xBRIEFs, unresolved dependencies, items requiring design decisions
248
248
  - **Decomposition needed**: epic/phase scopes that must go through `skills/deft-directive-decompose/SKILL.md` before swarm allocation
249
249
  - **Incomplete xBRIEFs**: stories with missing or empty acceptance criteria
@@ -293,7 +293,7 @@ Cross-references:
293
293
  #### Mode A -- Pre-created worktree map (C3, headless via `--worktree-map`)
294
294
 
295
295
  - ! 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 }`.
296
- - ! The launch engine resolves the map via `resolve_worktree_map(mapping, base_branch, create_missing=True)` in `scripts/swarm_worktrees.py`, which returns 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).
296
+ - ! 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).
297
297
  - ! 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`.
298
298
 
299
299
  #### Mode B -- Monitor-created worktrees (interactive path)
@@ -361,12 +361,12 @@ git worktree add <path> -b <branch-name> <configured-base-branch>
361
361
 
362
362
  ### Step 1a: Worker Runtime and GitHub Auth Preflight (#1557)
363
363
 
364
- ! Before dispatching workers that will call `gh`, probe the **worker execution envelope** (not the parent monitor shell) for runtime mode and GitHub credential readiness. The read-only capability probe (`scripts/platform_capabilities.py`, #1557a) and auth validator (`scripts/github_auth_modes.py`, #1557b) MUST run from the same environment the worker will use.
364
+ ! Before dispatching workers that will call `gh`, probe the **worker execution envelope** (not the parent monitor shell) for runtime mode and GitHub credential readiness. The read-only capability probe (`packages/core/src/platform/platform-capabilities.ts`, #1557a) and auth validator (`packages/core/src/intake/github-auth-modes.ts`, #1557b) MUST run from the same environment the worker will use.
365
365
 
366
366
  1. ! **Classify runtime mode** — run the capability probe from each worker worktree (or dispatch target):
367
367
 
368
- ```pwsh path=null start=null
369
- uv --project . run python scripts/platform_capabilities.py --json
368
+ ```
369
+ task verify:tools -- --json
370
370
  ```
371
371
 
372
372
  The probe returns one of:
@@ -379,8 +379,8 @@ The probe returns one of:
379
379
 
380
380
  3. ! **Validate GitHub auth from the worker environment** — run auth validation from the same envelope:
381
381
 
382
- ```pwsh path=null start=null
383
- uv --project . run python scripts/github_auth_modes.py --json
382
+ ```
383
+ task verify:gh-auth -- --json
384
384
  ```
385
385
 
386
386
  Modes:
@@ -400,7 +400,7 @@ Modes:
400
400
  ⊗ Present sandbox UID 0 or sandbox-root cwd ownership as host-root access — UID remap means sandbox identity is a view of the host user (#1557).
401
401
  ⊗ Paste `GH_TOKEN` / `GITHUB_TOKEN` values into worker prompts or dispatch envelopes — use invocation-layer handoff only (#1557).
402
402
 
403
- Cross-references: `scripts/platform_capabilities.py` (#1557a), `scripts/github_auth_modes.py` (#1557b), `tests/cli/test_platform_capabilities.py`, `tests/cli/test_github_auth_modes.py`, `docs/subagent-heartbeat.md` (runtime/auth troubleshooting). Refs #1557.
403
+ Cross-references: `packages/core/src/platform/platform-capabilities.ts` (#1557a), `packages/core/src/intake/github-auth-modes.ts` (#1557b), `docs/subagent-heartbeat.md` (runtime/auth troubleshooting). Refs #1557.
404
404
 
405
405
  ### Step 1b: Provider-neutral sub-agent routing (#1531)
406
406
 
@@ -427,7 +427,7 @@ Cross-references: `scripts/platform_capabilities.py` (#1557a), `scripts/github_a
427
427
  ⊗ Treat Grok Build `spawn_subagent` as the only supported sub-agent backend in swarm guidance — provider-neutral routing explicitly includes Composer-class coding agents, Cursor/cloud agents, and future adapters (#1531).
428
428
  ⊗ Route orchestration, review-cycle decisions, conflict-resolution rebase, merge cascade, or release gates to cheaper leaf agents — irreversible-damage surfaces stay on strong/review-capable agents (#1531).
429
429
 
430
- Cross-references: `scripts/policy.py` (`KNOWN_SUBAGENT_BACKEND_IDS`, `SWARM_WORKER_ROLES`), `templates/agent-prompt-preamble.md` (dispatch envelope metadata), `docs/the-harness-is-everything.md` (orchestrator -> commodity-coder layering). Refs #1531.
430
+ Cross-references: `packages/core/src/swarm/routing.ts` (`SWARM_WORKER_ROLES`), `templates/agent-prompt-preamble.md` (dispatch envelope metadata), `docs/the-harness-is-everything.md` (orchestrator -> commodity-coder layering). Refs #1531.
431
431
 
432
432
 
433
433
  ### Orchestrator dispatch doctrine (#1880)
@@ -518,11 +518,11 @@ Agents execute on remote VMs without local MCP servers, codebase indexing, or Wa
518
518
 
519
519
  ! 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).
520
520
 
521
- ! 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 `scripts/subagent_monitor.py` (three-state exit 0 ok / 1 stale-or-malformed / 2 config error). Default threshold is 30 minutes; `--threshold-minutes` overrides.
521
+ ! 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.
522
522
 
523
- ```pwsh path=null start=null
523
+ ```
524
524
  # Scan all worktrees in the cohort
525
- uv --project . run python scripts/subagent_monitor.py \
525
+ task agent:monitor -- \
526
526
  --scratch-dir <worktree-1>/.deft-scratch/subagent-status \
527
527
  --scratch-dir <worktree-2>/.deft-scratch/subagent-status
528
528
  ```
@@ -605,15 +605,15 @@ All PRs meet ALL of:
605
605
  - `task check` passed (or equivalent validation completed)
606
606
  - CHANGELOG entries present under `[Unreleased]`
607
607
 
608
- ! **Mandatory cohort verifier (#1364):** After every poller (Phase 6 review-cycle sub-agent) reports back, the monitor MUST run `task swarm:verify-review-clean -- <pr-numbers...>` (script: `scripts/swarm_verify_review_clean.py`) and confirm exit 0 BEFORE evaluating the rest of the Exit Condition or surfacing the Phase 5 -> 6 gate. The verifier re-uses the Greptile rolling-summary parser from `scripts/pr_merge_readiness.py` so the per-PR merge gate and the cohort gate stay in lockstep (a parser fix lands in both surfaces at once). Exit codes: 0 (cohort CLEAN -- all PRs simultaneously have SHA match + confidence > 3 + zero P0/P1 + not errored on current HEAD); 1 (one or more PRs unclean with per-PR diagnostics -- re-dispatch the poller for the unclean PR or address findings, then re-run the verifier); 2 (config error -- empty cohort, malformed xBRIEF glob, gh missing). The verifier is the structural answer to the #1166 swarm execution recurrence where multiple pollers exited with `clean_gate_holdout=confidence` (confidence == 3) and the monitor still raised the Phase 5 -> 6 gate because the trigger keyed on "all pollers have reported back" rather than "every PR in the cohort is objectively CLEAN".
608
+ ! **Mandatory cohort verifier (#1364):** After every poller (Phase 6 review-cycle sub-agent) reports back, the monitor MUST run `task swarm:verify-review-clean -- <pr-numbers...>` and confirm exit 0 BEFORE evaluating the rest of the Exit Condition or surfacing the Phase 5 -> 6 gate. The verifier re-uses the Greptile rolling-summary parser from `task pr:merge-ready` so the per-PR merge gate and the cohort gate stay in lockstep (a parser fix lands in both surfaces at once). Exit codes: 0 (cohort CLEAN -- all PRs simultaneously have SHA match + confidence > 3 + zero P0/P1 + not errored on current HEAD); 1 (one or more PRs unclean with per-PR diagnostics -- re-dispatch the poller for the unclean PR or address findings, then re-run the verifier); 2 (config error -- empty cohort, malformed xBRIEF glob, gh missing). The verifier is the structural answer to the #1166 swarm execution recurrence where multiple pollers exited with `clean_gate_holdout=confidence` (confidence == 3) and the monitor still raised the Phase 5 -> 6 gate because the trigger keyed on "all pollers have reported back" rather than "every PR in the cohort is objectively CLEAN".
609
609
 
610
- ! **Resilient long-running monitor (#1368):** When a Phase 5 monitor needs to wait on an in-flight PR for an extended window (cascade rebase + re-review, late Greptile pass, CI sweep), use `scripts/monitor_pr.py <N> --repo <owner>/<repo>` as the canonical wait-until-ready helper. The script loops `scripts/pr_merge_readiness.py` with adaptive cadence (~1m for the first 3 polls, ~3m next, ~5m thereafter), routes subprocess capture through `_safe_subprocess.run_text` (#1366), and tolerates layered fallback responses without going blind on a transient gh failure. Exit codes: 0 (PR reached primary/fallback1 CLEAN), 1 (poll cap reached -- escalate to operator), 2 (config error -- gh missing / invalid args), 3 (PR merged or closed out from under the monitor before reaching CLEAN). The helper writes one terse status line per poll to stderr so the orchestrator transcript shows progress; the final verdict (JSON when `--json` is passed) lands on stdout.
610
+ ! **Resilient long-running monitor (#1368):** When a Phase 5 monitor needs to wait on an in-flight PR for an extended window (cascade rebase + re-review, late Greptile pass, CI sweep), use `task pr:watch -- <N> --repo <owner>/<repo>` as the canonical wait-until-ready helper. The task loops `task pr:merge-ready` with adaptive cadence (~1m for the first 3 polls, ~3m next, ~5m thereafter), tolerates layered fallback responses without going blind on a transient gh failure. Exit codes: 0 (PR reached primary/fallback1 CLEAN), 1 (poll cap reached -- escalate to operator), 2 (config error -- gh missing / invalid args), 3 (PR merged or closed out from under the monitor before reaching CLEAN). The helper writes one terse status line per poll to stderr so the orchestrator transcript shows progress; the final verdict (JSON when `--json` is passed) lands on stdout.
611
611
 
612
- ! **Fallback-chain discriminator semantics (#1368):** `scripts/pr_merge_readiness.py --json` ALWAYS emits a `via` discriminator on every response. `via="primary"` and `via="fallback1"` are authoritative -- a `merge_ready: true` verdict on either is CLEAN. `via="fallback2"` is the coarse PR-view + check-run last-resort signal: it surfaces the PR's `state` / `merged` / `mergeable` / flattened check-run summary so a monitor can keep stepping forward through transient gh failures, but it is NEVER CLEAN -- the failure list carries the sentinel `"fallback2 is a coarse signal, not a CLEAN verdict ..."` and the merge cascade MUST keep waiting for a primary/fallback1 CLEAN. `via="error"` (every layer failed) is also non-CLEAN; the response carries `error` (one-line summary) + `partial_data` (per-layer diagnostics) so the monitor can step forward without blinding. Both `task swarm:verify-review-clean` and `task pr:merge-ready` treat fallback2 and error as merge-blocked.
612
+ ! **Fallback-chain discriminator semantics (#1368):** `task pr:merge-ready -- <N> --json` ALWAYS emits a `via` discriminator on every response. `via="primary"` and `via="fallback1"` are authoritative -- a `merge_ready: true` verdict on either is CLEAN. `via="fallback2"` is the coarse PR-view + check-run last-resort signal: it surfaces the PR's `state` / `merged` / `mergeable` / flattened check-run summary so a monitor can keep stepping forward through transient gh failures, but it is NEVER CLEAN -- the failure list carries the sentinel `"fallback2 is a coarse signal, not a CLEAN verdict ..."` and the merge cascade MUST keep waiting for a primary/fallback1 CLEAN. `via="error"` (every layer failed) is also non-CLEAN; the response carries `error` (one-line summary) + `partial_data` (per-layer diagnostics) so the monitor can step forward without blinding. Both `task swarm:verify-review-clean` and `task pr:merge-ready` treat fallback2 and error as merge-blocked.
613
613
 
614
614
  ⊗ Surface or discuss the Phase 5 -> 6 merge cascade gate while `task swarm:verify-review-clean` has not yet exited 0 on the current cohort (#1364). Keying the transition on poller lifecycle completion alone -- i.e. treating "every poller sub-agent returned a terminal message" as sufficient -- is the exact recurrence pattern this rule closes. The verifier is the only authoritative cohort-level CLEAN signal; a poller's `clean_gate_holdout=confidence` / `clean_gate_holdout=has_blocking` / `clean_gate_holdout=sha_match` / `clean_gate_holdout=errored` exit IS a non-CLEAN report and MUST hold the gate even if every sub-agent has technically returned.
615
615
 
616
- ⊗ Treat a `via="fallback2"` or `via="error"` response from `scripts/pr_merge_readiness.py` as CLEAN, regardless of the surrounding `merge_ready` field (#1368). Fallback2 is structurally never CLEAN -- the Greptile rolling-summary comment was unreachable on both the primary and fallback1 paths, so any merge taken on the basis of the coarse signal alone bypasses the SUCCESS-with-findings blind spot the per-PR gate was designed to close (#796 / #652). The merge cascade MUST keep waiting for a primary/fallback1 CLEAN.
616
+ ⊗ Treat a `via="fallback2"` or `via="error"` response from `task pr:merge-ready` as CLEAN, regardless of the surrounding `merge_ready` field (#1368). Fallback2 is structurally never CLEAN -- the Greptile rolling-summary comment was unreachable on both the primary and fallback1 paths, so any merge taken on the basis of the coarse signal alone bypasses the SUCCESS-with-findings blind spot the per-PR gate was designed to close (#796 / #652). The merge cascade MUST keep waiting for a primary/fallback1 CLEAN.
617
617
 
618
618
  ### Phase 5→6 Gate: Release Decision Checkpoint
619
619
 
@@ -634,7 +634,7 @@ All PRs meet ALL of:
634
634
 
635
635
  ! **Cohort gate (#1364):** Before the merge-readiness checklist is even emitted, the monitor MUST have already passed `task swarm:verify-review-clean -- <pr-numbers...>` per the Phase 5 Exit Condition above. The cohort gate is the structural pre-condition for this entire Phase 5 -> 6 sequence -- without exit 0 on the verifier, the checklist below MUST NOT be presented to the user. The per-merge `task pr:merge-ready` gate below remains the merge-time freshness-window-atomic check; the cohort verifier is the once-after-pollers gate that gates the discussion at all.
636
636
 
637
- ! **Programmatic gate:** Before each `gh pr merge` call, the monitor MUST run `task pr:merge-ready -- <N>` (script: `scripts/pr_merge_readiness.py`) and abort the cascade on non-zero exit. The Taskfile target parses the Greptile rolling-summary comment **body** (confidence, P0 / P1 badge counts, errored sentinel, HEAD-SHA freshness) -- not the GitHub CheckRun status. The CheckRun goes green when Greptile finishes its review pass, irrespective of findings; relying on it alone is the SUCCESS-with-findings blind spot that started the PR #652 incident merge cascade against `Confidence: 3/5 + 1×P1 + 2×P2`.
637
+ ! **Programmatic gate:** Before each `gh pr merge` call, the monitor MUST run `task pr:merge-ready -- <N>` and abort the cascade on non-zero exit. The task parses the Greptile rolling-summary comment **body** (confidence, P0 / P1 badge counts, errored sentinel, HEAD-SHA freshness) -- not the GitHub CheckRun status. The CheckRun goes green when Greptile finishes its review pass, irrespective of findings; relying on it alone is the SUCCESS-with-findings blind spot that started the PR #652 incident merge cascade against `Confidence: 3/5 + 1×P1 + 2×P2`.
638
638
 
639
639
  ! **Atomic gate (freshness window):** The monitor MUST invoke `task pr:merge-ready -- <N>` and `gh pr merge <N>` in the same shell call (e.g. `task pr:merge-ready -- <N> && gh pr merge <N> --squash --delete-branch --admin`) so no time elapses between verdict and merge. A readiness check more than ~60 seconds stale is a Mode-1 false-positive risk: in the elapsed window an unrelated commit may land on master, auto-rebase trigger a fresh Greptile pass, and the new pass surface a P1 the cached verdict did not see. Re-invoking the gate is cheap (single `gh api` call); the shell-`&&` chain makes the freshness window structurally enforceable rather than prose-trust.
640
640
 
@@ -652,7 +652,7 @@ All PRs meet ALL of:
652
652
 
653
653
  ! **Post-PR sub-agents are review-cycle agents (#727):** Sub-agents addressing review findings, waiting for re-review, and iterating to clean MUST embody `skills/deft-directive-review-cycle/SKILL.md` end-to-end as a single coherent role. Do NOT split the review-cycle into separate "poll" and "fix" agents -- pollers that spawn separate fix agents create cross-agent state-handoff hazards and double the chance of an agent exiting at the wrong lifecycle boundary.
654
654
 
655
- ! **Sub-agents MUST emit a heartbeat (#1365):** every long-running review-cycle / poller sub-agent dispatched under Phase 6 MUST write a heartbeat record to `.deft-scratch/subagent-status/<agent-id>.json` per the contract in `docs/subagent-heartbeat.md`. The canonical poller template (`templates/swarm-greptile-poller-prompt.md` bounded poll loop) already encodes the per-iteration heartbeat write and the final terminal heartbeat, and the canonical orchestrator preamble (`templates/agent-prompt-preamble.md` § 10.5) restates the contract for any non-poller long-running sub-agent. The monitor watches via `scripts/subagent_monitor.py` -- see Phase 4 Heartbeat liveness check. Without the heartbeat, a `spawn_subagent`-dispatched poller that stalls is indistinguishable from a healthy mid-poll one (the #1166 recurrence).
655
+ ! **Sub-agents MUST emit a heartbeat (#1365):** every long-running review-cycle / poller sub-agent dispatched under Phase 6 MUST write a heartbeat record to `.deft-scratch/subagent-status/<agent-id>.json` per the contract in `docs/subagent-heartbeat.md`. The canonical poller template (`templates/swarm-greptile-poller-prompt.md` bounded poll loop) already encodes the per-iteration heartbeat write and the final terminal heartbeat, and the canonical orchestrator preamble (`templates/agent-prompt-preamble.md` § 10.5) restates the contract for any non-poller long-running sub-agent. The monitor watches via `task agent:monitor` -- see Phase 4 Heartbeat liveness check. Without the heartbeat, a `spawn_subagent`-dispatched poller that stalls is indistinguishable from a healthy mid-poll one (the #1166 recurrence).
656
656
 
657
657
  ! **Post-PR monitoring runs in a fresh sub-agent (#727):** Post-PR monitoring (Greptile, CI checks, downloadCount drift, lifecycle events, etc.) MUST be done by spawning a fresh short-lived sub-agent via the platform adapter's dispatch primitive for the detected runtime (e.g. `spawn_subagent` when the Grok Build / non-Warp platform is active, `start_agent` for Warp-orchestrated environments). The parent yields with no tool calls and waits for the sub-agent's messages -- this preserves conversation steerability so the user can interrupt or redirect while the watch is pending. The platform adapter (introduced in slices 1-3 of #1342) supplies the appropriate async callback channel and spawn surface per the runtime capability detection matrix; every Taskfile / shell-sleep / `time.sleep` / synchronous tool-call alternative blocks the parent's turn for the duration of the watch.
658
658
 
@@ -708,9 +708,9 @@ If any protected (umbrella / staying-OPEN) issue number appears in the output, t
708
708
 
709
709
  ! **Autonomous re-review monitoring after force-push:** After each `--force-with-lease` push of a rebased branch in the cascade, the monitor MUST autonomously wait for the Greptile re-review to complete before proceeding to the next merge. Use the tiered monitoring approach defined in `skills/deft-directive-review-cycle/SKILL.md` Step 4 Review Monitoring (Approach 1: spawn sub-agent via the platform adapter's dispatch primitive (e.g. `spawn_subagent` or `start_agent`) to poll and report back; Approach 2 fallback: discrete `run_shell_command` wait-mode calls with yield between polls, adaptive cadence -- see deft-directive-review-cycle SKILL.md). Do NOT duplicate the full monitoring logic here -- follow the canonical skill.
710
710
 
711
- ~ **Resilient wait-until-ready helper (#1368):** For the in-cascade wait between a force-push and the next merge, the canonical surface is `scripts/monitor_pr.py <N> --repo <owner>/<repo> --cap-minutes <M>`. It loops `scripts/pr_merge_readiness.py` with adaptive cadence (~1m -> 3m -> 5m), routes through `_safe_subprocess.run_text` (#1366), tolerates `via="fallback1"` / `via="fallback2"` / `via="error"` responses without blinding, and exits 0 only on a primary or fallback1 CLEAN (never fallback2 -- the coarse signal is a monitor heartbeat, not a merge gate). A `via="fallback2"` payload reporting `partial_data.merged == true` short-circuits the loop with exit code 3 (PR-TERMINAL) so a cascade can detect a sibling-merged-out-from-under-us state without burning the full cap. Use this in place of hand-rolled `time.sleep` polling loops in long-running cascade waits.
711
+ ~ **Resilient wait-until-ready helper (#1368):** For the in-cascade wait between a force-push and the next merge, the canonical surface is `task pr:watch -- <N> --repo <owner>/<repo> --cap-minutes <M>`. It loops `task pr:merge-ready` with adaptive cadence (~1m -> 3m -> 5m), tolerates `via="fallback1"` / `via="fallback2"` / `via="error"` responses without blinding, and exits 0 only on a primary or fallback1 CLEAN (never fallback2 -- the coarse signal is a monitor heartbeat, not a merge gate). A `via="fallback2"` payload reporting `partial_data.merged == true` short-circuits the loop with exit code 3 (PR-TERMINAL) so a cascade can detect a sibling-merged-out-from-under-us state without burning the full cap. Use this in place of hand-rolled polling loops in long-running cascade waits.
712
712
 
713
- ! **Cascade automation surface (#1369):** The canonical one-verb compose-point for "wait until PR <N> is mergeable, then squash-merge with admin" is `task pr:wait-mergeable-and-merge -- <N> --repo <owner>/<repo>` (script: `scripts/pr_wait_mergeable.py`). The helper wraps `scripts/monitor_pr.py` (#1368) for the resilient wait loop and `scripts/pr_check_protected_issues.py` (#701) for the Layer-3 protected-issue link inspection AHEAD of any merge call, then invokes `gh pr merge <N> --squash --delete-branch --admin` only after the wait loop exits CLEAN on the current HEAD. Three-state exit (0 merged / 1 timeout-or-escalation / 2 config error) mirrors every other framework verb. Pass `--protected <issue-numbers>` for the Layer-3 chain when the PR is known to reference any umbrella / staying-OPEN issue -- the helper short-circuits with exit 1 BEFORE the merge call if a persistent `closingIssuesReferences` link is detected. The Wave-3 surface is the automated cascade wrapper; the per-PR atomic gate (`task pr:merge-ready -- <N> && gh pr merge <N>`) documented above remains the manual freshness-window-atomic check the monitor MUST use when running merges by hand. The two co-exist -- the cascade surface is the automation, the per-PR atomic gate is the manual fall-through. See AGENTS.md `## Cascade automation surface (#1369)`.
713
+ ! **Cascade automation surface (#1369):** The canonical one-verb compose-point for "wait until PR <N> is mergeable, then squash-merge with admin" is `task pr:wait-mergeable-and-merge -- <N> --repo <owner>/<repo>`. The helper runs the resilient wait loop (#1368) and the Layer-3 protected-issue link inspection (#701) AHEAD of any merge call, then invokes `gh pr merge <N> --squash --delete-branch --admin` only after the wait loop exits CLEAN on the current HEAD. Three-state exit (0 merged / 1 timeout-or-escalation / 2 config error) mirrors every other framework verb. Pass `--protected <issue-numbers>` for the Layer-3 chain when the PR is known to reference any umbrella / staying-OPEN issue -- the helper short-circuits with exit 1 BEFORE the merge call if a persistent `closingIssuesReferences` link is detected. The Wave-3 surface is the automated cascade wrapper; the per-PR atomic gate (`task pr:merge-ready -- <N> && gh pr merge <N>`) documented above remains the manual freshness-window-atomic check the monitor MUST use when running merges by hand. The two co-exist -- the cascade surface is the automation, the per-PR atomic gate is the manual fall-through. See AGENTS.md `## Cascade automation surface (#1369)`.
714
714
 
715
715
  ⊗ Hand-roll a cascade `while ...; do task pr:merge-ready ...; done` shell loop (or equivalent ad-hoc Python monitor) when `task pr:wait-mergeable-and-merge` is available (#1369). The Wave-1+2 hardening (`_safe_subprocess.run_text` #1366, `pr_merge_readiness.py` layered fallbacks #1368, `monitor_pr.py` resilient wait loop #1368) is composed inside the helper; hand-rolled loops re-introduce the `head: None` / babysit-each-PR failure mode #1369 closes.
716
716
 
@@ -765,11 +765,11 @@ task swarm:complete-cohort -- --cohort 'xbrief/active/*.xbrief.json'
765
765
  task swarm:complete-cohort -- xbrief/active/<story-a>.xbrief.json xbrief/active/<story-b>.xbrief.json
766
766
  ```
767
767
 
768
- What the sweep does (script: `scripts/swarm_complete_cohort.py`):
768
+ What the sweep does (`task scope:complete` per story):
769
769
 
770
770
  1. ! **Stage 1 -- stories:** every cohort story xBRIEF still in `xbrief/active/` is completed (`active/` -> `completed/`, status `completed`). A story already terminal (`completed/` / `cancelled/`) is an idempotent no-op, so the sweep is safe to re-run.
771
771
  2. ! **Stage 2 -- epic parents:** each decompose-created epic parent is completed once ALL of its `x-xbrief/plan` children are settled (in `completed/` or `cancelled/`). A parent in `pending/` is bridged `activate` -> `complete`; a parent in `active/` is completed directly. The sweep iterates to a fixpoint, so nested decomposition (phase -> epic -> story) collapses bottom-up. A parent with even one still-active sibling outside the cohort is left untouched.
772
- 3. ! **D4 stays green automatically:** every move routes through `scripts/scope_lifecycle.py`, which keeps the decomposed parent<->child references in sync on BOTH directions -- child moves update the parent's forward `x-xbrief/plan` reference (#1485) and parent moves update each child's `planRef` back-pointer (#1487). Do NOT hand-edit references to "fix" linkage; the helper already does it.
772
+ 3. ! **D4 stays green automatically:** every move via `task scope:complete` keeps the decomposed parent<->child references in sync on BOTH directions -- child moves update the parent's forward `x-xbrief/plan` reference (#1485) and parent moves update each child's `planRef` back-pointer (#1487). Do NOT hand-edit references to "fix" linkage; the task already does it.
773
773
  4. ! After the sweep, the monitor MUST run `task xbrief:validate` and confirm it exits 0 (no D4 regressions). Exit codes for the sweep itself: 0 (sweep clean), 1 (one or more transitions failed -- per-item diagnostics printed), 2 (config error -- empty cohort or missing `xbrief/`).
774
774
 
775
775
  ! **Interactive path:** the monitor runs `task swarm:complete-cohort` by hand (or `--dry-run` first to preview the planned transitions) once the merge cascade finishes, then runs `task xbrief:validate`.
@@ -808,11 +808,11 @@ The monitor MUST, from its OWN worktree and on the configured base branch:
808
808
 
809
809
  0. ! **Fast-forward the local base branch FIRST:** `git fetch origin && git merge --ff-only origin/<configured-base-branch>` (equivalently `git pull --ff-only origin <configured-base-branch>`). The merge cascade (Step 1) advanced the REMOTE base branch by N squash-merge commits, but the local base branch in this worktree has not yet been pulled (Step 3's canonical pull runs AFTER this step). Without this fast-forward the commit below is built on a stale base and the push in step 4 is rejected as non-fast-forward, stranding the agent. Doing the `--ff-only` sync first makes the subsequent commit + push fast-forward by construction; a non-fast-forward `--ff-only` failure here means an unexpected divergence -- stop and reconcile rather than force-push.
810
810
  1. ! Confirm the lifecycle moves are present (the Step 1.5 sweep already ran `task scope:complete <file>` per story, `active/` -> `completed/`). If the sweep was skipped, run `task swarm:complete-cohort` now -- do NOT hand-move xBRIEF files.
811
- 2. ! Stage ALL lifecycle moves: `git add -A xbrief/` -- this captures both the `active/` deletions and the `completed/` additions, plus any parent/child `planRef` / `x-xbrief/plan` reference edits `scripts/scope_lifecycle.py` wrote during the sweep.
811
+ 2. ! Stage ALL lifecycle moves: `git add -A xbrief/` -- this captures both the `active/` deletions and the `completed/` additions, plus any parent/child `planRef` / `x-xbrief/plan` reference edits made during the sweep.
812
812
  3. ! Commit them in a SINGLE commit on the base branch: `git commit -m "chore(xbrief): complete <slugs> post-merge"`, where `<slugs>` enumerates the completed story xBRIEF slugs (or the cohort label) so the commit is self-describing.
813
813
  4. ! Push to origin: `git push origin <configured-base-branch>`. Because step 0 fast-forwarded the local base ahead of the commit, this push is a fast-forward and will not be rejected.
814
814
 
815
- ! **Authoritative lifecycle record (#1358):** this commit is what keeps the release ceremony's xBRIEF-lifecycle-sync gate green. The release pipeline's deterministic gate (`scripts/release.py::check_vbrief_lifecycle_sync`) and the release skill's Phase 1 sync gate (`skills/deft-directive-release/SKILL.md` Phase 1 -- `task reconcile:issues -- --apply-lifecycle-fixes`) both refuse to cut a release while a closed-issue xBRIEF still sits outside `xbrief/completed/`. Committing the moves here, at swarm close-out, is the **prevention** so the next release does not have to reconcile drift the swarm itself created. If drift is nevertheless detected later, `task reconcile:issues -- --apply-lifecycle-fixes` (script: `scripts/reconcile_issues.py`) is the recovery path -- but the post-merge commit in this step is what stops the drift from being authored in the first place.
815
+ ! **Authoritative lifecycle record (#1358):** this commit is what keeps the release ceremony's xBRIEF-lifecycle-sync gate green. The release pipeline's deterministic gate and the release skill's Phase 1 sync gate (`skills/deft-directive-release/SKILL.md` Phase 1 -- `task reconcile:issues -- --apply-lifecycle-fixes`) both refuse to cut a release while a closed-issue xBRIEF still sits outside `xbrief/completed/`. Committing the moves here, at swarm close-out, is the **prevention** so the next release does not have to reconcile drift the swarm itself created. If drift is nevertheless detected later, `task reconcile:issues -- --apply-lifecycle-fixes` is the recovery path -- but the post-merge commit in this step is what stops the drift from being authored in the first place.
816
816
 
817
817
  ⊗ Declare a swarm closed while the cohort's `active/` -> `completed/` lifecycle moves remain uncommitted in the merger's worktree -- an uncommitted lifecycle record is invisible to every other clone and re-surfaces as `check_vbrief_lifecycle_sync` drift at the next release (#1358). The Step 1.5 sweep moves the files; this step makes the move durable.
818
818
 
@@ -977,7 +977,7 @@ CONSTRAINTS:
977
977
  - ⊗ Hardcode a 1:1 xBRIEF-per-agent allocation rule — the monitor decides allocation dynamically based on scope, complexity, and dependencies
978
978
  - ⊗ Complete a story without moving its xBRIEF from `active/` to `completed/` and updating its origin references
979
979
  - ⊗ Declare a swarm closed without running the Phase 6 Step 1.5 cohort completion sweep (`task swarm:complete-cohort`) and confirming `task xbrief:validate` is green -- skipping it leaves the cohort's story xBRIEFs stranded in `active/` and their decompose-created epic parents stranded in `pending/`, the exact #1487 recurrence (the headless / multi-worker close-out is where the sweep was historically missed)
980
- - ⊗ Declare a swarm closed while the cohort's `active/` -> `completed/` lifecycle moves remain uncommitted -- after the Step 1.5 sweep the monitor MUST commit them in a single `chore(xbrief): complete <slugs> post-merge` commit on the base branch and `git push origin <configured-base-branch>` (Phase 6 Step 2b). An uncommitted lifecycle record is invisible to every other clone and re-surfaces as `scripts/release.py::check_vbrief_lifecycle_sync` drift at the next release; the post-merge commit is the prevention, `task reconcile:issues -- --apply-lifecycle-fixes` is only the recovery (#1358)
980
+ - ⊗ Declare a swarm closed while the cohort's `active/` -> `completed/` lifecycle moves remain uncommitted -- after the Step 1.5 sweep the monitor MUST commit them in a single `chore(xbrief): complete <slugs> post-merge` commit on the base branch and `git push origin <configured-base-branch>` (Phase 6 Step 2b). An uncommitted lifecycle record is invisible to every other clone and re-surfaces as lifecycle-sync drift at the next release; the post-merge commit is the prevention, `task reconcile:issues -- --apply-lifecycle-fixes` is only the recovery (#1358)
981
981
  - ⊗ Hardcode `master` as the base branch -- always use the configured base branch from Phase 0
982
982
  - ⊗ Treat a Greptile GitHub CheckRun of COMPLETED/NEUTRAL as equivalent to a passing review without inspecting the comment body. NEUTRAL is the result both when Greptile intentionally has nothing to say AND when it errored out mid-review; the two cases require opposite responses (#526)
983
983
  - ⊗ Loop the monitor indefinitely on the Greptile-service-errored state or time out silently at the poll cap -- detect the "Greptile encountered an error" comment body, retry once via `@greptileai review` with a 10-minute cap, and on second error escalate to the user with the three-way choice (wait / empty retrigger commit / documented override) per Phase 6 Step 1 (#526)
@@ -990,7 +990,7 @@ CONSTRAINTS:
990
990
  - ⊗ Skip the Phase 0 Step 0.5 lifecycle bridge (#1025) and let the Step 1 preflight gate reject candidate scope xBRIEFs wholesale. The setup skill deposits scope xBRIEFs in `xbrief/proposed/` and the refinement skill leaves them in `xbrief/pending/`; the swarm Phase 0 Step 1 preflight only accepts `xbrief/active/` with `plan.status == "running"`. The bridge step (`task scope:promote -- <path>` then `task scope:activate -- <path>`) is the contract that converts proposed/pending candidates to active before allocation -- bypassing it re-surfaces the originating 2026-05-10 first-session consumer-swarm failure mode (`Invalid transition: 'activate' requires file in pending/`)
991
991
  - ⊗ Auto-promote + activate every candidate in `xbrief/proposed/` or `xbrief/pending/` during the Phase 0 Step 0.5 bridge without explicit user approval (#1025). Proposed-stage xBRIEFs may be in a deliberate refinement queue (`skills/deft-directive-refinement/SKILL.md` Phase 4); silent promotion bypasses the user's lifecycle intent and may flip `plan.status` to `running` on scopes the user has not yet refined. Broad affirmatives (`proceed`, `do it`, `go ahead`) do NOT satisfy the bridge approval gate -- require an explicit `yes` / `confirmed` / `approve`
992
992
  - ⊗ Describe heterogeneous sub-agent routing as Grok Build-only — provider-neutral dispatch separates dispatch provider, worker role, and model or agent selection; Composer-class coding agents, Cursor/cloud agents, and future adapters are first-class backends alongside Grok Build `spawn_subagent` (#1531)
993
- - ⊗ Assume parent-shell `gh auth status` proves a worker sandbox can authenticate or reach GitHub — always run `scripts/github_auth_modes.py` from the worker envelope and surface full-access execution, trusted `gh` allowlisting, or injected-token handoff when sandbox auth fails (#1557)
993
+ - ⊗ Assume parent-shell `gh auth status` proves a worker sandbox can authenticate or reach GitHub — always run `task verify:gh-auth` from the worker envelope and surface full-access execution, trusted `gh` allowlisting, or injected-token handoff when sandbox auth fails (#1557)
994
994
  - ⊗ Present Cursor sandbox UID 0 or sandbox-root cwd ownership as host-root access — `sandbox_uid_remap` means the sandbox identity is remapped to the host user, not real root (#1557)
995
995
  - ⊗ Fall through to the manual-terminal fallback (Step 2b) when spawn_subagent is available -- Step 2d is the first-class grok-build launch path; manual terminal is for environments with no orchestration primitive at all (#1331)
996
996
  - ⊗ Surface, propose, or discuss the Phase 5 -> 6 merge cascade gate while `task swarm:verify-review-clean -- <pr-numbers...>` has not yet exited 0 on the current cohort (#1364). Keying the transition on poller lifecycle completion alone -- i.e. treating "every poller sub-agent returned a terminal message" as sufficient to surface the merge gate -- is the recurrence pattern from the #1166 swarm execution where multiple pollers exited with `clean_gate_holdout=confidence` (confidence == 3) and the monitor still raised the Phase 5 -> 6 gate. The cohort verifier is the only authoritative CLEAN signal at the cohort level; a poller's `clean_gate_holdout=*` exit IS a non-CLEAN report and MUST hold the gate even when every sub-agent has technically returned
@@ -58,7 +58,7 @@ Heterogeneous swarm dispatch (#1531) assigns each worker a **dispatch provider**
58
58
  When present, the section documents these fields in order:
59
59
 
60
60
  - `dispatch_provider`: the runtime primitive that launched this worker -- e.g. `spawn_subagent`, `start_agent`, `cursor-composer`, `cursor-cloud-agent`, or a future adapter id. Names the harness surface, not the model.
61
- - `worker_role`: the role boundary for this dispatch -- one of `leaf-implementation`, `orchestrator`, `review-monitor`, or `merge-release` (stable ids from `scripts/policy.py` `SWARM_WORKER_ROLES`). Tells the worker which preamble rules and skill surfaces apply.
61
+ - `worker_role`: the role boundary for this dispatch -- one of `leaf-implementation`, `orchestrator`, `review-monitor`, or `merge-release` (stable ids from `packages/core/src/swarm/routing.ts` `SWARM_WORKER_ROLES`). Tells the worker which preamble rules and skill surfaces apply.
62
62
  - `selected_backend`: the stable backend id from `plan.policy.swarmSubagentBackend` / `task policy:subagent-backends` (e.g. `composer`, `grok-build`, `cursor-cloud`) | null -- which catalogued coding backend the operator selected for this role.
63
63
  - `routing_policy`: <path or reference to the operator's routing file / tiering policy> | null -- when backend selection is delegated to harness routing instead of a typed policy field, cite the policy handle here so postmortems can reconstruct the route. The canonical handle is the gitignored, per-machine `.deft/routing.local.json` (#1739), keyed by `(dispatch_provider, worker_role)`; set decisions with `task swarm:routing-set -- --role <role> (--model <slug> | --harness-default)`.
64
64
  - `resolved_model` (#1739): the concrete model slug the operator pinned for this `(provider, role)` | null for an explicit harness default. Resolved from `.deft/routing.local.json` and stamped into the `task swarm:launch` manifest. **This is the field the dispatch primitive must actually honor** -- see the threading rule below.
@@ -98,7 +98,7 @@ Worked example (a tiered leaf worker on Composer):
98
98
 
99
99
  ! Pre-dispatch gate (#1739 / #1877): run `task verify:routing` before spawning ANY sub-agent (cohort OR solo) — it fails when a dispatched worker role has no decision (pinned model or explicit harness default) for the active provider. `task verify:story-ready` chains the same routing gate for single Cursor/Grok Task dispatches (#1877). Session start runs `task verify:routing -- --advise` (non-blocking disclosure).
100
100
 
101
- Reference: `.deft/routing.local.json` + `task swarm:routing-set` + `task verify:routing` (#1739, supersedes the `plan.policy.swarmSubagentBackend` enum of #1531a / #1735), `scripts/policy.py` `SWARM_WORKER_ROLES`, issue #1531 scope update (dispatch provider / worker role / model selection are three separate concerns).
101
+ Reference: `.deft/routing.local.json` + `task swarm:routing-set` + `task verify:routing` (#1739, supersedes the `plan.policy.swarmSubagentBackend` enum of #1531a / #1735), `packages/core/src/swarm/routing.ts` `SWARM_WORKER_ROLES`, issue #1531 scope update (dispatch provider / worker role / model selection are three separate concerns).
102
102
 
103
103
  ## 2.7 Runtime and GitHub auth mode (#1557)
104
104
 
@@ -129,7 +129,7 @@ Worked example (cloud / headless worker):
129
129
  - github_auth_mode: injected-token
130
130
  ```
131
131
 
132
- Reference: `scripts/platform_capabilities.py` (#1557a), `scripts/github_auth_modes.py` (#1557b), issue #1557.
132
+ Reference: `packages/core/src/platform/platform-capabilities.ts` (#1557a), `packages/core/src/intake/github-auth-modes.ts` (#1557b), issue #1557.
133
133
 
134
134
  ## 3. PowerShell 5.1 non-ASCII rule (#798)
135
135
 
@@ -154,24 +154,24 @@ When running under the Grok Build runtime on Windows + pwsh 7+, `run_terminal_co
154
154
 
155
155
  This rule applies to the Grok Build runtime (pwsh 7+); Warp + Claude (PTY-based) is not affected by this wrapper leakage.
156
156
 
157
- ## 3.6 Safe subprocess on Windows -- UTF-8 capture helper (#1366)
157
+ ## 3.6 Safe subprocess on Windows -- UTF-8 capture (#1366)
158
158
 
159
- Windows hosts running deft tooling (Grok Build, native PowerShell, scheduled / cloud agents) inherit the locale codepage (cp1252 / cp437) as the default `text=True` decode encoding for `subprocess.run`. When the child process (most commonly `gh api` returning a Greptile rolling-summary body) emits bytes that are not valid in that codepage, Python's internal `Thread-3 (_readerthread)` crashes with `UnicodeDecodeError`. The calling script then returns empty / malformed stdout, and any monitor parsing the JSON sees `head: None` -- the exact failure mode behind the #1166 swarm `Still waiting... (last reviewed: none, head: None)` symptom.
159
+ **Historical note:** The `scripts/` Python directory was removed in #2022 (TS-native migration). The `scripts/_safe_subprocess.py::run_text` helper no longer exists. The underlying risk -- locale-codepage decode failures when capturing `gh api` output on Windows -- still applies to any TS tooling that shells out.
160
160
 
161
- **Directive rule:** Any deft script that captures `gh` output or another Python subprocess for parsing MUST route its capture through `scripts/_safe_subprocess.py::run_text` (or pass `encoding="utf-8", errors="replace"` to `subprocess.run` directly). The helper FORCES `capture_output=True`, `text=True`, `encoding="utf-8"`, `errors="replace"`, and `shell=False`; callers cannot regress the safety contract via kwargs.
161
+ **Directive rule for TS tooling:** Any TS script that captures `gh` output or other child-process output for parsing MUST use `execa` (preferred) or `child_process.spawn` with explicit `encoding: "utf8"`. Never use `execSync` / `spawnSync` without explicit encoding when the output may carry non-ASCII glyphs (Greptile bodies, gh REST bodies, user-authored commit messages).
162
162
 
163
- ```python path=null start=null
164
- # WRONG -- crashes Thread-3 (_readerthread) on Windows when output contains non-cp1252 bytes
165
- result = subprocess.run(cmd, capture_output=True, text=True, timeout=60)
163
+ ```typescript
164
+ // WRONG -- Buffer return; non-ASCII bytes become mojibake or throw on .toString()
165
+ const out = execSync("gh api ...");
166
166
 
167
- # RIGHT -- bytes that don't decode under utf-8 become U+FFFD; the reader thread never crashes
168
- from _safe_subprocess import run_text
169
- result = run_text(cmd, timeout=60)
167
+ // RIGHT -- explicit utf8 encoding; non-ASCII bytes survive the round-trip
168
+ import { execa } from "execa";
169
+ const { stdout } = await execa("gh", ["api", "..."], { encoding: "utf8" });
170
170
  ```
171
171
 
172
- This rule applies on every platform but BITES on Windows + Grok Build / cmd / PowerShell hosts where the locale codepage is not UTF-8. Linux / macOS hosts generally default to UTF-8 already and so do not reproduce the crash, but routing through `run_text` keeps the behavior identical across platforms.
172
+ This rule bites on Windows + Grok Build / cmd / PowerShell hosts where the default codepage is not UTF-8. Linux / macOS generally default to UTF-8 and do not reproduce the crash, but explicit encoding keeps behavior identical across platforms.
173
173
 
174
- Reference: AGENTS.md `## Safe subprocess capture (#1366)`. Recurrence record: the #1166 swarm session repeatedly observed `Thread-3 (_readerthread) UnicodeDecodeError` across multiple gh-shelling tools; #1366 is the structural fix.
174
+ Reference: AGENTS.md `## Safe subprocess capture (#1366)`. Recurrence record: the #1166 swarm session repeatedly observed `Thread-3 (_readerthread) UnicodeDecodeError` across multiple gh-shelling tools; #1366 is the structural fix. `scripts/_safe_subprocess.py` was the Python-era solution; the TS-era solution is explicit encoding on every `execa`/`spawn` call.
175
175
 
176
176
  ## 3.7 Per-run unique pytest basetemp under concurrent swarm dispatch (#1681)
177
177
 
@@ -239,7 +239,7 @@ task scm:body:issue:edit -- --repo OWNER/REPO --issue 1555 --body-file "$bodyFil
239
239
  task scm:body:pr:edit -- --repo OWNER/REPO --pr 42 --body-file "$bodyFile"
240
240
  ```
241
241
 
242
- The wrapper reads UTF-8 body text from a file or stdin, sends JSON to `gh api --input -` via `_safe_subprocess.run_text` with `shell=False`, and prints the live post-mutation read-back object. Use live `gh` for immediate verification after mutations; do not use `ghx` for the first read-back because it may serve a cached stale GET.
242
+ The wrapper reads UTF-8 body text from a file and invokes the `github-body` TS CLI (which routes through `gh api --input -` with explicit UTF-8 encoding), then prints the live post-mutation read-back object. Use live `gh` for immediate verification after mutations; do not use `ghx` for the first read-back because it may serve a cached stale GET.
243
243
 
244
244
  ## 5.6 Issue reading — body then comments (#2143 / #2066)
245
245
 
@@ -262,7 +262,8 @@ Reference: AGENTS.md `## Issue body→comments reading (#2143)`, `## Umbrella cu
262
262
 
263
263
  Value attribution, budgeted session readbacks, and upstream gap escalation are gated on `plan.policy.valueFeedback` (default OFF). Workers MUST NOT emit value claims, session readback lines, or file upstream framework-gap issues unless the relevant sub-flag is ON and the operator has confirmed enablement where required.
264
264
 
265
- - ! While `valueFeedback.enabled` is false, treat every value-feedback path as a no-op -- no ledger writes, no session lines, no upstream prompts, no token spend.
265
+ - ! Trusted-org local auto-enable (#2376): a repo whose GitHub origin belongs to a company-owned org (default `deftai`; extend via `DEFT_VALUE_AUTOENABLE_ORGS`) auto-resolves LOCAL emit + session readback ON with `source=org-auto` and network/upstream OFF -- no per-repo confirmation. An explicit typed `valueFeedback` block (including `enabled: false`) always wins; any other repo or no origin remote stays OFF.
266
+ - ! While `valueFeedback.enabled` is false AND no trusted-org auto-enable applies, treat every value-feedback path as a no-op -- no ledger writes, no session lines, no upstream prompts, no token spend.
266
267
  - ! Value claims MUST cite concrete attributed ledger events; silence when nothing is attributable.
267
268
  - ! Session readback repeats suppress for 4 hours per attribution event id (same debounce class as #1279 triage welcome). Pull-based detail uses `task value:show` / `deft value:show`, not ambient pushes.
268
269
  - ! Upstream gap filing is confirmation-gated -- route through `deft-directive-feedback`; draft + dedup with `task feedback:file` / `deft feedback:file`, then re-run with `--confirm` only after explicit operator approval. Consumer projects only; maintainer repo no-ops unless `DEFT_VALUE_SELF_DOGFOOD=1`.
@@ -403,7 +404,7 @@ The contract in one paragraph:
403
404
  - The record is JSON with at least `agent_id` (matches filename), `parent_id`, `last_heartbeat_at` (ISO-8601 UTC, `Z`-suffix), `last_message` (one human-readable line), `phase` (one of `starting | implementing | validating | committing | pushing | polling | fixing | terminal`), and optional `terminal_state`.
404
405
  - Writes MUST be atomic (write-to-temp + rename) so the monitor never reads a half-written file.
405
406
 
406
- The parent monitor watches via `scripts/subagent_monitor.py` (three-state exit 0 ok / 1 stale-or-malformed / 2 config error). Skipping the heartbeat is a hard `⊗` for any long-running sub-agent: a stalled agent with no heartbeat surface is the exact #1166 failure mode this contract closes.
407
+ The parent monitor watches the heartbeat file directly (three-state exit 0 ok / 1 stale-or-malformed / 2 config error). Skipping the heartbeat is a hard `⊗` for any long-running sub-agent: a stalled agent with no heartbeat surface is the exact #1166 failure mode this contract closes.
407
408
 
408
409
  ## 11. Mandatory DONE message even on early exit
409
410
 
@@ -432,7 +433,7 @@ The `--allow-stale` override is per-shell and audited: the dispatcher MAY pass i
432
433
 
433
434
  The `--allow-missing-bootstrap` flag exists for the framework's own `task check` wiring (so a fresh framework checkout doesn't fail its own `verify:cache-fresh` aggregate run) and MUST NOT be passed by dispatchers. Consumer dispatchers leave it OFF; a missing cache is a real failure for them.
434
435
 
435
- Reference: the gate is implemented at `scripts/preflight_cache.py` and exposed via `task verify:cache-fresh`; the subscription scope is read via the D12 surface `scripts/triage_scope.py` so a consumer that has tightened `plan.policy.triageScope[]` is not gated by stale entries outside their subscription.
436
+ Reference: the gate is exposed via `task verify:cache-fresh`; the subscription scope is read via the D12 surface (`task triage:scope`) so a consumer that has tightened `plan.policy.triageScope[]` is not gated by stale entries outside their subscription.
436
437
 
437
438
  ## 13. Cancellation Attribution (#1300)
438
439
 
@@ -19,7 +19,7 @@ Deft is installed in .deft/core/. Full guidelines: .deft/core/main.md
19
19
 
20
20
  **Pre-cutover detected** if ANY of the following are true:
21
21
 
22
- - ./SPECIFICATION.md exists and is neither a deprecation redirect nor a current generated spec export. A current generated spec export contains `<!-- Purpose: rendered specification -->` and `<!-- Source of truth: xbrief/specification.xbrief.json -->`, and `./xbrief/specification.xbrief.json` plus all five lifecycle folders exist. This mirrors `.deft/core/scripts/_precutover.py`.
22
+ - ./SPECIFICATION.md exists and is neither a deprecation redirect nor a current generated spec export. A current generated spec export contains `<!-- Purpose: rendered specification -->` and `<!-- Source of truth: xbrief/specification.xbrief.json -->`, and `./xbrief/specification.xbrief.json` plus all five lifecycle folders exist.
23
23
  - ./PROJECT.md exists and is not a deprecation redirect (`<!-- deft:deprecated-redirect -->` or `<!-- Purpose: deprecation redirect -->`).
24
24
  - ./xbrief/ exists but any of the five lifecycle subfolders (proposed/, pending/, active/, completed/, cancelled/) is missing
25
25
 
@@ -29,13 +29,15 @@ Deft is installed in .deft/core/. Full guidelines: .deft/core/main.md
29
29
 
30
30
  ## First Session
31
31
 
32
- Check what exists before doing anything else:
32
+ ! Check what exists before doing anything else -- do NOT respond to any user request until the correct phase fires:
33
33
 
34
34
  **USER.md missing** (~/.config/deft/USER.md or %APPDATA%\deft\USER.md):
35
- Read .deft/core/.agents/skills/deft-directive-setup/SKILL.md and start Phase 1 (user preferences)
35
+ ! Read .deft/core/.agents/skills/deft-directive-setup/SKILL.md and immediately start Phase 1 (user preferences). Do not wait for a user prompt.
36
36
 
37
- **USER.md exists, PROJECT-DEFINITION.xbrief.json missing** (./xbrief/):
38
- Read .deft/core/.agents/skills/deft-directive-setup/SKILL.md and start Phase 2 (project definition)
37
+ **USER.md exists, `xbrief/PROJECT-DEFINITION.xbrief.json` missing**:
38
+ ! Read .deft/core/.agents/skills/deft-directive-setup/SKILL.md and immediately start Phase 2 (project definition). This branch MUST fire even when USER.md already exists from a prior install or another project -- a pre-existing USER.md is not a reason to skip Phase 2 on a greenfield project.
39
+
40
+ ⊗ Respond to any user query (greet, answer questions, take requests) before the correct phase has completed -- first-session phase routing is mandatory, not advisory.
39
41
 
40
42
  ## Returning Sessions
41
43
 
@@ -149,12 +151,14 @@ Skill routing (which skill answers which trigger) is not a table in this policy
149
151
 
150
152
  ## Value feedback and attribution (#1709)
151
153
 
152
- - ! `plan.policy.valueFeedback.enabled` defaults OFF -- while false, every downstream path (emit-only ledger, budgeted session readback, upstream gap escalation) short-circuits with zero token spend. Opt-in ONLY via `deft policy:enable-value-feedback -- --confirm` after the capability-cost disclosure prints. Inspect with `deft policy:show --field=valueFeedback`.
154
+ - ! `plan.policy.valueFeedback.enabled` defaults OFF for non-org repos -- while off, every downstream path (emit-only ledger, budgeted session readback, upstream gap escalation) short-circuits with zero token spend. Opt-in for any repo via `deft policy:enable-value-feedback -- --confirm` after the capability-cost disclosure prints. Inspect with `deft policy:show --field=valueFeedback`.
155
+ - ! Trusted-org local auto-enable (#2376) -- for a repo whose GitHub origin belongs to a company-owned org (built-in default `deftai`; extend via the `DEFT_VALUE_AUTOENABLE_ORGS` env override), LOCAL emit + session readback resolve ON with `source=org-auto` and network/upstream OFF, with NO per-repo or per-machine confirmation: org membership IS the consent for local, no-egress collection on company-owned resources. An explicit typed `valueFeedback` block always wins (including `enabled: false`); a non-matching org or no origin remote stays OFF (fail-safe).
156
+ - ! Attribution records are enriched at emit time (#2376) with `repo`, `directive_version`, `install_id` (a stable per-checkout uuid under gitignored `.deft-cache/`), and `schema_version`, so a later collector can aggregate cross-repo without re-deriving provenance.
153
157
  - ! Value claims MUST be attributed-only -- point to concrete logged events ("encoding gate caught 2 corruptions"), never vague quality claims. Silence when the ledger has nothing attributable for the session slot.
154
158
  - ! Budgeted awareness -- at most one session readback line when `sessionLine` is allowed; repeat suppression uses a 4-hour window per attribution event id (parity with #1279 triage welcome debounce). Pull-based detail is `deft value:show`, not pushed.
155
159
  - ! Gap escalation to `deftai/directive` is confirmation-gated -- route conversational filing through `deft-directive-feedback`; the agent drafts + dedups; the operator approves before `deft feedback:file -- --confirm`. Use `Refs #1709` in upstream bodies, not `Closes`.
156
- - ! Gap escalation is consumer-only -- no-op inside the directive maintainer repo unless `DEFT_VALUE_SELF_DOGFOOD=1`.
157
- - ⊗ Enable value-feedback surfaces without explicit operator confirmation on the typed policy flag.
160
+ - ! Gap escalation is consumer-only -- no-op inside the directive maintainer repo unless `DEFT_VALUE_SELF_DOGFOOD=1`. Trusted-org auto-enable still turns LOCAL emit ON inside the maintainer repo, but session readback stays gated behind `DEFT_VALUE_SELF_DOGFOOD=1`.
161
+ - ⊗ Enable any NETWORK or upstream value-feedback surface (upstream gap escalation / `deft feedback:file`) without operator confirmation -- trusted-org auto-enable authorizes LOCAL, no-egress collection ONLY.
158
162
  - ⊗ File upstream framework-gap issues without operator confirmation or past duplicate detection.
159
163
  - ⊗ Treat unattributed self-promotion as value feedback -- if there is no ledger event, emit nothing.
160
164
 
@@ -180,7 +184,7 @@ When the active project's `xbrief/PROJECT-DEFINITION.xbrief.json` has `plan.poli
180
184
 
181
185
  > "[deft policy] Direct commits to the default branch are ENABLED (source: typed). Branch-protection policy is OFF."
182
186
 
183
- This phrasing comes from `.deft/core/scripts/policy.py::disclosure_line` and stays in lockstep with the typed surface (#746). When the policy is OFF (default; `allowDirectCommitsToMaster=false`), no session-start disclosure is required -- the absence of the disclosure line itself signals the default-enforcing state.
187
+ This phrasing is produced by `deft policy:show --field=allowDirectCommitsToMaster` and stays in lockstep with the typed surface (#746). When the policy is OFF (default; `allowDirectCommitsToMaster=false`), no session-start disclosure is required -- the absence of the disclosure line itself signals the default-enforcing state.
184
188
 
185
189
  Override paths (`deft policy:show` / `deft policy:enforce-branches` / `deft policy:allow-direct-commits -- --confirm` / `DEFT_ALLOW_DEFAULT_BRANCH_COMMIT=1`) are detailed in the Branch policy & branch verification section above.
186
190