@deftai/directive 0.69.0 → 0.70.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.
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, inspectAllPolicies, inspectOnePolicy, loadProjectDefinition, projectDefinitionPath, pythonListRepr, pythonStringRepr, registeredPolicyNames, renderJson, renderText, resolvePolicy, 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 " +
@@ -202,13 +202,30 @@ export function parseArgs(argv) {
202
202
  }
203
203
  return makeSetError(`unknown subcommand: ${cmd}`);
204
204
  }
205
+ /**
206
+ * Emit a loud warning to stderr for every plan-extension key whose bare block
207
+ * silently shadows the namespaced form (#2301). Never fails / throws: a missing
208
+ * or malformed PROJECT-DEFINITION simply yields no warnings.
209
+ */
210
+ function emitPlanExtensionShadowWarnings(projectRoot) {
211
+ const [data] = loadProjectDefinition(projectRoot);
212
+ if (data === null)
213
+ return;
214
+ const shadows = detectShadowedPlanExtensions(data.plan);
215
+ for (const shadow of shadows) {
216
+ process.stderr.write(`[policy:show] WARNING: ${describeShadowedPlanExtension(shadow)}\n`);
217
+ }
218
+ }
205
219
  function runShow(args) {
206
220
  const projectRoot = pathResolve(args.projectRoot);
207
- const pdPath = join(projectRoot, PROJECT_DEFINITION_REL_PATH);
221
+ // Layout-aware (#2302): name the resolved PROJECT-DEFINITION path (xbrief on a
222
+ // migrated tree, else vbrief) instead of the hardcoded vbrief/ literal.
223
+ const pdPath = projectDefinitionPath(projectRoot);
208
224
  if (!existsSync(pdPath)) {
209
225
  process.stderr.write(`[policy:show] PROJECT-DEFINITION not found at ${pdPath}; ` +
210
226
  "rendering framework defaults.\n");
211
227
  }
228
+ emitPlanExtensionShadowWarnings(projectRoot);
212
229
  if (args.field !== null) {
213
230
  const field = inspectOnePolicy(args.field, projectRoot);
214
231
  if (field === null) {
@@ -280,7 +297,8 @@ function runSet(args) {
280
297
  const message = err instanceof Error ? err.message : String(err);
281
298
  if (message.includes("PROJECT-DEFINITION not found")) {
282
299
  process.stderr.write(`\u274c ${message}\n`);
283
- process.stderr.write(" Recovery: run `task setup` to generate vbrief/PROJECT-DEFINITION.vbrief.json.\n");
300
+ const pdRel = relative(projectRoot, projectDefinitionPath(projectRoot));
301
+ process.stderr.write(` Recovery: run \`task setup\` to generate ${pdRel}.\n`);
284
302
  return 2;
285
303
  }
286
304
  process.stderr.write(`\u274c Config error: ${message}\n`);
@@ -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) {
@@ -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.70.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.70.0",
35
+ "@deftai/directive-content": "^0.70.0"
36
36
  },
37
37
  "scripts": {
38
38
  "build": "tsc -b"