@principles/pd-cli 1.119.0 → 1.120.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 (35) hide show
  1. package/dist/commands/__tests__/legacy-cleanup.test.d.ts +18 -0
  2. package/dist/commands/__tests__/legacy-cleanup.test.d.ts.map +1 -0
  3. package/dist/commands/__tests__/legacy-cleanup.test.js +459 -0
  4. package/dist/commands/__tests__/legacy-cleanup.test.js.map +1 -0
  5. package/dist/commands/__tests__/rulecode-flag-wiring.test.d.ts +21 -0
  6. package/dist/commands/__tests__/rulecode-flag-wiring.test.d.ts.map +1 -0
  7. package/dist/commands/__tests__/rulecode-flag-wiring.test.js +179 -0
  8. package/dist/commands/__tests__/rulecode-flag-wiring.test.js.map +1 -0
  9. package/dist/commands/__tests__/rulecode-handler.test.d.ts +16 -0
  10. package/dist/commands/__tests__/rulecode-handler.test.d.ts.map +1 -0
  11. package/dist/commands/__tests__/rulecode-handler.test.js +285 -0
  12. package/dist/commands/__tests__/rulecode-handler.test.js.map +1 -0
  13. package/dist/commands/legacy-cleanup.d.ts +72 -6
  14. package/dist/commands/legacy-cleanup.d.ts.map +1 -1
  15. package/dist/commands/legacy-cleanup.js +243 -23
  16. package/dist/commands/legacy-cleanup.js.map +1 -1
  17. package/dist/commands/rulecode.d.ts +85 -0
  18. package/dist/commands/rulecode.d.ts.map +1 -0
  19. package/dist/commands/rulecode.js +356 -0
  20. package/dist/commands/rulecode.js.map +1 -0
  21. package/dist/commands/runtime-internalization-run-rulehost.d.ts.map +1 -1
  22. package/dist/commands/runtime-internalization-run-rulehost.js +4 -7
  23. package/dist/commands/runtime-internalization-run-rulehost.js.map +1 -1
  24. package/dist/index.js +30 -9
  25. package/dist/index.js.map +1 -1
  26. package/package.json +1 -1
  27. package/scripts/llm-dogfood.ts +8 -12
  28. package/src/commands/__tests__/legacy-cleanup.test.ts +596 -0
  29. package/src/commands/__tests__/rulecode-flag-wiring.test.ts +230 -0
  30. package/src/commands/__tests__/rulecode-handler.test.ts +369 -0
  31. package/src/commands/legacy-cleanup.ts +335 -27
  32. package/src/commands/rulecode.ts +434 -0
  33. package/src/commands/runtime-internalization-run-rulehost.ts +3 -8
  34. package/src/index.ts +31 -9
  35. package/tests/commands/cli-command-tree.test.ts +40 -0
@@ -0,0 +1,179 @@
1
+ /**
2
+ * Parser-level tests for `pd rulecode spec|validate|replay` flags (PRI-439 Phase 5).
3
+ *
4
+ * CLI gate rule 7: "Test the real command wiring — when behavior depends on
5
+ * Commander options, add a command-registration or parser test that exercises
6
+ * the actual flags."
7
+ *
8
+ * Tests the real `registerRulecodeCommand` helper (single source of truth
9
+ * shared with `index.ts`). Flag typos in production surface here at
10
+ * parseAsync time, not at handler dispatch.
11
+ *
12
+ * Covers:
13
+ * - `spec` subcommand: --json, --workspace/-w registered; no --code
14
+ * - `validate` subcommand: --code required, --code-file, --json, --workspace/-w
15
+ * - `replay` subcommand: --code required, --code-file, --golden-trace required,
16
+ * --json, --workspace/-w
17
+ * - --no-* negations are NOT registered (no accidental negation)
18
+ * - parseAsync actually dispatches the right opts to the handler
19
+ */
20
+ import { describe, it, expect } from 'vitest';
21
+ import { Command } from 'commander';
22
+ import { registerRulecodeCommand } from '../rulecode.js';
23
+ function attachCapture(cmd, state) {
24
+ cmd.action(function captureAction(...args) {
25
+ let optsArg = null;
26
+ for (let i = args.length - 1; i >= 0; i--) {
27
+ const arg = args[i];
28
+ if (arg !== null && typeof arg === 'object' && !(arg instanceof Command)) {
29
+ optsArg = arg;
30
+ break;
31
+ }
32
+ }
33
+ if (optsArg !== null && typeof optsArg === 'object') {
34
+ state.opts = optsArg;
35
+ }
36
+ else {
37
+ state.opts = {};
38
+ }
39
+ });
40
+ }
41
+ function freshProgram() {
42
+ const program = new Command();
43
+ program.name('pd').exitOverride();
44
+ return program;
45
+ }
46
+ describe('pd rulecode — flag wiring (CLI gate rule 7)', () => {
47
+ // ── spec subcommand ───────────────────────────────────────────────────────
48
+ it('registers spec subcommand with --json and --workspace', () => {
49
+ const program = freshProgram();
50
+ const rulecodeCmd = registerRulecodeCommand(program);
51
+ const specCmd = rulecodeCmd.commands.find((c) => c.name() === 'spec');
52
+ expect(specCmd).toBeDefined();
53
+ const jsonOpt = specCmd.options.find((o) => o.long === '--json');
54
+ expect(jsonOpt).toBeDefined();
55
+ const wsOpt = specCmd.options.find((o) => o.long === '--workspace');
56
+ expect(wsOpt).toBeDefined();
57
+ expect(wsOpt?.short).toBe('-w');
58
+ });
59
+ it('spec subcommand does NOT register --code', () => {
60
+ const program = freshProgram();
61
+ const rulecodeCmd = registerRulecodeCommand(program);
62
+ const specCmd = rulecodeCmd.commands.find((c) => c.name() === 'spec');
63
+ const codeOpt = specCmd.options.find((o) => o.long === '--code');
64
+ expect(codeOpt).toBeUndefined();
65
+ });
66
+ // ── validate subcommand ───────────────────────────────────────────────────
67
+ it('registers validate subcommand with --code, --code-file, --json, --workspace', () => {
68
+ const program = freshProgram();
69
+ const rulecodeCmd = registerRulecodeCommand(program);
70
+ const validateCmd = rulecodeCmd.commands.find((c) => c.name() === 'validate');
71
+ expect(validateCmd).toBeDefined();
72
+ const codeOpt = validateCmd.options.find((o) => o.long === '--code');
73
+ expect(codeOpt).toBeDefined();
74
+ const codeFileOpt = validateCmd.options.find((o) => o.long === '--code-file');
75
+ expect(codeFileOpt).toBeDefined();
76
+ const jsonOpt = validateCmd.options.find((o) => o.long === '--json');
77
+ expect(jsonOpt).toBeDefined();
78
+ const wsOpt = validateCmd.options.find((o) => o.long === '--workspace');
79
+ expect(wsOpt).toBeDefined();
80
+ expect(wsOpt?.short).toBe('-w');
81
+ });
82
+ it('validate --code is NOT required at parser level (can use --code-file instead)', async () => {
83
+ const program = freshProgram();
84
+ const rulecodeCmd = registerRulecodeCommand(program);
85
+ const validateCmd = rulecodeCmd.commands.find((c) => c.name() === 'validate');
86
+ const captured = { opts: null };
87
+ attachCapture(validateCmd, captured);
88
+ // parseAsync should NOT reject when --code is missing (handler validates)
89
+ await program.parseAsync(['node', 'pd', 'rulecode', 'validate', '--json']);
90
+ expect(captured.opts).not.toBeNull();
91
+ expect(captured.opts.code).toBeUndefined();
92
+ });
93
+ // ── replay subcommand ─────────────────────────────────────────────────────
94
+ it('registers replay subcommand with --code, --code-file, --golden-trace, --json, --workspace', () => {
95
+ const program = freshProgram();
96
+ const rulecodeCmd = registerRulecodeCommand(program);
97
+ const replayCmd = rulecodeCmd.commands.find((c) => c.name() === 'replay');
98
+ expect(replayCmd).toBeDefined();
99
+ const codeOpt = replayCmd.options.find((o) => o.long === '--code');
100
+ expect(codeOpt).toBeDefined();
101
+ const codeFileOpt = replayCmd.options.find((o) => o.long === '--code-file');
102
+ expect(codeFileOpt).toBeDefined();
103
+ const gtOpt = replayCmd.options.find((o) => o.long === '--golden-trace');
104
+ expect(gtOpt).toBeDefined();
105
+ const jsonOpt = replayCmd.options.find((o) => o.long === '--json');
106
+ expect(jsonOpt).toBeDefined();
107
+ const wsOpt = replayCmd.options.find((o) => o.long === '--workspace');
108
+ expect(wsOpt).toBeDefined();
109
+ expect(wsOpt?.short).toBe('-w');
110
+ });
111
+ it('replay --golden-trace is required', () => {
112
+ const program = freshProgram();
113
+ const rulecodeCmd = registerRulecodeCommand(program);
114
+ const replayCmd = rulecodeCmd.commands.find((c) => c.name() === 'replay');
115
+ const gtOpt = replayCmd.options.find((o) => o.long === '--golden-trace');
116
+ expect(gtOpt?.required).toBe(true);
117
+ });
118
+ // ── No accidental negations ───────────────────────────────────────────────
119
+ it('does NOT register --no-json on any subcommand', () => {
120
+ const program = freshProgram();
121
+ const rulecodeCmd = registerRulecodeCommand(program);
122
+ for (const sub of rulecodeCmd.commands) {
123
+ const noJson = sub.options.find((o) => o.long === '--no-json');
124
+ expect(noJson).toBeUndefined();
125
+ }
126
+ });
127
+ // ── Parser-level dispatch ─────────────────────────────────────────────────
128
+ it('parseAsync dispatches spec subcommand with json=true', async () => {
129
+ const program = freshProgram();
130
+ const rulecodeCmd = registerRulecodeCommand(program);
131
+ const specCmd = rulecodeCmd.commands.find((c) => c.name() === 'spec');
132
+ const captured = { opts: null };
133
+ attachCapture(specCmd, captured);
134
+ await program.parseAsync(['node', 'pd', 'rulecode', 'spec', '--json']);
135
+ expect(captured.opts).not.toBeNull();
136
+ expect(captured.opts.json).toBe(true);
137
+ });
138
+ it('parseAsync dispatches validate with --code', async () => {
139
+ const program = freshProgram();
140
+ const rulecodeCmd = registerRulecodeCommand(program);
141
+ const validateCmd = rulecodeCmd.commands.find((c) => c.name() === 'validate');
142
+ const captured = { opts: null };
143
+ attachCapture(validateCmd, captured);
144
+ await program.parseAsync([
145
+ 'node', 'pd', 'rulecode', 'validate',
146
+ '--code', 'function evaluate(input, helpers) { return { decision: "allow", matched: false, reason: "x" }; }',
147
+ '--json',
148
+ ]);
149
+ expect(captured.opts).not.toBeNull();
150
+ expect(captured.opts.code).toContain('function evaluate');
151
+ expect(captured.opts.json).toBe(true);
152
+ });
153
+ it('parseAsync dispatches replay with --code and --golden-trace', async () => {
154
+ const program = freshProgram();
155
+ const rulecodeCmd = registerRulecodeCommand(program);
156
+ const replayCmd = rulecodeCmd.commands.find((c) => c.name() === 'replay');
157
+ const captured = { opts: null };
158
+ attachCapture(replayCmd, captured);
159
+ await program.parseAsync([
160
+ 'node', 'pd', 'rulecode', 'replay',
161
+ '--code', 'function evaluate(input, helpers) { return { decision: "allow", matched: false, reason: "x" }; }',
162
+ '--golden-trace', '/tmp/trace.json',
163
+ '--json',
164
+ ]);
165
+ expect(captured.opts).not.toBeNull();
166
+ expect(captured.opts.code).toContain('function evaluate');
167
+ expect(captured.opts.goldenTrace).toBe('/tmp/trace.json');
168
+ expect(captured.opts.json).toBe(true);
169
+ });
170
+ it('parseAsync rejects replay without --golden-trace (requiredOption)', async () => {
171
+ const program = freshProgram();
172
+ registerRulecodeCommand(program);
173
+ await expect(program.parseAsync([
174
+ 'node', 'pd', 'rulecode', 'replay',
175
+ '--code', 'function evaluate() {}',
176
+ ])).rejects.toThrow(/golden-trace/);
177
+ });
178
+ });
179
+ //# sourceMappingURL=rulecode-flag-wiring.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rulecode-flag-wiring.test.js","sourceRoot":"","sources":["../../../src/commands/__tests__/rulecode-flag-wiring.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Handler tests for `pd rulecode spec|validate|replay` (PRI-439 Phase 5).
3
+ *
4
+ * Tests the actual handler logic (not Commander parser wiring — that's in
5
+ * rulecode-flag-wiring.test.ts). Verifies:
6
+ * - spec returns the canonical RuleCode dialect spec text
7
+ * - validate detects forbidden patterns, missing return fields, matched=false
8
+ * - validate passes clean code
9
+ * - replay runs sandbox replay against a golden trace file
10
+ * - failure paths include structured reason + nextAction (CLI gate rule 6)
11
+ * - --json outputs exactly one parseable JSON object (CLI gate rule 1)
12
+ * - missing --code/--code-file fails loud with reason (ERR-009)
13
+ * - missing/malformed --golden-trace fails loud with reason (ERR-009)
14
+ */
15
+ export {};
16
+ //# sourceMappingURL=rulecode-handler.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rulecode-handler.test.d.ts","sourceRoot":"","sources":["../../../src/commands/__tests__/rulecode-handler.test.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG"}
@@ -0,0 +1,285 @@
1
+ /**
2
+ * Handler tests for `pd rulecode spec|validate|replay` (PRI-439 Phase 5).
3
+ *
4
+ * Tests the actual handler logic (not Commander parser wiring — that's in
5
+ * rulecode-flag-wiring.test.ts). Verifies:
6
+ * - spec returns the canonical RuleCode dialect spec text
7
+ * - validate detects forbidden patterns, missing return fields, matched=false
8
+ * - validate passes clean code
9
+ * - replay runs sandbox replay against a golden trace file
10
+ * - failure paths include structured reason + nextAction (CLI gate rule 6)
11
+ * - --json outputs exactly one parseable JSON object (CLI gate rule 1)
12
+ * - missing --code/--code-file fails loud with reason (ERR-009)
13
+ * - missing/malformed --golden-trace fails loud with reason (ERR-009)
14
+ */
15
+ import { describe, it, expect, vi } from 'vitest';
16
+ import * as fs from 'node:fs';
17
+ import * as path from 'node:path';
18
+ import * as os from 'node:os';
19
+ import { handleRulecodeSpec, handleRulecodeValidate, handleRulecodeReplay, } from '../rulecode.js';
20
+ // ── Helpers ──────────────────────────────────────────────────────────────────
21
+ async function runHandler(fn) {
22
+ const stdoutChunks = [];
23
+ const stderrChunks = [];
24
+ const logSpy = vi.spyOn(console, 'log').mockImplementation((...args) => {
25
+ stdoutChunks.push(args.map(String).join(' '));
26
+ });
27
+ const errorSpy = vi.spyOn(console, 'error').mockImplementation((...args) => {
28
+ stderrChunks.push(args.map(String).join(' '));
29
+ });
30
+ process.exitCode = undefined;
31
+ try {
32
+ await fn();
33
+ }
34
+ finally {
35
+ logSpy.mockRestore();
36
+ errorSpy.mockRestore();
37
+ }
38
+ const exitCode = process.exitCode;
39
+ process.exitCode = undefined;
40
+ return {
41
+ stdout: stdoutChunks.join(''),
42
+ stderr: stderrChunks.join(''),
43
+ exitCode,
44
+ };
45
+ }
46
+ function parseJson(stdout) {
47
+ return JSON.parse(stdout);
48
+ }
49
+ const CLEAN_CODE = `function evaluate(input, helpers) {
50
+ if (helpers.getToolName() === 'Bash') {
51
+ return { decision: "block", matched: true, reason: "bash commands blocked" };
52
+ }
53
+ return { decision: "allow", matched: false, reason: "non-bash allowed" };
54
+ }`;
55
+ const FORBIDDEN_CODE = `function evaluate(input, helpers) {
56
+ require('fs');
57
+ return { decision: "allow", matched: false, reason: "x" };
58
+ }`;
59
+ const MISSING_FIELDS_CODE = `function evaluate(input, helpers) {
60
+ if (helpers.isRiskPath()) {
61
+ return { matched: true };
62
+ }
63
+ return { decision: "allow", matched: false, reason: "safe" };
64
+ }`;
65
+ // ── Tests ────────────────────────────────────────────────────────────────────
66
+ describe('pd rulecode spec', () => {
67
+ it('returns the canonical spec text as JSON', async () => {
68
+ const { stdout, exitCode } = await runHandler(() => handleRulecodeSpec({ json: true }));
69
+ const output = parseJson(stdout);
70
+ expect(output.status).toBe('ok');
71
+ expect(output.spec).toContain('RuleCode Dialect Spec');
72
+ expect(output.spec).toContain('CANONICAL FORM');
73
+ expect(output.spec).toContain('FORBIDDEN PATTERNS');
74
+ expect(exitCode).toBeUndefined();
75
+ });
76
+ it('outputs text when --json is false', async () => {
77
+ const { stdout, exitCode } = await runHandler(() => handleRulecodeSpec({ json: false }));
78
+ expect(stdout).toContain('RuleCode Dialect Spec');
79
+ expect(stdout.startsWith('{')).toBe(false);
80
+ expect(exitCode).toBeUndefined();
81
+ });
82
+ it('does not set exit code on success', async () => {
83
+ const { exitCode } = await runHandler(() => handleRulecodeSpec({ json: true }));
84
+ expect(exitCode).toBeUndefined();
85
+ });
86
+ });
87
+ describe('pd rulecode validate', () => {
88
+ it('passes clean code with valid=true', async () => {
89
+ const { stdout, exitCode } = await runHandler(() => handleRulecodeValidate({ code: CLEAN_CODE, json: true }));
90
+ const output = parseJson(stdout);
91
+ expect(output.status).toBe('ok');
92
+ expect(output.valid).toBe(true);
93
+ expect(output.violationCount).toBe(0);
94
+ expect(output.violations).toEqual([]);
95
+ expect(exitCode).toBeUndefined();
96
+ });
97
+ it('detects forbidden patterns', async () => {
98
+ const { stdout, exitCode } = await runHandler(() => handleRulecodeValidate({ code: FORBIDDEN_CODE, json: true }));
99
+ const output = parseJson(stdout);
100
+ expect(output.status).toBe('failed');
101
+ expect(output.valid).toBe(false);
102
+ expect(output.violationCount).toBeGreaterThan(0);
103
+ expect(output.violations.some((v) => v.includes('forbidden pattern'))).toBe(true);
104
+ expect(output.reason).toBeDefined();
105
+ expect(output.nextAction).toBeDefined();
106
+ expect(exitCode).toBe(1);
107
+ });
108
+ it('detects missing return fields', async () => {
109
+ const { stdout, exitCode } = await runHandler(() => handleRulecodeValidate({ code: MISSING_FIELDS_CODE, json: true }));
110
+ const output = parseJson(stdout);
111
+ expect(output.valid).toBe(false);
112
+ expect(output.violations.length).toBeGreaterThan(0);
113
+ expect(exitCode).toBe(1);
114
+ });
115
+ it('fails loud when no --code or --code-file provided', async () => {
116
+ const { stdout, exitCode } = await runHandler(() => handleRulecodeValidate({ json: true }));
117
+ const output = parseJson(stdout);
118
+ expect(output.status).toBe('failed');
119
+ expect(output.valid).toBe(false);
120
+ expect(output.reason).toContain('no code provided');
121
+ expect(output.nextAction).toContain('--code');
122
+ expect(exitCode).toBe(1);
123
+ });
124
+ it('reads code from --code-file', async () => {
125
+ const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'pd-rulecode-test-'));
126
+ const codeFile = path.join(tmpDir, 'rule.js');
127
+ fs.writeFileSync(codeFile, CLEAN_CODE, 'utf8');
128
+ try {
129
+ const { stdout, exitCode } = await runHandler(() => handleRulecodeValidate({ codeFile, json: true }));
130
+ const output = parseJson(stdout);
131
+ expect(output.valid).toBe(true);
132
+ expect(exitCode).toBeUndefined();
133
+ }
134
+ finally {
135
+ fs.rmSync(tmpDir, { recursive: true, force: true });
136
+ }
137
+ });
138
+ it('fails loud when --code-file does not exist', async () => {
139
+ const { stdout, exitCode } = await runHandler(() => handleRulecodeValidate({ codeFile: '/nonexistent/path/rule.js', json: true }));
140
+ const output = parseJson(stdout);
141
+ expect(output.status).toBe('failed');
142
+ expect(output.reason).toContain('cannot read');
143
+ expect(output.nextAction).toBeDefined();
144
+ expect(exitCode).toBe(1);
145
+ });
146
+ });
147
+ describe('pd rulecode replay', () => {
148
+ const GOLDEN_TRACE_CASES = [
149
+ {
150
+ caseId: 'pos-1',
151
+ kind: 'positive',
152
+ toolName: 'Write',
153
+ params: { normalizedPath: 'src/safe.ts' },
154
+ expectedDecision: 'allow',
155
+ },
156
+ {
157
+ caseId: 'neg-1',
158
+ kind: 'negative',
159
+ toolName: 'Bash',
160
+ params: { command: 'rm -rf /' },
161
+ expectedDecision: 'block',
162
+ },
163
+ ];
164
+ function writeGoldenTraceFile(cases) {
165
+ const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'pd-rulecode-replay-'));
166
+ const filePath = path.join(tmpDir, 'trace.json');
167
+ fs.writeFileSync(filePath, JSON.stringify(cases, null, 2), 'utf8');
168
+ return filePath;
169
+ }
170
+ it('passes replay with clean code and valid golden trace', async () => {
171
+ const traceFile = writeGoldenTraceFile(GOLDEN_TRACE_CASES);
172
+ try {
173
+ const { stdout, exitCode } = await runHandler(() => handleRulecodeReplay({ code: CLEAN_CODE, goldenTrace: traceFile, json: true }));
174
+ const output = parseJson(stdout);
175
+ expect(output.status).toBe('ok');
176
+ expect(output.decision).toBe('accepted_shadow');
177
+ expect(exitCode).toBeUndefined();
178
+ }
179
+ finally {
180
+ fs.rmSync(path.dirname(traceFile), { recursive: true, force: true });
181
+ }
182
+ });
183
+ it('fails loud when --golden-trace file does not exist', async () => {
184
+ const { stdout, exitCode } = await runHandler(() => handleRulecodeReplay({
185
+ code: CLEAN_CODE,
186
+ goldenTrace: '/nonexistent/trace.json',
187
+ json: true,
188
+ }));
189
+ const output = parseJson(stdout);
190
+ expect(output.status).toBe('failed');
191
+ expect(output.reason).toContain('cannot read');
192
+ expect(exitCode).toBe(1);
193
+ });
194
+ it('fails loud when golden trace is not valid JSON', async () => {
195
+ const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'pd-rulecode-replay-'));
196
+ const traceFile = path.join(tmpDir, 'trace.json');
197
+ fs.writeFileSync(traceFile, '{ not valid json', 'utf8');
198
+ try {
199
+ const { stdout, exitCode } = await runHandler(() => handleRulecodeReplay({ code: CLEAN_CODE, goldenTrace: traceFile, json: true }));
200
+ const output = parseJson(stdout);
201
+ expect(output.status).toBe('failed');
202
+ expect(output.reason).toContain('not valid JSON');
203
+ expect(exitCode).toBe(1);
204
+ }
205
+ finally {
206
+ fs.rmSync(tmpDir, { recursive: true, force: true });
207
+ }
208
+ });
209
+ it('fails loud when golden trace is not an array', async () => {
210
+ const traceFile = writeGoldenTraceFile({ not: 'an array' });
211
+ try {
212
+ const { stdout, exitCode } = await runHandler(() => handleRulecodeReplay({ code: CLEAN_CODE, goldenTrace: traceFile, json: true }));
213
+ const output = parseJson(stdout);
214
+ expect(output.status).toBe('failed');
215
+ expect(output.reason).toContain('must contain a JSON array');
216
+ expect(exitCode).toBe(1);
217
+ }
218
+ finally {
219
+ fs.rmSync(path.dirname(traceFile), { recursive: true, force: true });
220
+ }
221
+ });
222
+ it('fails loud when golden trace has fewer than 2 cases', async () => {
223
+ const traceFile = writeGoldenTraceFile([GOLDEN_TRACE_CASES[0]]);
224
+ try {
225
+ const { stdout, exitCode } = await runHandler(() => handleRulecodeReplay({ code: CLEAN_CODE, goldenTrace: traceFile, json: true }));
226
+ const output = parseJson(stdout);
227
+ expect(output.status).toBe('failed');
228
+ expect(output.reason).toContain('at least 2 cases');
229
+ expect(exitCode).toBe(1);
230
+ }
231
+ finally {
232
+ fs.rmSync(path.dirname(traceFile), { recursive: true, force: true });
233
+ }
234
+ });
235
+ it('fails loud when a golden trace case is malformed', async () => {
236
+ const traceFile = writeGoldenTraceFile([
237
+ { caseId: 'x' }, // missing required fields
238
+ GOLDEN_TRACE_CASES[1],
239
+ ]);
240
+ try {
241
+ const { stdout, exitCode } = await runHandler(() => handleRulecodeReplay({ code: CLEAN_CODE, goldenTrace: traceFile, json: true }));
242
+ const output = parseJson(stdout);
243
+ expect(output.status).toBe('failed');
244
+ expect(output.reason).toContain('malformed');
245
+ expect(exitCode).toBe(1);
246
+ }
247
+ finally {
248
+ fs.rmSync(path.dirname(traceFile), { recursive: true, force: true });
249
+ }
250
+ });
251
+ it('fails loud when no --code or --code-file provided', async () => {
252
+ const traceFile = writeGoldenTraceFile(GOLDEN_TRACE_CASES);
253
+ try {
254
+ const { stdout, exitCode } = await runHandler(() => handleRulecodeReplay({ goldenTrace: traceFile, json: true }));
255
+ const output = parseJson(stdout);
256
+ expect(output.status).toBe('failed');
257
+ expect(output.reason).toContain('no code provided');
258
+ expect(exitCode).toBe(1);
259
+ }
260
+ finally {
261
+ fs.rmSync(path.dirname(traceFile), { recursive: true, force: true });
262
+ }
263
+ });
264
+ it('reports sandbox failures with structured reason + nextAction', async () => {
265
+ const traceFile = writeGoldenTraceFile(GOLDEN_TRACE_CASES);
266
+ // Code with forbidden pattern — sandbox will reject
267
+ const badCode = `function evaluate(input, helpers) {
268
+ eval('1');
269
+ return { decision: "allow", matched: false, reason: "x" };
270
+ }`;
271
+ try {
272
+ const { stdout, exitCode } = await runHandler(() => handleRulecodeReplay({ code: badCode, goldenTrace: traceFile, json: true }));
273
+ const output = parseJson(stdout);
274
+ expect(output.status).toBe('failed');
275
+ expect(output.decision).not.toBe('accepted_shadow');
276
+ expect(output.reason).toBeDefined();
277
+ expect(output.nextAction).toBeDefined();
278
+ expect(exitCode).toBe(1);
279
+ }
280
+ finally {
281
+ fs.rmSync(path.dirname(traceFile), { recursive: true, force: true });
282
+ }
283
+ });
284
+ });
285
+ //# sourceMappingURL=rulecode-handler.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rulecode-handler.test.js","sourceRoot":"","sources":["../../../src/commands/__tests__/rulecode-handler.test.ts"],"names":[],"mappings":"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"}
@@ -9,19 +9,85 @@
9
9
  * - .state/.diagnostician_report_* (archives)
10
10
  * - ~/.openclaw/cron/jobs.json (removes pd-empathy-optimizer cron jobs)
11
11
  *
12
+ * PRI-439 Phase 6: V1 Artificer artifact cleanup.
13
+ * - Identifies V1 artifacts: task_kind=artificer + artifact_kind=principle + no implementationCode
14
+ * - Preserves V2 artifacts (with implementationCode), pain, Dreamer, Philosopher, Scribe
15
+ * - --apply deletes activations → approvals → pi_artifacts (in that order, no cascade)
16
+ * - No V1 runtime reader — V1 artifacts are removed, not interpreted
17
+ *
12
18
  * Usage:
13
- * pd legacy cleanup --workspace <path> --dry-run
14
- * pd legacy cleanup --workspace <path> --apply
19
+ * pd legacy cleanup --workspace <path> # dry-run (default)
20
+ * pd legacy cleanup --workspace <path> --dry-run # explicit dry-run
21
+ * pd legacy cleanup --workspace <path> --apply # apply cleanup
22
+ * pd legacy cleanup --workspace <path> --apply --json # apply with JSON output
15
23
  */
24
+ import type { Database } from 'better-sqlite3';
16
25
  interface CleanupTarget {
17
26
  path: string;
18
27
  action: 'remove' | 'archive';
19
28
  reason: string;
20
29
  archivePath?: string;
21
30
  }
22
- export declare function handleLegacyCleanup(workspacePath: string, dryRun: boolean): Promise<{
23
- targets: CleanupTarget[];
24
- applied: number;
25
- }>;
31
+ /**
32
+ * A V1 Artificer artifact identified for cleanup.
33
+ * - artifactId: pi_artifacts.artifact_id
34
+ * - sourceTaskId: pi_artifacts.source_task_id (references tasks.task_id with task_kind='artificer')
35
+ * - approvalCount: number of approvals referencing this artifact
36
+ * - activationCount: number of activations referencing this artifact
37
+ */
38
+ export interface V1ArtifactTarget {
39
+ artifactId: string;
40
+ sourceTaskId: string;
41
+ createdAt: string;
42
+ approvalCount: number;
43
+ activationCount: number;
44
+ }
45
+ export interface LegacyCleanupOptions {
46
+ workspacePath: string;
47
+ /** Dry-run mode (default). Mutually exclusive with `apply`. */
48
+ dryRun?: boolean;
49
+ /** Apply mode. Mutually exclusive with `dryRun`. */
50
+ apply?: boolean;
51
+ /** Output raw JSON */
52
+ json?: boolean;
53
+ }
54
+ export interface LegacyCleanupResult {
55
+ status: 'ok' | 'partial' | 'failed';
56
+ mode: 'dry-run' | 'apply';
57
+ fileTargets: CleanupTarget[];
58
+ v1Artifacts: V1ArtifactTarget[];
59
+ appliedFiles: number;
60
+ appliedV1Artifacts: number;
61
+ appliedApprovals: number;
62
+ appliedActivations: number;
63
+ errors: string[];
64
+ reason?: string;
65
+ nextAction?: string;
66
+ }
67
+ /**
68
+ * Returns true if the parsed content_json represents a V1 Artificer output
69
+ * (i.e., no valid non-empty `implementationCode` string).
70
+ *
71
+ * V1 = plan-only acceptance path (removed in PRI-439).
72
+ * V2 = unified ArtificerRuleOutput with mandatory implementationCode.
73
+ *
74
+ * Returns false for:
75
+ * - V2 artifacts (with non-empty implementationCode string)
76
+ * - Invalid JSON (skip — do not delete corrupted artifacts)
77
+ * - null/non-object JSON
78
+ */
79
+ export declare function isV1ArtificerArtifact(contentJson: string): boolean;
80
+ /**
81
+ * Queries the SQLite DB for V1 Artificer artifacts.
82
+ *
83
+ * V1 criteria:
84
+ * - pi_artifacts.artifact_kind = 'principle'
85
+ * - tasks.task_kind = 'artificer' (joined via source_task_id)
86
+ * - content_json lacks a non-empty implementationCode (checked in JS via isV1ArtificerArtifact)
87
+ *
88
+ * Returns the list of V1 artifacts with their approval/activation counts.
89
+ */
90
+ export declare function findV1ArtificerArtifacts(db: Database): V1ArtifactTarget[];
91
+ export declare function handleLegacyCleanup(opts: LegacyCleanupOptions): Promise<LegacyCleanupResult>;
26
92
  export {};
27
93
  //# sourceMappingURL=legacy-cleanup.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"legacy-cleanup.d.ts","sourceRoot":"","sources":["../../src/commands/legacy-cleanup.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAMH,UAAU,aAAa;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,QAAQ,GAAG,SAAS,CAAC;IAC7B,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAyID,wBAAsB,mBAAmB,CACvC,aAAa,EAAE,MAAM,EACrB,MAAM,EAAE,OAAO,GACd,OAAO,CAAC;IAAE,OAAO,EAAE,aAAa,EAAE,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC,CAwCxD"}
1
+ {"version":3,"file":"legacy-cleanup.d.ts","sourceRoot":"","sources":["../../src/commands/legacy-cleanup.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAKH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAK/C,UAAU,aAAa;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,QAAQ,GAAG,SAAS,CAAC;IAC7B,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAkBD;;;;;;GAMG;AACH,MAAM,WAAW,gBAAgB;IAC/B,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,MAAM,CAAC;IACtB,eAAe,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,oBAAoB;IACnC,aAAa,EAAE,MAAM,CAAC;IACtB,+DAA+D;IAC/D,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,oDAAoD;IACpD,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,sBAAsB;IACtB,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AAED,MAAM,WAAW,mBAAmB;IAClC,MAAM,EAAE,IAAI,GAAG,SAAS,GAAG,QAAQ,CAAC;IACpC,IAAI,EAAE,SAAS,GAAG,OAAO,CAAC;IAC1B,WAAW,EAAE,aAAa,EAAE,CAAC;IAC7B,WAAW,EAAE,gBAAgB,EAAE,CAAC;IAChC,YAAY,EAAE,MAAM,CAAC;IACrB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,gBAAgB,EAAE,MAAM,CAAC;IACzB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAID;;;;;;;;;;;GAWG;AACH,wBAAgB,qBAAqB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CA0BlE;AAaD;;;;;;;;;GASG;AACH,wBAAgB,wBAAwB,CAAC,EAAE,EAAE,QAAQ,GAAG,gBAAgB,EAAE,CAmCzE;AA2KD,wBAAsB,mBAAmB,CAAC,IAAI,EAAE,oBAAoB,GAAG,OAAO,CAAC,mBAAmB,CAAC,CAsJlG"}