@xenonbyte/da-vinci-workflow 0.1.17 → 0.1.19
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 +29 -0
- package/README.md +73 -4
- package/README.zh-CN.md +72 -5
- package/SKILL.md +64 -2
- package/commands/claude/da-vinci.md +1 -0
- package/commands/claude/dv/continue.md +2 -0
- package/commands/claude/dv/design.md +3 -2
- package/commands/claude/dv/intake.md +2 -0
- package/commands/codex/prompts/da-vinci.md +1 -0
- package/commands/codex/prompts/dv-continue.md +2 -0
- package/commands/codex/prompts/dv-design.md +3 -2
- package/commands/codex/prompts/dv-intake.md +2 -1
- package/commands/gemini/da-vinci.toml +1 -0
- package/commands/gemini/dv/continue.toml +2 -0
- package/commands/gemini/dv/design.toml +3 -2
- package/commands/gemini/dv/intake.toml +2 -0
- package/docs/codex-natural-language-usage.md +10 -0
- package/docs/dv-command-reference.md +402 -0
- package/docs/mode-use-cases.md +95 -3
- package/docs/pencil-rendering-workflow.md +279 -0
- package/docs/prompt-entrypoints.md +28 -0
- package/docs/prompt-presets/README.md +82 -1
- package/docs/prompt-presets/desktop-app.md +103 -5
- package/docs/prompt-presets/mobile-app.md +103 -5
- package/docs/prompt-presets/tablet-app.md +103 -5
- package/docs/prompt-presets/web-app.md +103 -5
- package/docs/visual-adapters.md +190 -0
- package/docs/visual-assist-presets/README.md +28 -5
- package/docs/visual-assist-presets/desktop-app.md +88 -2
- package/docs/visual-assist-presets/mobile-app.md +89 -2
- package/docs/visual-assist-presets/tablet-app.md +88 -2
- package/docs/visual-assist-presets/web-app.md +88 -2
- package/docs/workflow-examples.md +31 -4
- package/docs/workflow-overview.md +243 -0
- package/docs/zh-CN/codex-natural-language-usage.md +10 -0
- package/docs/zh-CN/dv-command-reference.md +402 -0
- package/docs/zh-CN/mode-use-cases.md +49 -4
- package/docs/zh-CN/pencil-rendering-workflow.md +281 -0
- package/docs/zh-CN/prompt-entrypoints.md +28 -0
- package/docs/zh-CN/prompt-presets/README.md +82 -1
- package/docs/zh-CN/prompt-presets/desktop-app.md +103 -5
- package/docs/zh-CN/prompt-presets/mobile-app.md +103 -5
- package/docs/zh-CN/prompt-presets/tablet-app.md +103 -5
- package/docs/zh-CN/prompt-presets/web-app.md +103 -5
- package/docs/zh-CN/visual-adapters.md +190 -0
- package/docs/zh-CN/visual-assist-presets/README.md +28 -5
- package/docs/zh-CN/visual-assist-presets/desktop-app.md +88 -1
- package/docs/zh-CN/visual-assist-presets/mobile-app.md +89 -2
- package/docs/zh-CN/visual-assist-presets/tablet-app.md +89 -2
- package/docs/zh-CN/visual-assist-presets/web-app.md +88 -1
- package/docs/zh-CN/workflow-examples.md +34 -4
- package/docs/zh-CN/workflow-overview.md +245 -0
- package/lib/audit.js +199 -0
- package/lib/pencil-lock.js +15 -4
- package/package.json +4 -1
- package/references/artifact-templates.md +65 -0
- package/references/checkpoints.md +43 -19
- package/references/design-inputs.md +6 -0
- package/references/modes.md +34 -0
- package/references/page-mapping.md +58 -0
- package/references/pencil-design-to-code.md +8 -2
- package/references/platform-adapters.md +1 -0
- package/references/prompt-recipes.md +44 -0
- package/scripts/test-audit-design-supervisor.js +348 -0
- package/scripts/test-mode-consistency.js +289 -0
- package/scripts/test-pencil-lock.js +130 -0
|
@@ -0,0 +1,348 @@
|
|
|
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 createHarness() {
|
|
27
|
+
const base = fs.mkdtempSync(path.join(os.tmpdir(), "da-vinci-audit-supervisor-"));
|
|
28
|
+
return {
|
|
29
|
+
base,
|
|
30
|
+
home: path.join(base, "home")
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function runCli(harness, args) {
|
|
35
|
+
const [command, ...rest] = args;
|
|
36
|
+
const result = spawnSync(process.execPath, [cli, command, "--home", harness.home, ...rest], {
|
|
37
|
+
cwd: repo,
|
|
38
|
+
encoding: "utf8",
|
|
39
|
+
maxBuffer: 8 * 1024 * 1024
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
return {
|
|
43
|
+
code: result.status,
|
|
44
|
+
stdout: (result.stdout || "").trim(),
|
|
45
|
+
stderr: (result.stderr || "").trim()
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function expectOk(step, result) {
|
|
50
|
+
assert.equal(result.code, 0, `${step} failed:\n${result.stderr || result.stdout}`);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function writeJson(filePath, payload) {
|
|
54
|
+
fs.mkdirSync(path.dirname(filePath), { recursive: true });
|
|
55
|
+
fs.writeFileSync(filePath, JSON.stringify(payload, null, 2));
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function writeText(filePath, text) {
|
|
59
|
+
fs.mkdirSync(path.dirname(filePath), { recursive: true });
|
|
60
|
+
fs.writeFileSync(filePath, text);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function setupProject(harness, name, options = {}) {
|
|
64
|
+
const root = path.join(harness.base, name);
|
|
65
|
+
const daVinciDir = path.join(root, ".da-vinci");
|
|
66
|
+
const changeDir = path.join(daVinciDir, "changes", changeId);
|
|
67
|
+
const penPath = path.join(daVinciDir, "designs", `${name}.pen`);
|
|
68
|
+
const nodesFile = path.join(root, `${name}-nodes.json`);
|
|
69
|
+
const variablesFile = path.join(root, `${name}-variables.json`);
|
|
70
|
+
const configureReviewers = options.configureReviewers !== false;
|
|
71
|
+
const requireSupervisorReview = options.requireSupervisorReview === true;
|
|
72
|
+
|
|
73
|
+
const visualAssistLines = [
|
|
74
|
+
"# DA-VINCI",
|
|
75
|
+
"",
|
|
76
|
+
"## Visual Assist",
|
|
77
|
+
"- Preferred adapters:",
|
|
78
|
+
" - frontend-skill"
|
|
79
|
+
];
|
|
80
|
+
|
|
81
|
+
if (configureReviewers) {
|
|
82
|
+
visualAssistLines.push("- Design-supervisor reviewers:");
|
|
83
|
+
visualAssistLines.push(" - frontend-skill");
|
|
84
|
+
visualAssistLines.push("- Design-supervisor review mode:");
|
|
85
|
+
visualAssistLines.push(" - screenshot-and-theme");
|
|
86
|
+
visualAssistLines.push("- Design-supervisor review inputs:");
|
|
87
|
+
visualAssistLines.push(" - screenshots");
|
|
88
|
+
visualAssistLines.push(" - pencil variables");
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
visualAssistLines.push("- Require Supervisor Review:");
|
|
92
|
+
visualAssistLines.push(` - ${requireSupervisorReview ? "true" : "false"}`);
|
|
93
|
+
visualAssistLines.push("");
|
|
94
|
+
|
|
95
|
+
writeText(
|
|
96
|
+
path.join(root, "DA-VINCI.md"),
|
|
97
|
+
visualAssistLines.join("\n")
|
|
98
|
+
);
|
|
99
|
+
writeText(path.join(daVinciDir, "project-inventory.md"), "# Inventory\n");
|
|
100
|
+
writeText(path.join(daVinciDir, "page-map.md"), "# Page Map\n");
|
|
101
|
+
writeText(
|
|
102
|
+
path.join(daVinciDir, "design-registry.md"),
|
|
103
|
+
`# Registry\n- Preferred .pen: .da-vinci/designs/${name}.pen\n`
|
|
104
|
+
);
|
|
105
|
+
writeText(path.join(changeDir, "design-brief.md"), "# Brief\n");
|
|
106
|
+
writeText(path.join(changeDir, "design.md"), "# Design\n");
|
|
107
|
+
writeText(path.join(changeDir, "pencil-bindings.md"), "# Bindings\n");
|
|
108
|
+
|
|
109
|
+
writeJson(nodesFile, { nodes: fixture.children });
|
|
110
|
+
writeJson(variablesFile, { variables: fixture.variables });
|
|
111
|
+
|
|
112
|
+
expectOk(
|
|
113
|
+
`${name} begin`,
|
|
114
|
+
runCli(harness, ["pencil-session", "begin", "--project", root, "--pen", penPath])
|
|
115
|
+
);
|
|
116
|
+
expectOk(
|
|
117
|
+
`${name} persist`,
|
|
118
|
+
runCli(harness, [
|
|
119
|
+
"pencil-session",
|
|
120
|
+
"persist",
|
|
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
|
+
expectOk(
|
|
134
|
+
`${name} end`,
|
|
135
|
+
runCli(harness, [
|
|
136
|
+
"pencil-session",
|
|
137
|
+
"end",
|
|
138
|
+
"--project",
|
|
139
|
+
root,
|
|
140
|
+
"--pen",
|
|
141
|
+
penPath,
|
|
142
|
+
"--nodes-file",
|
|
143
|
+
nodesFile,
|
|
144
|
+
"--variables-file",
|
|
145
|
+
variablesFile,
|
|
146
|
+
"--version",
|
|
147
|
+
fixture.version
|
|
148
|
+
])
|
|
149
|
+
);
|
|
150
|
+
|
|
151
|
+
return {
|
|
152
|
+
root,
|
|
153
|
+
changeDir,
|
|
154
|
+
pencilDesignPath: path.join(changeDir, "pencil-design.md")
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
runTest("completion audit warns when supervisor reviewers are configured but not required and no review is recorded", () => {
|
|
159
|
+
const harness = createHarness();
|
|
160
|
+
const project = setupProject(harness, "missing-supervisor-review");
|
|
161
|
+
|
|
162
|
+
writeText(project.pencilDesignPath, "# Pencil Design\n");
|
|
163
|
+
|
|
164
|
+
const result = auditProject(project.root, {
|
|
165
|
+
mode: "completion",
|
|
166
|
+
changeId
|
|
167
|
+
});
|
|
168
|
+
|
|
169
|
+
assert.equal(result.status, "WARN");
|
|
170
|
+
assert.match(
|
|
171
|
+
result.warnings.join("\n"),
|
|
172
|
+
/Design-supervisor reviewers.*does not record a `## Design-Supervisor Review` section/i
|
|
173
|
+
);
|
|
174
|
+
});
|
|
175
|
+
|
|
176
|
+
runTest("completion audit fails when supervisor review is required but no review is recorded", () => {
|
|
177
|
+
const harness = createHarness();
|
|
178
|
+
const project = setupProject(harness, "required-supervisor-review", {
|
|
179
|
+
requireSupervisorReview: true
|
|
180
|
+
});
|
|
181
|
+
|
|
182
|
+
writeText(project.pencilDesignPath, "# Pencil Design\n");
|
|
183
|
+
|
|
184
|
+
const result = auditProject(project.root, {
|
|
185
|
+
mode: "completion",
|
|
186
|
+
changeId
|
|
187
|
+
});
|
|
188
|
+
|
|
189
|
+
assert.equal(result.status, "FAIL");
|
|
190
|
+
assert.match(
|
|
191
|
+
result.failures.join("\n"),
|
|
192
|
+
/Design-supervisor reviewers.*does not record a `## Design-Supervisor Review` section/i
|
|
193
|
+
);
|
|
194
|
+
});
|
|
195
|
+
|
|
196
|
+
runTest("completion audit fails when supervisor review is required but no reviewers are configured", () => {
|
|
197
|
+
const harness = createHarness();
|
|
198
|
+
const project = setupProject(harness, "missing-supervisor-reviewers", {
|
|
199
|
+
configureReviewers: false,
|
|
200
|
+
requireSupervisorReview: true
|
|
201
|
+
});
|
|
202
|
+
|
|
203
|
+
writeText(project.pencilDesignPath, "# Pencil Design\n");
|
|
204
|
+
|
|
205
|
+
const result = auditProject(project.root, {
|
|
206
|
+
mode: "completion",
|
|
207
|
+
changeId
|
|
208
|
+
});
|
|
209
|
+
|
|
210
|
+
assert.equal(result.status, "FAIL");
|
|
211
|
+
assert.match(
|
|
212
|
+
result.failures.join("\n"),
|
|
213
|
+
/Require Supervisor Review: true.*no `Design-supervisor reviewers` are configured/i
|
|
214
|
+
);
|
|
215
|
+
});
|
|
216
|
+
|
|
217
|
+
runTest("completion audit does not treat an empty reviewers field as configured", () => {
|
|
218
|
+
const harness = createHarness();
|
|
219
|
+
const project = setupProject(harness, "empty-supervisor-reviewers", {
|
|
220
|
+
configureReviewers: false,
|
|
221
|
+
requireSupervisorReview: false
|
|
222
|
+
});
|
|
223
|
+
|
|
224
|
+
writeText(
|
|
225
|
+
path.join(project.root, "DA-VINCI.md"),
|
|
226
|
+
[
|
|
227
|
+
"# DA-VINCI",
|
|
228
|
+
"",
|
|
229
|
+
"## Visual Assist",
|
|
230
|
+
"- Preferred adapters:",
|
|
231
|
+
" - frontend-skill",
|
|
232
|
+
"- Design-supervisor reviewers:",
|
|
233
|
+
"- Design-supervisor review mode:",
|
|
234
|
+
" - screenshot-and-theme",
|
|
235
|
+
"- Design-supervisor review inputs:",
|
|
236
|
+
" - screenshots",
|
|
237
|
+
" - pencil variables",
|
|
238
|
+
"- Require Supervisor Review:",
|
|
239
|
+
" - false",
|
|
240
|
+
""
|
|
241
|
+
].join("\n")
|
|
242
|
+
);
|
|
243
|
+
writeText(project.pencilDesignPath, "# Pencil Design\n");
|
|
244
|
+
|
|
245
|
+
const result = auditProject(project.root, {
|
|
246
|
+
mode: "completion",
|
|
247
|
+
changeId
|
|
248
|
+
});
|
|
249
|
+
|
|
250
|
+
assert.equal(result.status, "PASS");
|
|
251
|
+
assert.doesNotMatch(
|
|
252
|
+
result.warnings.join("\n"),
|
|
253
|
+
/Design-supervisor reviewers.*does not record a `## Design-Supervisor Review` section/i
|
|
254
|
+
);
|
|
255
|
+
});
|
|
256
|
+
|
|
257
|
+
runTest("integrity audit warns when supervisor review is required but no review is recorded", () => {
|
|
258
|
+
const harness = createHarness();
|
|
259
|
+
const project = setupProject(harness, "warn-supervisor-review", {
|
|
260
|
+
requireSupervisorReview: true
|
|
261
|
+
});
|
|
262
|
+
|
|
263
|
+
writeText(project.pencilDesignPath, "# Pencil Design\n");
|
|
264
|
+
|
|
265
|
+
const result = auditProject(project.root, {
|
|
266
|
+
mode: "integrity"
|
|
267
|
+
});
|
|
268
|
+
|
|
269
|
+
assert.equal(result.status, "WARN");
|
|
270
|
+
assert.match(
|
|
271
|
+
result.warnings.join("\n"),
|
|
272
|
+
/Design-supervisor reviewers.*does not record a `## Design-Supervisor Review` section/i
|
|
273
|
+
);
|
|
274
|
+
});
|
|
275
|
+
|
|
276
|
+
runTest("completion audit fails when required supervisor review is missing Issue list or Revision outcome", () => {
|
|
277
|
+
const harness = createHarness();
|
|
278
|
+
const project = setupProject(harness, "malformed-supervisor-review", {
|
|
279
|
+
requireSupervisorReview: true
|
|
280
|
+
});
|
|
281
|
+
|
|
282
|
+
writeText(
|
|
283
|
+
project.pencilDesignPath,
|
|
284
|
+
[
|
|
285
|
+
"# Pencil Design",
|
|
286
|
+
"",
|
|
287
|
+
"## Design-Supervisor Review",
|
|
288
|
+
"- Configured reviewers: frontend-skill",
|
|
289
|
+
"- Review mode: screenshot-and-theme",
|
|
290
|
+
"- Review inputs: screenshots, pencil variables",
|
|
291
|
+
"- Status: PASS",
|
|
292
|
+
""
|
|
293
|
+
].join("\n")
|
|
294
|
+
);
|
|
295
|
+
|
|
296
|
+
const result = auditProject(project.root, {
|
|
297
|
+
mode: "completion",
|
|
298
|
+
changeId
|
|
299
|
+
});
|
|
300
|
+
|
|
301
|
+
assert.equal(result.status, "FAIL");
|
|
302
|
+
assert.match(
|
|
303
|
+
result.failures.join("\n"),
|
|
304
|
+
/missing required field\(s\): Issue list and Revision outcome/i
|
|
305
|
+
);
|
|
306
|
+
});
|
|
307
|
+
|
|
308
|
+
runTest("completion audit passes when required supervisor review is recorded as PASS", () => {
|
|
309
|
+
const harness = createHarness();
|
|
310
|
+
const project = setupProject(harness, "pass-supervisor-review", {
|
|
311
|
+
requireSupervisorReview: true
|
|
312
|
+
});
|
|
313
|
+
|
|
314
|
+
writeText(
|
|
315
|
+
project.pencilDesignPath,
|
|
316
|
+
[
|
|
317
|
+
"# Pencil Design",
|
|
318
|
+
"",
|
|
319
|
+
"## Design-Supervisor Review",
|
|
320
|
+
"- Configured reviewers: frontend-skill",
|
|
321
|
+
"- Review mode: screenshot-and-theme",
|
|
322
|
+
"- Review inputs: screenshots, pencil variables, visual thesis, content plan, interaction thesis",
|
|
323
|
+
"- Status: PASS",
|
|
324
|
+
"- Issue list: none",
|
|
325
|
+
"- Revision outcome: approved",
|
|
326
|
+
"- Broad expansion approved: yes",
|
|
327
|
+
"- Implementation-task handoff approved: yes",
|
|
328
|
+
""
|
|
329
|
+
].join("\n")
|
|
330
|
+
);
|
|
331
|
+
|
|
332
|
+
const result = auditProject(project.root, {
|
|
333
|
+
mode: "completion",
|
|
334
|
+
changeId
|
|
335
|
+
});
|
|
336
|
+
|
|
337
|
+
assert.equal(
|
|
338
|
+
result.status,
|
|
339
|
+
"PASS",
|
|
340
|
+
`expected completion audit to pass:\n${JSON.stringify(result, null, 2)}`
|
|
341
|
+
);
|
|
342
|
+
assert.match(
|
|
343
|
+
result.notes.join("\n"),
|
|
344
|
+
/Detected design-supervisor review status PASS/i
|
|
345
|
+
);
|
|
346
|
+
});
|
|
347
|
+
|
|
348
|
+
console.log("All design-supervisor audit tests passed.");
|
|
@@ -0,0 +1,289 @@
|
|
|
1
|
+
const assert = require("assert/strict");
|
|
2
|
+
const fs = require("fs");
|
|
3
|
+
const path = require("path");
|
|
4
|
+
|
|
5
|
+
const repo = path.resolve(__dirname, "..");
|
|
6
|
+
|
|
7
|
+
const MODES = [
|
|
8
|
+
"greenfield-spec",
|
|
9
|
+
"greenfield-brainstorm",
|
|
10
|
+
"redesign-from-code",
|
|
11
|
+
"overhaul-from-code",
|
|
12
|
+
"feature-change"
|
|
13
|
+
];
|
|
14
|
+
|
|
15
|
+
function read(relativePath) {
|
|
16
|
+
return fs.readFileSync(path.join(repo, relativePath), "utf8");
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function runTest(name, fn) {
|
|
20
|
+
try {
|
|
21
|
+
fn();
|
|
22
|
+
console.log(`PASS ${name}`);
|
|
23
|
+
} catch (error) {
|
|
24
|
+
console.error(`FAIL ${name}`);
|
|
25
|
+
throw error;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function assertContainsInOrder(text, parts, label) {
|
|
30
|
+
let index = -1;
|
|
31
|
+
for (const part of parts) {
|
|
32
|
+
const next = text.indexOf(part, index + 1);
|
|
33
|
+
assert.notEqual(next, -1, `${label} is missing ${part}`);
|
|
34
|
+
assert.ok(next > index, `${label} does not keep ${part} in order`);
|
|
35
|
+
index = next;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function assertAllModesPresent(text, label) {
|
|
40
|
+
for (const mode of MODES) {
|
|
41
|
+
assert.match(text, new RegExp(mode.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")), `${label} is missing ${mode}`);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
runTest("core references keep all five workflow modes in order", () => {
|
|
46
|
+
const skill = read("SKILL.md");
|
|
47
|
+
const modesReference = read("references/modes.md");
|
|
48
|
+
const modeUseCases = read("docs/mode-use-cases.md");
|
|
49
|
+
const zhModeUseCases = read("docs/zh-CN/mode-use-cases.md");
|
|
50
|
+
|
|
51
|
+
assertContainsInOrder(skill, MODES, "SKILL.md");
|
|
52
|
+
assertContainsInOrder(modesReference, MODES, "references/modes.md");
|
|
53
|
+
assertContainsInOrder(modeUseCases, MODES, "docs/mode-use-cases.md");
|
|
54
|
+
assertContainsInOrder(zhModeUseCases, MODES, "docs/zh-CN/mode-use-cases.md");
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
runTest("workflow overviews include overhaul mode and its pre-design artifact chain", () => {
|
|
58
|
+
const overview = read("docs/workflow-overview.md");
|
|
59
|
+
const zhOverview = read("docs/zh-CN/workflow-overview.md");
|
|
60
|
+
|
|
61
|
+
assertAllModesPresent(overview, "docs/workflow-overview.md");
|
|
62
|
+
assertAllModesPresent(zhOverview, "docs/zh-CN/workflow-overview.md");
|
|
63
|
+
for (const required of ["project-inventory.md", "proposal.md", "migration-contract.md", "page-map.md", "design-registry.md", "design.md"]) {
|
|
64
|
+
assert.match(overview, new RegExp(required.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")), `workflow overview is missing ${required}`);
|
|
65
|
+
assert.match(zhOverview, new RegExp(required.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")), `zh workflow overview is missing ${required}`);
|
|
66
|
+
}
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
runTest("overhaul mode is wired into artifact and checkpoint guidance", () => {
|
|
70
|
+
const readme = read("README.md");
|
|
71
|
+
const zhReadme = read("README.zh-CN.md");
|
|
72
|
+
const artifacts = read("references/artifact-templates.md");
|
|
73
|
+
const checkpoints = read("references/checkpoints.md");
|
|
74
|
+
const designInputs = read("references/design-inputs.md");
|
|
75
|
+
const pencilToCode = read("references/pencil-design-to-code.md");
|
|
76
|
+
|
|
77
|
+
for (const content of [readme, zhReadme, artifacts, checkpoints, designInputs, pencilToCode]) {
|
|
78
|
+
assert.match(content, /migration-contract\.md/, "expected migration-contract.md guidance is missing");
|
|
79
|
+
assert.match(content, /overhaul-from-code/, "expected overhaul-from-code guidance is missing");
|
|
80
|
+
}
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
runTest("all intake entrypoints route broad existing-project rewrites to overhaul-from-code", () => {
|
|
84
|
+
const claude = read("commands/claude/dv/intake.md");
|
|
85
|
+
const codex = read("commands/codex/prompts/dv-intake.md");
|
|
86
|
+
const gemini = read("commands/gemini/dv/intake.toml");
|
|
87
|
+
|
|
88
|
+
for (const [label, content] of [
|
|
89
|
+
["Claude intake", claude],
|
|
90
|
+
["Codex intake", codex],
|
|
91
|
+
["Gemini intake", gemini]
|
|
92
|
+
]) {
|
|
93
|
+
assert.match(content, /prefer `redesign-from-code`, `overhaul-from-code`, or `feature-change`/, `${label} is missing existing-project routing guidance`);
|
|
94
|
+
assert.match(content, /prefer `overhaul-from-code` when an existing project is redefining flows or logic rather than only replacing UI/, `${label} is missing overhaul routing guidance`);
|
|
95
|
+
}
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
runTest("readmes and command reference document overhaul examples and rollback behavior", () => {
|
|
99
|
+
const readme = read("README.md");
|
|
100
|
+
const zhReadme = read("README.zh-CN.md");
|
|
101
|
+
const commandRef = read("docs/dv-command-reference.md");
|
|
102
|
+
const zhCommandRef = read("docs/zh-CN/dv-command-reference.md");
|
|
103
|
+
|
|
104
|
+
assert.match(readme, /### Overhaul from code/, "README.md is missing overhaul example section");
|
|
105
|
+
assert.match(zhReadme, /### Overhaul from code/, "README.zh-CN.md is missing overhaul example section");
|
|
106
|
+
assert.match(readme, /Continue after overhaul planning/, "README.md is missing overhaul continue section");
|
|
107
|
+
assert.match(zhReadme, /大改版场景继续推进/, "README.zh-CN.md is missing overhaul continue section");
|
|
108
|
+
assert.match(commandRef, /migration-contract\.md/, "docs/dv-command-reference.md is missing overhaul rollback references");
|
|
109
|
+
assert.match(zhCommandRef, /migration-contract\.md/, "docs/zh-CN/dv-command-reference.md is missing overhaul rollback references");
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
runTest("prompt preset guidance keeps overhaul as a pre-design routing concern instead of a redesign preset alias", () => {
|
|
113
|
+
const presetReadme = read("docs/prompt-presets/README.md");
|
|
114
|
+
const zhPresetReadme = read("docs/zh-CN/prompt-presets/README.md");
|
|
115
|
+
const mobilePreset = read("docs/prompt-presets/mobile-app.md");
|
|
116
|
+
const desktopPreset = read("docs/prompt-presets/desktop-app.md");
|
|
117
|
+
const webPreset = read("docs/prompt-presets/web-app.md");
|
|
118
|
+
const tabletPreset = read("docs/prompt-presets/tablet-app.md");
|
|
119
|
+
const zhMobilePreset = read("docs/zh-CN/prompt-presets/mobile-app.md");
|
|
120
|
+
const zhDesktopPreset = read("docs/zh-CN/prompt-presets/desktop-app.md");
|
|
121
|
+
const zhWebPreset = read("docs/zh-CN/prompt-presets/web-app.md");
|
|
122
|
+
const zhTabletPreset = read("docs/zh-CN/prompt-presets/tablet-app.md");
|
|
123
|
+
|
|
124
|
+
assert.match(presetReadme, /prefer `overhaul-from-code` plus `intake`\/custom prompt setup first/, "prompt preset README is missing overhaul guidance");
|
|
125
|
+
assert.match(presetReadme, /## `overhaul-from-code` Prompt Templates/, "prompt preset README is missing overhaul template section");
|
|
126
|
+
assert.match(zhPresetReadme, /应该先用 `overhaul-from-code`/, "zh prompt preset README is missing overhaul guidance");
|
|
127
|
+
assert.match(zhPresetReadme, /## `overhaul-from-code` 提示词模板/, "zh prompt preset README is missing overhaul template section");
|
|
128
|
+
assert.match(mobilePreset, /use redesign-from-code to redesign this existing mobile app\./, "existing redesign presets should remain redesign-oriented");
|
|
129
|
+
for (const [label, content] of [
|
|
130
|
+
["mobile preset", mobilePreset],
|
|
131
|
+
["desktop preset", desktopPreset],
|
|
132
|
+
["web preset", webPreset],
|
|
133
|
+
["tablet preset", tabletPreset]
|
|
134
|
+
]) {
|
|
135
|
+
assert.match(content, /## Overhaul From Code/, `${label} is missing the overhaul section`);
|
|
136
|
+
assert.match(content, /### Overhaul Intake/, `${label} is missing overhaul intake`);
|
|
137
|
+
assert.match(content, /### Overhaul Breakdown/, `${label} is missing overhaul breakdown`);
|
|
138
|
+
assert.match(content, /### Overhaul Design/, `${label} is missing overhaul design`);
|
|
139
|
+
assert.match(content, /### Overhaul Continue/, `${label} is missing overhaul continue`);
|
|
140
|
+
}
|
|
141
|
+
for (const [label, content] of [
|
|
142
|
+
["zh mobile preset", zhMobilePreset],
|
|
143
|
+
["zh desktop preset", zhDesktopPreset],
|
|
144
|
+
["zh web preset", zhWebPreset],
|
|
145
|
+
["zh tablet preset", zhTabletPreset]
|
|
146
|
+
]) {
|
|
147
|
+
assert.match(content, /## Overhaul From Code/, `${label} is missing the overhaul section`);
|
|
148
|
+
assert.match(content, /### Overhaul Intake/, `${label} is missing overhaul intake`);
|
|
149
|
+
assert.match(content, /### Overhaul Breakdown/, `${label} is missing overhaul breakdown`);
|
|
150
|
+
assert.match(content, /### Overhaul Design/, `${label} is missing overhaul design`);
|
|
151
|
+
assert.match(content, /### Overhaul Continue/, `${label} is missing overhaul continue`);
|
|
152
|
+
}
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
runTest("redesign prompt docs make full-delivery explicit and keep stop semantics in design-only only", () => {
|
|
156
|
+
const presetFiles = [
|
|
157
|
+
"docs/prompt-presets/mobile-app.md",
|
|
158
|
+
"docs/prompt-presets/desktop-app.md",
|
|
159
|
+
"docs/prompt-presets/web-app.md",
|
|
160
|
+
"docs/prompt-presets/tablet-app.md",
|
|
161
|
+
"docs/zh-CN/prompt-presets/mobile-app.md",
|
|
162
|
+
"docs/zh-CN/prompt-presets/desktop-app.md",
|
|
163
|
+
"docs/zh-CN/prompt-presets/web-app.md",
|
|
164
|
+
"docs/zh-CN/prompt-presets/tablet-app.md"
|
|
165
|
+
];
|
|
166
|
+
|
|
167
|
+
for (const file of presetFiles) {
|
|
168
|
+
const content = read(file);
|
|
169
|
+
const fullDeliveryCount = (content.match(/Treat this as full-delivery unless explicitly changed\./g) || []).length;
|
|
170
|
+
assert.ok(fullDeliveryCount >= 3, `${file} should make full-delivery explicit in redesign variants`);
|
|
171
|
+
assert.match(
|
|
172
|
+
content,
|
|
173
|
+
/Do not stop after discovery, anchor surfaces, phase summaries, or task generation; continue through tasks, build, and verify once the corresponding checkpoints pass\./,
|
|
174
|
+
`${file} should forbid redesign variants from stopping at anchor or task summaries`
|
|
175
|
+
);
|
|
176
|
+
assert.match(content, /Treat this as design-only, not full-delivery\./, `${file} should explicitly reserve stop semantics for design-only`);
|
|
177
|
+
assert.doesNotMatch(content, /Stop after .*tasks\.md\./, `${file} should not let design-only prompts generate tasks.md by default`);
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
const promptRecipes = read("references/prompt-recipes.md");
|
|
181
|
+
assert.match(promptRecipes, /treat the request as `full-delivery` unless the user explicitly says `design-only`/, "prompt recipes should require explicit redesign delivery intent");
|
|
182
|
+
assert.match(promptRecipes, /do not stop at anchor-surface summaries, phase summaries, or task generation once the corresponding checkpoints pass/, "prompt recipes should forbid redesign prompts from stopping at phase summaries");
|
|
183
|
+
});
|
|
184
|
+
|
|
185
|
+
runTest("pencil session docs keep project-local .pen seeding as a required step on autonomous redesign runs", () => {
|
|
186
|
+
const keyFiles = [
|
|
187
|
+
"commands/claude/dv/design.md",
|
|
188
|
+
"commands/codex/prompts/dv-design.md",
|
|
189
|
+
"commands/gemini/dv/design.toml",
|
|
190
|
+
"docs/pencil-rendering-workflow.md",
|
|
191
|
+
"docs/zh-CN/pencil-rendering-workflow.md",
|
|
192
|
+
"README.md",
|
|
193
|
+
"README.zh-CN.md",
|
|
194
|
+
"docs/prompt-presets/mobile-app.md",
|
|
195
|
+
"docs/prompt-presets/desktop-app.md",
|
|
196
|
+
"docs/prompt-presets/web-app.md",
|
|
197
|
+
"docs/prompt-presets/tablet-app.md",
|
|
198
|
+
"docs/zh-CN/prompt-presets/mobile-app.md",
|
|
199
|
+
"docs/zh-CN/prompt-presets/desktop-app.md",
|
|
200
|
+
"docs/zh-CN/prompt-presets/web-app.md",
|
|
201
|
+
"docs/zh-CN/prompt-presets/tablet-app.md",
|
|
202
|
+
"docs/workflow-examples.md",
|
|
203
|
+
"docs/zh-CN/workflow-examples.md",
|
|
204
|
+
"references/pencil-design-to-code.md"
|
|
205
|
+
];
|
|
206
|
+
|
|
207
|
+
for (const file of keyFiles) {
|
|
208
|
+
const content = read(file);
|
|
209
|
+
assert.doesNotMatch(content, /Prefer the session wrapper commands/, `${file} should not weaken the session wrapper to a preference`);
|
|
210
|
+
assert.doesNotMatch(content, /Before the first Pencil edit, prefer `da-vinci pencil-session begin/, `${file} should require pencil-session begin before first edit`);
|
|
211
|
+
assert.doesNotMatch(content, /Prefer `da-vinci pencil-session begin --project <project-path> --pen <path>/, `${file} should not describe pencil-session begin as optional`);
|
|
212
|
+
assert.doesNotMatch(content, /优先执行 `da-vinci pencil-session begin --project <project-path> --pen <path>`/, `${file} should not describe pencil-session begin as optional in Chinese`);
|
|
213
|
+
assert.doesNotMatch(content, /优先通过 `da-vinci pencil-session begin`/, `${file} should not describe pencil-session begin as optional in Chinese mode guidance`);
|
|
214
|
+
assert.doesNotMatch(content, /先允许第一个通过审查的 live anchor surface 在内存里完成/, `${file} should not allow in-memory-first anchor work before seeding the project-local .pen`);
|
|
215
|
+
}
|
|
216
|
+
});
|
|
217
|
+
|
|
218
|
+
runTest("design-supervisor review stays distinct from preferred adapters and is wired into design prompts", () => {
|
|
219
|
+
const keyDocs = [
|
|
220
|
+
"SKILL.md",
|
|
221
|
+
"references/checkpoints.md",
|
|
222
|
+
"references/artifact-templates.md",
|
|
223
|
+
"docs/pencil-rendering-workflow.md",
|
|
224
|
+
"docs/zh-CN/pencil-rendering-workflow.md",
|
|
225
|
+
"docs/visual-adapters.md",
|
|
226
|
+
"docs/zh-CN/visual-adapters.md",
|
|
227
|
+
"docs/workflow-overview.md",
|
|
228
|
+
"docs/zh-CN/workflow-overview.md",
|
|
229
|
+
"docs/dv-command-reference.md",
|
|
230
|
+
"docs/zh-CN/dv-command-reference.md"
|
|
231
|
+
];
|
|
232
|
+
|
|
233
|
+
for (const file of keyDocs) {
|
|
234
|
+
const content = read(file);
|
|
235
|
+
assert.match(content, /Design-supervisor reviewers|design-supervisor review/, `${file} should document the design-supervisor review gate`);
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
for (const file of [
|
|
239
|
+
"references/checkpoints.md",
|
|
240
|
+
"docs/pencil-rendering-workflow.md",
|
|
241
|
+
"docs/zh-CN/pencil-rendering-workflow.md",
|
|
242
|
+
"docs/visual-adapters.md",
|
|
243
|
+
"docs/zh-CN/visual-adapters.md"
|
|
244
|
+
]) {
|
|
245
|
+
const content = read(file);
|
|
246
|
+
assert.match(content, /Require Supervisor Review/, `${file} should explain when supervisor review becomes a hard gate`);
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
const visualPresetFiles = [
|
|
250
|
+
"docs/visual-assist-presets/README.md",
|
|
251
|
+
"docs/visual-assist-presets/mobile-app.md",
|
|
252
|
+
"docs/visual-assist-presets/desktop-app.md",
|
|
253
|
+
"docs/visual-assist-presets/web-app.md",
|
|
254
|
+
"docs/visual-assist-presets/tablet-app.md",
|
|
255
|
+
"docs/zh-CN/visual-assist-presets/README.md",
|
|
256
|
+
"docs/zh-CN/visual-assist-presets/mobile-app.md",
|
|
257
|
+
"docs/zh-CN/visual-assist-presets/desktop-app.md",
|
|
258
|
+
"docs/zh-CN/visual-assist-presets/web-app.md",
|
|
259
|
+
"docs/zh-CN/visual-assist-presets/tablet-app.md"
|
|
260
|
+
];
|
|
261
|
+
|
|
262
|
+
for (const file of visualPresetFiles) {
|
|
263
|
+
const content = read(file);
|
|
264
|
+
assert.match(content, /Design-supervisor reviewers/, `${file} should keep reviewer configuration visible in Visual Assist guidance`);
|
|
265
|
+
assert.match(content, /Require Supervisor Review/, `${file} should document the reviewer requirement toggle`);
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
const designPrompts = [
|
|
269
|
+
"commands/claude/dv/design.md",
|
|
270
|
+
"commands/codex/prompts/dv-design.md",
|
|
271
|
+
"commands/gemini/dv/design.toml",
|
|
272
|
+
"docs/prompt-presets/mobile-app.md",
|
|
273
|
+
"docs/prompt-presets/desktop-app.md",
|
|
274
|
+
"docs/prompt-presets/web-app.md",
|
|
275
|
+
"docs/prompt-presets/tablet-app.md",
|
|
276
|
+
"docs/zh-CN/prompt-presets/mobile-app.md",
|
|
277
|
+
"docs/zh-CN/prompt-presets/desktop-app.md",
|
|
278
|
+
"docs/zh-CN/prompt-presets/web-app.md",
|
|
279
|
+
"docs/zh-CN/prompt-presets/tablet-app.md"
|
|
280
|
+
];
|
|
281
|
+
|
|
282
|
+
for (const file of designPrompts) {
|
|
283
|
+
const content = read(file);
|
|
284
|
+
assert.match(content, /design-supervisor review/, `${file} should instruct design flows to run design-supervisor review when configured`);
|
|
285
|
+
assert.match(content, /Require Supervisor Review: true/, `${file} should explain the hard-gate branch for supervisor review`);
|
|
286
|
+
}
|
|
287
|
+
});
|
|
288
|
+
|
|
289
|
+
console.log("All mode consistency tests passed.");
|