@deftai/directive 0.69.0 → 0.71.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.
@@ -71,6 +71,7 @@ export const SUBCOMMAND_ROUTES = {
71
71
  "policy:show": ["policy", "show"],
72
72
  "policy:enforce-branches": ["policy", "enforce-branches"],
73
73
  "policy:allow-direct-commits": ["policy", "allow-direct-commits"],
74
+ "policy:enable-value-feedback": ["policy", "enable-value-feedback"],
74
75
  "vbrief:reconcile-graph": ["vbrief-reconcile", "graph"],
75
76
  "vbrief:reconcile-labels": ["vbrief-reconcile", "labels"],
76
77
  "vbrief:reconcile-umbrellas": ["vbrief-reconcile", "umbrellas"],
@@ -10,9 +10,9 @@ export interface DispatchIo {
10
10
  writeErr: (text: string) => void;
11
11
  }
12
12
  /** CLI modules in packages/cli/src (excluding parity harnesses and bin/index). */
13
- export declare const CLI_MODULE_VERBS: readonly ["agents-refresh", "cache", "check", "capacity-backfill", "capacity-show", "codebase-default-extractor", "codebase-map", "codebase-map-fresh", "codebase-projection-registry", "codebase-provider", "doctor", "install-upgrade", "install-uninstall", "migrate-preflight", "migrate-xbrief", "migrate-category-b", "framework-check-updates", "umbrella-current-shape", "changelog-check", "change-init", "commit-lint", "policy", "pr-closing-keywords", "pr-merge-readiness", "pr-monitor", "pr-protected-issues", "pr-wait-mergeable", "pr-watch", "preflight-cache", "preflight-gh", "probe-session", "release", "release-e2e", "release-publish", "release-rollback", "scope-lifecycle", "session-start", "slice", "subagent-monitor", "toolchain-check", "triage-actions", "triage-bootstrap", "triage-bulk", "triage-classify", "triage-help", "triage-queue", "triage-reconcile", "triage-refresh", "triage-scope", "triage-scope-drift", "triage-smoketest", "triage-subscribe", "triage-summary", "triage-welcome", "ts-check-lane", "vbrief-activate", "vbrief-build", "vbrief-preflight", "vbrief-reconcile", "vbrief-validate", "vbrief-validation", "verify-branch", "verify-encoding", "verify-forward-coverage", "verify-hooks-installed", "verify-investigation", "verify-judgment-gates", "verify-no-task-runtime", "validate-links", "validate-strategy-output", "verify-biome-config", "verify-bridge-drift", "verify-capacity", "verify-content-manifest", "verify-contract-drift", "verify-cursor-tier1", "verify-go-freeze", "verify-scm-boundary", "verify-session-ritual", "verify-stubs", "verify-xbrief-drift", "rule-ownership-lint", "verify-story-ready", "verify-tools", "verify-wip-cap", "verify-agents-md-budget", "verify-agents-md-advisory"];
13
+ export declare const CLI_MODULE_VERBS: readonly ["agents-refresh", "cache", "check", "capacity-backfill", "capacity-show", "codebase-default-extractor", "codebase-map", "codebase-map-fresh", "codebase-projection-registry", "codebase-provider", "doctor", "install-upgrade", "install-uninstall", "migrate-preflight", "migrate-xbrief", "migrate-category-b", "framework-check-updates", "umbrella-current-shape", "changelog-check", "change-init", "commit-lint", "policy", "pr-closing-keywords", "pr-merge-readiness", "pr-monitor", "pr-protected-issues", "pr-wait-mergeable", "pr-watch", "preflight-cache", "preflight-gh", "probe-session", "release", "release-e2e", "release-publish", "release-rollback", "scope-lifecycle", "session-start", "slice", "subagent-monitor", "toolchain-check", "triage-actions", "triage-bootstrap", "triage-bulk", "triage-classify", "triage-help", "triage-queue", "triage-reconcile", "triage-refresh", "triage-scope", "triage-scope-drift", "triage-smoketest", "triage-subscribe", "triage-summary", "triage-welcome", "ts-check-lane", "vbrief-activate", "vbrief-build", "vbrief-preflight", "vbrief-reconcile", "vbrief-validate", "vbrief-validation", "verify-branch", "verify-encoding", "verify-forward-coverage", "verify-hooks-installed", "verify-investigation", "verify-judgment-gates", "verify-no-task-runtime", "validate-links", "validate-strategy-output", "verify-biome-config", "verify-bridge-drift", "verify-capacity", "verify-content-manifest", "verify-contract-drift", "verify-cursor-tier1", "verify-go-freeze", "verify-scm-boundary", "verify-session-ritual", "verify-stubs", "verify-xbrief-drift", "rule-ownership-lint", "verify-story-ready", "verify-tools", "verify-wip-cap", "verify-agents-md-budget", "verify-agents-md-advisory", "eval-health", "eval-run", "eval-report"];
14
14
  /** Core-only CLI entrypoints without a packages/cli wrapper. */
15
- export declare const CORE_MODULE_VERBS: readonly ["scm", "github-auth-modes", "github-body", "issue-emit", "issue-ingest", "reconcile-issues", "swarm-launch", "swarm-complete-cohort", "swarm-finalize-cohort", "swarm-readiness", "swarm-routing-verify", "swarm-routing-set", "swarm-verify-review-clean", "swarm-worktrees", "framework-commands", "pack-render", "packs-slice", "prd-render", "export-spec", "project-render", "roadmap-render", "spec-render", "spec-validate", "code-structure-validate", "pack-migrate-skills", "pack-migrate-rules", "pack-migrate-strategies", "pack-migrate-patterns", "pack-migrate-swarm-spec", "policy-set", "setup-ghx", "scope-undo", "scope-demote", "scope-decompose", "changelog-resolve-unreleased", "architecture-preflight-sor"];
15
+ export declare const CORE_MODULE_VERBS: readonly ["scm", "github-auth-modes", "github-body", "issue-emit", "issue-ingest", "reconcile-issues", "swarm-launch", "swarm-complete-cohort", "swarm-finalize-cohort", "swarm-readiness", "swarm-routing-verify", "swarm-routing-set", "swarm-verify-review-clean", "swarm-worktrees", "framework-commands", "pack-render", "packs-slice", "prd-render", "export-spec", "project-render", "roadmap-render", "spec-render", "spec-validate", "code-structure-validate", "pack-migrate-skills", "pack-migrate-rules", "pack-migrate-strategies", "pack-migrate-patterns", "pack-migrate-swarm-spec", "policy-set", "setup-ghx", "scope-undo", "scope-demote", "scope-decompose", "changelog-resolve-unreleased", "architecture-preflight-sor", "feedback-file", "value-readback"];
16
16
  /** Colon aliases for triage-actions (mirrors cli-router SUBCOMMAND_ROUTES). */
17
17
  export declare const TRIAGE_ACTION_ALIAS_SUBCOMMANDS: Readonly<Record<string, string>>;
18
18
  /** Task-style aliases (framework_commands / Taskfile names). */
package/dist/dispatch.js CHANGED
@@ -111,6 +111,9 @@ export const CLI_MODULE_VERBS = [
111
111
  "verify-wip-cap",
112
112
  "verify-agents-md-budget",
113
113
  "verify-agents-md-advisory",
114
+ "eval-health",
115
+ "eval-run",
116
+ "eval-report",
114
117
  ];
115
118
  /** Core-only CLI entrypoints without a packages/cli wrapper. */
116
119
  export const CORE_MODULE_VERBS = [
@@ -150,6 +153,8 @@ export const CORE_MODULE_VERBS = [
150
153
  "scope-decompose",
151
154
  "changelog-resolve-unreleased",
152
155
  "architecture-preflight-sor",
156
+ "feedback-file",
157
+ "value-readback",
153
158
  ];
154
159
  /** Colon aliases for triage-actions (mirrors cli-router SUBCOMMAND_ROUTES). */
155
160
  export const TRIAGE_ACTION_ALIAS_SUBCOMMANDS = {
@@ -222,6 +227,12 @@ export const VERB_ALIASES = {
222
227
  "project:render": "project-render",
223
228
  "project:export-spec": "export-spec",
224
229
  doctor: "doctor",
230
+ "eval:health": "eval-health",
231
+ "feedback:file": "feedback-file",
232
+ "value:show": "value-readback",
233
+ "triage:metrics": "value-readback",
234
+ "eval:run": "eval-run",
235
+ "eval:report": "eval-report",
225
236
  build: "framework-commands",
226
237
  "setup:ghx": "setup-ghx",
227
238
  };
@@ -2282,6 +2293,14 @@ async function loadCoreModuleHandler(verb, io) {
2282
2293
  const { architecturePreflightSorMain } = await import("@deftai/directive-core/dist/architecture/sor-preflight.js");
2283
2294
  return architecturePreflightSorMain;
2284
2295
  }
2296
+ case "feedback-file": {
2297
+ const { mainEntry } = await import("@deftai/directive-core/dist/value/feedback-file.js");
2298
+ return mainEntry;
2299
+ }
2300
+ case "value-readback": {
2301
+ const { mainEntry } = await import("@deftai/directive-core/dist/value/readback.js");
2302
+ return mainEntry;
2303
+ }
2285
2304
  default:
2286
2305
  throw new Error(`unknown core verb: ${verb}`);
2287
2306
  }
@@ -0,0 +1,13 @@
1
+ #!/usr/bin/env node
2
+ interface ParsedArgs {
3
+ projectRoot: string;
4
+ json: boolean;
5
+ noPersist: boolean;
6
+ error?: string;
7
+ }
8
+ /** Parse eval-health CLI args. */
9
+ export declare function parseArgs(argv: string[]): ParsedArgs;
10
+ /** Run eval:health and return the process exit code. */
11
+ export declare function run(argv: string[]): number;
12
+ export {};
13
+ //# sourceMappingURL=eval-health.d.ts.map
@@ -0,0 +1,63 @@
1
+ #!/usr/bin/env node
2
+ import { resolve } from "node:path";
3
+ import { fileURLToPath } from "node:url";
4
+ import { evaluateHealth } from "@deftai/directive-core/eval";
5
+ /** Parse eval-health CLI args. */
6
+ export function parseArgs(argv) {
7
+ const parsed = {
8
+ projectRoot: ".",
9
+ json: false,
10
+ noPersist: false,
11
+ };
12
+ for (let i = 0; i < argv.length; i += 1) {
13
+ const arg = argv[i];
14
+ if (arg === "--json") {
15
+ parsed.json = true;
16
+ }
17
+ else if (arg === "--no-persist") {
18
+ parsed.noPersist = true;
19
+ }
20
+ else if (arg === "--project-root") {
21
+ const value = argv[i + 1];
22
+ if (value === undefined) {
23
+ return { ...parsed, error: "argument --project-root: expected one argument" };
24
+ }
25
+ parsed.projectRoot = value;
26
+ i += 1;
27
+ }
28
+ else if (arg?.startsWith("--project-root=")) {
29
+ parsed.projectRoot = arg.slice("--project-root=".length);
30
+ }
31
+ else {
32
+ return { ...parsed, error: `unrecognized argument: ${arg}` };
33
+ }
34
+ }
35
+ return parsed;
36
+ }
37
+ /** Run eval:health and return the process exit code. */
38
+ export function run(argv) {
39
+ const args = parseArgs(argv);
40
+ if (args.error !== undefined) {
41
+ process.stderr.write(`eval:health: ${args.error}\n`);
42
+ return 2;
43
+ }
44
+ const result = evaluateHealth({
45
+ projectRoot: resolve(args.projectRoot),
46
+ persist: !args.noPersist,
47
+ });
48
+ if (result.report === null) {
49
+ process.stderr.write(`${result.message}\n`);
50
+ return result.code;
51
+ }
52
+ if (args.json) {
53
+ process.stdout.write(`${JSON.stringify(result.report, null, 2)}\n`);
54
+ }
55
+ else {
56
+ process.stdout.write(`${result.message}\n`);
57
+ }
58
+ return result.code;
59
+ }
60
+ if (process.argv[1] !== undefined && fileURLToPath(import.meta.url) === process.argv[1]) {
61
+ process.exit(run(process.argv.slice(2)));
62
+ }
63
+ //# sourceMappingURL=eval-health.js.map
@@ -0,0 +1,15 @@
1
+ #!/usr/bin/env node
2
+ interface ParsedArgs {
3
+ projectRoot: string;
4
+ championVersion: string;
5
+ challengerVersion: string;
6
+ model: string;
7
+ json: boolean;
8
+ error?: string;
9
+ }
10
+ /** Parse eval-report CLI args. */
11
+ export declare function parseArgs(argv: string[]): ParsedArgs;
12
+ /** Run eval:report and return the process exit code. */
13
+ export declare function run(argv: string[]): number;
14
+ export {};
15
+ //# sourceMappingURL=eval-report.d.ts.map
@@ -0,0 +1,97 @@
1
+ #!/usr/bin/env node
2
+ import { resolve } from "node:path";
3
+ import { fileURLToPath } from "node:url";
4
+ import { reportGoldenEval } from "@deftai/directive-core/eval/report";
5
+ /** Parse eval-report CLI args. */
6
+ export function parseArgs(argv) {
7
+ const parsed = {
8
+ projectRoot: ".",
9
+ championVersion: "",
10
+ challengerVersion: "",
11
+ model: "",
12
+ json: false,
13
+ };
14
+ for (let i = 0; i < argv.length; i += 1) {
15
+ const arg = argv[i];
16
+ if (arg === "--json") {
17
+ parsed.json = true;
18
+ }
19
+ else if (arg === "--champion") {
20
+ const value = argv[i + 1];
21
+ if (value === undefined) {
22
+ return { ...parsed, error: "argument --champion: expected one argument" };
23
+ }
24
+ parsed.championVersion = value;
25
+ i += 1;
26
+ }
27
+ else if (arg?.startsWith("--champion=")) {
28
+ parsed.championVersion = arg.slice("--champion=".length);
29
+ }
30
+ else if (arg === "--challenger") {
31
+ const value = argv[i + 1];
32
+ if (value === undefined) {
33
+ return { ...parsed, error: "argument --challenger: expected one argument" };
34
+ }
35
+ parsed.challengerVersion = value;
36
+ i += 1;
37
+ }
38
+ else if (arg?.startsWith("--challenger=")) {
39
+ parsed.challengerVersion = arg.slice("--challenger=".length);
40
+ }
41
+ else if (arg === "--model") {
42
+ const value = argv[i + 1];
43
+ if (value === undefined) {
44
+ return { ...parsed, error: "argument --model: expected one argument" };
45
+ }
46
+ parsed.model = value;
47
+ i += 1;
48
+ }
49
+ else if (arg?.startsWith("--model=")) {
50
+ parsed.model = arg.slice("--model=".length);
51
+ }
52
+ else if (arg === "--project-root") {
53
+ const value = argv[i + 1];
54
+ if (value === undefined) {
55
+ return { ...parsed, error: "argument --project-root: expected one argument" };
56
+ }
57
+ parsed.projectRoot = value;
58
+ i += 1;
59
+ }
60
+ else if (arg?.startsWith("--project-root=")) {
61
+ parsed.projectRoot = arg.slice("--project-root=".length);
62
+ }
63
+ else {
64
+ return { ...parsed, error: `unrecognized argument: ${arg}` };
65
+ }
66
+ }
67
+ return parsed;
68
+ }
69
+ /** Run eval:report and return the process exit code. */
70
+ export function run(argv) {
71
+ const args = parseArgs(argv);
72
+ if (args.error !== undefined) {
73
+ process.stderr.write(`eval:report: ${args.error}\n`);
74
+ return 2;
75
+ }
76
+ const result = reportGoldenEval({
77
+ projectRoot: resolve(args.projectRoot),
78
+ championVersion: args.championVersion,
79
+ challengerVersion: args.challengerVersion,
80
+ model: args.model,
81
+ });
82
+ if (result.report === null) {
83
+ process.stderr.write(`${result.message}\n`);
84
+ return result.code;
85
+ }
86
+ if (args.json) {
87
+ process.stdout.write(`${JSON.stringify(result.report, null, 2)}\n`);
88
+ }
89
+ else {
90
+ process.stdout.write(`${result.message}\n`);
91
+ }
92
+ return result.code;
93
+ }
94
+ if (process.argv[1] !== undefined && fileURLToPath(import.meta.url) === process.argv[1]) {
95
+ process.exit(run(process.argv.slice(2)));
96
+ }
97
+ //# sourceMappingURL=eval-report.js.map
@@ -0,0 +1,17 @@
1
+ #!/usr/bin/env node
2
+ interface ParsedArgs {
3
+ projectRoot: string;
4
+ model: string;
5
+ seeds: number[];
6
+ directiveVersion?: string;
7
+ harness?: string;
8
+ json: boolean;
9
+ noPersist: boolean;
10
+ error?: string;
11
+ }
12
+ /** Parse eval-run CLI args. */
13
+ export declare function parseArgs(argv: string[]): ParsedArgs;
14
+ /** Run eval:run and return the process exit code. */
15
+ export declare function run(argv: string[]): number;
16
+ export {};
17
+ //# sourceMappingURL=eval-run.d.ts.map
@@ -0,0 +1,122 @@
1
+ #!/usr/bin/env node
2
+ import { resolve } from "node:path";
3
+ import { fileURLToPath } from "node:url";
4
+ import { runGoldenEval } from "@deftai/directive-core/eval/run";
5
+ /** Parse eval-run CLI args. */
6
+ export function parseArgs(argv) {
7
+ const parsed = {
8
+ projectRoot: ".",
9
+ model: "",
10
+ seeds: [],
11
+ json: false,
12
+ noPersist: false,
13
+ };
14
+ for (let i = 0; i < argv.length; i += 1) {
15
+ const arg = argv[i];
16
+ if (arg === "--json") {
17
+ parsed.json = true;
18
+ }
19
+ else if (arg === "--no-persist") {
20
+ parsed.noPersist = true;
21
+ }
22
+ else if (arg === "--model") {
23
+ const value = argv[i + 1];
24
+ if (value === undefined) {
25
+ return { ...parsed, error: "argument --model: expected one argument" };
26
+ }
27
+ parsed.model = value;
28
+ i += 1;
29
+ }
30
+ else if (arg?.startsWith("--model=")) {
31
+ parsed.model = arg.slice("--model=".length);
32
+ }
33
+ else if (arg === "--seed") {
34
+ const value = argv[i + 1];
35
+ if (value === undefined) {
36
+ return { ...parsed, error: "argument --seed: expected one argument" };
37
+ }
38
+ const seedNum = Number(value);
39
+ if (!Number.isFinite(seedNum)) {
40
+ return { ...parsed, error: `argument --seed: expected an integer, got: ${value}` };
41
+ }
42
+ parsed.seeds.push(seedNum);
43
+ i += 1;
44
+ }
45
+ else if (arg?.startsWith("--seed=")) {
46
+ const rawSeed = arg.slice("--seed=".length);
47
+ const seedNum = Number(rawSeed);
48
+ if (!Number.isFinite(seedNum)) {
49
+ return { ...parsed, error: `argument --seed: expected an integer, got: ${rawSeed}` };
50
+ }
51
+ parsed.seeds.push(seedNum);
52
+ }
53
+ else if (arg === "--directive-version") {
54
+ const value = argv[i + 1];
55
+ if (value === undefined) {
56
+ return { ...parsed, error: "argument --directive-version: expected one argument" };
57
+ }
58
+ parsed.directiveVersion = value;
59
+ i += 1;
60
+ }
61
+ else if (arg?.startsWith("--directive-version=")) {
62
+ parsed.directiveVersion = arg.slice("--directive-version=".length);
63
+ }
64
+ else if (arg === "--harness") {
65
+ const value = argv[i + 1];
66
+ if (value === undefined) {
67
+ return { ...parsed, error: "argument --harness: expected one argument" };
68
+ }
69
+ parsed.harness = value;
70
+ i += 1;
71
+ }
72
+ else if (arg?.startsWith("--harness=")) {
73
+ parsed.harness = arg.slice("--harness=".length);
74
+ }
75
+ else if (arg === "--project-root") {
76
+ const value = argv[i + 1];
77
+ if (value === undefined) {
78
+ return { ...parsed, error: "argument --project-root: expected one argument" };
79
+ }
80
+ parsed.projectRoot = value;
81
+ i += 1;
82
+ }
83
+ else if (arg?.startsWith("--project-root=")) {
84
+ parsed.projectRoot = arg.slice("--project-root=".length);
85
+ }
86
+ else {
87
+ return { ...parsed, error: `unrecognized argument: ${arg}` };
88
+ }
89
+ }
90
+ return parsed;
91
+ }
92
+ /** Run eval:run and return the process exit code. */
93
+ export function run(argv) {
94
+ const args = parseArgs(argv);
95
+ if (args.error !== undefined) {
96
+ process.stderr.write(`eval:run: ${args.error}\n`);
97
+ return 2;
98
+ }
99
+ const result = runGoldenEval({
100
+ projectRoot: resolve(args.projectRoot),
101
+ model: args.model,
102
+ seeds: args.seeds.length > 0 ? args.seeds : undefined,
103
+ directiveVersion: args.directiveVersion,
104
+ harness: args.harness,
105
+ persist: !args.noPersist,
106
+ });
107
+ if (result.record === null) {
108
+ process.stderr.write(`${result.message}\n`);
109
+ return result.code;
110
+ }
111
+ if (args.json) {
112
+ process.stdout.write(`${JSON.stringify(result.record, null, 2)}\n`);
113
+ }
114
+ else {
115
+ process.stdout.write(`${result.message}\n`);
116
+ }
117
+ return result.code;
118
+ }
119
+ if (process.argv[1] !== undefined && fileURLToPath(import.meta.url) === process.argv[1]) {
120
+ process.exit(run(process.argv.slice(2)));
121
+ }
122
+ //# sourceMappingURL=eval-run.js.map
package/dist/policy.d.ts CHANGED
@@ -7,7 +7,7 @@ interface ShowArgs {
7
7
  error?: string;
8
8
  }
9
9
  interface SetArgs {
10
- cmd: "show" | "enforce-branches" | "allow-direct-commits" | "resolve";
10
+ cmd: "show" | "enforce-branches" | "allow-direct-commits" | "enable-value-feedback" | "resolve";
11
11
  confirm: boolean;
12
12
  actor: string;
13
13
  note: string;
package/dist/policy.js CHANGED
@@ -4,9 +4,9 @@
4
4
  * mirroring scripts/_policy_show_cli.py and scripts/policy_set.py.
5
5
  */
6
6
  import { existsSync } from "node:fs";
7
- import { join, resolve as pathResolve } from "node:path";
7
+ import { resolve as pathResolve, relative } from "node:path";
8
8
  import { fileURLToPath } from "node:url";
9
- import { disclosureLine, inspectAllPolicies, inspectOnePolicy, PROJECT_DEFINITION_REL_PATH, pythonListRepr, pythonStringRepr, registeredPolicyNames, renderJson, renderText, resolvePolicy, setPolicy, } from "@deftai/directive-core/policy";
9
+ import { describeShadowedPlanExtension, detectShadowedPlanExtensions, disclosureLine, enableValueFeedback, FIELD_VALUE_FEEDBACK, FIELD_VALUE_FEEDBACK_CLI_ALIAS, formatValueFeedbackStatusLine, inspectAllPolicies, inspectOnePolicy, loadProjectDefinition, projectDefinitionPath, pythonListRepr, pythonStringRepr, registeredPolicyNames, renderJson, renderText, resolvePolicy, resolveValueFeedback, setPolicy, } from "@deftai/directive-core/policy";
10
10
  const CAPABILITY_COST_DISCLOSURE = "\u26a0 Capability-cost disclosure -- enabling direct commits to the default " +
11
11
  "branch turns OFF the deft branch-protection policy.\n" +
12
12
  " \u2022 Pre-commit + pre-push hooks will no longer block default-branch " +
@@ -112,7 +112,8 @@ export function parseShowArgs(argv) {
112
112
  /** Parse argv for the policy CLI (show + set subcommands). */
113
113
  export function parseArgs(argv) {
114
114
  if (argv.length === 0) {
115
- return makeSetError("usage: policy [show|enforce-branches|allow-direct-commits|resolve] ...");
115
+ const usage = "usage: policy [show|enforce-branches|allow-direct-commits|enable-value-feedback|resolve] ...";
116
+ return makeSetError(usage);
116
117
  }
117
118
  const cmd = argv[0];
118
119
  if (cmd === "show") {
@@ -143,11 +144,15 @@ export function parseArgs(argv) {
143
144
  error: root.error,
144
145
  };
145
146
  }
146
- if (cmd === "enforce-branches" || cmd === "allow-direct-commits") {
147
+ if (cmd === "enforce-branches" ||
148
+ cmd === "allow-direct-commits" ||
149
+ cmd === "enable-value-feedback") {
147
150
  let confirm = false;
148
151
  let actor = cmd === "enforce-branches"
149
152
  ? "task policy:enforce-branches"
150
- : "task policy:allow-direct-commits";
153
+ : cmd === "allow-direct-commits"
154
+ ? "task policy:allow-direct-commits"
155
+ : "task policy:enable-value-feedback";
151
156
  let note = "";
152
157
  let projectRoot = ".";
153
158
  for (let i = 1; i < argv.length; i += 1) {
@@ -202,13 +207,33 @@ export function parseArgs(argv) {
202
207
  }
203
208
  return makeSetError(`unknown subcommand: ${cmd}`);
204
209
  }
210
+ /**
211
+ * Emit a loud warning to stderr for every plan-extension key whose bare block
212
+ * silently shadows the namespaced form (#2301). Never fails / throws: a missing
213
+ * or malformed PROJECT-DEFINITION simply yields no warnings.
214
+ */
215
+ function emitPlanExtensionShadowWarnings(projectRoot) {
216
+ const [data] = loadProjectDefinition(projectRoot);
217
+ if (data === null)
218
+ return;
219
+ const shadows = detectShadowedPlanExtensions(data.plan);
220
+ for (const shadow of shadows) {
221
+ process.stderr.write(`[policy:show] WARNING: ${describeShadowedPlanExtension(shadow)}\n`);
222
+ }
223
+ }
224
+ function valueFeedbackGateSummary(projectRoot) {
225
+ return formatValueFeedbackStatusLine(resolveValueFeedback(projectRoot));
226
+ }
205
227
  function runShow(args) {
206
228
  const projectRoot = pathResolve(args.projectRoot);
207
- const pdPath = join(projectRoot, PROJECT_DEFINITION_REL_PATH);
229
+ // Layout-aware (#2302): name the resolved PROJECT-DEFINITION path (xbrief on a
230
+ // migrated tree, else vbrief) instead of the hardcoded vbrief/ literal.
231
+ const pdPath = projectDefinitionPath(projectRoot);
208
232
  if (!existsSync(pdPath)) {
209
233
  process.stderr.write(`[policy:show] PROJECT-DEFINITION not found at ${pdPath}; ` +
210
234
  "rendering framework defaults.\n");
211
235
  }
236
+ emitPlanExtensionShadowWarnings(projectRoot);
212
237
  if (args.field !== null) {
213
238
  const field = inspectOnePolicy(args.field, projectRoot);
214
239
  if (field === null) {
@@ -222,6 +247,9 @@ function runShow(args) {
222
247
  }
223
248
  else {
224
249
  process.stdout.write(`${renderText([field])}\n`);
250
+ if (field.name === FIELD_VALUE_FEEDBACK || args.field === FIELD_VALUE_FEEDBACK_CLI_ALIAS) {
251
+ process.stdout.write(`\n${valueFeedbackGateSummary(projectRoot)}\n`);
252
+ }
225
253
  }
226
254
  return 0;
227
255
  }
@@ -250,6 +278,15 @@ function runResolve(projectRoot) {
250
278
  process.stdout.write(`${disclosureLine(result)}\n`);
251
279
  return 0;
252
280
  }
281
+ function runEnableValueFeedback(args) {
282
+ const result = enableValueFeedback(pathResolve(args.projectRoot), {
283
+ confirm: args.confirm,
284
+ actor: args.actor,
285
+ note: args.note,
286
+ });
287
+ process.stdout.write(result.stdout);
288
+ return result.exitCode;
289
+ }
253
290
  function runSet(args) {
254
291
  const projectRoot = pathResolve(args.projectRoot);
255
292
  if (args.cmd === "allow-direct-commits" && !args.confirm) {
@@ -280,7 +317,8 @@ function runSet(args) {
280
317
  const message = err instanceof Error ? err.message : String(err);
281
318
  if (message.includes("PROJECT-DEFINITION not found")) {
282
319
  process.stderr.write(`\u274c ${message}\n`);
283
- process.stderr.write(" Recovery: run `task setup` to generate vbrief/PROJECT-DEFINITION.vbrief.json.\n");
320
+ const pdRel = relative(projectRoot, projectDefinitionPath(projectRoot));
321
+ process.stderr.write(` Recovery: run \`task setup\` to generate ${pdRel}.\n`);
284
322
  return 2;
285
323
  }
286
324
  process.stderr.write(`\u274c Config error: ${message}\n`);
@@ -308,6 +346,9 @@ export function run(argv) {
308
346
  if (args.cmd === "enforce-branches" || args.cmd === "allow-direct-commits") {
309
347
  return runSet(args);
310
348
  }
349
+ if (args.cmd === "enable-value-feedback") {
350
+ return runEnableValueFeedback(args);
351
+ }
311
352
  return 2;
312
353
  }
313
354
  if (process.argv[1] !== undefined && fileURLToPath(import.meta.url) === process.argv[1]) {
@@ -1,5 +1,4 @@
1
1
  #!/usr/bin/env node
2
- import { join, resolve } from "node:path";
3
2
  import { fileURLToPath } from "node:url";
4
3
  import { bulkActionWithDefaults, CacheEmptyError, } from "@deftai/directive-core/dist/triage/bulk/index.js";
5
4
  import { interceptHelp } from "@deftai/directive-core/dist/triage/help/index.js";
@@ -125,8 +124,10 @@ export function run(argv) {
125
124
  process.stderr.write("triage_bulk: --repo is required\n");
126
125
  return 2;
127
126
  }
127
+ // #2279: the bulk path defaults to native TypeScript actions. It no longer
128
+ // resolves a project/DEFT_ROOT `scripts/` dir, so an attacker-planted
129
+ // `scripts/triage_actions.py` can never be executed. Pass only projectRoot.
128
130
  const projectRoot = process.cwd();
129
- const frameworkRoot = resolve(process.env.DEFT_ROOT ?? projectRoot);
130
131
  try {
131
132
  bulkActionWithDefaults(args.action, args.repo, {
132
133
  label: args.label,
@@ -135,8 +136,7 @@ export function run(argv) {
135
136
  cluster: args.cluster,
136
137
  reason: args.reason,
137
138
  reAction: args.reAction,
138
- deftRoot: projectRoot,
139
- scriptsDir: join(frameworkRoot, "scripts"),
139
+ projectRoot,
140
140
  });
141
141
  }
142
142
  catch (exc) {
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import { resolve } from "node:path";
3
3
  import { fileURLToPath } from "node:url";
4
- import { resolveEvalPath } from "@deftai/directive-core/dist/layout/resolve.js";
4
+ import { resolveTriageCachePath } from "@deftai/directive-core/dist/triage/cache-path.js";
5
5
  import { activeReferencedIssueNumbers, buildQueue, collectOrphanIssueNumbers, DEFAULT_QUEUE_LIMIT, loadCachedIssues, loadSliceRecords, readAuditEntries, reconcileLiveOpenState, renderQueue, resolveRankingLabels, resolveRepo, } from "@deftai/directive-core/dist/triage/queue/index.js";
6
6
  import { resolveScopeIgnores } from "@deftai/directive-core/dist/triage/scope-drift/index.js";
7
7
  /** Parse triage-queue CLI args for the queue subcommand. */
@@ -146,12 +146,12 @@ export function run(argv, options = {}) {
146
146
  const issuesWithClosed = loadCachedIssues(repo, { projectRoot, includeClosed: true });
147
147
  const issuesByNumber = new Map(issuesWithClosed.map((row) => [row.number, row]));
148
148
  const auditEntries = readAuditEntries(repo, {
149
- auditLogPath: args.auditLog ?? resolveEvalPath(projectRoot, "candidates.jsonl"),
149
+ auditLogPath: args.auditLog ?? resolveTriageCachePath(projectRoot, "candidates.jsonl"),
150
150
  });
151
151
  const rankingLabels = resolveRankingLabels(projectRoot);
152
152
  const activeRefs = activeReferencedIssueNumbers(projectRoot);
153
153
  const sliceRecords = loadSliceRecords({
154
- slicesLogPath: args.slicesLog ?? resolveEvalPath(projectRoot, "slices.jsonl"),
154
+ slicesLogPath: args.slicesLog ?? resolveTriageCachePath(projectRoot, "slices.jsonl"),
155
155
  });
156
156
  const orphanNumbers = collectOrphanIssueNumbers(sliceRecords, issuesByNumber);
157
157
  const limit = args.limit === 0 ? null : Math.max(0, args.limit);
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import { resolve } from "node:path";
3
3
  import { fileURLToPath } from "node:url";
4
- import { resolveEvalPath } from "@deftai/directive-core/dist/layout/resolve.js";
4
+ import { resolveTriageCachePath } from "@deftai/directive-core/dist/triage/cache-path.js";
5
5
  import { appendHistory, computeSummary, formatSummary, pythonStyleStringify, summaryResultToRecord, utcIso, } from "@deftai/directive-core/dist/triage/summary/index.js";
6
6
  /** Parse triage-summary CLI args, mirroring the Python argparse surface. */
7
7
  export function parseArgs(argv) {
@@ -67,7 +67,7 @@ export function run(argv) {
67
67
  process.stdout.write(`${line}\n`);
68
68
  }
69
69
  if (!args.noHistory) {
70
- const historyPath = resolveEvalPath(projectRoot, "summary-history.jsonl");
70
+ const historyPath = resolveTriageCachePath(projectRoot, "summary-history.jsonl");
71
71
  appendHistory(historyPath, result, line, { emittedAt });
72
72
  }
73
73
  return 0;
@@ -4,6 +4,8 @@ interface ParsedArgs {
4
4
  onboard: boolean;
5
5
  noHistory: boolean;
6
6
  taskPrefix: string;
7
+ preset: string | null;
8
+ wipCap: number | null;
7
9
  error?: string;
8
10
  }
9
11
  export declare function parseArgs(argv: string[]): ParsedArgs;
@@ -2,13 +2,17 @@
2
2
  import { statSync } from "node:fs";
3
3
  import { resolve } from "node:path";
4
4
  import { fileURLToPath } from "node:url";
5
+ import { interceptHelp } from "@deftai/directive-core/dist/triage/help/index.js";
5
6
  import { runDefaultMode } from "@deftai/directive-core/dist/triage/welcome/default-mode.js";
7
+ import { runOnboardMode } from "@deftai/directive-core/dist/triage/welcome/onboard.js";
6
8
  export function parseArgs(argv) {
7
9
  const parsed = {
8
10
  projectRoot: process.env.DEFT_PROJECT_ROOT ?? ".",
9
11
  onboard: false,
10
12
  noHistory: false,
11
13
  taskPrefix: process.env.DEFT_TASK_PREFIX ?? "",
14
+ preset: null,
15
+ wipCap: null,
12
16
  };
13
17
  for (let i = 0; i < argv.length; i += 1) {
14
18
  const arg = argv[i];
@@ -16,6 +20,36 @@ export function parseArgs(argv) {
16
20
  parsed.onboard = true;
17
21
  else if (arg === "--no-history")
18
22
  parsed.noHistory = true;
23
+ else if (arg === "--preset") {
24
+ const value = argv[i + 1];
25
+ if (value === undefined)
26
+ return { ...parsed, error: "argument --preset: expected one argument" };
27
+ parsed.preset = value;
28
+ i += 1;
29
+ }
30
+ else if (arg?.startsWith("--preset=")) {
31
+ const value = arg.slice("--preset=".length);
32
+ if (value === "")
33
+ return { ...parsed, error: "argument --preset: expected one argument" };
34
+ parsed.preset = value;
35
+ }
36
+ else if (arg === "--wip-cap") {
37
+ const value = argv[i + 1];
38
+ if (value === undefined)
39
+ return { ...parsed, error: "argument --wip-cap: expected one argument" };
40
+ const parsedCap = Number(value);
41
+ if (!Number.isInteger(parsedCap))
42
+ return { ...parsed, error: `argument --wip-cap: expected an integer, got ${value}` };
43
+ parsed.wipCap = parsedCap;
44
+ i += 1;
45
+ }
46
+ else if (arg?.startsWith("--wip-cap=")) {
47
+ const value = arg.slice("--wip-cap=".length);
48
+ const parsedCap = Number(value);
49
+ if (!Number.isInteger(parsedCap))
50
+ return { ...parsed, error: `argument --wip-cap: expected an integer, got ${value}` };
51
+ parsed.wipCap = parsedCap;
52
+ }
19
53
  else if (arg === "--project-root") {
20
54
  const value = argv[i + 1];
21
55
  if (value === undefined)
@@ -46,6 +80,10 @@ export function parseArgs(argv) {
46
80
  return parsed;
47
81
  }
48
82
  export function run(argv) {
83
+ const helpRc = interceptHelp("triage_welcome", argv);
84
+ if (helpRc !== null) {
85
+ return helpRc;
86
+ }
49
87
  const args = parseArgs(argv);
50
88
  if (args.error !== undefined) {
51
89
  process.stderr.write(`triage:welcome: ${args.error}\n`);
@@ -63,8 +101,13 @@ export function run(argv) {
63
101
  return 2;
64
102
  }
65
103
  if (args.onboard) {
66
- process.stderr.write("triage:welcome: --onboard is not implemented in the TypeScript CLI yet.\n");
67
- return 2;
104
+ const onboardOutcome = runOnboardMode(projectRoot, {
105
+ preset: args.preset,
106
+ wipCap: args.wipCap,
107
+ writeHistory: !args.noHistory,
108
+ taskPrefix: args.taskPrefix || null,
109
+ });
110
+ return onboardOutcome.exitCode;
68
111
  }
69
112
  const outcome = runDefaultMode(projectRoot, {
70
113
  writeHistory: !args.noHistory,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@deftai/directive",
3
- "version": "0.69.0",
3
+ "version": "0.71.0",
4
4
  "description": "Directive CLI — npm install path for the Deft Directive framework.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -31,8 +31,8 @@
31
31
  "provenance": true
32
32
  },
33
33
  "dependencies": {
34
- "@deftai/directive-core": "^0.69.0",
35
- "@deftai/directive-content": "^0.69.0"
34
+ "@deftai/directive-core": "^0.71.0",
35
+ "@deftai/directive-content": "^0.71.0"
36
36
  },
37
37
  "scripts": {
38
38
  "build": "tsc -b"