@deftai/directive 0.88.0 → 0.90.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.
@@ -0,0 +1,112 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * CLI: deft session:ready — one-shot mutation recovery (#2993).
4
+ *
5
+ * Composes session:start (when needed) + verify:session-ritual --tier=gated
6
+ * + cache fetch-all recovery so PreToolUse gated inspect goes green in one verb.
7
+ */
8
+ import { resolve } from "node:path";
9
+ import { fileURLToPath } from "node:url";
10
+ import { runSessionReady } from "@deftai/directive-core/session";
11
+ /** Parse session:ready CLI args. */
12
+ export function parseArgs(argv) {
13
+ const parsed = {
14
+ projectRoot: ".",
15
+ emitJson: false,
16
+ withNetwork: false,
17
+ repo: null,
18
+ };
19
+ for (let i = 0; i < argv.length; i += 1) {
20
+ const arg = argv[i];
21
+ if (arg === undefined)
22
+ continue;
23
+ if (arg === "--")
24
+ continue;
25
+ if (arg === "--json") {
26
+ parsed.emitJson = true;
27
+ continue;
28
+ }
29
+ if (arg === "--with-network") {
30
+ parsed.withNetwork = true;
31
+ continue;
32
+ }
33
+ if (arg === "--help" || arg === "-h") {
34
+ return {
35
+ ...parsed,
36
+ error: "usage: session:ready [--project-root <path>] [--repo OWNER/NAME] [--with-network] [--json]\n" +
37
+ " One-shot recovery: session:start (if needed) + gated ritual + cache recovery (#2993).",
38
+ };
39
+ }
40
+ if (arg === "--project-root") {
41
+ const value = argv[i + 1];
42
+ if (value === undefined) {
43
+ return { ...parsed, error: "argument --project-root: expected one argument" };
44
+ }
45
+ parsed.projectRoot = value;
46
+ i += 1;
47
+ continue;
48
+ }
49
+ if (arg.startsWith("--project-root=")) {
50
+ parsed.projectRoot = arg.slice("--project-root=".length);
51
+ continue;
52
+ }
53
+ if (arg === "--repo") {
54
+ const value = argv[i + 1];
55
+ if (value === undefined) {
56
+ return { ...parsed, error: "argument --repo: expected one argument" };
57
+ }
58
+ parsed.repo = value;
59
+ i += 1;
60
+ continue;
61
+ }
62
+ if (arg.startsWith("--repo=")) {
63
+ parsed.repo = arg.slice("--repo=".length);
64
+ continue;
65
+ }
66
+ if (arg.startsWith("-")) {
67
+ return { ...parsed, error: `unrecognized argument: ${arg}` };
68
+ }
69
+ return { ...parsed, error: `unexpected argument: ${arg}` };
70
+ }
71
+ return parsed;
72
+ }
73
+ /** Native session:ready handler (#2993). */
74
+ export function run(argv = process.argv.slice(2)) {
75
+ const args = parseArgs(argv);
76
+ if (args.error !== undefined) {
77
+ process.stderr.write(`session_ready: ${args.error}\n`);
78
+ return 2;
79
+ }
80
+ const projectRoot = resolve(args.projectRoot);
81
+ const result = runSessionReady(projectRoot, {
82
+ repo: args.repo,
83
+ sessionStartOptions: {
84
+ allowOptionalNetwork: args.withNetwork ? true : undefined,
85
+ writeHistory: false,
86
+ },
87
+ });
88
+ if (args.emitJson) {
89
+ process.stdout.write(`${JSON.stringify({
90
+ ready: result.code === 0,
91
+ exit_code: result.code,
92
+ path: result.path,
93
+ message: result.message,
94
+ steps: result.steps,
95
+ duration_ms: result.duration_ms,
96
+ })}\n`);
97
+ return result.code;
98
+ }
99
+ const sink = result.code === 0 ? process.stdout : process.stderr;
100
+ // Prefer the canonical single success/failure line; keep intermediate lines
101
+ // only when they add recovery context (start output / cache progress).
102
+ const intermediates = result.lines.filter((line) => line !== result.message);
103
+ for (const line of intermediates) {
104
+ sink.write(`${line}\n`);
105
+ }
106
+ sink.write(`${result.message}\n`);
107
+ return result.code;
108
+ }
109
+ if (process.argv[1] !== undefined && fileURLToPath(import.meta.url) === process.argv[1]) {
110
+ process.exit(run(process.argv.slice(2)));
111
+ }
112
+ //# sourceMappingURL=session-ready.js.map
@@ -1,10 +1,15 @@
1
1
  #!/usr/bin/env node
2
+ import { type SessionCeremonyTier } from "@deftai/directive-core/session";
2
3
  export interface ParsedSessionStartArgs {
3
4
  projectRoot: string;
4
5
  deferValues: string[];
5
6
  emitJson: boolean;
6
7
  noHistory: boolean;
7
8
  readOnly: boolean;
9
+ /** #2991: opt into optional network (release probe + triage cache hydrate). */
10
+ withNetwork: boolean;
11
+ /** #2992: cold (full) vs rearm (clock/HEAD refresh without fat path). */
12
+ ceremonyTier: SessionCeremonyTier;
8
13
  error?: string;
9
14
  }
10
15
  /** Parse session:start CLI args, mirroring scripts/session_start.py. */
@@ -1,7 +1,14 @@
1
1
  #!/usr/bin/env node
2
2
  import { resolve } from "node:path";
3
3
  import { fileURLToPath } from "node:url";
4
- import { parseDeferrals, READ_ONLY_POSTURE, ritualStatePath, runSessionStart, } from "@deftai/directive-core/session";
4
+ import { COLD_CEREMONY_TIER, parseDeferrals, READ_ONLY_POSTURE, REARM_CEREMONY_TIER, ritualStatePath, runSessionStart, SESSION_CEREMONY_TIERS, } from "@deftai/directive-core/session";
5
+ function parseCeremonyTier(raw) {
6
+ const value = raw.trim().toLowerCase();
7
+ if (SESSION_CEREMONY_TIERS.includes(value)) {
8
+ return value;
9
+ }
10
+ return null;
11
+ }
5
12
  /** Parse session:start CLI args, mirroring scripts/session_start.py. */
6
13
  export function parseArgs(argv) {
7
14
  const parsed = {
@@ -10,6 +17,8 @@ export function parseArgs(argv) {
10
17
  emitJson: false,
11
18
  noHistory: false,
12
19
  readOnly: false,
20
+ withNetwork: false,
21
+ ceremonyTier: COLD_CEREMONY_TIER,
13
22
  };
14
23
  for (let i = 0; i < argv.length; i += 1) {
15
24
  const arg = argv[i];
@@ -22,6 +31,39 @@ export function parseArgs(argv) {
22
31
  else if (arg === "--read-only") {
23
32
  parsed.readOnly = true;
24
33
  }
34
+ else if (arg === "--with-network") {
35
+ parsed.withNetwork = true;
36
+ }
37
+ else if (arg === "--rearm") {
38
+ // #2992: shortcut for --tier=rearm
39
+ parsed.ceremonyTier = REARM_CEREMONY_TIER;
40
+ }
41
+ else if (arg === "--tier") {
42
+ const value = argv[i + 1];
43
+ if (value === undefined) {
44
+ return { ...parsed, error: "argument --tier: expected one argument (cold|rearm)" };
45
+ }
46
+ const tier = parseCeremonyTier(value);
47
+ if (tier === null) {
48
+ return {
49
+ ...parsed,
50
+ error: `argument --tier: expected cold|rearm, got ${JSON.stringify(value)}`,
51
+ };
52
+ }
53
+ parsed.ceremonyTier = tier;
54
+ i += 1;
55
+ }
56
+ else if (arg?.startsWith("--tier=")) {
57
+ const value = arg.slice("--tier=".length);
58
+ const tier = parseCeremonyTier(value);
59
+ if (tier === null) {
60
+ return {
61
+ ...parsed,
62
+ error: `argument --tier: expected cold|rearm, got ${JSON.stringify(value)}`,
63
+ };
64
+ }
65
+ parsed.ceremonyTier = tier;
66
+ }
25
67
  else if (arg === "--project-root") {
26
68
  const value = argv[i + 1];
27
69
  if (value === undefined) {
@@ -81,6 +123,8 @@ export function run(argv) {
81
123
  deferrals,
82
124
  writeHistory: !args.noHistory,
83
125
  posture: args.readOnly ? READ_ONLY_POSTURE : undefined,
126
+ allowOptionalNetwork: args.withNetwork ? true : undefined,
127
+ ceremonyTier: args.ceremonyTier,
84
128
  });
85
129
  }
86
130
  finally {
@@ -0,0 +1,13 @@
1
+ #!/usr/bin/env node
2
+ interface ParsedArgs {
3
+ projectRoot: string;
4
+ enforce: boolean;
5
+ help?: boolean;
6
+ error?: string;
7
+ }
8
+ /** Parse verify-contained-writes CLI args (#2951). */
9
+ export declare function parseArgs(argv: string[]): ParsedArgs;
10
+ /** Run the gate and return the process exit code. */
11
+ export declare function run(argv: string[]): number;
12
+ export {};
13
+ //# sourceMappingURL=verify-contained-writes.d.ts.map
@@ -0,0 +1,67 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * CLI for task verify:contained-writes (#2951 Phase 1).
4
+ * Fail-open by default; pass --enforce for fail-closed (later phases).
5
+ */
6
+ import { resolve } from "node:path";
7
+ import { fileURLToPath } from "node:url";
8
+ import { evaluateContainedWrites } from "@deftai/directive-core/verify-source";
9
+ /** Parse verify-contained-writes CLI args (#2951). */
10
+ export function parseArgs(argv) {
11
+ const parsed = { projectRoot: ".", enforce: false };
12
+ for (let i = 0; i < argv.length; i += 1) {
13
+ const arg = argv[i];
14
+ if (arg === "--project-root") {
15
+ const value = argv[i + 1];
16
+ if (value === undefined) {
17
+ return { ...parsed, error: "argument --project-root: expected one argument" };
18
+ }
19
+ parsed.projectRoot = value;
20
+ i += 1;
21
+ }
22
+ else if (arg?.startsWith("--project-root=")) {
23
+ parsed.projectRoot = arg.slice("--project-root=".length);
24
+ }
25
+ else if (arg === "--enforce") {
26
+ parsed.enforce = true;
27
+ }
28
+ else if (arg === "--help" || arg === "-h") {
29
+ return { ...parsed, help: true };
30
+ }
31
+ else {
32
+ return { ...parsed, error: `unrecognized argument: ${arg}` };
33
+ }
34
+ }
35
+ return parsed;
36
+ }
37
+ const HELP_TEXT = "Usage: verify-contained-writes [--project-root <path>] [--enforce]\n" +
38
+ " Inventory raw write sinks outside the allowlist (#2951).\n" +
39
+ " Default: fail-open (exit 0 with advisory report).\n" +
40
+ " --enforce: fail closed (exit 1) when non-allowlisted sinks remain.\n";
41
+ /** Run the gate and return the process exit code. */
42
+ export function run(argv) {
43
+ const args = parseArgs(argv);
44
+ if (args.help === true) {
45
+ process.stdout.write(HELP_TEXT);
46
+ return 0;
47
+ }
48
+ if (args.error !== undefined) {
49
+ process.stderr.write(`verify_contained_writes: ${args.error}\n`);
50
+ return 2;
51
+ }
52
+ const result = evaluateContainedWrites({
53
+ projectRoot: resolve(args.projectRoot),
54
+ enforce: args.enforce,
55
+ });
56
+ if (result.stream === "stdout") {
57
+ process.stdout.write(`${result.message}\n`);
58
+ }
59
+ else {
60
+ process.stderr.write(`${result.message}\n`);
61
+ }
62
+ return result.code;
63
+ }
64
+ if (process.argv[1] !== undefined && fileURLToPath(import.meta.url) === process.argv[1]) {
65
+ process.exit(run(process.argv.slice(2)));
66
+ }
67
+ //# sourceMappingURL=verify-contained-writes.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@deftai/directive",
3
- "version": "0.88.0",
3
+ "version": "0.90.0",
4
4
  "description": "Directive CLI — npm install path for the Deft Directive framework.",
5
5
  "license": "MIT",
6
6
  "homepage": "https://deftai.github.io/directive/",
@@ -34,8 +34,8 @@
34
34
  "provenance": true
35
35
  },
36
36
  "dependencies": {
37
- "@deftai/directive-core": "^0.88.0",
38
- "@deftai/directive-content": "^0.88.0"
37
+ "@deftai/directive-core": "^0.90.0",
38
+ "@deftai/directive-content": "^0.90.0"
39
39
  },
40
40
  "scripts": {
41
41
  "build": "tsc -b"