@deftai/directive-core 0.105.0 → 0.106.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (85) hide show
  1. package/dist/authz/classify.js +591 -34
  2. package/dist/check/named-cause.js +1 -1
  3. package/dist/forward-coverage/diff-coverage.d.ts +39 -0
  4. package/dist/forward-coverage/diff-coverage.js +112 -0
  5. package/dist/forward-coverage/diff-lines.d.ts +19 -0
  6. package/dist/forward-coverage/diff-lines.js +173 -0
  7. package/dist/forward-coverage/evaluate.d.ts +24 -9
  8. package/dist/forward-coverage/evaluate.js +125 -19
  9. package/dist/init-deposit/agent-hooks.d.ts +1 -1
  10. package/dist/init-deposit/agent-hooks.js +1 -1
  11. package/dist/intake/clause-derivation.d.ts +9 -0
  12. package/dist/intake/clause-derivation.js +30 -3
  13. package/dist/lifecycle-visible/evaluate.d.ts +98 -0
  14. package/dist/lifecycle-visible/evaluate.js +710 -0
  15. package/dist/lifecycle-visible/index.d.ts +2 -0
  16. package/dist/lifecycle-visible/index.js +2 -0
  17. package/dist/literal-acceptance/capture.js +3 -3
  18. package/dist/orchestration/judgment-policy.d.ts +13 -0
  19. package/dist/orchestration/judgment-policy.js +15 -0
  20. package/dist/orchestration/probe-session.js +13 -8
  21. package/dist/orchestration/verify-judgment-gates.d.ts +4 -0
  22. package/dist/orchestration/verify-judgment-gates.js +43 -11
  23. package/dist/policy/ceremony-dial.js +7 -7
  24. package/dist/policy/host-hooks.d.ts +20 -0
  25. package/dist/policy/host-hooks.js +121 -2
  26. package/dist/policy/org-force-on-migration.js +2 -1
  27. package/dist/policy/plan-extensions.d.ts +1 -1
  28. package/dist/policy/plan-extensions.js +2 -0
  29. package/dist/policy/product-signal.js +6 -7
  30. package/dist/policy/require-human-merge.js +8 -6
  31. package/dist/policy/resolve.d.ts +7 -2
  32. package/dist/policy/resolve.js +25 -8
  33. package/dist/policy/value-feedback.js +7 -8
  34. package/dist/preflight-cache/evaluate.d.ts +12 -0
  35. package/dist/preflight-cache/evaluate.js +15 -1
  36. package/dist/preflight-cache/index.d.ts +1 -1
  37. package/dist/preflight-cache/index.js +1 -1
  38. package/dist/product-first-done-gate/evaluate.d.ts +4 -0
  39. package/dist/product-first-done-gate/evaluate.js +46 -5
  40. package/dist/release/closed-verb-gate.d.ts +12 -0
  41. package/dist/release/closed-verb-gate.js +51 -0
  42. package/dist/release/index.d.ts +1 -0
  43. package/dist/release/index.js +1 -0
  44. package/dist/release/pipeline.js +7 -0
  45. package/dist/release/types.d.ts +12 -0
  46. package/dist/render/constants.d.ts +2 -1
  47. package/dist/render/constants.js +2 -1
  48. package/dist/render/framework-commands.js +4 -0
  49. package/dist/render/spec-validate.js +23 -12
  50. package/dist/run-summary/types.d.ts +4 -0
  51. package/dist/scope/main.js +15 -5
  52. package/dist/scope/promote-from-issue.js +5 -5
  53. package/dist/scope-provenance/evaluate.js +3 -3
  54. package/dist/session/ac-pass-banking.d.ts +5 -0
  55. package/dist/session/ac-pass-banking.js +3 -2
  56. package/dist/session/process-cost.d.ts +32 -10
  57. package/dist/session/process-cost.js +189 -1
  58. package/dist/session/product-state-hash.js +41 -24
  59. package/dist/session/ritual-entrypoint.js +16 -1
  60. package/dist/session/session-start.d.ts +6 -0
  61. package/dist/session/session-start.js +32 -2
  62. package/dist/session/verify-session-ritual.d.ts +24 -1
  63. package/dist/session/verify-session-ritual.js +89 -6
  64. package/dist/swarm/finalize-cohort-cli.d.ts +7 -2
  65. package/dist/swarm/finalize-cohort-cli.js +165 -35
  66. package/dist/swarm/finalize-cohort.d.ts +1 -0
  67. package/dist/swarm/finalize-cohort.js +14 -2
  68. package/dist/swarm/routing-set-cli.js +2 -0
  69. package/dist/swarm/routing-verify.d.ts +1 -1
  70. package/dist/swarm/routing-verify.js +2 -2
  71. package/dist/triage/bootstrap/index.js +6 -6
  72. package/dist/triage/help/registry-data.d.ts +1 -1
  73. package/dist/triage/help/registry-data.js +1 -1
  74. package/dist/triage/welcome/writers.d.ts +1 -1
  75. package/dist/triage/welcome/writers.js +10 -5
  76. package/dist/value/readback.d.ts +4 -1
  77. package/dist/value/readback.js +51 -12
  78. package/dist/vbrief-validate/schema.d.ts +4 -0
  79. package/dist/vbrief-validate/schema.js +1 -1
  80. package/dist/verify-env/agent-hook-readiness.d.ts +2 -2
  81. package/dist/verify-env/agent-hook-readiness.js +12 -8
  82. package/dist/verify-env/agent-hooks-live-probe.d.ts +5 -1
  83. package/dist/verify-env/agent-hooks-live-probe.js +26 -5
  84. package/dist/verify-env/agent-hooks.js +3 -4
  85. package/package.json +7 -3
@@ -1,5 +1,8 @@
1
- import { existsSync } from "node:fs";
1
+ import { existsSync, readdirSync } from "node:fs";
2
+ import { join } from "node:path";
2
3
  import { readCorePackageVersion } from "../engine-version.js";
4
+ import { hasArtifactSuffix } from "../layout/resolve.js";
5
+ import { readPlanSequence } from "../plan-sequence/store.js";
3
6
  import { formatFrameworkCommand } from "../render/framework-commands.js";
4
7
  import { checkActiveCliAgainstTarget, } from "./active-cli.js";
5
8
  import { defaultGitRunner, gitHead, gitIsAncestor, worktreePath } from "./git.js";
@@ -17,6 +20,64 @@ export const GATED_ENTRYPOINT_COMMANDS = {
17
20
  doctor: ["doctor"],
18
21
  cache_fresh: ["verify:cache-fresh"],
19
22
  };
23
+ /** Explicit skip flag threaded through the gated `cache_fresh` argv (#3507). */
24
+ export const SKIP_DRIFT_PROBE_FLAG = "--skip-drift-probe";
25
+ /** Explicit work-selection flag threaded through the gated `cache_fresh` argv (#3507). */
26
+ export const WORK_SELECTION_FLAG = "--work-selection";
27
+ /** Distinct ritual-state field — never `deferred_reason` (#3507). */
28
+ export const DRIFT_PROBE_SKIPPED_NO_WORK_SELECTION = "skipped-no-work-selection";
29
+ function hasActiveStoryArtifact(projectRoot) {
30
+ for (const dirName of ["xbrief", "vbrief"]) {
31
+ const activeDir = join(projectRoot, dirName, "active");
32
+ try {
33
+ for (const entry of readdirSync(activeDir, { withFileTypes: true })) {
34
+ if (entry.isFile() && hasArtifactSuffix(entry.name))
35
+ return true;
36
+ }
37
+ }
38
+ catch {
39
+ /* missing or unreadable active folder is not work selection */
40
+ }
41
+ }
42
+ return false;
43
+ }
44
+ function hasUnexhaustedPlanSequence(projectRoot) {
45
+ try {
46
+ const sequence = readPlanSequence(projectRoot);
47
+ if (sequence === null || sequence.exhausted === true)
48
+ return null;
49
+ return sequence.sequence_kind === "triage" ? "triage-queue" : "ordered-plan";
50
+ }
51
+ catch {
52
+ return null;
53
+ }
54
+ }
55
+ /**
56
+ * Default work-selection detector for the gated `cache_fresh` seam (#3507).
57
+ * Active story xBRIEF (scope:activate residue), unexhausted ordered-plan /
58
+ * triage sequence. `--for-issue` is a positive evaluate override, not this
59
+ * detector — the gated argv never carries it.
60
+ */
61
+ export function detectWorkSelection(projectRoot) {
62
+ if (hasActiveStoryArtifact(projectRoot)) {
63
+ return { inPlay: true, kind: "active-story" };
64
+ }
65
+ const planKind = hasUnexhaustedPlanSequence(projectRoot);
66
+ if (planKind !== null) {
67
+ return { inPlay: true, kind: planKind };
68
+ }
69
+ return { inPlay: false, kind: "none" };
70
+ }
71
+ export function resolveGatedEntrypointCommand(stepName, projectRoot, detect = detectWorkSelection) {
72
+ const base = [...GATED_ENTRYPOINT_COMMANDS[stepName]];
73
+ if (stepName !== "cache_fresh")
74
+ return base;
75
+ const selection = detect(projectRoot);
76
+ if (selection.inPlay) {
77
+ return [...base, WORK_SELECTION_FLAG];
78
+ }
79
+ return [...base, SKIP_DRIFT_PROBE_FLAG];
80
+ }
20
81
  function truthy(raw) {
21
82
  return new Set(["1", "true", "yes", "on"]).has((raw ?? "").trim().toLowerCase());
22
83
  }
@@ -25,6 +86,7 @@ function stepPasses(step) {
25
86
  return false;
26
87
  if (step.deferred_reason)
27
88
  return true;
89
+ // `drift_probe` is a distinct diagnostic; it must never satisfy a step (#3507).
28
90
  return step.ok === true;
29
91
  }
30
92
  function failedStepMessage(tierName, stepName, step) {
@@ -52,14 +114,29 @@ export function formatRitualRecoveryInstruction(tier = "cold") {
52
114
  }
53
115
  /**
54
116
  * Sanctioned audited defer copy for gated `cache_fresh` failure (#3506 / #3507).
55
- * The gated argv is always `["verify:cache-fresh"]`, so this is unconditional.
117
+ * Independent of the #3507 work-selection argv seam — defer is still the
118
+ * operator-audited escape, not the drift-probe skip.
56
119
  */
57
120
  export function formatCacheFreshDeferSoftPath() {
58
121
  const cmd = formatFrameworkCommand(["session:start", "--", "--defer", "cache_fresh=<reason>"]);
59
122
  return `Soft path (audited): \`${cmd}\`.`;
60
123
  }
61
- function runGatedStep(projectRoot, payload, stepName, runner, now) {
62
- const command = [...GATED_ENTRYPOINT_COMMANDS[stepName]];
124
+ function applyCacheFreshDriftProbeField(payload, command) {
125
+ if (command.includes(SKIP_DRIFT_PROBE_FLAG)) {
126
+ payload.drift_probe = DRIFT_PROBE_SKIPPED_NO_WORK_SELECTION;
127
+ return;
128
+ }
129
+ if (payload.drift_probe === DRIFT_PROBE_SKIPPED_NO_WORK_SELECTION) {
130
+ delete payload.drift_probe;
131
+ }
132
+ }
133
+ function shouldRearmDriftProbe(payload, projectRoot, detect) {
134
+ if (payload.drift_probe !== DRIFT_PROBE_SKIPPED_NO_WORK_SELECTION)
135
+ return false;
136
+ return detect(projectRoot).inPlay;
137
+ }
138
+ function runGatedStep(projectRoot, payload, stepName, runner, now, detect = detectWorkSelection) {
139
+ const command = resolveGatedEntrypointCommand(stepName, projectRoot, detect);
63
140
  const { code, stdout, stderr } = runner(command, projectRoot);
64
141
  const message = stdout.trim() || stderr.trim() || `${command[0]} exited ${code}`;
65
142
  const gated = payload.gated_steps ?? {};
@@ -71,6 +148,9 @@ function runGatedStep(projectRoot, payload, stepName, runner, now) {
71
148
  command,
72
149
  });
73
150
  payload.gated_steps = gated;
151
+ if (stepName === "cache_fresh") {
152
+ applyCacheFreshDriftProbeField(payload, command);
153
+ }
74
154
  try {
75
155
  writeRitualState(projectRoot, payload);
76
156
  }
@@ -361,6 +441,7 @@ export function verifySessionRitual(projectRoot, options = {}) {
361
441
  payload.gated_steps = gated;
362
442
  const runCmd = options.runner ?? defaultRitualRunner;
363
443
  const forced = new Set(options.forceGatedSteps ?? []);
444
+ const detect = options.detectWorkSelection ?? detectWorkSelection;
364
445
  for (const stepName of GATED_STEPS) {
365
446
  const step = gated[stepName];
366
447
  if (step?.deferred_reason && stepName !== "agent_hooks")
@@ -368,9 +449,11 @@ export function verifySessionRitual(projectRoot, options = {}) {
368
449
  // Hook readiness is a live mutation prerequisite, not a cacheable doctor
369
450
  // result. Re-run it at every gated boundary so registration/shim drift
370
451
  // cannot remain hidden behind an earlier green ritual record.
371
- if (stepName !== "agent_hooks" && stepPasses(step) && !forced.has(stepName))
452
+ const rearmDrift = stepName === "cache_fresh" && shouldRearmDriftProbe(payload, projectRoot, detect);
453
+ if (stepName !== "agent_hooks" && stepPasses(step) && !forced.has(stepName) && !rearmDrift) {
372
454
  continue;
373
- const writeError = runGatedStep(projectRoot, payload, stepName, runCmd, instant);
455
+ }
456
+ const writeError = runGatedStep(projectRoot, payload, stepName, runCmd, instant, detect);
374
457
  if (writeError !== null) {
375
458
  return {
376
459
  code: 2,
@@ -1,5 +1,10 @@
1
1
  #!/usr/bin/env node
2
- import { finalizeCohort } from "./finalize-cohort.js";
3
- export declare function parseFinalizeCohortArgv(argv: readonly string[]): Parameters<typeof finalizeCohort>[0];
2
+ import { type FinalizeCohortArgs } from "./finalize-cohort.js";
3
+ export interface ParsedFinalizeCohortArgv extends FinalizeCohortArgs {
4
+ readonly help: boolean;
5
+ readonly error: string | null;
6
+ }
7
+ export declare const FINALIZE_COHORT_USAGE = "Usage: task swarm:finalize-cohort -- [--pr <n>[,<n>...]] [--stories <ids|paths>] [options]\n\nAfter cohort PRs merge, sweep story briefs active/ -> completed/ and open the lifecycle PR.\n\nOptions:\n --pr <n>[,<n>...] Merged PR numbers (closing issues map to active stories)\n --stories <ids|paths> Explicit story tokens (repeatable)\n --repo OWNER/REPO GitHub repo (or $GH_REPO)\n --project-root <path> Project root (default: cwd)\n --base-branch <name> Sweep/PR base (default: resolved delivery branch)\n --delivery-branch <name> Delivery-branch override when policy is untyped\n --label <name> Feature-branch label\n --dry-run Print plan; no git mutation\n --no-commit Sweep without committing / opening a PR\n --no-open-pr Commit without opening a PR\n --json Machine-readable result\n -h, --help Show this help\n";
8
+ export declare function parseFinalizeCohortArgv(argv: readonly string[]): ParsedFinalizeCohortArgv;
4
9
  export declare function finalizeCohortMain(argv?: string[]): number;
5
10
  //# sourceMappingURL=finalize-cohort-cli.d.ts.map
@@ -1,67 +1,181 @@
1
1
  #!/usr/bin/env node
2
2
  import { fileURLToPath } from "node:url";
3
+ import { EXIT_CONFIG_ERROR, EXIT_OK } from "./constants.js";
3
4
  import { finalizeCohort } from "./finalize-cohort.js";
5
+ export const FINALIZE_COHORT_USAGE = `Usage: task swarm:finalize-cohort -- [--pr <n>[,<n>...]] [--stories <ids|paths>] [options]
6
+
7
+ After cohort PRs merge, sweep story briefs active/ -> completed/ and open the lifecycle PR.
8
+
9
+ Options:
10
+ --pr <n>[,<n>...] Merged PR numbers (closing issues map to active stories)
11
+ --stories <ids|paths> Explicit story tokens (repeatable)
12
+ --repo OWNER/REPO GitHub repo (or $GH_REPO)
13
+ --project-root <path> Project root (default: cwd)
14
+ --base-branch <name> Sweep/PR base (default: resolved delivery branch)
15
+ --delivery-branch <name> Delivery-branch override when policy is untyped
16
+ --label <name> Feature-branch label
17
+ --dry-run Print plan; no git mutation
18
+ --no-commit Sweep without committing / opening a PR
19
+ --no-open-pr Commit without opening a PR
20
+ --json Machine-readable result
21
+ -h, --help Show this help
22
+ `;
23
+ function equalsValue(arg, flag) {
24
+ return arg.slice(flag.length + 1);
25
+ }
26
+ function parsePrList(raw, flag, prNumbers, reject) {
27
+ if (raw.trim().length === 0) {
28
+ reject(flag);
29
+ return;
30
+ }
31
+ for (const piece of raw.split(",")) {
32
+ const trimmed = piece.trim();
33
+ if (trimmed.length === 0) {
34
+ reject(flag);
35
+ return;
36
+ }
37
+ if (!/^\d+$/.test(trimmed)) {
38
+ reject(flag);
39
+ return;
40
+ }
41
+ prNumbers.push(Number.parseInt(trimmed, 10));
42
+ }
43
+ }
4
44
  export function parseFinalizeCohortArgv(argv) {
5
45
  const prNumbers = [];
6
46
  const storyTokens = [];
7
47
  let repo = null;
8
48
  let projectRoot = ".";
9
- let baseBranch = "master";
49
+ let baseBranch;
10
50
  let deliveryBranch = null;
11
51
  let label = null;
12
52
  let dryRun = false;
13
53
  let noCommit = false;
14
54
  let noOpenPr = false;
15
55
  let emitJson = false;
56
+ let help = false;
57
+ let error = null;
58
+ const reject = (arg) => {
59
+ error ??= `unrecognized argument: ${arg}`;
60
+ };
61
+ const takeValue = (flag, nextValue) => {
62
+ if (nextValue === undefined || nextValue.startsWith("-")) {
63
+ reject(flag);
64
+ return null;
65
+ }
66
+ return nextValue;
67
+ };
16
68
  for (let i = 0; i < argv.length; i += 1) {
17
69
  const arg = argv[i];
18
70
  const next = argv[i + 1];
19
- if (arg === "--pr" && next !== undefined) {
20
- for (const piece of next.split(",")) {
21
- const trimmed = piece.trim();
22
- if (/^\d+$/.test(trimmed)) {
23
- prNumbers.push(Number.parseInt(trimmed, 10));
24
- }
71
+ if (arg === "--help" || arg === "-h") {
72
+ help = true;
73
+ }
74
+ else if (arg === "--pr") {
75
+ const value = takeValue(arg, next);
76
+ if (value !== null) {
77
+ parsePrList(value, arg, prNumbers, reject);
78
+ i += 1;
25
79
  }
26
- i += 1;
27
80
  }
28
81
  else if (arg?.startsWith("--pr=")) {
29
- for (const piece of arg.slice("--pr=".length).split(",")) {
30
- const trimmed = piece.trim();
31
- if (/^\d+$/.test(trimmed)) {
32
- prNumbers.push(Number.parseInt(trimmed, 10));
33
- }
82
+ parsePrList(equalsValue(arg, "--pr"), arg, prNumbers, reject);
83
+ }
84
+ else if (arg === "--stories") {
85
+ const value = takeValue(arg, next);
86
+ if (value !== null) {
87
+ storyTokens.push(value);
88
+ i += 1;
34
89
  }
35
90
  }
36
- else if (arg === "--stories" && next !== undefined) {
37
- storyTokens.push(next);
38
- i += 1;
91
+ else if (arg?.startsWith("--stories=")) {
92
+ const value = equalsValue(arg, "--stories");
93
+ if (value.length === 0) {
94
+ reject(arg);
95
+ }
96
+ else {
97
+ storyTokens.push(value);
98
+ }
39
99
  }
40
- else if (arg === "--repo" && next !== undefined) {
41
- repo = next;
42
- i += 1;
100
+ else if (arg === "--repo") {
101
+ const value = takeValue(arg, next);
102
+ if (value !== null) {
103
+ repo = value;
104
+ i += 1;
105
+ }
43
106
  }
44
107
  else if (arg?.startsWith("--repo=")) {
45
- repo = arg.slice("--repo=".length);
108
+ const value = equalsValue(arg, "--repo");
109
+ if (value.length === 0) {
110
+ reject(arg);
111
+ }
112
+ else {
113
+ repo = value;
114
+ }
115
+ }
116
+ else if (arg === "--project-root") {
117
+ const value = takeValue(arg, next);
118
+ if (value !== null) {
119
+ projectRoot = value;
120
+ i += 1;
121
+ }
46
122
  }
47
- else if (arg === "--project-root" && next !== undefined) {
48
- projectRoot = next;
49
- i += 1;
123
+ else if (arg?.startsWith("--project-root=")) {
124
+ const value = equalsValue(arg, "--project-root");
125
+ if (value.length === 0) {
126
+ reject(arg);
127
+ }
128
+ else {
129
+ projectRoot = value;
130
+ }
50
131
  }
51
- else if (arg === "--base-branch" && next !== undefined) {
52
- baseBranch = next;
53
- i += 1;
132
+ else if (arg === "--base-branch") {
133
+ const value = takeValue(arg, next);
134
+ if (value !== null) {
135
+ baseBranch = value;
136
+ i += 1;
137
+ }
54
138
  }
55
- else if (arg === "--delivery-branch" && next !== undefined) {
56
- deliveryBranch = next;
57
- i += 1;
139
+ else if (arg?.startsWith("--base-branch=")) {
140
+ const value = equalsValue(arg, "--base-branch");
141
+ if (value.length === 0) {
142
+ reject(arg);
143
+ }
144
+ else {
145
+ baseBranch = value;
146
+ }
147
+ }
148
+ else if (arg === "--delivery-branch") {
149
+ const value = takeValue(arg, next);
150
+ if (value !== null) {
151
+ deliveryBranch = value;
152
+ i += 1;
153
+ }
58
154
  }
59
155
  else if (arg?.startsWith("--delivery-branch=")) {
60
- deliveryBranch = arg.slice("--delivery-branch=".length);
156
+ const value = equalsValue(arg, "--delivery-branch");
157
+ if (value.length === 0) {
158
+ reject(arg);
159
+ }
160
+ else {
161
+ deliveryBranch = value;
162
+ }
163
+ }
164
+ else if (arg === "--label") {
165
+ const value = takeValue(arg, next);
166
+ if (value !== null) {
167
+ label = value;
168
+ i += 1;
169
+ }
61
170
  }
62
- else if (arg === "--label" && next !== undefined) {
63
- label = next;
64
- i += 1;
171
+ else if (arg?.startsWith("--label=")) {
172
+ const value = equalsValue(arg, "--label");
173
+ if (value.length === 0) {
174
+ reject(arg);
175
+ }
176
+ else {
177
+ label = value;
178
+ }
65
179
  }
66
180
  else if (arg === "--dry-run") {
67
181
  dryRun = true;
@@ -78,23 +192,37 @@ export function parseFinalizeCohortArgv(argv) {
78
192
  else if (arg !== undefined && !arg.startsWith("-")) {
79
193
  storyTokens.push(arg);
80
194
  }
195
+ else if (arg !== undefined) {
196
+ reject(arg);
197
+ }
81
198
  }
82
199
  return {
83
200
  prNumbers,
84
201
  storyTokens,
85
202
  repo,
86
203
  projectRoot,
87
- baseBranch,
204
+ ...(baseBranch !== undefined ? { baseBranch } : {}),
88
205
  deliveryBranch,
89
206
  label,
90
207
  dryRun,
91
208
  noCommit,
92
209
  noOpenPr,
93
210
  emitJson,
211
+ help,
212
+ error,
94
213
  };
95
214
  }
96
215
  export function finalizeCohortMain(argv = process.argv.slice(2)) {
97
- const result = finalizeCohort(parseFinalizeCohortArgv(argv));
216
+ const parsed = parseFinalizeCohortArgv(argv);
217
+ if (parsed.help) {
218
+ process.stdout.write(FINALIZE_COHORT_USAGE);
219
+ return EXIT_OK;
220
+ }
221
+ if (parsed.error !== null) {
222
+ process.stderr.write(`${parsed.error}\n`);
223
+ return EXIT_CONFIG_ERROR;
224
+ }
225
+ const result = finalizeCohort(parsed);
98
226
  if (result.stdout.length > 0) {
99
227
  process.stdout.write(result.stdout);
100
228
  }
@@ -103,7 +231,9 @@ export function finalizeCohortMain(argv = process.argv.slice(2)) {
103
231
  }
104
232
  return result.exitCode;
105
233
  }
234
+ /* v8 ignore start -- entry guard */
106
235
  if (process.argv[1] !== undefined && fileURLToPath(import.meta.url) === process.argv[1]) {
107
236
  process.exit(finalizeCohortMain());
108
237
  }
238
+ /* v8 ignore stop */
109
239
  //# sourceMappingURL=finalize-cohort-cli.js.map
@@ -13,6 +13,7 @@ export interface FinalizeCohortResult {
13
13
  readonly branch: string | null;
14
14
  readonly pr_url: string | null;
15
15
  readonly delivery_branch: string | null;
16
+ readonly sweep_base: string;
16
17
  readonly delivery_errors: readonly string[];
17
18
  readonly errors: readonly string[];
18
19
  readonly warnings: readonly string[];
@@ -327,8 +327,6 @@ export function finalizeCohort(args) {
327
327
  const prNumbers = [...(args.prNumbers ?? [])].sort((a, b) => a - b);
328
328
  const storyTokens = splitCsv(args.storyTokens ?? []);
329
329
  const repo = args.repo ?? process.env.GH_REPO ?? null;
330
- // baseBranch is for the lifecycle sweep PR only — not delivery proof (#3041).
331
- const baseBranch = args.baseBranch ?? "master";
332
330
  const dryRun = args.dryRun ?? false;
333
331
  const noCommit = args.noCommit ?? false;
334
332
  const noOpenPr = args.noOpenPr ?? false;
@@ -351,6 +349,12 @@ export function finalizeCohort(args) {
351
349
  const deliveryBranch = policyDelivery.source === "typed"
352
350
  ? policyDelivery.branch
353
351
  : (cliDelivery ?? policyDelivery.branch);
352
+ // Sweep/PR base is distinct from delivery proof (#3041). Default via the resolved
353
+ // delivery branch — never a hardcoded "master". --base-branch remains the override.
354
+ const explicitSweepBase = args.baseBranch !== undefined && args.baseBranch !== null && args.baseBranch.trim().length > 0
355
+ ? args.baseBranch.trim()
356
+ : null;
357
+ const baseBranch = explicitSweepBase ?? deliveryBranch;
354
358
  if (!existsSync(projectRoot)) {
355
359
  return buildResponse({
356
360
  projectRoot,
@@ -364,6 +368,7 @@ export function finalizeCohort(args) {
364
368
  branch: null,
365
369
  prUrl: null,
366
370
  deliveryBranch,
371
+ sweepBase: baseBranch,
367
372
  deliveryErrors: [],
368
373
  errors: [`project root does not exist: ${projectRoot}`],
369
374
  warnings: [],
@@ -385,6 +390,7 @@ export function finalizeCohort(args) {
385
390
  branch: null,
386
391
  prUrl: null,
387
392
  deliveryBranch,
393
+ sweepBase: baseBranch,
388
394
  deliveryErrors: [],
389
395
  errors: [`no xbrief/ directory under project root: ${projectRoot}`],
390
396
  warnings: [],
@@ -546,6 +552,7 @@ export function finalizeCohort(args) {
546
552
  branch: null,
547
553
  prUrl: null,
548
554
  deliveryBranch,
555
+ sweepBase: baseBranch,
549
556
  deliveryErrors,
550
557
  errors,
551
558
  warnings,
@@ -572,6 +579,7 @@ export function finalizeCohort(args) {
572
579
  branch: null,
573
580
  prUrl: null,
574
581
  deliveryBranch,
582
+ sweepBase: baseBranch,
575
583
  deliveryErrors,
576
584
  errors,
577
585
  warnings,
@@ -673,6 +681,7 @@ export function finalizeCohort(args) {
673
681
  branch: null,
674
682
  prUrl: null,
675
683
  deliveryBranch,
684
+ sweepBase: baseBranch,
676
685
  deliveryErrors,
677
686
  errors,
678
687
  warnings,
@@ -712,6 +721,7 @@ export function finalizeCohort(args) {
712
721
  branch,
713
722
  prUrl,
714
723
  deliveryBranch,
724
+ sweepBase: baseBranch,
715
725
  deliveryErrors,
716
726
  errors,
717
727
  warnings,
@@ -733,6 +743,7 @@ function buildResponse(input) {
733
743
  branch: input.branch,
734
744
  pr_url: input.prUrl,
735
745
  delivery_branch: input.deliveryBranch,
746
+ sweep_base: input.sweepBase,
736
747
  delivery_errors: input.deliveryErrors,
737
748
  errors: input.errors,
738
749
  warnings: input.warnings,
@@ -754,6 +765,7 @@ function buildResponse(input) {
754
765
  if (input.deliveryBranch !== null) {
755
766
  lines.push(` Delivery branch: ${input.deliveryBranch}`);
756
767
  }
768
+ lines.push(` Sweep base: ${input.sweepBase}`);
757
769
  if (input.prNumbers.length > 0) {
758
770
  lines.push(` PRs: ${input.prNumbers.map((n) => `#${n}`).join(", ")}`);
759
771
  }
@@ -22,6 +22,8 @@ export function routingSetMain(argv = process.argv.slice(2), environ = process.e
22
22
  let harnessDefault = false;
23
23
  for (let i = 0; i < argv.length; i += 1) {
24
24
  const arg = argv[i];
25
+ if (arg === "--")
26
+ continue;
25
27
  if (arg === "--project-root" && argv[i + 1] !== undefined) {
26
28
  projectRoot = argv[i + 1] ?? ".";
27
29
  i += 1;
@@ -1,5 +1,5 @@
1
1
  import { type RoutingFile } from "./routing.js";
2
- export declare const ROUTING_SET_CMD = "task swarm:routing-set -- --role <role> --model <slug> (or --harness-default)";
2
+ export declare const ROUTING_SET_CMD = "deft swarm:routing-set --role <role> --model <slug> (or --harness-default)";
3
3
  /** Roles the pre-dispatch gate checks by default: the actual model lever. */
4
4
  export declare const DEFAULT_GATED_ROLES: readonly ["leaf-implementation"];
5
5
  export interface VerifyRoutingOptions {
@@ -12,7 +12,7 @@
12
12
  */
13
13
  import { EXIT_CONFIG_ERROR, EXIT_GATE_FAILED, EXIT_OK } from "./constants.js";
14
14
  import { dispatchProviderFromRuntime, emptyHostDetectProbes, HARNESS_BOUND_PROVIDERS, loadRoutingFile, ROUTING_MODE_HARNESS_DEFAULT, resolveDispatchProvider, resolveModelRoute, resolveRoutingPath, } from "./routing.js";
15
- export const ROUTING_SET_CMD = "task swarm:routing-set -- --role <role> --model <slug> (or --harness-default)";
15
+ export const ROUTING_SET_CMD = "deft swarm:routing-set --role <role> --model <slug> (or --harness-default)";
16
16
  /** Roles the pre-dispatch gate checks by default: the actual model lever. */
17
17
  export const DEFAULT_GATED_ROLES = ["leaf-implementation"];
18
18
  function resolveProvider(options) {
@@ -105,7 +105,7 @@ export function verifyRouting(options) {
105
105
  };
106
106
  }
107
107
  if (options.advise) {
108
- const note = "[deft routing] NOTE: plan.policy.swarmSubagentBackend enum is deprecated (#1891); use 'task swarm:routing-set' / .deft/routing.local.json instead.";
108
+ const note = "[deft routing] NOTE: plan.policy.swarmSubagentBackend enum is deprecated (#1891); use 'deft swarm:routing-set' / .deft/routing.local.json instead.";
109
109
  let body;
110
110
  if (undecided.length === 0 && invalid.length === 0) {
111
111
  body = `[deft routing] provider '${provider}': all ${roles.length} gated role(s) decided.`;
@@ -370,12 +370,12 @@ export function formatSummary(result) {
370
370
  if (result.exitCode === 0) {
371
371
  lines.push("");
372
372
  lines.push("Next steps:");
373
- lines.push(" task cache:fetch-all -- --source=github-issue --repo OWNER/NAME # refresh the cache (#883 Story 2)");
374
- lines.push(" task cache:get -- github-issue OWNER/NAME/<N> # inspect cached issue N");
375
- lines.push(" task triage:accept -- --issue <N> --repo OWNER/NAME # accept issue N (#845 Story 3)");
376
- lines.push(" task triage:reject -- --issue <N> --repo OWNER/NAME --reason 'why' # reject issue N");
377
- lines.push(" task triage:bulk-accept -- --repo OWNER/NAME --label adoption-blocker # bulk accept");
378
- lines.push(" task triage:refresh-active # pre-swarm freshness gate");
373
+ lines.push(" deft cache:fetch-all --source=github-issue --repo OWNER/NAME # refresh the cache (#883 Story 2)");
374
+ lines.push(" deft cache:get github-issue OWNER/NAME/<N> # inspect cached issue N");
375
+ lines.push(" deft triage:accept --issue <N> --repo OWNER/NAME # accept issue N (#845 Story 3)");
376
+ lines.push(" deft triage:reject --issue <N> --repo OWNER/NAME --reason 'why' # reject issue N");
377
+ lines.push(" deft triage:bulk-accept --repo OWNER/NAME --label adoption-blocker # bulk accept");
378
+ lines.push(" deft triage:refresh-active # pre-swarm freshness gate");
379
379
  }
380
380
  return lines.join("\n");
381
381
  }
@@ -357,7 +357,7 @@ export declare const registryData: {
357
357
  readonly name: "task triage:metrics";
358
358
  readonly summary: "Attributed-value trend from the events ledger";
359
359
  readonly refs: "(#1709)";
360
- 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.";
360
+ 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. Also composes a ceremony-cost rollup (#3508): last cold vs re-arm CLI process time, per-step ms, blocked-ritual count, recovery-tier distribution. Alias of the value:show handler. Attribution requires plan.policy.valueFeedback.enabled (default OFF) — exits blocked when disabled, but still prints the ceremony-cost section. An empty attribution ledger prints a no-signals message. In the maintainer repo, attribution is skipped unless DEFT_VALUE_SELF_DOGFOOD=1.";
361
361
  readonly usage: "task triage:metrics [-- --window=7d] [--format=text|json]";
362
362
  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)."]];
363
363
  readonly examples: readonly ["task triage:metrics", "task triage:metrics -- --window=30d --format=json"];
@@ -628,7 +628,7 @@ export const registryData = {
628
628
  name: "task triage:metrics",
629
629
  summary: "Attributed-value trend from the events ledger",
630
630
  refs: "(#1709)",
631
- 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.",
631
+ 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. Also composes a ceremony-cost rollup (#3508): last cold vs re-arm CLI process time, per-step ms, blocked-ritual count, recovery-tier distribution. Alias of the value:show handler. Attribution requires plan.policy.valueFeedback.enabled (default OFF) — exits blocked when disabled, but still prints the ceremony-cost section. An empty attribution ledger prints a no-signals message. In the maintainer repo, attribution is skipped unless DEFT_VALUE_SELF_DOGFOOD=1.",
632
632
  usage: "task triage:metrics [-- --window=7d] [--format=text|json]",
633
633
  flags: [
634
634
  ["--window WINDOW", "7d", "Time window (e.g. 7d, 30d, 24h)."],
@@ -1,4 +1,4 @@
1
- export declare function appendAuditEntry(projectRoot: string, entry: string): string;
1
+ export declare function appendAuditEntry(projectRoot: string, entry: string, changed?: boolean): string;
2
2
  export declare function writeTriageScope(projectRoot: string, rules: Array<Record<string, unknown>>, options?: {
3
3
  presetLabel: string;
4
4
  actor?: string;