@xenonbyte/da-vinci-workflow 0.2.2 → 0.2.3

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 (54) hide show
  1. package/CHANGELOG.md +15 -0
  2. package/README.md +24 -14
  3. package/README.zh-CN.md +25 -14
  4. package/commands/claude/dv/breakdown.md +8 -0
  5. package/commands/claude/dv/build.md +11 -0
  6. package/commands/claude/dv/design.md +5 -2
  7. package/commands/claude/dv/tasks.md +8 -0
  8. package/commands/claude/dv/verify.md +9 -0
  9. package/commands/codex/prompts/dv-breakdown.md +8 -0
  10. package/commands/codex/prompts/dv-build.md +11 -0
  11. package/commands/codex/prompts/dv-design.md +5 -2
  12. package/commands/codex/prompts/dv-tasks.md +8 -0
  13. package/commands/codex/prompts/dv-verify.md +8 -0
  14. package/commands/gemini/dv/breakdown.toml +8 -0
  15. package/commands/gemini/dv/build.toml +11 -0
  16. package/commands/gemini/dv/design.toml +5 -2
  17. package/commands/gemini/dv/tasks.toml +8 -0
  18. package/commands/gemini/dv/verify.toml +8 -0
  19. package/docs/dv-command-reference.md +43 -0
  20. package/docs/execution-chain-plan.md +10 -3
  21. package/docs/mode-use-cases.md +2 -1
  22. package/docs/pencil-rendering-workflow.md +15 -12
  23. package/docs/prompt-presets/README.md +1 -1
  24. package/docs/prompt-presets/desktop-app.md +3 -3
  25. package/docs/prompt-presets/mobile-app.md +3 -3
  26. package/docs/prompt-presets/tablet-app.md +3 -3
  27. package/docs/prompt-presets/web-app.md +3 -3
  28. package/docs/skill-usage.md +45 -38
  29. package/docs/workflow-examples.md +16 -13
  30. package/docs/workflow-overview.md +2 -0
  31. package/docs/zh-CN/dv-command-reference.md +43 -0
  32. package/docs/zh-CN/mode-use-cases.md +2 -1
  33. package/docs/zh-CN/pencil-rendering-workflow.md +15 -12
  34. package/docs/zh-CN/prompt-presets/README.md +1 -1
  35. package/docs/zh-CN/prompt-presets/desktop-app.md +3 -3
  36. package/docs/zh-CN/prompt-presets/mobile-app.md +3 -3
  37. package/docs/zh-CN/prompt-presets/tablet-app.md +3 -3
  38. package/docs/zh-CN/prompt-presets/web-app.md +3 -3
  39. package/docs/zh-CN/skill-usage.md +45 -38
  40. package/docs/zh-CN/workflow-examples.md +15 -13
  41. package/docs/zh-CN/workflow-overview.md +2 -0
  42. package/examples/greenfield-spec-markupflow/.da-vinci/state/execution-signals/demo__lint-tasks.json +16 -0
  43. package/lib/audit-parsers.js +18 -9
  44. package/lib/audit.js +3 -26
  45. package/lib/cli.js +50 -1
  46. package/lib/design-source-registry.js +146 -0
  47. package/lib/save-current-design.js +790 -0
  48. package/lib/supervisor-review.js +1 -1
  49. package/lib/workflow-bootstrap.js +2 -13
  50. package/lib/workflow-persisted-state.js +3 -1
  51. package/lib/workflow-state.js +51 -3
  52. package/package.json +1 -1
  53. package/tui/catalog.js +103 -0
  54. package/tui/index.js +2274 -418
@@ -416,7 +416,7 @@ function extractMcpRuntimeGateStatus(markdownText) {
416
416
  }
417
417
 
418
418
  const statusMatch = String(section).match(
419
- /(?:^|\n)\s*-\s*(?:Status|状态)\s*:\s*`?(PASS|WARN|BLOCK)`?\b/i
419
+ /(?:^|\n)\s*-\s*(?:Final runtime gate status|Status|状态)\s*:\s*`?(PASS|WARN|BLOCK)`?\b/i
420
420
  );
421
421
  return statusMatch ? String(statusMatch[1]).toUpperCase() : "";
422
422
  }
@@ -1,8 +1,8 @@
1
1
  const fs = require("fs");
2
2
  const path = require("path");
3
3
 
4
- const { isPathInside } = require("./fs-safety");
5
4
  const { ensurePenFile } = require("./pen-persistence");
5
+ const { resolvePreferredRegisteredPenPath } = require("./design-source-registry");
6
6
  const { pathExists, readTextIfExists, writeFileAtomic } = require("./utils");
7
7
 
8
8
  const DEFAULT_PROJECT_PEN_RELATIVE_PATH = ".da-vinci/designs/project-baseline.pen";
@@ -20,17 +20,6 @@ function validateChangeId(changeId) {
20
20
  return normalized;
21
21
  }
22
22
 
23
- function extractRegisteredPenPath(projectRoot, registryText) {
24
- const matches = String(registryText || "").match(/\.da-vinci\/designs\/[^\s`]+\.pen/g) || [];
25
- for (const relativePath of matches) {
26
- const resolvedPath = path.resolve(projectRoot, relativePath);
27
- if (isPathInside(projectRoot, resolvedPath)) {
28
- return resolvedPath;
29
- }
30
- }
31
- return "";
32
- }
33
-
34
23
  function buildProjectTemplates(preferredPenRelativePath) {
35
24
  return {
36
25
  "DA-VINCI.md": [
@@ -151,7 +140,7 @@ function bootstrapProjectArtifacts(projectPathInput, options = {}) {
151
140
  fs.mkdirSync(path.join(projectRoot, ".da-vinci", "changes"), { recursive: true });
152
141
 
153
142
  const existingRegistryText = readTextIfExists(path.join(projectRoot, ".da-vinci", "design-registry.md"));
154
- const registeredPenPath = extractRegisteredPenPath(projectRoot, existingRegistryText);
143
+ const registeredPenPath = resolvePreferredRegisteredPenPath(projectRoot, existingRegistryText);
155
144
  const preferredPenPath = registeredPenPath || path.join(projectRoot, DEFAULT_PROJECT_PEN_RELATIVE_PATH);
156
145
  const preferredPenRelativePath = path.relative(projectRoot, preferredPenPath) || DEFAULT_PROJECT_PEN_RELATIVE_PATH;
157
146
 
@@ -2,7 +2,7 @@ const fs = require("fs");
2
2
  const path = require("path");
3
3
  const { writeFileAtomic, pathExists, readTextIfExists } = require("./utils");
4
4
 
5
- const WORKFLOW_STATE_VERSION = 1;
5
+ const WORKFLOW_STATE_VERSION = 2;
6
6
  const DEFAULT_STALE_WINDOW_MS = 24 * 60 * 60 * 1000;
7
7
  const PERSISTED_NOTE_EXCLUDE_PATTERNS = [
8
8
  /^No persisted workflow state found for this change; deriving from artifacts\.$/i,
@@ -38,7 +38,9 @@ function fingerprintForPath(targetPath) {
38
38
  function buildWorkflowFingerprint(projectRoot, changeId) {
39
39
  const changeRoot = changeId ? path.join(projectRoot, ".da-vinci", "changes", changeId) : "";
40
40
  const candidates = [
41
+ path.join(projectRoot, "DA-VINCI.md"),
41
42
  path.join(projectRoot, ".da-vinci", "page-map.md"),
43
+ path.join(projectRoot, ".da-vinci", "design-registry.md"),
42
44
  path.join(changeRoot, "proposal.md"),
43
45
  path.join(changeRoot, "design.md"),
44
46
  path.join(changeRoot, "pencil-design.md"),
@@ -13,7 +13,8 @@ const {
13
13
  STATUS,
14
14
  CHECKPOINT_LABELS,
15
15
  HANDOFF_GATES,
16
- getStageById
16
+ getStageById,
17
+ mergeStatuses
17
18
  } = require("./workflow-contract");
18
19
  const {
19
20
  selectPersistedStateForChange,
@@ -49,6 +50,14 @@ function dedupeFindings(findings) {
49
50
  findings.notes = dedupeMessages(findings.notes);
50
51
  }
51
52
 
53
+ function normalizeCheckpointStatus(status) {
54
+ const normalized = String(status || "").toUpperCase();
55
+ if (normalized === STATUS.PASS || normalized === STATUS.WARN || normalized === STATUS.BLOCK) {
56
+ return normalized;
57
+ }
58
+ return STATUS.PASS;
59
+ }
60
+
52
61
  function collectIntegrityAudit(projectRoot, workflowRoot, signalSummary) {
53
62
  if (!pathExists(workflowRoot)) {
54
63
  return null;
@@ -266,6 +275,24 @@ function deriveStageFromArtifacts(artifactState, checkpointStatuses, findings) {
266
275
  findings.warnings.push("`design checkpoint` is WARN.");
267
276
  }
268
277
 
278
+ const designSourceCheckpoint = checkpointStatuses[CHECKPOINT_LABELS.DESIGN_SOURCE];
279
+ if (designSourceCheckpoint === STATUS.BLOCK) {
280
+ findings.blockers.push("`design source checkpoint` is BLOCK.");
281
+ return "design";
282
+ }
283
+ if (designSourceCheckpoint === STATUS.WARN) {
284
+ findings.warnings.push("`design source checkpoint` is WARN.");
285
+ }
286
+
287
+ const runtimeGateCheckpoint = checkpointStatuses[CHECKPOINT_LABELS.RUNTIME_GATE];
288
+ if (runtimeGateCheckpoint === STATUS.BLOCK) {
289
+ findings.blockers.push("`mcp runtime gate` is BLOCK.");
290
+ return "design";
291
+ }
292
+ if (runtimeGateCheckpoint === STATUS.WARN) {
293
+ findings.warnings.push("`mcp runtime gate` is WARN.");
294
+ }
295
+
269
296
  const mappingCheckpoint = checkpointStatuses[CHECKPOINT_LABELS.MAPPING];
270
297
  if (mappingCheckpoint === STATUS.BLOCK) {
271
298
  findings.blockers.push("`mapping checkpoint` is BLOCK.");
@@ -482,6 +509,15 @@ function deriveWorkflowStatus(projectPathInput, options = {}) {
482
509
  )
483
510
  : {};
484
511
  const integrityAudit = collectIntegrityAudit(projectRoot, workflowRoot, signalSummary);
512
+ const designCheckpointStatus = normalizeCheckpointStatus(checkpointStatuses[CHECKPOINT_LABELS.DESIGN]);
513
+ const designSourceCheckpointStatus = normalizeCheckpointStatus(
514
+ checkpointStatuses[CHECKPOINT_LABELS.DESIGN_SOURCE]
515
+ );
516
+ const runtimeGateCheckpointStatus = normalizeCheckpointStatus(
517
+ checkpointStatuses[CHECKPOINT_LABELS.RUNTIME_GATE]
518
+ );
519
+ const mappingCheckpointStatus = normalizeCheckpointStatus(checkpointStatuses[CHECKPOINT_LABELS.MAPPING]);
520
+ const taskCheckpointStatus = normalizeCheckpointStatus(checkpointStatuses[CHECKPOINT_LABELS.TASK]);
485
521
 
486
522
  if (activeChangeId) {
487
523
  const persistedSelection = selectPersistedStateForChange(projectRoot, activeChangeId, {
@@ -579,11 +615,23 @@ function deriveWorkflowStatus(projectPathInput, options = {}) {
579
615
  const gates = {
580
616
  [HANDOFF_GATES.BREAKDOWN_TO_DESIGN]:
581
617
  artifactState.proposal && artifactState.specFiles.length > 0 ? STATUS.PASS : STATUS.BLOCK,
582
- [HANDOFF_GATES.DESIGN_TO_TASKS]:
618
+ [HANDOFF_GATES.DESIGN_TO_TASKS]: mergeStatuses([
583
619
  artifactState.design && artifactState.pencilDesign && artifactState.pencilBindings
584
620
  ? STATUS.PASS
585
621
  : STATUS.BLOCK,
586
- [HANDOFF_GATES.TASKS_TO_BUILD]: artifactState.tasks ? STATUS.PASS : STATUS.BLOCK,
622
+ designCheckpointStatus,
623
+ designSourceCheckpointStatus,
624
+ runtimeGateCheckpointStatus,
625
+ mappingCheckpointStatus
626
+ ]),
627
+ [HANDOFF_GATES.TASKS_TO_BUILD]: mergeStatuses([
628
+ artifactState.tasks ? STATUS.PASS : STATUS.BLOCK,
629
+ designCheckpointStatus,
630
+ designSourceCheckpointStatus,
631
+ runtimeGateCheckpointStatus,
632
+ mappingCheckpointStatus,
633
+ taskCheckpointStatus
634
+ ]),
587
635
  [HANDOFF_GATES.BUILD_TO_VERIFY]: artifactState.verification ? STATUS.PASS : STATUS.BLOCK,
588
636
  [HANDOFF_GATES.VERIFY_TO_COMPLETE]:
589
637
  completionAudit && completionAudit.status === "PASS" ? STATUS.PASS : STATUS.WARN
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xenonbyte/da-vinci-workflow",
3
- "version": "0.2.2",
3
+ "version": "0.2.3",
4
4
  "description": "Requirement-to-design-to-code workflow skill for Codex, Claude, and Gemini",
5
5
  "bin": {
6
6
  "da-vinci": "bin/da-vinci.js",
package/tui/catalog.js CHANGED
@@ -80,6 +80,86 @@ const STAGES = [
80
80
  }
81
81
  ];
82
82
 
83
+ const SCENES = [
84
+ {
85
+ id: "install-uninstall",
86
+ title: {
87
+ en: "Install & Uninstall",
88
+ zh: "安装与卸载"
89
+ },
90
+ summary: {
91
+ en: "Choose install or uninstall and run it against all supported platforms.",
92
+ zh: "选择安装或卸载,并直接对所有支持平台执行。"
93
+ }
94
+ },
95
+ {
96
+ id: "current-status",
97
+ title: {
98
+ en: "Current Status",
99
+ zh: "当前状态"
100
+ },
101
+ summary: {
102
+ en: "Run workflow-status plus next-step, then show the current workflow summary and recommended next move.",
103
+ zh: "执行 workflow-status 与 next-step,并汇总当前工作流状态和建议下一步。"
104
+ }
105
+ },
106
+ {
107
+ id: "switch-work-item",
108
+ title: {
109
+ en: "Switch Work Item",
110
+ zh: "切换工作项"
111
+ },
112
+ summary: {
113
+ en: "Choose the active change from existing work items in this project.",
114
+ zh: "从当前项目已有的工作项目中选择正在处理的 change。"
115
+ }
116
+ },
117
+ {
118
+ id: "design-work",
119
+ title: {
120
+ en: "Design Ops",
121
+ zh: "设计操作"
122
+ },
123
+ summary: {
124
+ en: "Run design-save, icon sync, and managed Visual Assist generation.",
125
+ zh: "执行设计保存、图标同步和受控 Visual Assist 生成。"
126
+ }
127
+ },
128
+ {
129
+ id: "pre-implementation-checks",
130
+ title: {
131
+ en: "Pre-Implementation Checks",
132
+ zh: "实施前检查"
133
+ },
134
+ summary: {
135
+ en: "Run planning and readiness checks before writing implementation code.",
136
+ zh: "在开始实现代码前执行规划与就绪度检查。"
137
+ }
138
+ },
139
+ {
140
+ id: "pre-completion-validation",
141
+ title: {
142
+ en: "Pre-Acceptance Checks",
143
+ zh: "验收前检查"
144
+ },
145
+ summary: {
146
+ en: "Run the pre-acceptance verify chain before completion claims.",
147
+ zh: "在完成声明前运行验收前 verify 链路。"
148
+ }
149
+ },
150
+ {
151
+ id: "more",
152
+ title: {
153
+ en: "Settings",
154
+ zh: "设置"
155
+ },
156
+ summary: {
157
+ en: "Language and logs.",
158
+ zh: "语言与日志。"
159
+ }
160
+ }
161
+ ];
162
+
83
163
  function normalizeLanguage(value) {
84
164
  return value === "zh" ? "zh" : "en";
85
165
  }
@@ -765,6 +845,28 @@ const COMMANDS = [
765
845
  return args;
766
846
  }
767
847
  }),
848
+ createCommand({
849
+ id: "save-current-design",
850
+ stageId: "pencil",
851
+ title: { en: "save-current-design", zh: "save-current-design" },
852
+ summary: {
853
+ en: "Run the high-level bound-source save flow for the active Pencil design session.",
854
+ zh: "运行高层绑定源保存流程,保存当前活跃 Pencil 设计会话。"
855
+ },
856
+ details: {
857
+ en: "This flow validates registered/session/editor convergence and reports saved, blocked, or unavailable honestly.",
858
+ zh: "该流程会校验 registered/session/editor 三方收敛,并明确返回 saved、blocked 或 unavailable。"
859
+ },
860
+ supportsJson: true,
861
+ supportsContinueOnError: true,
862
+ buildArgs(context) {
863
+ const args = ["save-current-design"];
864
+ maybeProject(args, context, { force: true });
865
+ maybeJson(args, context, true);
866
+ maybeContinueOnError(args, context, true);
867
+ return args;
868
+ }
869
+ }),
768
870
  createCommand({
769
871
  id: "pencil-session-end",
770
872
  stageId: "pencil",
@@ -1175,6 +1277,7 @@ function tokenizeCommandLine(input) {
1175
1277
  }
1176
1278
 
1177
1279
  module.exports = {
1280
+ SCENES,
1178
1281
  STAGES,
1179
1282
  COMMANDS,
1180
1283
  buildCommandArgs,