@deftai/directive 0.75.0 → 0.76.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/dispatch.js CHANGED
@@ -191,6 +191,7 @@ export const VERB_ALIASES = {
191
191
  "verify:no-task-runtime": "verify-no-task-runtime",
192
192
  "vbrief:validate": "vbrief-validate",
193
193
  "vbrief:preflight": "vbrief-preflight",
194
+ "xbrief:preflight": "vbrief-preflight",
194
195
  "vbrief:activate": "vbrief-activate",
195
196
  "verify:story-ready": "verify-story-ready",
196
197
  "verify:tools": "verify-tools",
@@ -4,6 +4,7 @@ export interface ParsedSessionStartArgs {
4
4
  deferValues: string[];
5
5
  emitJson: boolean;
6
6
  noHistory: boolean;
7
+ readOnly: boolean;
7
8
  error?: string;
8
9
  }
9
10
  /** Parse session:start CLI args, mirroring scripts/session_start.py. */
@@ -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 { parseDeferrals, ritualStatePath, runSessionStart } from "@deftai/directive-core/session";
4
+ import { parseDeferrals, READ_ONLY_POSTURE, ritualStatePath, runSessionStart, } from "@deftai/directive-core/session";
5
5
  /** Parse session:start CLI args, mirroring scripts/session_start.py. */
6
6
  export function parseArgs(argv) {
7
7
  const parsed = {
@@ -9,6 +9,7 @@ export function parseArgs(argv) {
9
9
  deferValues: [],
10
10
  emitJson: false,
11
11
  noHistory: false,
12
+ readOnly: false,
12
13
  };
13
14
  for (let i = 0; i < argv.length; i += 1) {
14
15
  const arg = argv[i];
@@ -18,6 +19,9 @@ export function parseArgs(argv) {
18
19
  else if (arg === "--no-history") {
19
20
  parsed.noHistory = true;
20
21
  }
22
+ else if (arg === "--read-only") {
23
+ parsed.readOnly = true;
24
+ }
21
25
  else if (arg === "--project-root") {
22
26
  const value = argv[i + 1];
23
27
  if (value === undefined) {
@@ -76,6 +80,7 @@ export function run(argv) {
76
80
  result = runSessionStart(projectRoot, {
77
81
  deferrals,
78
82
  writeHistory: !args.noHistory,
83
+ posture: args.readOnly ? READ_ONLY_POSTURE : undefined,
79
84
  });
80
85
  }
81
86
  finally {
@@ -101,7 +106,13 @@ export function run(argv) {
101
106
  sink.write(`${line}\n`);
102
107
  }
103
108
  if (result.code === 0) {
104
- process.stdout.write(`[deft] session ritual recorded at ${ritualStatePath(projectRoot)}\n`);
109
+ const posture = result.payload.posture;
110
+ if (posture === READ_ONLY_POSTURE) {
111
+ process.stdout.write(`[deft] ${String(result.payload.message)}\n`);
112
+ }
113
+ else {
114
+ process.stdout.write(`[deft] session ritual recorded at ${ritualStatePath(projectRoot)} (diagnostic-only; not posture authority)\n`);
115
+ }
105
116
  }
106
117
  return result.code;
107
118
  }
@@ -4,7 +4,7 @@ interface ParsedArgs {
4
4
  emitJson: boolean;
5
5
  error?: string;
6
6
  }
7
- /** Parse vbrief-preflight CLI args, mirroring the Python argparse surface (#810). */
7
+ /** Parse vbrief-preflight / xbrief:preflight CLI args (#810 / #2449). */
8
8
  export declare function parseArgs(argv: string[]): ParsedArgs;
9
9
  /** Run the gate and return the process exit code (parse errors -> 2). */
10
10
  export declare function run(argv: string[]): number;
@@ -1,7 +1,17 @@
1
1
  #!/usr/bin/env node
2
2
  import { fileURLToPath } from "node:url";
3
- import { emitJson, evaluate } from "@deftai/directive-core/preflight";
4
- /** Parse vbrief-preflight CLI args, mirroring the Python argparse surface (#810). */
3
+ import { emitJson, evaluate, PREFLIGHT_USAGE_HINT } from "@deftai/directive-core/preflight";
4
+ const PATH_FLAG_NAMES = ["--vbrief-path", "--brief-path", "--xbrief-path"];
5
+ function assignPathFlag(parsed, value) {
6
+ if (value === undefined || value.length === 0) {
7
+ return { ...parsed, error: "argument --vbrief-path: expected one argument" };
8
+ }
9
+ if (parsed.vbriefPath !== null) {
10
+ return { ...parsed, error: "multiple path arguments are not allowed" };
11
+ }
12
+ return { ...parsed, vbriefPath: value };
13
+ }
14
+ /** Parse vbrief-preflight / xbrief:preflight CLI args (#810 / #2449). */
5
15
  export function parseArgs(argv) {
6
16
  const parsed = {
7
17
  vbriefPath: null,
@@ -11,24 +21,45 @@ export function parseArgs(argv) {
11
21
  const arg = argv[i];
12
22
  if (arg === "--json") {
13
23
  parsed.emitJson = true;
24
+ continue;
14
25
  }
15
- else if (arg === "--vbrief-path") {
16
- const value = argv[i + 1];
17
- if (value === undefined) {
18
- return { ...parsed, error: "argument --vbrief-path: expected one argument" };
19
- }
20
- parsed.vbriefPath = value;
26
+ if (arg === "--help" || arg === "-h") {
27
+ return parsed;
28
+ }
29
+ if (PATH_FLAG_NAMES.includes(arg)) {
30
+ const next = assignPathFlag(parsed, argv[i + 1]);
31
+ if (next?.error !== undefined)
32
+ return next;
33
+ parsed.vbriefPath = next?.vbriefPath ?? null;
21
34
  i += 1;
35
+ continue;
22
36
  }
23
- else if (arg?.startsWith("--vbrief-path=")) {
24
- parsed.vbriefPath = arg.slice("--vbrief-path=".length);
37
+ let matchedEqualsForm = false;
38
+ for (const flag of PATH_FLAG_NAMES) {
39
+ if (arg?.startsWith(`${flag}=`)) {
40
+ const next = assignPathFlag(parsed, arg.slice(flag.length + 1));
41
+ if (next?.error !== undefined)
42
+ return next;
43
+ parsed.vbriefPath = next?.vbriefPath ?? null;
44
+ matchedEqualsForm = true;
45
+ break;
46
+ }
25
47
  }
26
- else {
48
+ if (matchedEqualsForm)
49
+ continue;
50
+ if (arg?.startsWith("-")) {
27
51
  return { ...parsed, error: `unrecognized argument: ${arg}` };
28
52
  }
53
+ const next = assignPathFlag(parsed, arg);
54
+ if (next?.error !== undefined)
55
+ return next;
56
+ parsed.vbriefPath = next?.vbriefPath ?? null;
29
57
  }
30
58
  if (parsed.vbriefPath === null) {
31
- return { ...parsed, error: "the following arguments are required: --vbrief-path" };
59
+ return {
60
+ ...parsed,
61
+ error: `the following arguments are required: --vbrief-path (or positional path). ${PREFLIGHT_USAGE_HINT}`,
62
+ };
32
63
  }
33
64
  return parsed;
34
65
  }
@@ -1,7 +1,9 @@
1
1
  #!/usr/bin/env node
2
+ import { type DirectivePosture } from "@deftai/directive-core/session";
2
3
  interface ParsedArgs {
3
4
  projectRoot: string;
4
5
  tier: "quick" | "gated";
6
+ posture: DirectivePosture | null;
5
7
  emitJson: boolean;
6
8
  error?: string;
7
9
  }
@@ -2,9 +2,21 @@
2
2
  import { resolve } from "node:path";
3
3
  import { fileURLToPath } from "node:url";
4
4
  import { emitBypassWarning, emitVerifyJson, verifySessionRitual, } from "@deftai/directive-core/session";
5
+ function parsePosture(value) {
6
+ if (value === "read-only")
7
+ return "read-only";
8
+ if (value === "mutation" || value === "mutating")
9
+ return "mutation";
10
+ return null;
11
+ }
5
12
  /** Parse verify-session-ritual CLI args, mirroring scripts/verify_session_ritual.py. */
6
13
  export function parseArgs(argv) {
7
- const parsed = { projectRoot: ".", tier: "quick", emitJson: false };
14
+ const parsed = {
15
+ projectRoot: ".",
16
+ tier: "quick",
17
+ posture: null,
18
+ emitJson: false,
19
+ };
8
20
  for (let i = 0; i < argv.length; i += 1) {
9
21
  const arg = argv[i];
10
22
  if (arg === "--json") {
@@ -39,6 +51,32 @@ export function parseArgs(argv) {
39
51
  }
40
52
  parsed.tier = value;
41
53
  }
54
+ else if (arg === "--posture") {
55
+ const value = argv[i + 1];
56
+ if (value === undefined) {
57
+ return { ...parsed, error: "argument --posture: expected one argument" };
58
+ }
59
+ const posture = parsePosture(value);
60
+ if (posture === null) {
61
+ return {
62
+ ...parsed,
63
+ error: `argument --posture: invalid choice: '${value}' (expected read-only|mutation)`,
64
+ };
65
+ }
66
+ parsed.posture = posture;
67
+ i += 1;
68
+ }
69
+ else if (arg?.startsWith("--posture=")) {
70
+ const value = arg.slice("--posture=".length);
71
+ const posture = parsePosture(value);
72
+ if (posture === null) {
73
+ return {
74
+ ...parsed,
75
+ error: `argument --posture: invalid choice: '${value}' (expected read-only|mutation)`,
76
+ };
77
+ }
78
+ parsed.posture = posture;
79
+ }
42
80
  else {
43
81
  return { ...parsed, error: `unrecognized argument: ${arg}` };
44
82
  }
@@ -53,7 +91,10 @@ export function run(argv) {
53
91
  return 2;
54
92
  }
55
93
  const projectRoot = resolve(args.projectRoot);
56
- const result = verifySessionRitual(projectRoot, { tier: args.tier });
94
+ const result = verifySessionRitual(projectRoot, {
95
+ tier: args.tier,
96
+ posture: args.posture ?? undefined,
97
+ });
57
98
  const warning = emitBypassWarning(result);
58
99
  const warningNeeded = result.bypassed && result.wouldFailCode !== null;
59
100
  if (args.emitJson) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@deftai/directive",
3
- "version": "0.75.0",
3
+ "version": "0.76.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.75.0",
35
- "@deftai/directive-content": "^0.75.0"
34
+ "@deftai/directive-core": "^0.76.0",
35
+ "@deftai/directive-content": "^0.76.0"
36
36
  },
37
37
  "scripts": {
38
38
  "build": "tsc -b"