@deftai/directive-core 0.70.0 → 0.71.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.
Files changed (79) hide show
  1. package/dist/branch/evaluate.js +7 -0
  2. package/dist/doctor/doctor-state.js +2 -2
  3. package/dist/eval/crud-telemetry.d.ts +59 -0
  4. package/dist/eval/crud-telemetry.js +307 -0
  5. package/dist/eval/health.d.ts +52 -0
  6. package/dist/eval/health.js +240 -0
  7. package/dist/eval/readback.d.ts +38 -0
  8. package/dist/eval/readback.js +209 -0
  9. package/dist/eval/report.d.ts +53 -0
  10. package/dist/eval/report.js +161 -0
  11. package/dist/eval/run.d.ts +79 -0
  12. package/dist/eval/run.js +309 -0
  13. package/dist/events/attribution-constants.d.ts +13 -0
  14. package/dist/events/attribution-constants.js +18 -0
  15. package/dist/events/attribution-ledger.d.ts +43 -0
  16. package/dist/events/attribution-ledger.js +61 -0
  17. package/dist/index.d.ts +5 -0
  18. package/dist/index.js +5 -0
  19. package/dist/init-deposit/gitignore.js +15 -5
  20. package/dist/intake/candidates-log.d.ts +0 -1
  21. package/dist/intake/candidates-log.js +5 -2
  22. package/dist/intake/issue-ingest.d.ts +8 -0
  23. package/dist/intake/issue-ingest.js +19 -1
  24. package/dist/intake/reconcile-issues.js +9 -2
  25. package/dist/layout/resolve.d.ts +2 -2
  26. package/dist/layout/resolve.js +2 -2
  27. package/dist/lifecycle/events.js +2 -0
  28. package/dist/orchestration/subagent-monitor.js +2 -2
  29. package/dist/policy/index.d.ts +2 -1
  30. package/dist/policy/index.js +15 -2
  31. package/dist/policy/value-feedback.d.ts +56 -0
  32. package/dist/policy/value-feedback.js +284 -0
  33. package/dist/preflight-cache/evaluate.js +4 -3
  34. package/dist/scope/audit-log.js +3 -3
  35. package/dist/scope/transition.js +16 -5
  36. package/dist/session/session-start.js +20 -0
  37. package/dist/slice/record.js +3 -3
  38. package/dist/task-surface/index.js +4 -1
  39. package/dist/triage/actions/candidates-log.d.ts +4 -4
  40. package/dist/triage/actions/candidates-log.js +4 -7
  41. package/dist/triage/actions/index.js +8 -32
  42. package/dist/triage/bootstrap/gitignore.d.ts +9 -3
  43. package/dist/triage/bootstrap/gitignore.js +77 -40
  44. package/dist/triage/bootstrap/index.d.ts +1 -1
  45. package/dist/triage/bootstrap/index.js +4 -3
  46. package/dist/triage/bulk/index.js +2 -2
  47. package/dist/triage/cache-path.d.ts +41 -0
  48. package/dist/triage/cache-path.js +115 -0
  49. package/dist/triage/help/registry-data.d.ts +48 -15
  50. package/dist/triage/help/registry-data.js +86 -15
  51. package/dist/triage/index.d.ts +2 -0
  52. package/dist/triage/index.js +2 -0
  53. package/dist/triage/queue/audit.js +2 -2
  54. package/dist/triage/queue/cache.js +2 -2
  55. package/dist/triage/reconcile/reconcile.js +4 -3
  56. package/dist/triage/scope/mutations-core.js +3 -2
  57. package/dist/triage/subscribe/index.d.ts +1 -1
  58. package/dist/triage/subscribe/index.js +4 -3
  59. package/dist/triage/summary/index.d.ts +2 -2
  60. package/dist/triage/summary/index.js +4 -3
  61. package/dist/triage/summary/reconcilable.d.ts +1 -1
  62. package/dist/triage/summary/reconcilable.js +3 -2
  63. package/dist/triage/welcome/constants.d.ts +2 -2
  64. package/dist/triage/welcome/constants.js +2 -2
  65. package/dist/triage/welcome/prior-state.js +3 -2
  66. package/dist/triage/welcome/summary.js +5 -4
  67. package/dist/value/adoption-emit.d.ts +14 -0
  68. package/dist/value/adoption-emit.js +67 -0
  69. package/dist/value/adoption-registry.d.ts +62 -0
  70. package/dist/value/adoption-registry.js +214 -0
  71. package/dist/value/feedback-file.d.ts +67 -0
  72. package/dist/value/feedback-file.js +353 -0
  73. package/dist/value/friction-emit.d.ts +10 -0
  74. package/dist/value/friction-emit.js +24 -0
  75. package/dist/value/readback.d.ts +86 -0
  76. package/dist/value/readback.js +503 -0
  77. package/dist/vbrief-validate/decomposition.js +1 -1
  78. package/dist/wip-cap/evaluate.js +3 -0
  79. package/package.json +35 -3
@@ -1,6 +1,7 @@
1
1
  import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
2
2
  import { dirname, relative } from "node:path";
3
- import { resolveEvalPath } from "../../layout/resolve.js";
3
+ import { resolveLifecycleLayout } from "../../layout/resolve.js";
4
+ import { resolveCandidatesLogPath, resolveTriageCachePath, TRIAGE_CACHE_DIR_NAME, triageCacheRelPath, } from "../cache-path.js";
4
5
  /** POSIX-style display path for `absPath` relative to `projectRoot` (#2109). */
5
6
  function evalRelDisplay(projectRoot, absPath) {
6
7
  return relative(projectRoot, absPath).split(/[\\/]/).join("/");
@@ -10,21 +11,41 @@ export const GITIGNORE_DEFT_RUNTIME_SENTINELS = [
10
11
  ".deft/ritual-state.json",
11
12
  ".deft/last-session.json",
12
13
  ];
14
+ /** Legacy static vbrief paths kept for tests referencing the pre-#1703 constant shape. */
13
15
  export const GITIGNORE_EVAL_ENTRIES = [
14
- "vbrief/.eval/candidates.jsonl",
15
- "vbrief/.eval/summary-history.jsonl",
16
- "vbrief/.eval/scope-lifecycle.jsonl",
17
- "vbrief/.eval/decompositions/",
18
- "vbrief/.eval/doctor-state.json",
16
+ "vbrief/.triage-cache/candidates.jsonl",
17
+ "vbrief/.triage-cache/summary-history.jsonl",
18
+ "vbrief/.triage-cache/scope-lifecycle.jsonl",
19
+ "vbrief/.triage-cache/decompositions/",
20
+ "vbrief/.triage-cache/doctor-state.json",
21
+ ];
22
+ /** Layout-aware gitignore lines for triage working-set files (#1703). */
23
+ export function gitignoreTriageCacheEntries(projectRoot) {
24
+ const decomp = triageCacheRelPath(projectRoot, "decompositions");
25
+ return [
26
+ triageCacheRelPath(projectRoot, "candidates.jsonl"),
27
+ triageCacheRelPath(projectRoot, "summary-history.jsonl"),
28
+ triageCacheRelPath(projectRoot, "scope-lifecycle.jsonl"),
29
+ decomp.endsWith("/") ? decomp : `${decomp}/`,
30
+ triageCacheRelPath(projectRoot, "doctor-state.json"),
31
+ ];
32
+ }
33
+ export function gitattributesTriageCacheGlob(projectRoot) {
34
+ const layout = resolveLifecycleLayout(projectRoot);
35
+ return `${layout.artifactDir}/${TRIAGE_CACHE_DIR_NAME}/*.jsonl`;
36
+ }
37
+ export const GITATTRIBUTES_EVAL_RULE = "vbrief/.triage-cache/*.jsonl merge=union";
38
+ export const FORBIDDEN_BLANKET_EVAL_LINES = [
39
+ "vbrief/.triage-cache/",
40
+ "vbrief/.triage-cache",
41
+ "vbrief/.triage-cache/",
42
+ "vbrief/.eval",
19
43
  ];
20
- export const GITATTRIBUTES_EVAL_RULE = "vbrief/.eval/*.jsonl merge=union";
21
- export const FORBIDDEN_BLANKET_EVAL_LINES = ["vbrief/.eval/", "vbrief/.eval"];
22
- const GITATTRIBUTES_EVAL_GLOB = "vbrief/.eval/*.jsonl";
23
44
  const DEFT_CACHE_RATIONALE = "\n# Triage v1 local content cache (#845, #883). Mirrors upstream\n" +
24
45
  "# issues into .deft-cache/github-issue/<owner>/<repo>/<N>/. See\n" +
25
46
  "# docs/privacy-nfr.md for the gitignore-default + opt-in-commit-cache\n" +
26
47
  "# contract. Comment this line out to opt in to committing the cache.\n";
27
- const EVAL_ENTRIES_RATIONALE = "\n# vbrief/.eval/ tracking governance (#1144, N4 of #1119).\n" +
48
+ const EVAL_ENTRIES_RATIONALE = "\n# vbrief/.triage-cache/ tracking governance (#1144, N4 of #1119).\n" +
28
49
  "# Hybrid policy from the Current Shape comment on #1144:\n" +
29
50
  "# - candidates.jsonl -> gitignored (operator-private triage\n" +
30
51
  "# decisions; re-derive via\n" +
@@ -50,15 +71,15 @@ const EVAL_ENTRIES_RATIONALE = "\n# vbrief/.eval/ tracking governance (#1144, N4
50
71
  "# - slices.jsonl -> TRACKED (team-shared cohort records\n" +
51
72
  "# produced by slicing skills; see\n" +
52
73
  "# #1132 / D13).\n" +
53
- "# See vbrief/.eval/README.md for the full policy + merge=union\n" +
74
+ "# See vbrief/.triage-cache/README.md for the full policy + merge=union\n" +
54
75
  "# rebase note.\n";
55
- const GITATTRIBUTES_EVAL_RATIONALE = "\n# Append-only JSON-lines logs under vbrief/.eval/ use the union merge driver\n" +
76
+ const GITATTRIBUTES_EVAL_RATIONALE = "\n# Append-only JSON-lines logs under vbrief/.triage-cache/ use the union merge driver\n" +
56
77
  "# (#1144, N4 of #1119). Both branches' appended lines are concatenated on\n" +
57
78
  "# auto-merge so single-operator rebases of two append branches resolve\n" +
58
79
  "# without manual conflict surgery. Note: merge=union does NOT dedupe; see\n" +
59
- "# vbrief/.eval/README.md for the operator-facing semantics.\n";
60
- const EVAL_ENTRIES_RATIONALE_SENTINEL = "# vbrief/.eval/ tracking governance (#1144, N4 of #1119).";
61
- export const EVAL_README_BODY = `# \`vbrief/.eval/\` -- triage + slicing evaluation artefacts
80
+ "# vbrief/.triage-cache/README.md for the operator-facing semantics.\n";
81
+ const EVAL_ENTRIES_RATIONALE_SENTINEL = "# vbrief/.triage-cache/ tracking governance (#1144, N4 of #1119).";
82
+ export const EVAL_README_BODY = `# \`vbrief/.triage-cache/\` -- triage working-set artefacts
62
83
 
63
84
  This directory holds the append-only JSON-lines logs that the triage and
64
85
  slicing skills emit. The framework governs which files in here are tracked
@@ -75,9 +96,9 @@ by git versus gitignored using a **hybrid policy** (#1144, child of #1119).
75
96
  | \`decompositions/\` | No -- **gitignored** | Temporary story-decomposition proposal drafts. These JSON drafts are local scratch artifacts, not vBRIEFs; generated child story vBRIEFs are created by \`task scope:decompose\` in lifecycle folders, defaulting to \`vbrief/pending/\`. |
76
97
  | \`doctor-state.json\` | No -- **gitignored** | Per-machine \`task doctor\` throttle state (last exit code + timestamps) persisted to gate the 24h/4h re-probe window (#1308 / #1464). Local to each clone; never committed. |
77
98
 
78
- The gitignore lines live in the repo-root \`.gitignore\` (\`vbrief/.eval/candidates.jsonl\`,
79
- \`vbrief/.eval/summary-history.jsonl\`, \`vbrief/.eval/scope-lifecycle.jsonl\`,
80
- \`vbrief/.eval/decompositions/\`, and \`vbrief/.eval/doctor-state.json\`). All paths
99
+ The gitignore lines live in the repo-root \`.gitignore\` (\`vbrief/.triage-cache/candidates.jsonl\`,
100
+ \`vbrief/.triage-cache/summary-history.jsonl\`, \`vbrief/.triage-cache/scope-lifecycle.jsonl\`,
101
+ \`vbrief/.triage-cache/decompositions/\`, and \`vbrief/.triage-cache/doctor-state.json\`). All paths
81
102
  not listed above remain committed by default.
82
103
 
83
104
  ## Fresh-clone regeneration
@@ -90,7 +111,7 @@ task triage:bootstrap
90
111
  \`\`\`
91
112
 
92
113
  The bootstrap path detects the missing file, runs the auto-classifier, and
93
- writes a fresh \`vbrief/.eval/candidates.jsonl\`. It does NOT touch the tracked
114
+ writes a fresh \`vbrief/.triage-cache/candidates.jsonl\`. It does NOT touch the tracked
94
115
  \`slices.jsonl\`; cohort records remain a team-shared resource.
95
116
 
96
117
  ## \`merge=union\` policy for \`*.jsonl\`
@@ -98,7 +119,7 @@ writes a fresh \`vbrief/.eval/candidates.jsonl\`. It does NOT touch the tracked
98
119
  The repo-root \`.gitattributes\` declares:
99
120
 
100
121
  \`\`\`
101
- vbrief/.eval/*.jsonl merge=union
122
+ vbrief/.triage-cache/*.jsonl merge=union
102
123
  \`\`\`
103
124
 
104
125
  The \`union\` merge driver concatenates both sides' appended lines on
@@ -131,6 +152,12 @@ operators should know:
131
152
  - \`.gitattributes\` -- the \`merge=union\` rule.
132
153
  - \`scripts/candidates_log.py\` -- the writer for \`candidates.jsonl\`.
133
154
  `;
155
+ /** Layout-aware triage-cache README body for the active lifecycle tree (#2344 / #2349). */
156
+ export function generateTriageCacheReadmeBody(projectRoot) {
157
+ const layout = resolveLifecycleLayout(projectRoot);
158
+ const triagePrefix = `${layout.artifactDir}/${TRIAGE_CACHE_DIR_NAME}`;
159
+ return EVAL_README_BODY.replaceAll("vbrief/.triage-cache", triagePrefix);
160
+ }
134
161
  function stepOutcome(name, ok, message, details = {}, error = null) {
135
162
  return { name, ok, message, error, details };
136
163
  }
@@ -217,10 +244,10 @@ export function stepEnsureGitignoreEntry(projectRoot) {
217
244
  function formatBlanketWarning(blanketPresent) {
218
245
  if (!blanketPresent)
219
246
  return "";
220
- return (" WARNING: stale blanket vbrief/.eval/ line detected in .gitignore -- " +
247
+ return (" WARNING: stale blanket vbrief/.triage-cache/ line detected in .gitignore -- " +
221
248
  "remove it manually (it hides tracked slices.jsonl from git per #1251)");
222
249
  }
223
- function gitattributesHasEvalMergeUnion(body) {
250
+ function gitattributesHasEvalMergeUnion(body, glob) {
224
251
  for (const raw of body.split("\n")) {
225
252
  const stripped = raw.trim();
226
253
  if (stripped.length === 0 || stripped.startsWith("#"))
@@ -228,14 +255,14 @@ function gitattributesHasEvalMergeUnion(body) {
228
255
  const parts = stripped.split(/\s+/);
229
256
  if (parts.length === 0)
230
257
  continue;
231
- if (parts[0] !== GITATTRIBUTES_EVAL_GLOB)
258
+ if (parts[0] !== glob)
232
259
  continue;
233
260
  if (parts.slice(1).includes("merge=union"))
234
261
  return true;
235
262
  }
236
263
  return false;
237
264
  }
238
- function ensureGitignoreSelectiveEntries(gitignorePath, stepName) {
265
+ function ensureGitignoreSelectiveEntries(gitignorePath, stepName, entries) {
239
266
  let existing;
240
267
  try {
241
268
  existing = readFileSync(gitignorePath, { encoding: "utf8" });
@@ -249,7 +276,7 @@ function ensureGitignoreSelectiveEntries(gitignorePath, stepName) {
249
276
  .filter((stripped) => stripped.length > 0));
250
277
  const blanketPresent = FORBIDDEN_BLANKET_EVAL_LINES.some((forbidden) => existingLines.has(forbidden));
251
278
  const rationaleAlreadyPresent = existing.includes(EVAL_ENTRIES_RATIONALE_SENTINEL);
252
- const missing = GITIGNORE_EVAL_ENTRIES.filter((entry) => !existingLines.has(entry));
279
+ const missing = entries.filter((entry) => !existingLines.has(entry));
253
280
  const blanketWarning = formatBlanketWarning(blanketPresent);
254
281
  if (missing.length === 0) {
255
282
  return stepOutcome(stepName, true, `all #1144 selective entries already in .gitignore (no-op)${blanketWarning}`, {
@@ -277,7 +304,7 @@ function ensureGitignoreSelectiveEntries(gitignorePath, stepName) {
277
304
  rationale_already_present: rationaleAlreadyPresent,
278
305
  });
279
306
  }
280
- function ensureGitattributesMergeUnion(gitattributesPath, stepName) {
307
+ function ensureGitattributesMergeUnion(gitattributesPath, stepName, glob, ruleLine) {
281
308
  if (existsSync(gitattributesPath)) {
282
309
  let existing;
283
310
  try {
@@ -286,32 +313,39 @@ function ensureGitattributesMergeUnion(gitattributesPath, stepName) {
286
313
  catch (exc) {
287
314
  return stepOutcome(stepName, false, "could not read .gitattributes", { gitattributes_appended: false }, String(exc));
288
315
  }
289
- if (gitattributesHasEvalMergeUnion(existing)) {
290
- return stepOutcome(stepName, true, "vbrief/.eval/*.jsonl merge=union already in .gitattributes (no-op)", {
316
+ if (gitattributesHasEvalMergeUnion(existing, glob)) {
317
+ return stepOutcome(stepName, true, `${glob} merge=union already in .gitattributes (no-op)`, {
291
318
  gitattributes_appended: false,
292
319
  gitattributes_already_present: true,
293
320
  });
294
321
  }
295
322
  const suffix = existing.endsWith("\n") || existing === "" ? "" : "\n";
296
- const newContent = `${existing + suffix + GITATTRIBUTES_EVAL_RATIONALE + GITATTRIBUTES_EVAL_RULE}\n`;
323
+ const newContent = `${existing + suffix + GITATTRIBUTES_EVAL_RATIONALE + ruleLine}\n`;
297
324
  try {
298
325
  writeFileSync(gitattributesPath, newContent, { encoding: "utf8" });
299
326
  }
300
327
  catch (exc) {
301
328
  return stepOutcome(stepName, false, "could not write .gitattributes", { gitattributes_appended: false }, String(exc));
302
329
  }
303
- return stepOutcome(stepName, true, "appended vbrief/.eval/*.jsonl merge=union to .gitattributes", { gitattributes_appended: true, gitattributes_created: false });
330
+ return stepOutcome(stepName, true, `appended ${glob} merge=union to .gitattributes`, {
331
+ gitattributes_appended: true,
332
+ gitattributes_created: false,
333
+ });
304
334
  }
305
- const newContent = `${GITATTRIBUTES_EVAL_RATIONALE + GITATTRIBUTES_EVAL_RULE}\n`;
335
+ const newContent = `${GITATTRIBUTES_EVAL_RATIONALE + ruleLine}\n`;
306
336
  try {
307
337
  writeFileSync(gitattributesPath, newContent, { encoding: "utf8" });
308
338
  }
309
339
  catch (exc) {
310
340
  return stepOutcome(stepName, false, "could not create .gitattributes", { gitattributes_appended: false }, String(exc));
311
341
  }
312
- return stepOutcome(stepName, true, "created .gitattributes with vbrief/.eval/*.jsonl merge=union", { gitattributes_appended: true, gitattributes_created: true });
342
+ return stepOutcome(stepName, true, `created .gitattributes with ${glob} merge=union`, {
343
+ gitattributes_appended: true,
344
+ gitattributes_created: true,
345
+ });
313
346
  }
314
- function ensureEvalReadme(readmePath, readmeRel, stepName) {
347
+ function ensureEvalReadme(options) {
348
+ const { projectRoot, readmePath, readmeRel, stepName } = options;
315
349
  try {
316
350
  readFileSync(readmePath, { encoding: "utf8" });
317
351
  return stepOutcome(stepName, true, `${readmeRel} already present (no-op)`, {
@@ -324,7 +358,7 @@ function ensureEvalReadme(readmePath, readmeRel, stepName) {
324
358
  }
325
359
  try {
326
360
  mkdirSync(dirname(readmePath), { recursive: true });
327
- writeFileSync(readmePath, EVAL_README_BODY, { encoding: "utf8" });
361
+ writeFileSync(readmePath, generateTriageCacheReadmeBody(projectRoot), { encoding: "utf8" });
328
362
  }
329
363
  catch (exc) {
330
364
  return stepOutcome(stepName, false, `could not create ${readmePath}`, { readme_created: false }, String(exc));
@@ -339,23 +373,26 @@ export function stepEnsureGitignoreEvalEntries(projectRoot) {
339
373
  const gitattributesPath = `${projectRoot}/.gitattributes`;
340
374
  // Layout-aware (#2109): resolve the README under the active lifecycle `.eval`
341
375
  // dir (xbrief/ when migrated, else vbrief/) instead of a hardcoded vbrief/ path.
342
- const readmePath = resolveEvalPath(projectRoot, "README.md");
376
+ const readmePath = resolveTriageCachePath(projectRoot, "README.md");
343
377
  const readmeRel = evalRelDisplay(projectRoot, readmePath);
378
+ const entries = gitignoreTriageCacheEntries(projectRoot);
379
+ const glob = gitattributesTriageCacheGlob(projectRoot);
380
+ const ruleLine = `${glob} merge=union`;
344
381
  const stepName = "ensure_gitignore_eval_entries";
345
382
  const details = {};
346
- const giResult = ensureGitignoreSelectiveEntries(gitignorePath, stepName);
383
+ const giResult = ensureGitignoreSelectiveEntries(gitignorePath, stepName, entries);
347
384
  if (!giResult.ok) {
348
385
  Object.assign(details, giResult.details);
349
386
  return stepOutcome(stepName, false, giResult.message, details, giResult.error ?? null);
350
387
  }
351
388
  Object.assign(details, giResult.details);
352
- const gaResult = ensureGitattributesMergeUnion(gitattributesPath, stepName);
389
+ const gaResult = ensureGitattributesMergeUnion(gitattributesPath, stepName, glob, ruleLine);
353
390
  if (!gaResult.ok) {
354
391
  Object.assign(details, gaResult.details);
355
392
  return stepOutcome(stepName, false, gaResult.message, details, gaResult.error ?? null);
356
393
  }
357
394
  Object.assign(details, gaResult.details);
358
- const rdResult = ensureEvalReadme(readmePath, readmeRel, stepName);
395
+ const rdResult = ensureEvalReadme({ projectRoot, readmePath, readmeRel, stepName });
359
396
  if (!rdResult.ok) {
360
397
  Object.assign(details, rdResult.details);
361
398
  return stepOutcome(stepName, false, rdResult.message, details, rdResult.error ?? null);
@@ -386,11 +423,11 @@ export function stepEnsureGitignoreEvalEntries(projectRoot) {
386
423
  message += formatBlanketWarning(Boolean(details.blanket_present));
387
424
  return stepOutcome(stepName, true, message, details);
388
425
  }
389
- /** Ensure `vbrief/.eval/candidates.jsonl` exists (#1240 option A). */
426
+ /** Ensure `vbrief/.triage-cache/candidates.jsonl` exists (#1240 option A). */
390
427
  export function stepSeedCandidatesLog(projectRoot) {
391
428
  // Layout-aware (#2109): seed under the active lifecycle `.eval` dir (xbrief/
392
429
  // when migrated, else vbrief/) instead of a hardcoded vbrief/ path.
393
- const auditPath = resolveEvalPath(projectRoot, "candidates.jsonl");
430
+ const auditPath = resolveCandidatesLogPath(projectRoot);
394
431
  const auditRel = evalRelDisplay(projectRoot, auditPath);
395
432
  const auditDir = dirname(auditPath);
396
433
  try {
@@ -2,7 +2,7 @@ import type { BootstrapResult, CacheModule, RunBootstrapOptions, StepOutcome } f
2
2
  export * from "./gitignore.js";
3
3
  export * from "./types.js";
4
4
  export declare const CACHE_DIR_NAME = ".deft-cache";
5
- export declare const AUDIT_LOG_RELPATH = "vbrief/.eval/candidates.jsonl";
5
+ export declare const AUDIT_LOG_RELPATH = "vbrief/.triage-cache/candidates.jsonl";
6
6
  export declare const BACKFILL_FOLDERS: readonly ["proposed", "pending", "active"];
7
7
  export declare const BOOTSTRAP_ACTOR = "agent:bootstrap";
8
8
  export declare const DEFAULT_FETCH_TIMEOUT_S = 3600;
@@ -3,14 +3,15 @@ import { randomUUID } from "node:crypto";
3
3
  import { existsSync, mkdirSync, readdirSync, readFileSync, writeFileSync } from "node:fs";
4
4
  import { dirname, join, resolve } from "node:path";
5
5
  import { promisify } from "node:util";
6
- import { hasArtifactSuffix, resolveEvalPath, resolveLifecycleRoot } from "../../layout/resolve.js";
6
+ import { hasArtifactSuffix, resolveLifecycleRoot } from "../../layout/resolve.js";
7
7
  import { SUBPROCESS_MAX_BUFFER } from "../../subprocess/max-buffer.js";
8
+ import { resolveCandidatesLogPath } from "../cache-path.js";
8
9
  import { stepEnsureGitignoreEntry, stepEnsureGitignoreEvalEntries, stepSeedCandidatesLog, } from "./gitignore.js";
9
10
  import { PROGRESS_DEFAULT } from "./types.js";
10
11
  export * from "./gitignore.js";
11
12
  export * from "./types.js";
12
13
  export const CACHE_DIR_NAME = ".deft-cache";
13
- export const AUDIT_LOG_RELPATH = "vbrief/.eval/candidates.jsonl";
14
+ export const AUDIT_LOG_RELPATH = "vbrief/.triage-cache/candidates.jsonl";
14
15
  export const BACKFILL_FOLDERS = ["proposed", "pending", "active"];
15
16
  export const BOOTSTRAP_ACTOR = "agent:bootstrap";
16
17
  export const DEFAULT_FETCH_TIMEOUT_S = 3600;
@@ -377,7 +378,7 @@ export function stepBackfillAuditLog(projectRoot, repo, options = {}) {
377
378
  if (!existsSync(vbriefRoot)) {
378
379
  return stepOutcome("backfill_audit_log", true, `skipped (no vbrief/ directory under ${projectRoot})`, { skipped: "no-vbrief" });
379
380
  }
380
- const auditPath = resolveEvalPath(projectRoot, "candidates.jsonl");
381
+ const auditPath = resolveCandidatesLogPath(projectRoot);
381
382
  const alreadyLogged = existingAuditIssueNumbers(auditPath);
382
383
  const nowIso = options.nowIso ?? nowIsoDefault;
383
384
  const appendEntry = options.appendAuditEntry ?? appendAuditEntryDefault;
@@ -1,8 +1,8 @@
1
1
  import { spawnSync } from "node:child_process";
2
2
  import { existsSync, readdirSync, readFileSync } from "node:fs";
3
3
  import { dirname, join } from "node:path";
4
- import { resolveEvalPath } from "../../layout/resolve.js";
5
4
  import { createDefaultDeps, accept as nativeAccept, deferAction as nativeDefer, needsAc as nativeNeedsAc, reject as nativeReject, } from "../actions/index.js";
5
+ import { resolveCandidatesLogPath } from "../cache-path.js";
6
6
  export const ACTION_FN_NAMES = {
7
7
  accept: "accept",
8
8
  reject: "reject",
@@ -377,7 +377,7 @@ export function createFilesystemCacheModule() {
377
377
  CacheError,
378
378
  };
379
379
  }
380
- export function createFilesystemCandidatesLogModule(logPath = resolveEvalPath(process.cwd(), "candidates.jsonl")) {
380
+ export function createFilesystemCandidatesLogModule(logPath = resolveCandidatesLogPath(process.cwd())) {
381
381
  return {
382
382
  readAll(options) {
383
383
  if (!existsSync(logPath)) {
@@ -0,0 +1,41 @@
1
+ /**
2
+ * Layout-aware triage working-set cache paths (#1703 namespace cleanup).
3
+ *
4
+ * Triage append-only logs and scratch dirs live under `.triage-cache/` so the
5
+ * `.eval/` namespace can be reclaimed for version-eval results (#1703 Tier 2).
6
+ */
7
+ /** Directory name for the triage working-set cache (not version-eval results). */
8
+ export declare const TRIAGE_CACHE_DIR_NAME = ".triage-cache";
9
+ /** Legacy directory that previously held triage cache files before #1703. */
10
+ export declare const LEGACY_TRIAGE_EVAL_DIR_NAME = ".eval";
11
+ /** Known triage-cache file basenames migrated off the legacy `.eval/` tree. */
12
+ export declare const TRIAGE_CACHE_FILE_NAMES: readonly ["candidates.jsonl", "summary-history.jsonl", "scope-lifecycle.jsonl", "subscription-history.jsonl", "slices.jsonl", "doctor-state.json", "README.md"];
13
+ /** Known triage-cache directory names migrated off the legacy `.eval/` tree. */
14
+ export declare const TRIAGE_CACHE_DIR_NAMES: readonly ["decompositions"];
15
+ export interface TriageCacheMigrationResult {
16
+ readonly migratedFiles: readonly string[];
17
+ readonly skippedFiles: readonly string[];
18
+ readonly migratedDirs: readonly string[];
19
+ readonly regeneratedFiles: readonly string[];
20
+ readonly removedLegacyFiles: readonly string[];
21
+ }
22
+ /** Absolute path to the layout-aware `.triage-cache/` directory. */
23
+ export declare function resolveTriageCacheDir(projectRoot: string): string;
24
+ /** POSIX-style path relative to project root (e.g. `xbrief/.triage-cache/foo`). */
25
+ export declare function triageCacheRelPath(projectRoot: string, ...segments: string[]): string;
26
+ /**
27
+ * Idempotently move triage working-set artefacts from legacy `.eval/` into
28
+ * `.triage-cache/` when the new location is absent.
29
+ */
30
+ export declare function migrateLegacyTriageCacheFromEval(projectRoot: string): TriageCacheMigrationResult;
31
+ /** Resolve a path under `.triage-cache/`, migrating legacy `.eval/` files first. */
32
+ export declare function resolveTriageCachePath(projectRoot: string, ...segments: string[]): string;
33
+ /** Display helper: project-root-relative POSIX path for logs and gitignore copy. */
34
+ export declare function triageCacheDisplayPath(projectRoot: string, absPath: string): string;
35
+ /** Back-compat display constant; resolution flows through `resolveTriageCachePath`. */
36
+ export declare const TRIAGE_CANDIDATES_LOG_REL_PATH = "vbrief/.triage-cache/candidates.jsonl";
37
+ /** Layout-aware candidates audit-log path. */
38
+ export declare function resolveCandidatesLogPath(projectRoot: string): string;
39
+ /** Ensure the triage cache directory exists (post-migration). */
40
+ export declare function ensureTriageCacheDir(projectRoot: string): string;
41
+ //# sourceMappingURL=cache-path.d.ts.map
@@ -0,0 +1,115 @@
1
+ /**
2
+ * Layout-aware triage working-set cache paths (#1703 namespace cleanup).
3
+ *
4
+ * Triage append-only logs and scratch dirs live under `.triage-cache/` so the
5
+ * `.eval/` namespace can be reclaimed for version-eval results (#1703 Tier 2).
6
+ */
7
+ import { existsSync, mkdirSync, renameSync, unlinkSync, writeFileSync } from "node:fs";
8
+ import { join, relative } from "node:path";
9
+ import { resolveEvalDir, resolveLifecycleLayout, resolveLifecycleRoot } from "../layout/resolve.js";
10
+ import { generateTriageCacheReadmeBody } from "./bootstrap/gitignore.js";
11
+ /** Directory name for the triage working-set cache (not version-eval results). */
12
+ export const TRIAGE_CACHE_DIR_NAME = ".triage-cache";
13
+ /** Legacy directory that previously held triage cache files before #1703. */
14
+ export const LEGACY_TRIAGE_EVAL_DIR_NAME = ".eval";
15
+ /** Known triage-cache file basenames migrated off the legacy `.eval/` tree. */
16
+ export const TRIAGE_CACHE_FILE_NAMES = [
17
+ "candidates.jsonl",
18
+ "summary-history.jsonl",
19
+ "scope-lifecycle.jsonl",
20
+ "subscription-history.jsonl",
21
+ "slices.jsonl",
22
+ "doctor-state.json",
23
+ "README.md",
24
+ ];
25
+ /** Known triage-cache directory names migrated off the legacy `.eval/` tree. */
26
+ export const TRIAGE_CACHE_DIR_NAMES = ["decompositions"];
27
+ /** Absolute path to the layout-aware `.triage-cache/` directory. */
28
+ export function resolveTriageCacheDir(projectRoot) {
29
+ return join(resolveLifecycleRoot(projectRoot), TRIAGE_CACHE_DIR_NAME);
30
+ }
31
+ /** POSIX-style path relative to project root (e.g. `xbrief/.triage-cache/foo`). */
32
+ export function triageCacheRelPath(projectRoot, ...segments) {
33
+ const layout = resolveLifecycleLayout(projectRoot);
34
+ return [layout.artifactDir, TRIAGE_CACHE_DIR_NAME, ...segments].join("/");
35
+ }
36
+ /**
37
+ * Idempotently move triage working-set artefacts from legacy `.eval/` into
38
+ * `.triage-cache/` when the new location is absent.
39
+ */
40
+ export function migrateLegacyTriageCacheFromEval(projectRoot) {
41
+ const legacyDir = resolveEvalDir(projectRoot);
42
+ const targetDir = resolveTriageCacheDir(projectRoot);
43
+ const migratedFiles = [];
44
+ const skippedFiles = [];
45
+ const migratedDirs = [];
46
+ const regeneratedFiles = [];
47
+ const removedLegacyFiles = [];
48
+ if (!existsSync(legacyDir)) {
49
+ return { migratedFiles, skippedFiles, migratedDirs, regeneratedFiles, removedLegacyFiles };
50
+ }
51
+ mkdirSync(targetDir, { recursive: true });
52
+ for (const name of TRIAGE_CACHE_FILE_NAMES) {
53
+ const legacyPath = join(legacyDir, name);
54
+ const targetPath = join(targetDir, name);
55
+ if (!existsSync(legacyPath)) {
56
+ continue;
57
+ }
58
+ if (name === "README.md") {
59
+ if (existsSync(targetPath)) {
60
+ unlinkSync(legacyPath);
61
+ removedLegacyFiles.push(name);
62
+ }
63
+ else {
64
+ writeFileSync(targetPath, generateTriageCacheReadmeBody(projectRoot), "utf8");
65
+ unlinkSync(legacyPath);
66
+ regeneratedFiles.push(name);
67
+ }
68
+ continue;
69
+ }
70
+ if (existsSync(targetPath)) {
71
+ unlinkSync(legacyPath);
72
+ removedLegacyFiles.push(name);
73
+ continue;
74
+ }
75
+ renameSync(legacyPath, targetPath);
76
+ migratedFiles.push(name);
77
+ }
78
+ for (const name of TRIAGE_CACHE_DIR_NAMES) {
79
+ const legacyPath = join(legacyDir, name);
80
+ const targetPath = join(targetDir, name);
81
+ if (!existsSync(legacyPath)) {
82
+ continue;
83
+ }
84
+ if (existsSync(targetPath)) {
85
+ skippedFiles.push(`${name}/`);
86
+ continue;
87
+ }
88
+ renameSync(legacyPath, targetPath);
89
+ migratedDirs.push(name);
90
+ }
91
+ return { migratedFiles, skippedFiles, migratedDirs, regeneratedFiles, removedLegacyFiles };
92
+ }
93
+ /** Resolve a path under `.triage-cache/`, migrating legacy `.eval/` files first. */
94
+ export function resolveTriageCachePath(projectRoot, ...segments) {
95
+ migrateLegacyTriageCacheFromEval(projectRoot);
96
+ return join(resolveTriageCacheDir(projectRoot), ...segments);
97
+ }
98
+ /** Display helper: project-root-relative POSIX path for logs and gitignore copy. */
99
+ export function triageCacheDisplayPath(projectRoot, absPath) {
100
+ return relative(projectRoot, absPath).split(/[\\/]/).join("/");
101
+ }
102
+ /** Back-compat display constant; resolution flows through `resolveTriageCachePath`. */
103
+ export const TRIAGE_CANDIDATES_LOG_REL_PATH = "vbrief/.triage-cache/candidates.jsonl";
104
+ /** Layout-aware candidates audit-log path. */
105
+ export function resolveCandidatesLogPath(projectRoot) {
106
+ return resolveTriageCachePath(projectRoot, "candidates.jsonl");
107
+ }
108
+ /** Ensure the triage cache directory exists (post-migration). */
109
+ export function ensureTriageCacheDir(projectRoot) {
110
+ migrateLegacyTriageCacheFromEval(projectRoot);
111
+ const dir = resolveTriageCacheDir(projectRoot);
112
+ mkdirSync(dir, { recursive: true });
113
+ return dir;
114
+ }
115
+ //# sourceMappingURL=cache-path.js.map
@@ -5,7 +5,7 @@ export declare const registryData: {
5
5
  readonly name: "task triage:summary";
6
6
  readonly summary: "One-line state for session-start ritual";
7
7
  readonly refs: "(D2 / #1122)";
8
- readonly description: "Emit the one-line triage state consumed by the session-start ritual. Always exits 0 (status surface, not a gate); appends a JSONL record to vbrief/.eval/summary-history.jsonl for observability.";
8
+ readonly description: "Emit the one-line triage state consumed by the session-start ritual. Always exits 0 (status surface, not a gate); appends a JSONL record to vbrief/.triage-cache/summary-history.jsonl for observability.";
9
9
  readonly usage: "task triage:summary [-- --json] [--no-history]";
10
10
  readonly flags: readonly [readonly ["--json", "(off)", "Emit the structured record as JSON instead of the one-liner."], readonly ["--no-history", "(off)", "Suppress the history sidecar append (test-only)."], readonly ["--project-root PATH", "(cwd)", "Project root override (Taskfile threads USER_WORKING_DIR)."]];
11
11
  readonly examples: readonly ["task triage:summary", "task triage:summary -- --json | jq"];
@@ -203,7 +203,7 @@ export declare const registryData: {
203
203
  readonly name: "task triage:reconcile";
204
204
  readonly summary: "Self-heal audit log from on-disk vBRIEFs";
205
205
  readonly refs: "(#1468)";
206
- readonly description: "Idempotent repair verb: derive missing `accept` decisions for proposed/pending/active vBRIEFs that carry an x-vbrief/github-issue reference but have no entry in vbrief/.eval/candidates.jsonl. Recovers triage state after the gitignored audit log is reset/lost (#1464) without a full cache re-fetch. Never overrides an existing decision, so a re-run is a no-op.";
206
+ readonly description: "Idempotent repair verb: derive missing `accept` decisions for proposed/pending/active vBRIEFs that carry an x-vbrief/github-issue reference but have no entry in vbrief/.triage-cache/candidates.jsonl. Recovers triage state after the gitignored audit log is reset/lost (#1464) without a full cache re-fetch. Never overrides an existing decision, so a re-run is a no-op.";
207
207
  readonly usage: "task triage:reconcile [-- --repo owner/name] [--dry-run] [--json]";
208
208
  readonly flags: readonly [readonly ["--repo owner/name", "(ref URI / git remote)", "Fallback repo for refs lacking owner/name."], readonly ["--dry-run", "(off)", "Report what would be restored without writing."], readonly ["--json", "(off)", "Structured JSON output."]];
209
209
  readonly examples: readonly ["task triage:reconcile -- --dry-run", "task triage:reconcile -- --repo deftai/directive"];
@@ -280,7 +280,7 @@ export declare const registryData: {
280
280
  readonly name: "task triage:subscribe";
281
281
  readonly summary: "Add label/milestone/issue to subscription";
282
282
  readonly refs: "(D14 / #1133)";
283
- readonly description: "Subscribe to a label / milestone / issue by appending a rule to plan.policy.triageScope[]. Emits a JSONL audit record to vbrief/.eval/subscription-history.jsonl.";
283
+ readonly description: "Subscribe to a label / milestone / issue by appending a rule to plan.policy.triageScope[]. Emits a JSONL audit record to vbrief/.triage-cache/subscription-history.jsonl.";
284
284
  readonly usage: "task triage:subscribe -- (--label=L | --milestone=M | --issue=N)";
285
285
  readonly flags: readonly [readonly ["--label L", "(none)", "Subscribe to a label."], readonly ["--milestone M", "(none)", "Subscribe to a milestone."], readonly ["--issue N", "(none)", "Subscribe to a single issue."]];
286
286
  readonly examples: readonly ["task triage:subscribe -- --label='area:swarm'", "task triage:subscribe -- --milestone='v0.32.0'"];
@@ -335,7 +335,7 @@ export declare const registryData: {
335
335
  readonly name: "task triage:audit-log:rotate";
336
336
  readonly summary: "Rotate candidates.jsonl when bounded";
337
337
  readonly refs: "(D20, coming)";
338
- readonly description: "Rotate vbrief/.eval/candidates.jsonl when it exceeds the configured bound. Compacts terminal entries and preserves the open-work tail.";
338
+ readonly description: "Rotate vbrief/.triage-cache/candidates.jsonl when it exceeds the configured bound. Compacts terminal entries and preserves the open-work tail.";
339
339
  readonly usage: "task triage:audit-log:rotate [-- --max-lines N]";
340
340
  readonly flags: readonly [readonly ["--max-lines N", "(consumer default)", "Bound at which rotation fires."]];
341
341
  readonly examples: readonly ["task triage:audit-log:rotate -- --max-lines 10000"];
@@ -344,14 +344,47 @@ export declare const registryData: {
344
344
  };
345
345
  readonly "task triage:metrics": {
346
346
  readonly name: "task triage:metrics";
347
- readonly summary: "Trend lines from summary-history.jsonl";
348
- readonly refs: "(D17, coming)";
349
- readonly description: "Print trend lines computed from vbrief/.eval/summary-history.jsonl: decisions-per-day, defer/accept ratio, stale-defer drift, etc.";
347
+ readonly summary: "Attributed-value trend from the events ledger";
348
+ readonly refs: "(#1709)";
349
+ readonly description: "Report value-feedback attribution trends from .deft-cache/events.jsonl: total signal count plus per-class (value, bypass, adoption, friction) and per-event breakdowns over a time window. Alias of the value:show handler. Requires plan.policy.valueFeedback.enabled (default OFF) — exits blocked when disabled; an empty ledger prints a no-signals message. In the maintainer repo, skipped unless DEFT_VALUE_SELF_DOGFOOD=1.";
350
350
  readonly usage: "task triage:metrics [-- --window=7d] [--format=text|json]";
351
- readonly flags: readonly [readonly ["--window WINDOW", "7d", "Time window over which to aggregate."], readonly ["--format text|json", "text", "Output shape."]];
352
- readonly examples: readonly ["task triage:metrics -- --window 30d"];
353
- readonly see_also: readonly ["task triage:summary", "#1119 / D17"];
354
- readonly placeholder: true;
351
+ readonly flags: readonly [readonly ["--window WINDOW", "7d", "Time window (e.g. 7d, 30d, 24h)."], readonly ["--format text|json", "text", "Output shape (json emits the full trend object)."]];
352
+ readonly examples: readonly ["task triage:metrics", "task triage:metrics -- --window=30d --format=json"];
353
+ readonly see_also: readonly ["task policy:show --field=valueFeedback", "task policy:enable-value-feedback -- --confirm", "#1709"];
354
+ readonly placeholder: false;
355
+ };
356
+ readonly "task eval:health": {
357
+ readonly name: "task eval:health";
358
+ readonly summary: "Tier 0 static framework health score";
359
+ readonly refs: "(#1703)";
360
+ readonly description: "Aggregate static self-consistency gates (encoding, links, vBRIEF conformance, AGENTS.md freshness; content-manifest on framework-source trees) into a versioned 0–100 score. Detects contradictory / unsatisfiable gate pairs (#1694). Appends each run to .eval/results/health-history.jsonl. Session start may emit a budgeted [eval] advisory when health degrades.";
361
+ readonly usage: "task eval:health [-- --json] [--no-persist] [--project-root PATH]";
362
+ readonly flags: readonly [readonly ["--json", "(off)", "Emit the structured HealthReport instead of the human summary."], readonly ["--no-persist", "(off)", "Run probes without appending to the health history ledger."], readonly ["--project-root PATH", "(cwd)", "Project root override (Taskfile threads USER_WORKING_DIR)."]];
363
+ readonly examples: readonly ["task eval:health", "task eval:health -- --json"];
364
+ readonly see_also: readonly ["task eval:run", "task eval:report", "#1703"];
365
+ readonly placeholder: false;
366
+ };
367
+ readonly "task eval:run": {
368
+ readonly name: "task eval:run";
369
+ readonly summary: "Tier 2 golden corpus eval for a model";
370
+ readonly refs: "(#1703)";
371
+ readonly description: "Execute the fixed golden corpus with objective graders (CRUD schema/invention, surgical update, health fixture, rotating holdout tasks). Persists results to .eval/results/golden-runs.jsonl for champion–challenger diffs.";
372
+ readonly usage: "task eval:run -- --model MODEL [--seed N] [--directive-version V] [--harness NAME] [--json] [--no-persist]";
373
+ readonly flags: readonly [readonly ["--model MODEL", "(required)", "Model identifier for the run record."], readonly ["--seed N", "(1,2,3)", "Repeatable seed(s); pass multiple --seed flags."], readonly ["--directive-version V", "(engine version)", "Pin the directive version label."], readonly ["--harness NAME", "deterministic-fixture", "Harness label stored on the run record."], readonly ["--json", "(off)", "Emit the GoldenRunRecord JSON."], readonly ["--no-persist", "(off)", "Run without appending to golden-runs.jsonl."], readonly ["--project-root PATH", "(cwd)", "Project root override (Taskfile threads USER_WORKING_DIR)."]];
374
+ readonly examples: readonly ["task eval:run -- --model gpt-5", "task eval:run -- --model claude-sonnet --seed 1 --seed 2 --json"];
375
+ readonly see_also: readonly ["task eval:report", "task eval:health", "#1703"];
376
+ readonly placeholder: false;
377
+ };
378
+ readonly "task eval:report": {
379
+ readonly name: "task eval:report";
380
+ readonly summary: "Tier 2 champion–challenger diff with significance";
381
+ readonly refs: "(#1703)";
382
+ readonly description: "Diff two directive versions' latest golden runs for a model: primary/holdout/overall pass-rate deltas with two-proportion significance and a holdout tripwire when primary gains do not generalize (#1703 Goodhart guard).";
383
+ readonly usage: "task eval:report -- --champion V --challenger V --model MODEL [--json] [--project-root PATH]";
384
+ readonly flags: readonly [readonly ["--champion V", "(required)", "Baseline directive version."], readonly ["--challenger V", "(required)", "Candidate directive version."], readonly ["--model MODEL", "(required)", "Model identifier shared by both runs."], readonly ["--json", "(off)", "Emit the GoldenEvalReport JSON."], readonly ["--project-root PATH", "(cwd)", "Project root override (Taskfile threads USER_WORKING_DIR)."]];
385
+ readonly examples: readonly ["task eval:report -- --champion 0.58.0 --challenger 0.59.0 --model gpt-5"];
386
+ readonly see_also: readonly ["task eval:run", "task eval:health", "#1703"];
387
+ readonly placeholder: false;
355
388
  };
356
389
  readonly "task scope:promote": {
357
390
  readonly name: "task scope:promote";
@@ -368,7 +401,7 @@ export declare const registryData: {
368
401
  readonly name: "task scope:demote";
369
402
  readonly summary: "pending/ -> proposed/ (set status proposed)";
370
403
  readonly refs: "(D1 / #1121)";
371
- readonly description: "Demote a vBRIEF scope from vbrief/pending/ back to vbrief/proposed/ and append a structured audit entry (including a demote_meta block) to vbrief/.eval/scope-lifecycle.jsonl. Supports single-file and --batch (cohort shrink / cap relief) modes.";
404
+ readonly description: "Demote a vBRIEF scope from vbrief/pending/ back to vbrief/proposed/ and append a structured audit entry (including a demote_meta block) to vbrief/.triage-cache/scope-lifecycle.jsonl. Supports single-file and --batch (cohort shrink / cap relief) modes.";
372
405
  readonly usage: "task scope:demote -- <file> [--reason TEXT] | task scope:demote -- --batch [--older-than-days N]";
373
406
  readonly flags: readonly [readonly ["<file>", "(required for single)", "Path to vBRIEF."], readonly ["--batch", "(off)", "Batch mode: demote every pending older than --older-than-days."], readonly ["--older-than-days N", "45", "Batch-mode age threshold."], readonly ["--reason TEXT", "operator-requested", "Free-text reason for single-demote."], readonly ["--actor STR", "operator", "Actor identity recorded in the audit entry."]];
374
407
  readonly examples: readonly ["task scope:demote -- vbrief/pending/2026-05-19-foo.vbrief.json", "task scope:demote -- --batch --older-than-days 60"];
@@ -469,13 +502,13 @@ export declare const registryData: {
469
502
  readonly refs: "(deft-directive-decompose skill)";
470
503
  readonly description: "Validate or apply an approved epic/phase -> story decomposition draft. The draft is a temporary proposal artifact, not a vBRIEF. Writes pending child vBRIEFs and wires references back into the parent epic.";
471
504
  readonly usage: "task scope:decompose -- <parent> --draft <draft> [--check] [--date YYYY-MM-DD]";
472
- readonly flags: readonly [readonly ["<parent>", "(conditional)", "Parent epic/phase vBRIEF path; required with --draft, omit only for --check no-op."], readonly ["--draft PATH", "(required)", "Approved decomposition JSON draft; prefer vbrief/.eval/decompositions/<parent-slug>.json."], readonly ["--check", "(off)", "Validate only; do not write."], readonly ["--date YYYY-MM-DD", "today", "Creation date for generated child filenames."]];
473
- readonly examples: readonly ["task scope:decompose -- vbrief/active/epic.vbrief.json --draft vbrief/.eval/decompositions/epic.json --check"];
505
+ readonly flags: readonly [readonly ["<parent>", "(conditional)", "Parent epic/phase vBRIEF path; required with --draft, omit only for --check no-op."], readonly ["--draft PATH", "(required)", "Approved decomposition JSON draft; prefer vbrief/.triage-cache/decompositions/<parent-slug>.json."], readonly ["--check", "(off)", "Validate only; do not write."], readonly ["--date YYYY-MM-DD", "today", "Creation date for generated child filenames."]];
506
+ readonly examples: readonly ["task scope:decompose -- vbrief/active/epic.vbrief.json --draft vbrief/.triage-cache/decompositions/epic.json --check"];
474
507
  readonly see_also: readonly ["task scope:promote", "skills/deft-directive-decompose/SKILL.md"];
475
508
  readonly placeholder: false;
476
509
  };
477
510
  };
478
- readonly categoriesTriage: readonly [readonly ["Session-start", readonly ["task triage:summary", "task verify:cache-fresh"]], readonly ["State verbs (mutate audit log)", readonly ["task triage:accept", "task triage:defer", "task triage:reject", "task triage:needs-ac", "task triage:mark-duplicate", "task triage:reset", "task triage:status", "task triage:history"]], readonly ["Read verbs", readonly ["task triage:queue", "task triage:audit", "task triage:show", "task triage:scope", "task triage:scope-drift", "task triage:classify"]], readonly ["Lifecycle", readonly ["task triage:bootstrap", "task triage:welcome", "task triage:reconcile"]], readonly ["Bulk variants", readonly ["task triage:bulk-accept", "task triage:bulk-reject", "task triage:bulk-defer", "task triage:bulk-needs-ac", "task triage:refresh-active", "task triage:smoketest"]], readonly ["Subscription mutation", readonly ["task triage:subscribe", "task triage:unsubscribe"]], readonly ["Archive / rotation", readonly ["task triage:audit:prune", "task triage:archive-list", "task triage:restore-from-archive", "task triage:audit-log:rotate", "task triage:metrics"]]];
511
+ readonly categoriesTriage: readonly [readonly ["Session-start", readonly ["task triage:summary", "task verify:cache-fresh"]], readonly ["State verbs (mutate audit log)", readonly ["task triage:accept", "task triage:defer", "task triage:reject", "task triage:needs-ac", "task triage:mark-duplicate", "task triage:reset", "task triage:status", "task triage:history"]], readonly ["Read verbs", readonly ["task triage:queue", "task triage:audit", "task triage:show", "task triage:scope", "task triage:scope-drift", "task triage:classify"]], readonly ["Lifecycle", readonly ["task triage:bootstrap", "task triage:welcome", "task triage:reconcile"]], readonly ["Bulk variants", readonly ["task triage:bulk-accept", "task triage:bulk-reject", "task triage:bulk-defer", "task triage:bulk-needs-ac", "task triage:refresh-active", "task triage:smoketest"]], readonly ["Subscription mutation", readonly ["task triage:subscribe", "task triage:unsubscribe"]], readonly ["Archive / rotation", readonly ["task triage:audit:prune", "task triage:archive-list", "task triage:restore-from-archive", "task triage:audit-log:rotate", "task triage:metrics"]], readonly ["Framework eval (#1703)", readonly ["task eval:health", "task eval:run", "task eval:report"]]];
479
512
  readonly categoriesScope: readonly [readonly ["Promote / demote", readonly ["task scope:promote", "task scope:demote"]], readonly ["Activate / complete", readonly ["task scope:activate", "task scope:complete", "task scope:fail", "task scope:cancel", "task scope:block", "task scope:unblock"]], readonly ["Reversibility", readonly ["task scope:undo", "task scope:restore"]], readonly ["Decomposition", readonly ["task scope:decompose"]]];
480
513
  readonly scriptSubcommandMap: {
481
514
  readonly triage_actions: {