@xenonbyte/da-vinci-workflow 0.1.19 → 0.1.20
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/CHANGELOG.md +12 -0
- package/README.md +20 -1
- package/README.zh-CN.md +14 -1
- package/SKILL.md +4 -0
- package/commands/claude/dv/continue.md +4 -0
- package/commands/codex/prompts/dv-continue.md +4 -0
- package/commands/gemini/dv/continue.toml +4 -0
- package/docs/codex-natural-language-usage.md +3 -0
- package/docs/dv-command-reference.md +3 -0
- package/docs/mode-use-cases.md +2 -0
- package/docs/pencil-rendering-workflow.md +16 -0
- package/docs/prompt-entrypoints.md +7 -0
- package/docs/prompt-presets/README.md +2 -0
- package/docs/prompt-presets/desktop-app.md +4 -0
- package/docs/prompt-presets/mobile-app.md +4 -0
- package/docs/prompt-presets/tablet-app.md +4 -0
- package/docs/prompt-presets/web-app.md +4 -0
- package/docs/workflow-examples.md +2 -0
- package/docs/workflow-overview.md +11 -0
- package/docs/zh-CN/codex-natural-language-usage.md +3 -0
- package/docs/zh-CN/dv-command-reference.md +3 -0
- package/docs/zh-CN/mode-use-cases.md +2 -0
- package/docs/zh-CN/pencil-rendering-workflow.md +16 -0
- package/docs/zh-CN/prompt-entrypoints.md +7 -0
- package/docs/zh-CN/prompt-presets/README.md +2 -0
- package/docs/zh-CN/prompt-presets/desktop-app.md +3 -0
- package/docs/zh-CN/prompt-presets/mobile-app.md +3 -0
- package/docs/zh-CN/prompt-presets/tablet-app.md +3 -0
- package/docs/zh-CN/prompt-presets/web-app.md +3 -0
- package/docs/zh-CN/workflow-examples.md +2 -0
- package/docs/zh-CN/workflow-overview.md +11 -0
- package/lib/audit.js +455 -0
- package/package.json +2 -1
- package/references/artifact-templates.md +38 -0
- package/references/checkpoints.md +16 -0
- package/references/prompt-recipes.md +5 -0
- package/scripts/test-audit-context-delta.js +446 -0
|
@@ -0,0 +1,446 @@
|
|
|
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 { auditProject } = require("../lib/audit");
|
|
8
|
+
|
|
9
|
+
const repo = path.resolve(__dirname, "..");
|
|
10
|
+
const cli = path.join(repo, "bin", "da-vinci.js");
|
|
11
|
+
const fixture = JSON.parse(
|
|
12
|
+
fs.readFileSync(path.join(__dirname, "fixtures", "complex-sample.pen"), "utf8")
|
|
13
|
+
);
|
|
14
|
+
const changeId = "redesign-001";
|
|
15
|
+
|
|
16
|
+
function runTest(name, fn) {
|
|
17
|
+
try {
|
|
18
|
+
fn();
|
|
19
|
+
console.log(`PASS ${name}`);
|
|
20
|
+
} catch (error) {
|
|
21
|
+
console.error(`FAIL ${name}`);
|
|
22
|
+
throw error;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function assertFixtureShape() {
|
|
27
|
+
assert.equal(typeof fixture.version, "string", "fixture.version must be a string");
|
|
28
|
+
assert.ok(fixture.version.length > 0, "fixture.version must be non-empty");
|
|
29
|
+
assert.ok(Array.isArray(fixture.children), "fixture.children must be an array");
|
|
30
|
+
assert.ok(fixture.children.length > 0, "fixture.children must include at least one top-level node");
|
|
31
|
+
assert.equal(typeof fixture.variables, "object", "fixture.variables must be an object");
|
|
32
|
+
assert.ok(fixture.variables && Object.keys(fixture.variables).length > 0, "fixture.variables must be non-empty");
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function createHarness() {
|
|
36
|
+
const base = fs.mkdtempSync(path.join(os.tmpdir(), "da-vinci-audit-context-"));
|
|
37
|
+
return {
|
|
38
|
+
base,
|
|
39
|
+
home: path.join(base, "home")
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function runCli(harness, args) {
|
|
44
|
+
const [command, ...rest] = args;
|
|
45
|
+
const result = spawnSync(process.execPath, [cli, command, "--home", harness.home, ...rest], {
|
|
46
|
+
cwd: repo,
|
|
47
|
+
encoding: "utf8",
|
|
48
|
+
maxBuffer: 8 * 1024 * 1024
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
return {
|
|
52
|
+
code: result.status,
|
|
53
|
+
stdout: (result.stdout || "").trim(),
|
|
54
|
+
stderr: (result.stderr || "").trim()
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function expectOk(step, result) {
|
|
59
|
+
assert.equal(result.code, 0, `${step} failed:\n${result.stderr || result.stdout}`);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
function writeJson(filePath, payload) {
|
|
63
|
+
fs.mkdirSync(path.dirname(filePath), { recursive: true });
|
|
64
|
+
fs.writeFileSync(filePath, JSON.stringify(payload, null, 2));
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
function writeText(filePath, text) {
|
|
68
|
+
fs.mkdirSync(path.dirname(filePath), { recursive: true });
|
|
69
|
+
fs.writeFileSync(filePath, text);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
function setupProject(harness, name, pencilDesignBody) {
|
|
73
|
+
const root = path.join(harness.base, name);
|
|
74
|
+
const daVinciDir = path.join(root, ".da-vinci");
|
|
75
|
+
const changeDir = path.join(daVinciDir, "changes", changeId);
|
|
76
|
+
const penPath = path.join(daVinciDir, "designs", `${name}.pen`);
|
|
77
|
+
const nodesFile = path.join(root, `${name}-nodes.json`);
|
|
78
|
+
const variablesFile = path.join(root, `${name}-variables.json`);
|
|
79
|
+
|
|
80
|
+
writeText(path.join(root, "DA-VINCI.md"), "# DA-VINCI\n");
|
|
81
|
+
writeText(path.join(daVinciDir, "project-inventory.md"), "# Inventory\n");
|
|
82
|
+
writeText(path.join(daVinciDir, "page-map.md"), "# Page Map\n");
|
|
83
|
+
writeText(
|
|
84
|
+
path.join(daVinciDir, "design-registry.md"),
|
|
85
|
+
`# Registry\n- Preferred .pen: .da-vinci/designs/${name}.pen\n`
|
|
86
|
+
);
|
|
87
|
+
writeText(path.join(changeDir, "design-brief.md"), "# Brief\n");
|
|
88
|
+
writeText(path.join(changeDir, "design.md"), "# Design\n");
|
|
89
|
+
writeText(path.join(changeDir, "pencil-bindings.md"), "# Bindings\n");
|
|
90
|
+
writeText(path.join(changeDir, "pencil-design.md"), pencilDesignBody);
|
|
91
|
+
|
|
92
|
+
writeJson(nodesFile, { nodes: fixture.children });
|
|
93
|
+
writeJson(variablesFile, { variables: fixture.variables });
|
|
94
|
+
|
|
95
|
+
expectOk(
|
|
96
|
+
`${name} begin`,
|
|
97
|
+
runCli(harness, ["pencil-session", "begin", "--project", root, "--pen", penPath])
|
|
98
|
+
);
|
|
99
|
+
expectOk(
|
|
100
|
+
`${name} persist`,
|
|
101
|
+
runCli(harness, [
|
|
102
|
+
"pencil-session",
|
|
103
|
+
"persist",
|
|
104
|
+
"--project",
|
|
105
|
+
root,
|
|
106
|
+
"--pen",
|
|
107
|
+
penPath,
|
|
108
|
+
"--nodes-file",
|
|
109
|
+
nodesFile,
|
|
110
|
+
"--variables-file",
|
|
111
|
+
variablesFile,
|
|
112
|
+
"--version",
|
|
113
|
+
fixture.version
|
|
114
|
+
])
|
|
115
|
+
);
|
|
116
|
+
expectOk(
|
|
117
|
+
`${name} end`,
|
|
118
|
+
runCli(harness, [
|
|
119
|
+
"pencil-session",
|
|
120
|
+
"end",
|
|
121
|
+
"--project",
|
|
122
|
+
root,
|
|
123
|
+
"--pen",
|
|
124
|
+
penPath,
|
|
125
|
+
"--nodes-file",
|
|
126
|
+
nodesFile,
|
|
127
|
+
"--variables-file",
|
|
128
|
+
variablesFile,
|
|
129
|
+
"--version",
|
|
130
|
+
fixture.version
|
|
131
|
+
])
|
|
132
|
+
);
|
|
133
|
+
|
|
134
|
+
return {
|
|
135
|
+
root
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
assertFixtureShape();
|
|
140
|
+
|
|
141
|
+
runTest("completion audit warns when checkpoint-bearing artifacts have no concrete context delta", () => {
|
|
142
|
+
const harness = createHarness();
|
|
143
|
+
const project = setupProject(
|
|
144
|
+
harness,
|
|
145
|
+
"missing-context-delta",
|
|
146
|
+
[
|
|
147
|
+
"# Pencil Design",
|
|
148
|
+
"",
|
|
149
|
+
"## MCP Runtime Gate",
|
|
150
|
+
"- Final runtime gate status: PASS",
|
|
151
|
+
"",
|
|
152
|
+
"## Checkpoint Status",
|
|
153
|
+
"- `design checkpoint`: PASS",
|
|
154
|
+
"- `completion gate`: PASS",
|
|
155
|
+
""
|
|
156
|
+
].join("\n")
|
|
157
|
+
);
|
|
158
|
+
|
|
159
|
+
const result = auditProject(project.root, {
|
|
160
|
+
mode: "completion",
|
|
161
|
+
changeId
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
assert.equal(result.status, "WARN");
|
|
165
|
+
assert.equal(result.failures.length, 0);
|
|
166
|
+
assert.match(result.warnings.join("\n"), /Context Delta/i);
|
|
167
|
+
});
|
|
168
|
+
|
|
169
|
+
runTest("completion audit treats Context Delta Required truthy values as expectation signals", () => {
|
|
170
|
+
const harness = createHarness();
|
|
171
|
+
const project = setupProject(
|
|
172
|
+
harness,
|
|
173
|
+
"context-delta-required-yes",
|
|
174
|
+
[
|
|
175
|
+
"# Pencil Design",
|
|
176
|
+
"",
|
|
177
|
+
"- `Context Delta Required`: yes",
|
|
178
|
+
"",
|
|
179
|
+
"## Notes",
|
|
180
|
+
"- Explicit opt-in without checkpoint headings.",
|
|
181
|
+
""
|
|
182
|
+
].join("\n")
|
|
183
|
+
);
|
|
184
|
+
|
|
185
|
+
const result = auditProject(project.root, {
|
|
186
|
+
mode: "completion",
|
|
187
|
+
changeId
|
|
188
|
+
});
|
|
189
|
+
|
|
190
|
+
assert.equal(result.status, "WARN");
|
|
191
|
+
assert.equal(result.failures.length, 0);
|
|
192
|
+
assert.match(result.warnings.join("\n"), /Context Delta/i);
|
|
193
|
+
});
|
|
194
|
+
|
|
195
|
+
runTest("completion audit warns for context-delta and checkpoint status mismatches", () => {
|
|
196
|
+
const harness = createHarness();
|
|
197
|
+
const project = setupProject(
|
|
198
|
+
harness,
|
|
199
|
+
"stale-context-delta",
|
|
200
|
+
[
|
|
201
|
+
"# Pencil Design",
|
|
202
|
+
"",
|
|
203
|
+
"## MCP Runtime Gate",
|
|
204
|
+
"- Final runtime gate status: PASS",
|
|
205
|
+
"",
|
|
206
|
+
"## Checkpoint Status",
|
|
207
|
+
"- `design checkpoint`: PASS",
|
|
208
|
+
"",
|
|
209
|
+
"## Context Delta",
|
|
210
|
+
"- time: 2026-03-28T10:00:00.000Z",
|
|
211
|
+
"- checkpoint_type: design checkpoint",
|
|
212
|
+
"- goal: stabilize anchors",
|
|
213
|
+
"- decision: continue to mapping",
|
|
214
|
+
"- constraints: preserve behavior truth",
|
|
215
|
+
"- impact: keeps design pipeline moving",
|
|
216
|
+
"- status: WARN",
|
|
217
|
+
"- next_action: run mapping checkpoint",
|
|
218
|
+
""
|
|
219
|
+
].join("\n")
|
|
220
|
+
);
|
|
221
|
+
|
|
222
|
+
const result = auditProject(project.root, {
|
|
223
|
+
mode: "completion",
|
|
224
|
+
changeId
|
|
225
|
+
});
|
|
226
|
+
|
|
227
|
+
assert.equal(result.status, "WARN");
|
|
228
|
+
assert.equal(result.failures.length, 0);
|
|
229
|
+
assert.match(result.warnings.join("\n"), /status mismatch/i);
|
|
230
|
+
});
|
|
231
|
+
|
|
232
|
+
runTest("completion audit passes when context-delta and checkpoint status are aligned", () => {
|
|
233
|
+
const harness = createHarness();
|
|
234
|
+
const project = setupProject(
|
|
235
|
+
harness,
|
|
236
|
+
"healthy-context-delta",
|
|
237
|
+
[
|
|
238
|
+
"# Pencil Design",
|
|
239
|
+
"",
|
|
240
|
+
"## MCP Runtime Gate",
|
|
241
|
+
"- Final runtime gate status: PASS",
|
|
242
|
+
"",
|
|
243
|
+
"## Checkpoint Status",
|
|
244
|
+
"- `design checkpoint`: PASS",
|
|
245
|
+
"",
|
|
246
|
+
"## Context Delta",
|
|
247
|
+
"- time: 2026-03-28T11:00:00.000Z",
|
|
248
|
+
"- checkpoint_type: design checkpoint",
|
|
249
|
+
"- goal: stabilize anchors",
|
|
250
|
+
"- decision: continue to mapping",
|
|
251
|
+
"- constraints: preserve behavior truth",
|
|
252
|
+
"- impact: keeps design pipeline moving",
|
|
253
|
+
"- status: PASS",
|
|
254
|
+
"- next_action: run mapping checkpoint",
|
|
255
|
+
""
|
|
256
|
+
].join("\n")
|
|
257
|
+
);
|
|
258
|
+
|
|
259
|
+
const result = auditProject(project.root, {
|
|
260
|
+
mode: "completion",
|
|
261
|
+
changeId
|
|
262
|
+
});
|
|
263
|
+
|
|
264
|
+
assert.equal(result.status, "PASS");
|
|
265
|
+
assert.equal(result.failures.length, 0);
|
|
266
|
+
assert.equal(result.warnings.length, 0);
|
|
267
|
+
});
|
|
268
|
+
|
|
269
|
+
runTest("completion audit ignores verification outcome-only artifacts for context-delta expectations", () => {
|
|
270
|
+
const harness = createHarness();
|
|
271
|
+
const project = setupProject(
|
|
272
|
+
harness,
|
|
273
|
+
"outcome-only-verification",
|
|
274
|
+
[
|
|
275
|
+
"# Pencil Design",
|
|
276
|
+
"",
|
|
277
|
+
"## Notes",
|
|
278
|
+
"- No checkpoint headings in this artifact.",
|
|
279
|
+
""
|
|
280
|
+
].join("\n")
|
|
281
|
+
);
|
|
282
|
+
|
|
283
|
+
writeText(
|
|
284
|
+
path.join(project.root, ".da-vinci", "changes", changeId, "verification.md"),
|
|
285
|
+
[
|
|
286
|
+
"# Verification",
|
|
287
|
+
"",
|
|
288
|
+
"## Outcome",
|
|
289
|
+
"- PASS",
|
|
290
|
+
"- Next action: none",
|
|
291
|
+
""
|
|
292
|
+
].join("\n")
|
|
293
|
+
);
|
|
294
|
+
|
|
295
|
+
const result = auditProject(project.root, {
|
|
296
|
+
mode: "completion",
|
|
297
|
+
changeId
|
|
298
|
+
});
|
|
299
|
+
|
|
300
|
+
assert.equal(result.status, "PASS");
|
|
301
|
+
assert.equal(result.failures.length, 0);
|
|
302
|
+
assert.equal(result.warnings.length, 0);
|
|
303
|
+
});
|
|
304
|
+
|
|
305
|
+
runTest("completion audit warns when supersedes references missing context-delta entries", () => {
|
|
306
|
+
const harness = createHarness();
|
|
307
|
+
const project = setupProject(
|
|
308
|
+
harness,
|
|
309
|
+
"invalid-supersedes",
|
|
310
|
+
[
|
|
311
|
+
"# Pencil Design",
|
|
312
|
+
"",
|
|
313
|
+
"## MCP Runtime Gate",
|
|
314
|
+
"- Final runtime gate status: PASS",
|
|
315
|
+
"",
|
|
316
|
+
"## Checkpoint Status",
|
|
317
|
+
"- `design checkpoint`: PASS",
|
|
318
|
+
"",
|
|
319
|
+
"## Context Delta",
|
|
320
|
+
"- time: 2026-03-28T12:00:00.000Z",
|
|
321
|
+
"- checkpoint_type: design checkpoint",
|
|
322
|
+
"- goal: stabilize anchors",
|
|
323
|
+
"- decision: finish current anchor pass",
|
|
324
|
+
"- constraints: preserve behavior truth",
|
|
325
|
+
"- impact: keeps mapping handoff stable",
|
|
326
|
+
"- status: PASS",
|
|
327
|
+
"- next_action: prepare mapping checkpoint",
|
|
328
|
+
"",
|
|
329
|
+
"- time: 2026-03-28T13:00:00.000Z",
|
|
330
|
+
"- checkpoint_type: design checkpoint",
|
|
331
|
+
"- goal: finalize status consistency",
|
|
332
|
+
"- decision: retain PASS and continue",
|
|
333
|
+
"- constraints: keep traceability",
|
|
334
|
+
"- impact: no gating change",
|
|
335
|
+
"- status: PASS",
|
|
336
|
+
"- supersedes: 2026-03-28T09:00:00.000Z",
|
|
337
|
+
"- next_action: close design phase",
|
|
338
|
+
""
|
|
339
|
+
].join("\n")
|
|
340
|
+
);
|
|
341
|
+
|
|
342
|
+
const result = auditProject(project.root, {
|
|
343
|
+
mode: "completion",
|
|
344
|
+
changeId
|
|
345
|
+
});
|
|
346
|
+
|
|
347
|
+
assert.equal(result.status, "WARN");
|
|
348
|
+
assert.equal(result.failures.length, 0);
|
|
349
|
+
assert.match(result.warnings.join("\n"), /supersed/i);
|
|
350
|
+
});
|
|
351
|
+
|
|
352
|
+
runTest("completion audit accepts valid supersedes references to earlier context-delta entries", () => {
|
|
353
|
+
const harness = createHarness();
|
|
354
|
+
const project = setupProject(
|
|
355
|
+
harness,
|
|
356
|
+
"valid-supersedes",
|
|
357
|
+
[
|
|
358
|
+
"# Pencil Design",
|
|
359
|
+
"",
|
|
360
|
+
"## MCP Runtime Gate",
|
|
361
|
+
"- Final runtime gate status: PASS",
|
|
362
|
+
"",
|
|
363
|
+
"## Checkpoint Status",
|
|
364
|
+
"- `design checkpoint`: PASS",
|
|
365
|
+
"",
|
|
366
|
+
"## Context Delta",
|
|
367
|
+
"- time: 2026-03-28T12:00:00.000Z",
|
|
368
|
+
"- checkpoint_type: design checkpoint",
|
|
369
|
+
"- goal: stabilize anchors",
|
|
370
|
+
"- decision: finish current anchor pass",
|
|
371
|
+
"- constraints: preserve behavior truth",
|
|
372
|
+
"- impact: keeps mapping handoff stable",
|
|
373
|
+
"- status: PASS",
|
|
374
|
+
"- next_action: prepare mapping checkpoint",
|
|
375
|
+
"",
|
|
376
|
+
"- time: 2026-03-28T13:00:00.000Z",
|
|
377
|
+
"- checkpoint_type: design checkpoint",
|
|
378
|
+
"- goal: finalize status consistency",
|
|
379
|
+
"- decision: retain PASS and continue",
|
|
380
|
+
"- constraints: keep traceability",
|
|
381
|
+
"- impact: no gating change",
|
|
382
|
+
"- status: PASS",
|
|
383
|
+
"- supersedes: 2026-03-28T12:00:00.000Z",
|
|
384
|
+
"- next_action: close design phase",
|
|
385
|
+
""
|
|
386
|
+
].join("\n")
|
|
387
|
+
);
|
|
388
|
+
|
|
389
|
+
const result = auditProject(project.root, {
|
|
390
|
+
mode: "completion",
|
|
391
|
+
changeId
|
|
392
|
+
});
|
|
393
|
+
|
|
394
|
+
assert.equal(result.status, "PASS");
|
|
395
|
+
assert.equal(result.failures.length, 0);
|
|
396
|
+
assert.equal(result.warnings.length, 0);
|
|
397
|
+
});
|
|
398
|
+
|
|
399
|
+
runTest("completion audit accepts supersedes when timestamp formats differ but normalize to same time", () => {
|
|
400
|
+
const harness = createHarness();
|
|
401
|
+
const project = setupProject(
|
|
402
|
+
harness,
|
|
403
|
+
"normalized-time-supersedes",
|
|
404
|
+
[
|
|
405
|
+
"# Pencil Design",
|
|
406
|
+
"",
|
|
407
|
+
"## MCP Runtime Gate",
|
|
408
|
+
"- Final runtime gate status: PASS",
|
|
409
|
+
"",
|
|
410
|
+
"## Checkpoint Status",
|
|
411
|
+
"- `design checkpoint`: PASS",
|
|
412
|
+
"",
|
|
413
|
+
"## Context Delta",
|
|
414
|
+
"- time: 2026-03-28T12:00:00.000Z",
|
|
415
|
+
"- checkpoint_type: design checkpoint",
|
|
416
|
+
"- goal: stabilize anchors",
|
|
417
|
+
"- decision: pass design checkpoint",
|
|
418
|
+
"- constraints: preserve behavior truth",
|
|
419
|
+
"- impact: ready for mapping",
|
|
420
|
+
"- status: PASS",
|
|
421
|
+
"- next_action: run mapping checkpoint",
|
|
422
|
+
"",
|
|
423
|
+
"- time: 2026-03-28T13:00:00.000Z",
|
|
424
|
+
"- checkpoint_type: design checkpoint",
|
|
425
|
+
"- goal: retain continuity",
|
|
426
|
+
"- decision: keep status stable",
|
|
427
|
+
"- constraints: no regressions",
|
|
428
|
+
"- impact: no gate changes",
|
|
429
|
+
"- status: PASS",
|
|
430
|
+
"- supersedes: design checkpoint@2026-03-28 12:00:00Z",
|
|
431
|
+
"- next_action: continue implementation prep",
|
|
432
|
+
""
|
|
433
|
+
].join("\n")
|
|
434
|
+
);
|
|
435
|
+
|
|
436
|
+
const result = auditProject(project.root, {
|
|
437
|
+
mode: "completion",
|
|
438
|
+
changeId
|
|
439
|
+
});
|
|
440
|
+
|
|
441
|
+
assert.equal(result.status, "PASS");
|
|
442
|
+
assert.equal(result.failures.length, 0);
|
|
443
|
+
assert.equal(result.warnings.length, 0);
|
|
444
|
+
});
|
|
445
|
+
|
|
446
|
+
console.log("All audit context-delta tests passed.");
|