@xenonbyte/da-vinci-workflow 0.1.23 → 0.1.24

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,619 @@
1
+ const assert = require("assert/strict");
2
+ const fs = require("fs");
3
+ const os = require("os");
4
+ const path = require("path");
5
+ const { spawnSync } = require("child_process");
6
+
7
+ const repo = path.resolve(__dirname, "..");
8
+ const daVinciBin = path.join(repo, "bin", "da-vinci.js");
9
+ const designSupervisorBin = path.join(repo, "bin", "design-supervisor.js");
10
+ const fixture = JSON.parse(
11
+ fs.readFileSync(path.join(__dirname, "fixtures", "complex-sample.pen"), "utf8")
12
+ );
13
+
14
+ function runTest(name, fn) {
15
+ try {
16
+ fn();
17
+ console.log(`PASS ${name}`);
18
+ } catch (error) {
19
+ console.error(`FAIL ${name}`);
20
+ throw error;
21
+ }
22
+ }
23
+
24
+ function runNodeScript(scriptPath, args, env = process.env) {
25
+ return spawnSync(process.execPath, [scriptPath, ...args], {
26
+ cwd: repo,
27
+ encoding: "utf8",
28
+ maxBuffer: 8 * 1024 * 1024,
29
+ env
30
+ });
31
+ }
32
+
33
+ function runDaVinci(args, options = {}) {
34
+ const finalArgs = Array.isArray(args) ? [...args] : [];
35
+ if (options.home && finalArgs.length > 0) {
36
+ finalArgs.splice(1, 0, "--home", options.home);
37
+ }
38
+ return runNodeScript(daVinciBin, finalArgs, options.env || process.env);
39
+ }
40
+
41
+ function writeText(filePath, text) {
42
+ fs.mkdirSync(path.dirname(filePath), { recursive: true });
43
+ fs.writeFileSync(filePath, text);
44
+ }
45
+
46
+ function writeJson(filePath, payload) {
47
+ fs.mkdirSync(path.dirname(filePath), { recursive: true });
48
+ fs.writeFileSync(filePath, JSON.stringify(payload, null, 2));
49
+ }
50
+
51
+ function writeDaVinci(root, reviewers = ["frontend-skill"]) {
52
+ writeText(
53
+ path.join(root, "DA-VINCI.md"),
54
+ [
55
+ "# DA-VINCI",
56
+ "",
57
+ "## Visual Assist",
58
+ "- Preferred adapters:",
59
+ " - frontend-skill",
60
+ "- Design-supervisor reviewers:",
61
+ ...reviewers.map((reviewer) => ` - ${reviewer}`),
62
+ "- Require Supervisor Review:",
63
+ " - true",
64
+ ""
65
+ ].join("\n")
66
+ );
67
+ }
68
+
69
+ runTest("design-supervisor alias writes a structured review section", () => {
70
+ const base = fs.mkdtempSync(path.join(os.tmpdir(), "da-vinci-supervisor-cli-"));
71
+ const projectRoot = path.join(base, "project");
72
+ const pencilDesignPath = path.join(
73
+ projectRoot,
74
+ ".da-vinci",
75
+ "changes",
76
+ "change-001",
77
+ "pencil-design.md"
78
+ );
79
+
80
+ writeText(
81
+ pencilDesignPath,
82
+ [
83
+ "# Pencil Design",
84
+ "",
85
+ "## Screenshot Review Records",
86
+ "- `A_HOME` => `PASS`",
87
+ "",
88
+ "## Checkpoint Status",
89
+ "- Design checkpoint: `PASS`",
90
+ "",
91
+ "## Context Delta",
92
+ "- time: 2026-03-29T12:00:00Z",
93
+ "- checkpoint_type: Design checkpoint",
94
+ "- decision: supervisor review closed with PASS",
95
+ "- status: PASS",
96
+ "- next_action: run completion audit",
97
+ ""
98
+ ].join("\n")
99
+ );
100
+ writeDaVinci(projectRoot);
101
+
102
+ const result = runNodeScript(designSupervisorBin, [
103
+ "review",
104
+ "--project",
105
+ projectRoot,
106
+ "--change",
107
+ "change-001",
108
+ "--status",
109
+ "PASS",
110
+ "--issue-list",
111
+ "none",
112
+ "--revision-outcome",
113
+ "approved",
114
+ "--write"
115
+ ]);
116
+
117
+ assert.equal(result.status, 0, result.stderr || result.stdout);
118
+ const updated = fs.readFileSync(pencilDesignPath, "utf8");
119
+ assert.match(updated, /## Design-Supervisor Review \(CLI /);
120
+ assert.match(updated, /- Status: PASS/);
121
+ assert.match(updated, /- Issue list: none/);
122
+ assert.match(updated, /- Revision outcome: approved/);
123
+ });
124
+
125
+ runTest("design-supervisor alias supports review --help", () => {
126
+ const result = runNodeScript(designSupervisorBin, ["review", "--help"]);
127
+ assert.equal(result.status, 0, result.stderr || result.stdout);
128
+ assert.match(String(result.stdout || ""), /da-vinci supervisor-review/i);
129
+ });
130
+
131
+ runTest("da-vinci supervisor-review infers WARN from checkpoint state", () => {
132
+ const base = fs.mkdtempSync(path.join(os.tmpdir(), "da-vinci-supervisor-cli-"));
133
+ const projectRoot = path.join(base, "project");
134
+ const pencilDesignPath = path.join(
135
+ projectRoot,
136
+ ".da-vinci",
137
+ "changes",
138
+ "change-002",
139
+ "pencil-design.md"
140
+ );
141
+
142
+ writeText(
143
+ pencilDesignPath,
144
+ [
145
+ "# Pencil Design",
146
+ "",
147
+ "## Screenshot Review Records",
148
+ "- `A_HOME` => `PASS`",
149
+ "",
150
+ "## Checkpoint Status",
151
+ "- Design checkpoint: `WARN`",
152
+ ""
153
+ ].join("\n")
154
+ );
155
+ writeDaVinci(projectRoot);
156
+
157
+ const result = runNodeScript(daVinciBin, [
158
+ "supervisor-review",
159
+ "--project",
160
+ projectRoot,
161
+ "--change",
162
+ "change-002",
163
+ "--json"
164
+ ]);
165
+
166
+ assert.equal(result.status, 0, result.stderr || result.stdout);
167
+ const payload = JSON.parse(String(result.stdout || "{}").trim());
168
+ assert.equal(payload.status, "WARN");
169
+ assert.match(payload.issueList, /Design checkpoint/i);
170
+ assert.equal(payload.source, "inferred");
171
+ });
172
+
173
+ runTest("da-vinci supervisor-review skill source auto-populates executed reviewers from config", () => {
174
+ const base = fs.mkdtempSync(path.join(os.tmpdir(), "da-vinci-supervisor-cli-"));
175
+ const projectRoot = path.join(base, "project");
176
+ const pencilDesignPath = path.join(
177
+ projectRoot,
178
+ ".da-vinci",
179
+ "changes",
180
+ "change-003",
181
+ "pencil-design.md"
182
+ );
183
+
184
+ writeText(
185
+ pencilDesignPath,
186
+ [
187
+ "# Pencil Design",
188
+ "",
189
+ "## Screenshot Review Records",
190
+ "- `A_HOME` => `PASS`",
191
+ "",
192
+ "## Checkpoint Status",
193
+ "- Design checkpoint: `PASS`",
194
+ "",
195
+ "## Context Delta",
196
+ "- time: 2026-03-29T12:00:00Z",
197
+ "- checkpoint_type: Design checkpoint",
198
+ "- decision: supervisor review closed with PASS",
199
+ "- status: PASS",
200
+ "- next_action: run completion audit",
201
+ ""
202
+ ].join("\n")
203
+ );
204
+ writeDaVinci(projectRoot, ["frontend-skill", "ui-ux-pro-max"]);
205
+
206
+ const result = runNodeScript(daVinciBin, [
207
+ "supervisor-review",
208
+ "--project",
209
+ projectRoot,
210
+ "--change",
211
+ "change-003",
212
+ "--source",
213
+ "skill",
214
+ "--status",
215
+ "PASS",
216
+ "--issue-list",
217
+ "none",
218
+ "--revision-outcome",
219
+ "approved",
220
+ "--json"
221
+ ]);
222
+
223
+ assert.equal(result.status, 0, result.stderr || result.stdout);
224
+ const payload = JSON.parse(String(result.stdout || "{}").trim());
225
+ assert.equal(payload.source, "skill");
226
+ assert.deepEqual(payload.configuredReviewers, ["frontend-skill", "ui-ux-pro-max"]);
227
+ assert.deepEqual(payload.executedReviewers, ["frontend-skill", "ui-ux-pro-max"]);
228
+ });
229
+
230
+ runTest("da-vinci supervisor-review can auto-run configured reviewers via codex bridge", () => {
231
+ const base = fs.mkdtempSync(path.join(os.tmpdir(), "da-vinci-supervisor-cli-"));
232
+ const projectRoot = path.join(base, "project");
233
+ const pencilDesignPath = path.join(
234
+ projectRoot,
235
+ ".da-vinci",
236
+ "changes",
237
+ "change-004",
238
+ "pencil-design.md"
239
+ );
240
+ const exportsDir = path.join(projectRoot, ".da-vinci", "changes", "change-004", "exports");
241
+ fs.mkdirSync(exportsDir, { recursive: true });
242
+ fs.writeFileSync(path.join(exportsDir, "anchor.png"), "fake");
243
+ writeDaVinci(projectRoot, ["frontend-skill", "ui-ux-pro-max"]);
244
+ writeText(
245
+ pencilDesignPath,
246
+ [
247
+ "# Pencil Design",
248
+ "",
249
+ "## Screenshot Review Records",
250
+ "- `A_HOME` => `PASS`",
251
+ "",
252
+ "## Checkpoint Status",
253
+ "- Design checkpoint: `PASS`",
254
+ ""
255
+ ].join("\n")
256
+ );
257
+
258
+ const fakeCodexPath = path.join(base, "fake-codex.js");
259
+ writeText(
260
+ fakeCodexPath,
261
+ [
262
+ "#!/usr/bin/env node",
263
+ "const fs = require('fs');",
264
+ "const args = process.argv.slice(2);",
265
+ "const outputFlag = args.indexOf('--output-last-message');",
266
+ "if (outputFlag < 0) { process.exit(2); }",
267
+ "const outPath = args[outputFlag + 1];",
268
+ "const prompt = args[args.length - 1] || '';",
269
+ "const reviewer = /`([^`]+)`/.exec(prompt);",
270
+ "const reviewerName = reviewer ? reviewer[1] : 'unknown';",
271
+ "const payload = {",
272
+ " status: 'PASS',",
273
+ " issues: [],",
274
+ " revision_outcome: `approved by ${reviewerName}`",
275
+ "};",
276
+ "fs.writeFileSync(outPath, JSON.stringify(payload));"
277
+ ].join("\n")
278
+ );
279
+ fs.chmodSync(fakeCodexPath, 0o755);
280
+
281
+ const result = runNodeScript(
282
+ daVinciBin,
283
+ [
284
+ "supervisor-review",
285
+ "--project",
286
+ projectRoot,
287
+ "--change",
288
+ "change-004",
289
+ "--run-reviewers",
290
+ "--codex-bin",
291
+ fakeCodexPath,
292
+ "--write",
293
+ "--json"
294
+ ],
295
+ {
296
+ ...process.env,
297
+ DA_VINCI_CODEX_BIN: fakeCodexPath
298
+ }
299
+ );
300
+
301
+ assert.equal(result.status, 0, result.stderr || result.stdout);
302
+ const payload = JSON.parse(String(result.stdout || "{}").trim());
303
+ assert.equal(payload.source, "skill");
304
+ assert.deepEqual(payload.executedReviewers, ["frontend-skill", "ui-ux-pro-max"]);
305
+ assert.equal(payload.wrote, true);
306
+
307
+ const updated = fs.readFileSync(pencilDesignPath, "utf8");
308
+ assert.match(updated, /- Review source: skill/);
309
+ assert.match(updated, /- Executed reviewers: frontend-skill, ui-ux-pro-max/);
310
+ });
311
+
312
+ runTest("da-vinci supervisor-review retries transient reviewer failures", () => {
313
+ const base = fs.mkdtempSync(path.join(os.tmpdir(), "da-vinci-supervisor-cli-"));
314
+ const projectRoot = path.join(base, "project");
315
+ const changeId = "change-004b";
316
+ const pencilDesignPath = path.join(
317
+ projectRoot,
318
+ ".da-vinci",
319
+ "changes",
320
+ changeId,
321
+ "pencil-design.md"
322
+ );
323
+
324
+ writeDaVinci(projectRoot, ["frontend-skill"]);
325
+ writeText(
326
+ pencilDesignPath,
327
+ [
328
+ "# Pencil Design",
329
+ "",
330
+ "## Screenshot Review Records",
331
+ "- `A_HOME` => `PASS`",
332
+ "",
333
+ "## Checkpoint Status",
334
+ "- Design checkpoint: `PASS`",
335
+ ""
336
+ ].join("\n")
337
+ );
338
+
339
+ const fakeCodexPath = path.join(base, "fake-codex-retry.js");
340
+ const statePath = path.join(base, "retry-state.json");
341
+ writeText(
342
+ fakeCodexPath,
343
+ [
344
+ "#!/usr/bin/env node",
345
+ "const fs = require('fs');",
346
+ "const args = process.argv.slice(2);",
347
+ "const outputFlag = args.indexOf('--output-last-message');",
348
+ "if (outputFlag < 0) { process.exit(2); }",
349
+ "const outPath = args[outputFlag + 1];",
350
+ "const statePath = process.env.DA_VINCI_FAKE_STATE;",
351
+ "let count = 0;",
352
+ "if (statePath && fs.existsSync(statePath)) {",
353
+ " const payload = JSON.parse(fs.readFileSync(statePath, 'utf8'));",
354
+ " count = Number(payload.count || 0);",
355
+ "}",
356
+ "count += 1;",
357
+ "if (statePath) {",
358
+ " fs.writeFileSync(statePath, JSON.stringify({ count }));",
359
+ "}",
360
+ "if (count === 1) {",
361
+ " console.error('transient failure');",
362
+ " process.exit(1);",
363
+ "}",
364
+ "const payload = { status: 'PASS', issues: [], revision_outcome: 'approved' };",
365
+ "fs.writeFileSync(outPath, JSON.stringify(payload));"
366
+ ].join("\n")
367
+ );
368
+ fs.chmodSync(fakeCodexPath, 0o755);
369
+
370
+ const result = runNodeScript(
371
+ daVinciBin,
372
+ [
373
+ "supervisor-review",
374
+ "--project",
375
+ projectRoot,
376
+ "--change",
377
+ changeId,
378
+ "--run-reviewers",
379
+ "--review-retries",
380
+ "1",
381
+ "--review-retry-delay-ms",
382
+ "10",
383
+ "--codex-bin",
384
+ fakeCodexPath,
385
+ "--json"
386
+ ],
387
+ {
388
+ ...process.env,
389
+ DA_VINCI_CODEX_BIN: fakeCodexPath,
390
+ DA_VINCI_FAKE_STATE: statePath
391
+ }
392
+ );
393
+
394
+ assert.equal(result.status, 0, result.stderr || result.stdout);
395
+ const payload = JSON.parse(String(result.stdout || "{}").trim());
396
+ assert.equal(payload.status, "PASS");
397
+ assert.equal(payload.reviewerAttempts["frontend-skill"], 2);
398
+ });
399
+
400
+ runTest("da-vinci supervisor-review can run reviewers in parallel", () => {
401
+ const base = fs.mkdtempSync(path.join(os.tmpdir(), "da-vinci-supervisor-cli-"));
402
+ const projectRoot = path.join(base, "project");
403
+ const changeId = "change-004c";
404
+ const pencilDesignPath = path.join(
405
+ projectRoot,
406
+ ".da-vinci",
407
+ "changes",
408
+ changeId,
409
+ "pencil-design.md"
410
+ );
411
+
412
+ writeDaVinci(projectRoot, ["frontend-skill", "ui-ux-pro-max"]);
413
+ writeText(
414
+ pencilDesignPath,
415
+ [
416
+ "# Pencil Design",
417
+ "",
418
+ "## Screenshot Review Records",
419
+ "- `A_HOME` => `PASS`",
420
+ "",
421
+ "## Checkpoint Status",
422
+ "- Design checkpoint: `PASS`",
423
+ ""
424
+ ].join("\n")
425
+ );
426
+
427
+ const fakeCodexPath = path.join(base, "fake-codex-parallel.js");
428
+ writeText(
429
+ fakeCodexPath,
430
+ [
431
+ "#!/usr/bin/env node",
432
+ "const fs = require('fs');",
433
+ "const args = process.argv.slice(2);",
434
+ "const outputFlag = args.indexOf('--output-last-message');",
435
+ "if (outputFlag < 0) { process.exit(2); }",
436
+ "const outPath = args[outputFlag + 1];",
437
+ "Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, 800);",
438
+ "const payload = { status: 'PASS', issues: [], revision_outcome: 'approved' };",
439
+ "fs.writeFileSync(outPath, JSON.stringify(payload));"
440
+ ].join("\n")
441
+ );
442
+ fs.chmodSync(fakeCodexPath, 0o755);
443
+
444
+ const start = Date.now();
445
+ const result = runNodeScript(
446
+ daVinciBin,
447
+ [
448
+ "supervisor-review",
449
+ "--project",
450
+ projectRoot,
451
+ "--change",
452
+ changeId,
453
+ "--run-reviewers",
454
+ "--review-concurrency",
455
+ "2",
456
+ "--review-retries",
457
+ "0",
458
+ "--codex-bin",
459
+ fakeCodexPath,
460
+ "--json"
461
+ ],
462
+ {
463
+ ...process.env,
464
+ DA_VINCI_CODEX_BIN: fakeCodexPath
465
+ }
466
+ );
467
+ const elapsedMs = Date.now() - start;
468
+
469
+ assert.equal(result.status, 0, result.stderr || result.stdout);
470
+ const payload = JSON.parse(String(result.stdout || "{}").trim());
471
+ assert.equal(payload.reviewConcurrency, 2);
472
+ assert.equal(payload.reviewerAttempts["frontend-skill"], 1);
473
+ assert.equal(payload.reviewerAttempts["ui-ux-pro-max"], 1);
474
+ assert.ok(elapsedMs < 1450, `expected parallel execution under 1450ms, got ${elapsedMs}ms`);
475
+ });
476
+
477
+ runTest("completion audit passes after skill-based supervisor-review write", () => {
478
+ const base = fs.mkdtempSync(path.join(os.tmpdir(), "da-vinci-supervisor-cli-"));
479
+ const home = path.join(base, "home");
480
+ const projectRoot = path.join(base, "project");
481
+ const changeId = "change-005";
482
+ const daVinciDir = path.join(projectRoot, ".da-vinci");
483
+ const changeDir = path.join(daVinciDir, "changes", changeId);
484
+ const pencilDesignPath = path.join(changeDir, "pencil-design.md");
485
+ const penPath = path.join(daVinciDir, "designs", "reviewed.pen");
486
+ const nodesFile = path.join(base, "nodes.json");
487
+ const variablesFile = path.join(base, "variables.json");
488
+ const exportsDir = path.join(changeDir, "exports");
489
+
490
+ writeDaVinci(projectRoot, ["frontend-skill", "ui-ux-pro-max"]);
491
+ writeText(path.join(daVinciDir, "project-inventory.md"), "# Inventory\n");
492
+ writeText(path.join(daVinciDir, "page-map.md"), "# Page Map\n");
493
+ writeText(
494
+ path.join(daVinciDir, "design-registry.md"),
495
+ "# Registry\n- Preferred .pen: .da-vinci/designs/reviewed.pen\n"
496
+ );
497
+ writeText(path.join(changeDir, "design-brief.md"), "# Brief\n");
498
+ writeText(path.join(changeDir, "design.md"), "# Design\n");
499
+ writeText(path.join(changeDir, "pencil-bindings.md"), "# Bindings\n");
500
+ writeText(
501
+ pencilDesignPath,
502
+ [
503
+ "# Pencil Design",
504
+ "",
505
+ "## Screenshot Review Records",
506
+ "- `A_HOME` => `PASS`",
507
+ "",
508
+ "## Checkpoint Status",
509
+ "- Design checkpoint: `PASS`",
510
+ "",
511
+ "## Context Delta",
512
+ "- time: 2026-03-29T12:00:00Z",
513
+ "- checkpoint_type: Design checkpoint",
514
+ "- decision: supervisor review closed with PASS",
515
+ "- status: PASS",
516
+ "- next_action: run completion audit",
517
+ ""
518
+ ].join("\n")
519
+ );
520
+ fs.mkdirSync(exportsDir, { recursive: true });
521
+ fs.writeFileSync(path.join(exportsDir, "anchor.png"), "fake");
522
+ writeJson(nodesFile, { nodes: fixture.children });
523
+ writeJson(variablesFile, { variables: fixture.variables });
524
+
525
+ let result = runDaVinci(
526
+ ["pencil-session", "begin", "--project", projectRoot, "--pen", penPath],
527
+ { home }
528
+ );
529
+ assert.equal(result.status, 0, result.stderr || result.stdout);
530
+
531
+ result = runDaVinci(
532
+ [
533
+ "pencil-session",
534
+ "persist",
535
+ "--project",
536
+ projectRoot,
537
+ "--pen",
538
+ penPath,
539
+ "--nodes-file",
540
+ nodesFile,
541
+ "--variables-file",
542
+ variablesFile,
543
+ "--version",
544
+ fixture.version
545
+ ],
546
+ { home }
547
+ );
548
+ assert.equal(result.status, 0, result.stderr || result.stdout);
549
+
550
+ result = runDaVinci(
551
+ [
552
+ "pencil-session",
553
+ "end",
554
+ "--project",
555
+ projectRoot,
556
+ "--pen",
557
+ penPath,
558
+ "--nodes-file",
559
+ nodesFile,
560
+ "--variables-file",
561
+ variablesFile,
562
+ "--version",
563
+ fixture.version
564
+ ],
565
+ { home }
566
+ );
567
+ assert.equal(result.status, 0, result.stderr || result.stdout);
568
+
569
+ const fakeCodexPath = path.join(base, "fake-codex.js");
570
+ writeText(
571
+ fakeCodexPath,
572
+ [
573
+ "#!/usr/bin/env node",
574
+ "const fs = require('fs');",
575
+ "const args = process.argv.slice(2);",
576
+ "const outputFlag = args.indexOf('--output-last-message');",
577
+ "if (outputFlag < 0) { process.exit(2); }",
578
+ "const outPath = args[outputFlag + 1];",
579
+ "const payload = {",
580
+ " status: 'PASS',",
581
+ " issues: [],",
582
+ " revision_outcome: 'approved'",
583
+ "};",
584
+ "fs.writeFileSync(outPath, JSON.stringify(payload));"
585
+ ].join("\n")
586
+ );
587
+ fs.chmodSync(fakeCodexPath, 0o755);
588
+
589
+ result = runDaVinci(
590
+ [
591
+ "supervisor-review",
592
+ "--project",
593
+ projectRoot,
594
+ "--change",
595
+ changeId,
596
+ "--run-reviewers",
597
+ "--codex-bin",
598
+ fakeCodexPath,
599
+ "--write"
600
+ ],
601
+ {
602
+ home,
603
+ env: {
604
+ ...process.env,
605
+ DA_VINCI_CODEX_BIN: fakeCodexPath
606
+ }
607
+ }
608
+ );
609
+ assert.equal(result.status, 0, result.stderr || result.stdout);
610
+
611
+ result = runDaVinci(
612
+ ["audit", "--project", projectRoot, "--mode", "completion", "--change", changeId],
613
+ { home }
614
+ );
615
+ assert.equal(result.status, 0, result.stderr || result.stdout);
616
+ assert.match(String(result.stdout || ""), /Status: PASS/);
617
+ });
618
+
619
+ console.log("All supervisor-review CLI tests passed.");