@xenonbyte/da-vinci-workflow 0.1.13 → 0.1.15

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 (56) hide show
  1. package/CHANGELOG.md +21 -1
  2. package/README.md +23 -1
  3. package/README.zh-CN.md +23 -1
  4. package/SKILL.md +15 -0
  5. package/commands/claude/dv/design.md +2 -0
  6. package/commands/claude/dv/verify.md +2 -0
  7. package/commands/codex/prompts/dv-design.md +2 -0
  8. package/commands/codex/prompts/dv-verify.md +1 -0
  9. package/commands/gemini/dv/design.toml +2 -0
  10. package/commands/gemini/dv/verify.toml +1 -0
  11. package/docs/mcp-aware-gate-implementation.md +291 -0
  12. package/docs/mcp-aware-gate-tests.md +244 -0
  13. package/docs/mcp-aware-gate.md +246 -0
  14. package/docs/mode-use-cases.md +2 -0
  15. package/docs/prompt-presets/README.md +1 -0
  16. package/docs/prompt-presets/desktop-app.md +4 -0
  17. package/docs/prompt-presets/mobile-app.md +4 -0
  18. package/docs/prompt-presets/tablet-app.md +4 -0
  19. package/docs/prompt-presets/web-app.md +4 -0
  20. package/docs/visual-adapters.md +9 -0
  21. package/docs/visual-assist-presets/README.md +4 -2
  22. package/docs/visual-assist-presets/desktop-app.md +2 -0
  23. package/docs/visual-assist-presets/mobile-app.md +2 -0
  24. package/docs/visual-assist-presets/tablet-app.md +2 -0
  25. package/docs/visual-assist-presets/web-app.md +2 -0
  26. package/docs/workflow-examples.md +9 -4
  27. package/docs/zh-CN/mcp-aware-gate-implementation.md +290 -0
  28. package/docs/zh-CN/mcp-aware-gate-tests.md +244 -0
  29. package/docs/zh-CN/mcp-aware-gate.md +249 -0
  30. package/docs/zh-CN/mode-use-cases.md +3 -0
  31. package/docs/zh-CN/prompt-presets/README.md +1 -0
  32. package/docs/zh-CN/prompt-presets/desktop-app.md +4 -0
  33. package/docs/zh-CN/prompt-presets/mobile-app.md +4 -0
  34. package/docs/zh-CN/prompt-presets/tablet-app.md +4 -0
  35. package/docs/zh-CN/prompt-presets/web-app.md +4 -0
  36. package/docs/zh-CN/visual-adapters.md +9 -0
  37. package/docs/zh-CN/visual-assist-presets/README.md +5 -3
  38. package/docs/zh-CN/visual-assist-presets/desktop-app.md +2 -0
  39. package/docs/zh-CN/visual-assist-presets/mobile-app.md +2 -0
  40. package/docs/zh-CN/visual-assist-presets/tablet-app.md +2 -0
  41. package/docs/zh-CN/visual-assist-presets/web-app.md +2 -0
  42. package/docs/zh-CN/workflow-examples.md +9 -4
  43. package/examples/greenfield-spec-markupflow/DA-VINCI.md +1 -0
  44. package/examples/greenfield-spec-markupflow/README.md +3 -0
  45. package/examples/greenfield-spec-markupflow/design-registry.md +3 -0
  46. package/examples/greenfield-spec-markupflow/pencil-design.md +4 -0
  47. package/lib/audit.js +348 -0
  48. package/lib/cli.js +47 -1
  49. package/lib/mcp-runtime-gate.js +342 -0
  50. package/package.json +3 -2
  51. package/references/artifact-templates.md +35 -3
  52. package/references/checkpoints.md +69 -1
  53. package/references/design-inputs.md +9 -1
  54. package/references/layout-hygiene.md +117 -0
  55. package/references/pencil-design-to-code.md +8 -0
  56. package/scripts/test-mcp-runtime-gate.js +199 -0
@@ -0,0 +1,117 @@
1
+ # Layout Hygiene
2
+
3
+ Use this reference when screenshot review or the design checkpoint needs form-factor-specific layout hygiene rules.
4
+
5
+ This layer is separate from `Visual Assist`.
6
+
7
+ - visual adapters decide art direction and composition quality
8
+ - layout hygiene decides whether a screen is structurally healthy enough to expand or implement
9
+
10
+ ## Resolution Rule
11
+
12
+ Apply exactly one primary hygiene profile to each reviewed surface:
13
+
14
+ 1. mobile
15
+ 2. tablet
16
+ 3. desktop
17
+ 4. web
18
+
19
+ Use the resolved project form factor from `DA-VINCI.md`, `design-brief.md`, or stable codebase signals.
20
+
21
+ For mixed products:
22
+
23
+ - apply the dominant profile per surface
24
+ - record surface-specific exceptions in `design-brief.md` or `pencil-design.md`
25
+
26
+ ## Generic Checks
27
+
28
+ Apply these checks to every reviewed surface:
29
+
30
+ - no clipped or edge-colliding primary content
31
+ - no unexplained whitespace bands that break the screen's visual balance
32
+ - a clear dominant working surface or anchor
33
+ - aligned top-chrome rhythm across related screens
34
+ - spacing rhythm that does not bunch one region while leaving another region visually empty
35
+ - screenshot review findings must be interpreted, not treated as an automatic pass
36
+
37
+ ## Severity
38
+
39
+ Use these result levels:
40
+
41
+ - `PASS`
42
+ - no blocker-level hygiene failure is present
43
+ - `WARN`
44
+ - minor spacing, rhythm, or proportion issues exist, but the screen is still structurally coherent
45
+ - `BLOCK`
46
+ - any blocker-level hygiene failure exists
47
+ - or screenshot analysis reports hierarchy, spacing, clarity, inconsistency, clipping, or unresolved-placeholder issues and the screen is not revised
48
+
49
+ ## Mobile
50
+
51
+ Use for phone-first app screens.
52
+
53
+ Check:
54
+
55
+ - top inset and safe-area rhythm are respected unless the screen is intentionally full-bleed
56
+ - the first content band does not begin flush against the top edge without a clear chrome strategy
57
+ - the main task area is vertically balanced against top chrome and bottom actions
58
+ - bottom trays and action rows do not crowd the main content
59
+ - header and title start lines are consistent across related screens
60
+
61
+ Treat as `BLOCK` when:
62
+
63
+ - top content is visibly pinned to the edge without an intentional full-bleed reason
64
+ - a large unexplained void appears above or within the primary task area
65
+ - a bottom action tray compresses the main task area into an obviously cramped strip
66
+ - related anchor screens use incompatible top-chrome alignment systems
67
+
68
+ ## Tablet
69
+
70
+ Use for tablet-first flows or tablet-dominant surfaces.
71
+
72
+ Check:
73
+
74
+ - panes, canvases, and supporting rails use intentional proportions
75
+ - gutters are consistent across primary and secondary regions
76
+ - the screen is not just a stretched phone layout
77
+ - primary and secondary regions have a clear weight relationship
78
+
79
+ Treat as `BLOCK` when:
80
+
81
+ - one side of the screen is heavily compressed while another side is mostly empty without purpose
82
+ - pane ratios feel accidental or unstable
83
+ - the layout is essentially a phone stack widened onto a tablet canvas
84
+
85
+ ## Desktop
86
+
87
+ Use for desktop software and dense workspaces.
88
+
89
+ Check:
90
+
91
+ - toolbar, sidebar, workspace, and inspector edges align to a coherent system
92
+ - the main workspace visibly owns the screen
93
+ - panels feel attached to a layout system instead of floating independently
94
+ - chrome height and content start lines are consistent between related screens
95
+
96
+ Treat as `BLOCK` when:
97
+
98
+ - the workspace does not read as the dominant region
99
+ - panels feel like disconnected boxed islands or floating soup
100
+ - top chrome and content starts drift enough to make related screens feel structurally inconsistent
101
+
102
+ ## Web
103
+
104
+ Use for browser-based product UI and marketing/product hybrids.
105
+
106
+ Check:
107
+
108
+ - header plus first viewport content fit within a coherent viewport budget
109
+ - max-width and gutters are disciplined
110
+ - responsive behavior does not collapse hierarchy
111
+ - the first impression is not a generic card pile
112
+
113
+ Treat as `BLOCK` when:
114
+
115
+ - header plus hero or workspace visibly overruns the initial viewport without intent
116
+ - gutters or max-width rules drift enough to break hierarchy
117
+ - breakpoint changes turn the screen into a generic stacked-card filler layout
@@ -10,6 +10,11 @@ Use this priority order:
10
10
  2. Pencil data for presentation
11
11
  3. screenshots only as a visual check
12
12
 
13
+ Exported screenshots are review artifacts only.
14
+
15
+ - store them under `.da-vinci/changes/<change-id>/exports/`
16
+ - do not treat them as the persisted design source
17
+
13
18
  Do not infer behavior from appearance alone.
14
19
 
15
20
  ## Read From Pencil
@@ -33,6 +38,7 @@ If the current active Pencil editor does not match the preferred path in `design
33
38
  - do not silently continue from the unrelated editor
34
39
  - switch to the registered file when possible
35
40
  - otherwise reconstruct the registered project-local `.pen` file from MCP-readable document data before implementation depends on it
41
+ - if the editor is still `new` or another unnamed live document, do not describe the project-local `.pen` source as saved yet
36
42
 
37
43
  ## Visual Adapter Use
38
44
 
@@ -58,8 +64,10 @@ When generating or editing Pencil data:
58
64
  - use only Pencil-supported properties and layout concepts
59
65
  - do not emit web- or CSS-only properties such as `flex` or `margin`
60
66
  - prefer smaller, schema-safe batches on anchor screens so errors do not roll back large composition chunks
67
+ - if unsupported-property rollbacks repeat on the same anchor surface, stop treating that pass as stable forward progress until the schema usage is corrected
61
68
  - verify the registered project-local `.pen` path becomes shell-visible immediately after the first successful Pencil write
62
69
  - keep workflow markdown out of `.da-vinci/designs/`; reserve that directory for `.pen` files only
70
+ - keep screenshot exports out of `.da-vinci/designs/`; write them under `.da-vinci/changes/<change-id>/exports/`
63
71
  - after the first approved anchor surfaces, extract a shared primitive family before broad page expansion
64
72
 
65
73
  ## Map Pencil To Frontend
@@ -0,0 +1,199 @@
1
+ const assert = require("assert/strict");
2
+ const {
3
+ PASS,
4
+ WARN,
5
+ BLOCK,
6
+ SKIP,
7
+ evaluateMcpRuntimeGate,
8
+ formatMcpRuntimeGateSection
9
+ } = require("../lib/mcp-runtime-gate");
10
+
11
+ function runTest(name, fn) {
12
+ try {
13
+ fn();
14
+ console.log(`PASS ${name}`);
15
+ } catch (error) {
16
+ console.error(`FAIL ${name}`);
17
+ throw error;
18
+ }
19
+ }
20
+
21
+ runTest("healthy completion passes", () => {
22
+ const result = evaluateMcpRuntimeGate({
23
+ phase: "completion",
24
+ mcpAvailable: true,
25
+ projectRoot: "/repo",
26
+ activeEditor: "/repo/.da-vinci/designs/cipher-redesign.pen",
27
+ registeredPenPath: ".da-vinci/designs/cipher-redesign.pen",
28
+ shellVisiblePenPath: ".da-vinci/designs/cipher-redesign.pen",
29
+ shellVisiblePenExists: true,
30
+ claimedAnchorIds: ["GfwiK", "mCZ1G", "V8zfE"],
31
+ claimedReviewedScreenIds: ["GfwiK", "mCZ1G", "V8zfE"],
32
+ reviewTargets: ["GfwiK", "mCZ1G", "V8zfE"],
33
+ liveScreens: [
34
+ { id: "GfwiK", name: "Splash" },
35
+ { id: "mCZ1G", name: "Home" },
36
+ { id: "V8zfE", name: "SafeBox" }
37
+ ]
38
+ });
39
+
40
+ assert.equal(result.sourceConvergence.status, PASS);
41
+ assert.equal(result.screenPresence.status, PASS);
42
+ assert.equal(result.reviewExecution.status, PASS);
43
+ assert.equal(result.finalStatus, PASS);
44
+
45
+ const section = formatMcpRuntimeGateSection({}, result, { timestamp: "2026-03-27T00:00:00.000Z" });
46
+ assert.match(section, /Final runtime gate status: PASS/);
47
+ assert.match(section, /Source convergence: PASS/);
48
+ });
49
+
50
+ runTest("unnamed editor blocks runtime gate", () => {
51
+ const result = evaluateMcpRuntimeGate({
52
+ phase: "completion",
53
+ mcpAvailable: true,
54
+ activeEditor: "new",
55
+ registeredPenPath: ".da-vinci/designs/cipher-redesign.pen",
56
+ shellVisiblePenPath: ".da-vinci/designs/cipher-redesign.pen",
57
+ shellVisiblePenExists: true,
58
+ claimedAnchorIds: ["GfwiK"],
59
+ claimedReviewedScreenIds: ["GfwiK"],
60
+ reviewTargets: ["GfwiK"],
61
+ liveScreens: [{ id: "GfwiK", name: "Splash" }]
62
+ });
63
+
64
+ assert.equal(result.sourceConvergence.status, BLOCK);
65
+ assert.equal(result.finalStatus, BLOCK);
66
+ });
67
+
68
+ runTest("live screens without shell-visible pen block source convergence", () => {
69
+ const result = evaluateMcpRuntimeGate({
70
+ phase: "completion",
71
+ mcpAvailable: true,
72
+ projectRoot: "/repo",
73
+ activeEditor: "/repo/.da-vinci/designs/cipher-redesign.pen",
74
+ registeredPenPath: ".da-vinci/designs/cipher-redesign.pen",
75
+ shellVisiblePenPath: ".da-vinci/designs/cipher-redesign.pen",
76
+ shellVisiblePenExists: false,
77
+ claimedAnchorIds: ["GfwiK"],
78
+ claimedReviewedScreenIds: ["GfwiK"],
79
+ reviewTargets: ["GfwiK"],
80
+ liveScreens: [{ id: "GfwiK", name: "Splash" }]
81
+ });
82
+
83
+ assert.equal(result.sourceConvergence.status, BLOCK);
84
+ assert.equal(result.finalStatus, BLOCK);
85
+ });
86
+
87
+ runTest("missing claimed anchor blocks screen presence", () => {
88
+ const result = evaluateMcpRuntimeGate({
89
+ phase: "completion",
90
+ mcpAvailable: true,
91
+ projectRoot: "/repo",
92
+ activeEditor: "/repo/.da-vinci/designs/cipher-redesign.pen",
93
+ registeredPenPath: ".da-vinci/designs/cipher-redesign.pen",
94
+ shellVisiblePenPath: ".da-vinci/designs/cipher-redesign.pen",
95
+ shellVisiblePenExists: true,
96
+ claimedAnchorIds: ["GfwiK", "mCZ1G"],
97
+ claimedReviewedScreenIds: ["GfwiK"],
98
+ reviewTargets: ["GfwiK"],
99
+ liveScreens: [{ id: "GfwiK", name: "Splash" }]
100
+ });
101
+
102
+ assert.equal(result.screenPresence.status, BLOCK);
103
+ assert.equal(result.finalStatus, BLOCK);
104
+ });
105
+
106
+ runTest("ignored review blockers block review execution", () => {
107
+ const result = evaluateMcpRuntimeGate({
108
+ phase: "completion",
109
+ mcpAvailable: true,
110
+ projectRoot: "/repo",
111
+ activeEditor: "/repo/.da-vinci/designs/cipher-redesign.pen",
112
+ registeredPenPath: ".da-vinci/designs/cipher-redesign.pen",
113
+ shellVisiblePenPath: ".da-vinci/designs/cipher-redesign.pen",
114
+ shellVisiblePenExists: true,
115
+ claimedAnchorIds: ["GfwiK"],
116
+ claimedReviewedScreenIds: ["GfwiK"],
117
+ reviewTargets: ["GfwiK"],
118
+ liveScreens: [{ id: "GfwiK", name: "Splash" }],
119
+ reviewBlockersIgnored: true
120
+ });
121
+
122
+ assert.equal(result.reviewExecution.status, BLOCK);
123
+ assert.equal(result.finalStatus, BLOCK);
124
+ });
125
+
126
+ runTest("mcp unavailable warns instead of passing", () => {
127
+ const result = evaluateMcpRuntimeGate({
128
+ phase: "completion",
129
+ mcpAvailable: false,
130
+ activeEditor: "",
131
+ registeredPenPath: ".da-vinci/designs/cipher-redesign.pen",
132
+ shellVisiblePenPath: ".da-vinci/designs/cipher-redesign.pen",
133
+ shellVisiblePenExists: true
134
+ });
135
+
136
+ assert.equal(result.sourceConvergence.status, WARN);
137
+ assert.equal(result.screenPresence.status, WARN);
138
+ assert.equal(result.reviewExecution.status, WARN);
139
+ assert.equal(result.finalStatus, WARN);
140
+ });
141
+
142
+ runTest("first-write phase can skip screen and review checks", () => {
143
+ const result = evaluateMcpRuntimeGate({
144
+ phase: "first_write",
145
+ mcpAvailable: true,
146
+ projectRoot: "/repo",
147
+ activeEditor: "/repo/.da-vinci/designs/cipher-redesign.pen",
148
+ registeredPenPath: ".da-vinci/designs/cipher-redesign.pen",
149
+ shellVisiblePenPath: ".da-vinci/designs/cipher-redesign.pen",
150
+ shellVisiblePenExists: true,
151
+ liveScreens: [{ id: "GfwiK", name: "Splash" }]
152
+ });
153
+
154
+ assert.equal(result.sourceConvergence.status, PASS);
155
+ assert.equal(result.screenPresence.status, SKIP);
156
+ assert.equal(result.reviewExecution.status, SKIP);
157
+ assert.equal(result.finalStatus, PASS);
158
+ });
159
+
160
+ runTest("documented reconciliation downgrades mismatch to warn", () => {
161
+ const result = evaluateMcpRuntimeGate({
162
+ phase: "completion",
163
+ mcpAvailable: true,
164
+ projectRoot: "/repo",
165
+ activeEditor: "/tmp/other-live.pen",
166
+ registeredPenPath: ".da-vinci/designs/cipher-redesign.pen",
167
+ shellVisiblePenPath: ".da-vinci/designs/cipher-redesign.pen",
168
+ shellVisiblePenExists: true,
169
+ documentedReconciliation: true,
170
+ claimedAnchorIds: ["GfwiK"],
171
+ claimedReviewedScreenIds: ["GfwiK"],
172
+ reviewTargets: ["GfwiK"],
173
+ liveScreens: [{ id: "GfwiK", name: "Splash" }]
174
+ });
175
+
176
+ assert.equal(result.sourceConvergence.status, WARN);
177
+ assert.equal(result.finalStatus, WARN);
178
+ });
179
+
180
+ runTest("same basename but different absolute path blocks without reconciliation", () => {
181
+ const result = evaluateMcpRuntimeGate({
182
+ phase: "completion",
183
+ mcpAvailable: true,
184
+ projectRoot: "/repo",
185
+ activeEditor: "/tmp/cipher-redesign.pen",
186
+ registeredPenPath: ".da-vinci/designs/cipher-redesign.pen",
187
+ shellVisiblePenPath: ".da-vinci/designs/cipher-redesign.pen",
188
+ shellVisiblePenExists: true,
189
+ claimedAnchorIds: ["GfwiK"],
190
+ claimedReviewedScreenIds: ["GfwiK"],
191
+ reviewTargets: ["GfwiK"],
192
+ liveScreens: [{ id: "GfwiK", name: "Splash" }]
193
+ });
194
+
195
+ assert.equal(result.sourceConvergence.status, BLOCK);
196
+ assert.equal(result.finalStatus, BLOCK);
197
+ });
198
+
199
+ console.log("All MCP runtime gate tests passed.");