@deftai/directive-content 0.67.0 → 0.68.1

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.
@@ -97,6 +97,7 @@ Iterate until the user approves the breakdown.
97
97
 
98
98
  ### Step 5: Create the GitHub issues
99
99
 
100
+ - ! **Pre-filing master-diff check (#1102):** before filing an issue that proposes ADDING a file or directory, run `git ls-tree origin/master -- <path>` (or `gh api repos/{owner}/{repo}/contents/{path}` for repos without a local clone) to confirm the file does not already exist on master. If it does, scope the issue to the DELTA between current state and the proposed end-state, not the original "deposit this file" framing.
100
101
  - ! Create issues in dependency order (blockers first) so you can reference real issue numbers
101
102
  - ! Use `gh issue create` for each approved slice with the template below
102
103
  - ! Trace each issue back to the relevant SPECIFICATION.md phase/task IDs where applicable
@@ -197,3 +198,4 @@ task slice:list # enumerate recorded slices for verification
197
198
  - ⊗ Proceeding without `gh` authentication
198
199
  - ⊗ Omitting dependency ordering — blockers must be created first
199
200
  - ⊗ Describing implementation internals instead of observable behavior in issue bodies
201
+ - ⊗ File an issue proposing to add a file or directory that already exists on master without first running the `git ls-tree origin/master -- <path>` existence check (#1102) -- the stale "add file X" filing (#1099 proposed adding `.github/dependabot.yml`, which had already landed via #1070; closed as a duplicate and re-filed as the additive-delta #1100) is exactly the recurrence this check prevents
@@ -154,6 +154,8 @@ The agent may suggest the next phase, but the user decides. Phases can be entere
154
154
 
155
155
  ! Scan external sources for new work items and create proposed scope xBRIEFs.
156
156
 
157
+ ! **Pre-filing master-diff check (#1102).** When a refinement pass FILES a new GitHub issue that proposes ADDING a file or directory (rather than ingesting an existing issue), first run the pre-filing existence check from [`../deft-directive-gh-slice/SKILL.md`](../deft-directive-gh-slice/SKILL.md) Step 5 -- `git ls-tree origin/master -- <path>` (or `gh api repos/{owner}/{repo}/contents/{path}`) -- so a stale "add file X" issue is never opened against state that already exists on master (the #1099 -> #1100 close-and-refile recurrence).
158
+
157
159
  ### Step 1: Gather Sources
158
160
 
159
161
  1. ? Scan non-GitHub sources (Jira, direct user requests, etc.) manually if applicable — those ingest paths are not yet task-wrapped
@@ -774,7 +774,20 @@ What the sweep does (script: `scripts/swarm_complete_cohort.py`):
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`.
776
776
 
777
- ! **Headless / multi-worker path:** the cohort sweep is NOT optional here -- it is the structural fix for the #1487 recurrence where the multi-worker close-out never executed the per-cohort completion. The launching monitor (or the close-out automation that follows `task pr:wait-mergeable-and-merge`, #1369) MUST invoke `task swarm:complete-cohort -- --cohort '<cohort-glob>'` after the last cohort PR merges and MUST gate on its exit 0 plus a green `task xbrief:validate` before declaring the swarm closed. The `--json` flag emits a structured verdict for a parent monitor agent to consume.
777
+ ! **Headless / multi-worker path (#2225):** after the merge cascade (`task pr:wait-mergeable-and-merge`, #1369) reports the cohort's PRs MERGED, the monitor SHOULD invoke the automated finalize surface instead of hand-authoring a separate lifecycle-sweep PR:
778
+
779
+ ```pwsh path=null start=null
780
+ # Resolve merged stories from PR closing keywords and land the sweep PR:
781
+ task swarm:finalize-cohort -- --pr <N1>,<N2> --repo <owner/repo> [--label <cohort-label>]
782
+ # Preview only (no commit / no PR):
783
+ task swarm:finalize-cohort -- --pr <N1>,<N2> --repo <owner/repo> --dry-run
784
+ # Explicit story list when PR bodies omit Closes #N:
785
+ task swarm:finalize-cohort -- --stories <issue-or-path>... --repo <owner/repo>
786
+ ```
787
+
788
+ The finalize surface runs the same `completeCohort(...)` engine as `task swarm:complete-cohort`, fast-forwards the local base branch, creates a `swarm/finalize/<label>` feature branch (branch policy #747 safe), commits the `xbrief/` lifecycle moves, and auto-opens the sweep PR. Pass `--no-commit` to sweep only (manual Step 2b), or `--no-open-pr` to commit locally without opening the PR. Gate on exit 0 plus green `task xbrief:validate` before declaring the swarm closed.
789
+
790
+ ! **Manual fallback (#1487):** `task swarm:complete-cohort` remains the idempotent manual primitive when finalize automation is unavailable or you need a dry-run preview of transitions only. The headless path above replaces the historical requirement to hand-author a separate `chore(xbrief)` sweep PR every cycle.
778
791
 
779
792
  ⊗ Declare a swarm closed while any cohort story xBRIEF remains in `xbrief/active/` or any fully-childless decompose-created epic parent remains in `xbrief/pending/` -- run `task swarm:complete-cohort` and confirm `task xbrief:validate` is green first (#1487).
780
793
 
package/tasks/engine.yml CHANGED
@@ -37,7 +37,7 @@ tasks:
37
37
 
38
38
  invoke:
39
39
  internal: true
40
- desc: "Run a deft-ts verb from vendored bin.js (source checkout) or global deft (npm consumer deposit)."
40
+ desc: "Run a deft-ts verb from vendored bin.js (source checkout) or global deft (npm consumer deposit). Source checkouts without a built dist fail fast (#2181) -- runtime/session tasks must not trigger engine:_ts-build / pnpm."
41
41
  # Run from the operator project root so deft verbs resolve USER_WORKING_DIR
42
42
  # correctly; without this, included engine.yml defaults cwd to tasks/ (#2022).
43
43
  dir: '{{.USER_WORKING_DIR}}'
@@ -45,8 +45,33 @@ tasks:
45
45
  - |
46
46
  set -eu
47
47
  bin="{{.DEFT_ROOT}}/packages/cli/dist/bin.js"
48
+ root_pkg="{{.DEFT_ROOT}}/package.json"
49
+ is_buildable_source=0
50
+ if [ -f "{{.DEFT_ROOT}}/packages/cli/package.json" ] \
51
+ && [ -f "$root_pkg" ] \
52
+ && node -e "const fs=require('fs');const j=JSON.parse(fs.readFileSync(process.argv[1],'utf8'));process.exit(j.scripts&&j.scripts.build?0:1)" "$root_pkg"; then
53
+ is_buildable_source=1
54
+ fi
48
55
  if [ -f "$bin" ]; then
56
+ if [ "$is_buildable_source" = 1 ] && [ -f "$root_pkg" ]; then
57
+ node -e "
58
+ const fs=require('fs');
59
+ const pkg=JSON.parse(fs.readFileSync(process.argv[1],'utf8'));
60
+ const req=pkg.engines&&pkg.engines.node;
61
+ if(!req) process.exit(0);
62
+ const major=Number(process.versions.node.split('.')[0]);
63
+ const m=String(req).match(/>=\\s*(\\d+)/);
64
+ if(m&&major<Number(m[1])){
65
+ console.error('deft: Node '+process.versions.node+' does not satisfy engines.node '+req+' (read from '+process.argv[1]+').');
66
+ process.exit(2);
67
+ }
68
+ " "$root_pkg" || exit $?
69
+ fi
49
70
  node "$bin" {{.ENGINE_CMD}}
71
+ elif [ "$is_buildable_source" = 1 ]; then
72
+ echo "deft: CLI artifact missing at {{.DEFT_ROOT}}/packages/cli/dist/bin.js" >&2
73
+ echo " Run \`task build\` first (framework source checkout)." >&2
74
+ exit 2
50
75
  elif command -v deft >/dev/null 2>&1; then
51
76
  deft {{.ENGINE_CMD}}
52
77
  else
package/tasks/pr.yml CHANGED
@@ -95,3 +95,32 @@ tasks:
95
95
  - task: :engine:invoke
96
96
  vars:
97
97
  ENGINE_CMD: 'pr-wait-mergeable {{.CLI_ARGS}}'
98
+
99
+ # pr:watch -- deterministic PR-verdict polling surface (#1056). A
100
+ # blocking-by-default poll that resolves to a terminal three-state verdict
101
+ # (exit 0 CLEAN / 1 NEW_P0_P1 / 2 ERRORED|STALL|TIMEOUT|config), so an
102
+ # orchestrator that promises to poll a PR review to conclusion cannot
103
+ # silently forget (the invocation IS the wait). --one-shot degrades to a
104
+ # single probe. Reuses the CANONICAL Greptile/SLizard verdict detector
105
+ # (packages/core/src/content-contracts/skills/greptile-detector.ts -- the
106
+ # same module pr:merge-ready and the swarm poller template consume); no
107
+ # second detector. SHA-match gating means a stale pre-push review is never
108
+ # read as the verdict. All gh access routes through the UTF-8-safe
109
+ # execFile shim (#1366). Cross-referenced from the AGENTS.md
110
+ # `## Multi-agent orchestration discipline (#954)` Tier-4 pointer.
111
+ #
112
+ # Per `conventions/task-caching.md` (#574): NO `sources:` / `generates:`
113
+ # because user-facing flags (`--one-shot` / `--max-wait-minutes` /
114
+ # `--poll-seconds` / `--json` / `--repo` / `--project-root`) MUST NOT be
115
+ # silently swallowed by go-task's incremental-build cache.
116
+ #
117
+ # Companion module: packages/core/src/pr-watch/
118
+ # Companion tests: packages/core/src/pr-watch/*.test.ts
119
+ watch:
120
+ desc: "Blocking poll of a PR to a terminal three-state verdict (0 CLEAN / 1 NEW_P0_P1 / 2 ERRORED|STALL|TIMEOUT|config); --one-shot for a single probe (#1056)"
121
+ deps: [":engine:_ts-build"]
122
+ dir: '{{.USER_WORKING_DIR}}'
123
+ cmds:
124
+ - task: :engine:invoke
125
+ vars:
126
+ ENGINE_CMD: 'pr-watch {{.CLI_ARGS}}'
package/tasks/session.yml CHANGED
@@ -12,7 +12,7 @@ tasks:
12
12
  start:
13
13
  desc: "Run quick-tier session-start ritual and write .deft/ritual-state.json (#1348). Flags: --defer step=reason / --json"
14
14
  dir: '{{.USER_WORKING_DIR}}'
15
- deps: [":engine:_ts-build"]
15
+ # Runtime/session dispatch: no engine:_ts-build / pnpm build (#2181).
16
16
  env:
17
17
  PYTHONUTF8: "1"
18
18
  cmds:
package/tasks/swarm.yml CHANGED
@@ -93,3 +93,19 @@ tasks:
93
93
  - task: :engine:invoke
94
94
  vars:
95
95
  ENGINE_CMD: 'swarm-complete-cohort {{.CLI_ARGS}} --project-root "{{.USER_WORKING_DIR}}"'
96
+
97
+ # swarm:finalize-cohort -- post-merge cohort lifecycle automation (#2225).
98
+ # After a cohort's PRs merge, resolves the merged stories (via Closes #N ->
99
+ # active-brief mapping or an explicit --stories list), runs the same
100
+ # completeCohort(...) sweep as swarm:complete-cohort, and lands the
101
+ # active/ -> completed/ moves on a feature branch with an auto-opened PR —
102
+ # eliminating the hand-authored lifecycle-sweep PR tax for stop-at:pr-open
103
+ # swarms. swarm:complete-cohort remains the idempotent manual primitive.
104
+ finalize-cohort:
105
+ desc: "After cohort PRs merge, auto-sweep story briefs active/ -> completed/ and open the lifecycle PR (#2225)"
106
+ deps: [":engine:_ts-build"]
107
+ dir: '{{.USER_WORKING_DIR}}'
108
+ cmds:
109
+ - task: :engine:invoke
110
+ vars:
111
+ ENGINE_CMD: 'swarm-finalize-cohort {{.CLI_ARGS}} --project-root "{{.USER_WORKING_DIR}}"'
@@ -23,7 +23,7 @@ tasks:
23
23
  summary:
24
24
  desc: "Emit the D2 (#1122) one-line triage state for the session-start ritual (N9 / #1149). Always exits 0; appends a JSONL record to vbrief/.eval/summary-history.jsonl. -- task triage:summary -- [--json] [--no-history]"
25
25
  internal: true
26
- deps: [":engine:_ts-build"]
26
+ # Runtime/session dispatch: no engine:_ts-build / pnpm build (#2181).
27
27
  dir: '{{.USER_WORKING_DIR}}'
28
28
  cmds:
29
29
  - task: :engine:invoke
@@ -24,7 +24,7 @@ tasks:
24
24
  welcome:
25
25
  desc: "Run the 6-phase onboarding ritual (N3 / #1143): detect prior state, prompt subscription scope, run triage:bootstrap, prompt wipCap, offer WIP relief, print triage:summary. Idempotent; re-run resumes cleanly. -- task triage:welcome -- [--no-subprocess]"
26
26
  internal: true
27
- deps: [":engine:_ts-build"]
27
+ # Runtime/session dispatch: no engine:_ts-build / pnpm build (#2181).
28
28
  dir: '{{.USER_WORKING_DIR}}'
29
29
  env:
30
30
  DEFT_TASK_PREFIX: '{{.DEFT_TASK_PREFIX | default ""}}'
package/tasks/verify.yml CHANGED
@@ -157,6 +157,20 @@ tasks:
157
157
  vars:
158
158
  ENGINE_CMD: 'verify:encoding --project-root "{{.USER_WORKING_DIR}}" {{.CLI_ARGS}}'
159
159
 
160
+ forward-coverage:
161
+ desc: "Forward-coverage gate (#1310): fail when a NEW source file (scripts/, src/, cmd/, packages/*/src, or *.py/*.go/*.ts/*.tsx, excluding *.test.ts / *_test.go / test_*.py / *.d.ts) is added without a corresponding test in the SAME diff. Migrates the prose 'new source files MUST include tests' rule to deterministic enforcement, mirroring verify:encoding (#798) / verify:branch (#747). Defaults to the HEAD-relative diff; pass --staged for the pre-commit invocation. Three-state exit (0 clean / 1 missing forward coverage / 2 config error)."
162
+ dir: '{{.USER_WORKING_DIR}}'
163
+ deps:
164
+ - task: :engine:_ts-build
165
+ # Per `conventions/task-caching.md`: NO `sources:` / `generates:` because
166
+ # user-facing flags (--staged / --head / --allow-list <path> / --quiet) MUST
167
+ # NOT be silently swallowed by go-task's incremental-build cache (same
168
+ # rationale as verify:encoding above).
169
+ cmds:
170
+ - task: :engine:invoke
171
+ vars:
172
+ ENGINE_CMD: 'verify:forward-coverage --project-root "{{.USER_WORKING_DIR}}" {{.CLI_ARGS}}'
173
+
160
174
  vbrief-conformance:
161
175
  desc: "Detect bare non-conformant vBRIEF keys (#1620). Scans tracked vbrief/**/*.vbrief.json and flags any document/plan/item key that is not 0.6 spec-core, x-directive/-namespaced, or x-vbrief/-namespaced. plan.policy + plan.completedNote carry a TEMPORARY allow-list pending vBRIEF #12. Defaults to --all; pass --staged for the pre-commit invocation."
162
176
  dir: '{{.USER_WORKING_DIR}}'
@@ -190,8 +204,8 @@ tasks:
190
204
  cache-fresh:
191
205
  desc: "Pre-`start_agent` cache-freshness gate (#1127). Refuses implementation dispatch when the triage cache is stale, missing, or the target issue's latest decision is not `accept`. Subscription-aware via plan.policy.triageScope[] (D12 / #1131). Flags: --for-issue N / --max-age-hours N / --allow-stale / --repo OWNER/NAME / --allow-missing-bootstrap (consumed by the framework's own `task check` so a fresh checkout passes -- consumers leave it OFF)."
192
206
  dir: '{{.USER_WORKING_DIR}}'
193
- deps:
194
- - task: :engine:_ts-build
207
+ # Runtime/session + pre-dispatch gate: no engine:_ts-build / pnpm build (#2181).
208
+ # Parent `task check` still builds via its own engine:_ts-build dep first.
195
209
  # Per `conventions/task-caching.md` (#574): NO `sources:` / `generates:`
196
210
  # because the gate forwards user-facing flags via {{.CLI_ARGS}}
197
211
  # (--for-issue / --max-age-hours / --allow-stale / --repo) that
@@ -220,8 +234,7 @@ tasks:
220
234
  session-ritual:
221
235
  desc: "Fail-closed session ritual verifier (#1348). Flags: --tier quick|gated / --json. Set DEFT_SESSION_RITUAL_SKIP=1 for headless workers and CI."
222
236
  dir: '{{.USER_WORKING_DIR}}'
223
- deps:
224
- - task: :engine:_ts-build
237
+ # Runtime/session dispatch: no engine:_ts-build / pnpm build (#2181).
225
238
  # No sources/generates: this gate is time-, HEAD-, and worktree-sensitive.
226
239
  cmds:
227
240
  # Oracle/fallback (parity): scripts/verify_session_ritual.py (#1828 Wave 8 / #1854 s3).
@@ -232,8 +245,7 @@ tasks:
232
245
  tools:
233
246
  desc: "Detect required Deft host tools and print install or manual guidance (#1187). Flags: --install / --yes / --json"
234
247
  dir: '{{.USER_WORKING_DIR}}'
235
- deps:
236
- - task: :engine:_ts-build
248
+ # Runtime/session dispatch: no engine:_ts-build / pnpm build (#2181).
237
249
  cmds:
238
250
  # Oracle/fallback (parity): scripts/verify_tools.py (#1828 Wave 8).
239
251
  - task: :engine:invoke
@@ -130,6 +130,7 @@ Three consumer-facing surfaces enforce the branch-policy contract (#746 / #747):
130
130
  - `deft verify:branch` -- branch gate wired into the `deft check` aggregate; refuses a commit on the default branch unless `plan.policy.allowDirectCommitsToMaster = true` (typed) or `DEFT_ALLOW_DEFAULT_BRANCH_COMMIT=1` is set.
131
131
  - `.githooks/pre-commit` / `pre-push` -- local hooks installed via `deft setup`; verify via `deft verify:hooks-installed`. After a framework upgrade, run `deft update` to refresh hook templates to the current TS-native `deft verify:*` / `deft preflight-gh` wiring (#2049).
132
132
  - `deft policy:show --field=allowDirectCommitsToMaster` -- inspect the resolved policy; `deft policy:allow-direct-commits -- --confirm` writes the typed override with an audit row.
133
+ - `deft verify:forward-coverage` -- forward-coverage gate (#1310): a NEW source file (`scripts/`, `src/`, `cmd/`, `packages/*/src`, or `*.py`/`*.go`/`*.ts`/`*.tsx`, excluding tests + `*.d.ts`) added without a corresponding test in the SAME diff fails the gate. Wired into `deft check` + the pre-commit hook (`--staged`); document genuine exceptions (shims, generated code) via `--allow-list <path>`. Mirrors the `deft verify:encoding` (#798) prose->deterministic migration.
133
134
 
134
135
  ## Branch Policy Disclosure (#746)
135
136