@design-ai/cli 4.55.0 → 4.57.0

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 (301) hide show
  1. package/.claude-plugin/plugin.json +109 -25
  2. package/CHANGELOG.md +75 -0
  3. package/README.ko.md +15 -32
  4. package/README.md +18 -31
  5. package/cli/bin/design-ai.mjs +1 -0
  6. package/cli/commands/help.mjs +7 -4
  7. package/cli/commands/index.mjs +292 -0
  8. package/cli/commands/learn-help.mjs +149 -0
  9. package/cli/commands/learn-print-profile.mjs +373 -0
  10. package/cli/commands/learn-print-restore.mjs +349 -0
  11. package/cli/commands/learn-print-signals.mjs +453 -0
  12. package/cli/commands/learn.mjs +60 -1281
  13. package/cli/commands/pack.mjs +7 -3
  14. package/cli/commands/prompt.mjs +7 -3
  15. package/cli/commands/search.mjs +94 -1
  16. package/cli/lib/dispatch.mjs +3 -0
  17. package/cli/lib/embedding-index.mjs +199 -0
  18. package/cli/lib/embedding-provider.mjs +121 -0
  19. package/cli/lib/embedding-rerank.mjs +52 -0
  20. package/cli/lib/learn-args.mjs +490 -0
  21. package/cli/lib/learn-backup.mjs +748 -0
  22. package/cli/lib/learn-curation.mjs +612 -0
  23. package/cli/lib/learn-eval.mjs +459 -0
  24. package/cli/lib/learn-profile.mjs +763 -0
  25. package/cli/lib/learn-select.mjs +223 -0
  26. package/cli/lib/learn-shared.mjs +158 -0
  27. package/cli/lib/learn-test-support.mjs +218 -0
  28. package/cli/lib/learn-usage.mjs +360 -0
  29. package/cli/lib/learn.mjs +83 -3694
  30. package/cli/lib/lexical.mjs +137 -0
  31. package/cli/lib/local-config.mjs +110 -0
  32. package/cli/lib/mcp-server.mjs +221 -13
  33. package/cli/lib/pack.mjs +31 -4
  34. package/cli/lib/prompt.mjs +42 -4
  35. package/cli/lib/recall.mjs +193 -0
  36. package/cli/lib/retrieval-index.mjs +0 -0
  37. package/cli/lib/search-ranked.mjs +170 -0
  38. package/cli/lib/search.mjs +11 -1
  39. package/cli/lib/signals-backlog-commands.mjs +673 -0
  40. package/cli/lib/signals-backlog.mjs +361 -0
  41. package/cli/lib/signals-eval.mjs +176 -0
  42. package/cli/lib/signals-readiness.mjs +247 -0
  43. package/cli/lib/signals-registry.mjs +377 -0
  44. package/cli/lib/signals-render.mjs +478 -0
  45. package/cli/lib/signals-shared.mjs +75 -0
  46. package/cli/lib/signals.mjs +16 -2337
  47. package/cli/lib/site-analysis.mjs +297 -0
  48. package/cli/lib/site-args.mjs +433 -0
  49. package/cli/lib/site-bundle-build.mjs +127 -0
  50. package/cli/lib/site-bundle-check.mjs +454 -0
  51. package/cli/lib/site-bundle-commands.mjs +95 -0
  52. package/cli/lib/site-bundle-compare.mjs +157 -0
  53. package/cli/lib/site-bundle-contract.mjs +79 -0
  54. package/cli/lib/site-bundle-files.mjs +87 -0
  55. package/cli/lib/site-bundle-handoff-expected.mjs +173 -0
  56. package/cli/lib/site-bundle-handoff-runbook-action-summary.mjs +332 -0
  57. package/cli/lib/site-bundle-handoff-runbook-actions.mjs +113 -0
  58. package/cli/lib/site-bundle-handoff-runbook-evidence-fields.mjs +164 -0
  59. package/cli/lib/site-bundle-handoff-runbook-evidence.mjs +334 -0
  60. package/cli/lib/site-bundle-handoff-runbook-format.mjs +31 -0
  61. package/cli/lib/site-bundle-handoff-runbook-human-lines.mjs +167 -0
  62. package/cli/lib/site-bundle-handoff-runbook-maps.mjs +238 -0
  63. package/cli/lib/site-bundle-handoff-runbook-next-step.mjs +278 -0
  64. package/cli/lib/site-bundle-handoff-runbook-stage-metadata.mjs +84 -0
  65. package/cli/lib/site-bundle-handoff-runbook.mjs +444 -0
  66. package/cli/lib/site-bundle-handoff-summary.mjs +183 -0
  67. package/cli/lib/site-bundle-handoff.mjs +271 -0
  68. package/cli/lib/site-bundle-readme.mjs +98 -0
  69. package/cli/lib/site-bundle-repair-report.mjs +143 -0
  70. package/cli/lib/site-bundle-repair.mjs +68 -0
  71. package/cli/lib/site-content.mjs +399 -0
  72. package/cli/lib/site-evidence.mjs +35 -0
  73. package/cli/lib/site-mcp-commands.mjs +28 -0
  74. package/cli/lib/site-mcp-probes.mjs +159 -0
  75. package/cli/lib/site-mcp-readiness.mjs +157 -0
  76. package/cli/lib/site-mcp-report.mjs +324 -0
  77. package/cli/lib/site-next-actions.mjs +333 -0
  78. package/cli/lib/site-options.mjs +104 -0
  79. package/cli/lib/site-prompts.mjs +332 -0
  80. package/cli/lib/site-starter.mjs +153 -0
  81. package/cli/lib/site-strings.mjs +23 -0
  82. package/cli/lib/site-tasks.mjs +93 -0
  83. package/cli/lib/site-test-support.mjs +68 -0
  84. package/cli/lib/site-workflow-graph.mjs +309 -0
  85. package/cli/lib/site-workspace.mjs +492 -0
  86. package/cli/lib/site.mjs +108 -6617
  87. package/cli/lib/skill-proposals-apply-commands.mjs +135 -0
  88. package/cli/lib/skill-proposals-apply-contract.mjs +750 -0
  89. package/cli/lib/skill-proposals-apply-plan.mjs +118 -0
  90. package/cli/lib/skill-proposals-generate.mjs +298 -0
  91. package/cli/lib/skill-proposals-render.mjs +532 -0
  92. package/cli/lib/skill-proposals-review.mjs +262 -0
  93. package/cli/lib/skill-proposals.mjs +15 -2046
  94. package/cli/lib/workspace-args.mjs +83 -0
  95. package/cli/lib/workspace-git.mjs +169 -0
  96. package/cli/lib/workspace-learning.mjs +483 -0
  97. package/cli/lib/workspace-repo.mjs +139 -0
  98. package/cli/lib/workspace-report.mjs +283 -0
  99. package/cli/lib/workspace-test-support.mjs +99 -0
  100. package/cli/lib/workspace.mjs +30 -1056
  101. package/docs/AI-LEARNING-PHASE2.md +215 -0
  102. package/docs/DISTRIBUTION.ko.md +35 -6
  103. package/docs/DISTRIBUTION.md +35 -8
  104. package/docs/NEXT-SURFACE-DECISION.md +125 -0
  105. package/docs/PRODUCT-READINESS.md +3 -3
  106. package/docs/RELEASE-CHECKLIST.md +20 -3
  107. package/docs/RELEASE-GATES.ko.md +35 -0
  108. package/docs/RELEASE-GATES.md +234 -0
  109. package/docs/ROADMAP.md +2232 -8
  110. package/docs/external-status.md +20 -7
  111. package/docs/inspection-20260630.md +169 -0
  112. package/docs/integrations/design-ai-mcp-server.md +35 -3
  113. package/docs/integrations/vscode-walkthrough.ko.md +3 -3
  114. package/docs/integrations/vscode-walkthrough.md +3 -3
  115. package/docs/reference/ant-design.md +413 -0
  116. package/docs/reference/awesome-design-md.md +439 -0
  117. package/docs/reference/mui.md +783 -0
  118. package/docs/reference/shadcn-ui.md +298 -0
  119. package/docs/site-overrides/main.html +1 -1
  120. package/examples/component-accordion-actions.md +5 -5
  121. package/examples/component-accordion-details.md +5 -5
  122. package/examples/component-accordion-summary.md +5 -5
  123. package/examples/component-accordion.md +3 -3
  124. package/examples/component-affix.md +1 -1
  125. package/examples/component-alert-dialog.md +1 -1
  126. package/examples/component-alert-title.md +1 -1
  127. package/examples/component-alert.md +3 -3
  128. package/examples/component-anchor.md +1 -1
  129. package/examples/component-app-bar.md +1 -1
  130. package/examples/component-aspect-ratio.md +1 -1
  131. package/examples/component-auto-complete.md +2 -2
  132. package/examples/component-avatar-group.md +5 -5
  133. package/examples/component-avatar.md +3 -3
  134. package/examples/component-back-top.md +1 -1
  135. package/examples/component-backdrop.md +1 -1
  136. package/examples/component-badge.md +3 -3
  137. package/examples/component-border-beam.md +3 -3
  138. package/examples/component-bottom-navigation.md +1 -1
  139. package/examples/component-box.md +1 -1
  140. package/examples/component-breadcrumb.md +3 -3
  141. package/examples/component-button-base.md +3 -3
  142. package/examples/component-button-group.md +2 -2
  143. package/examples/component-button.md +3 -3
  144. package/examples/component-calendar.md +2 -2
  145. package/examples/component-card-actions.md +1 -1
  146. package/examples/component-card-content.md +1 -1
  147. package/examples/component-card-header.md +1 -1
  148. package/examples/component-card-media.md +1 -1
  149. package/examples/component-card.md +3 -3
  150. package/examples/component-carousel.md +2 -2
  151. package/examples/component-cascader.md +1 -1
  152. package/examples/component-chart.md +1 -1
  153. package/examples/component-checkbox.md +3 -3
  154. package/examples/component-click-away-listener.md +1 -1
  155. package/examples/component-code.md +1 -1
  156. package/examples/component-collapsible.md +1 -1
  157. package/examples/component-color-picker.md +1 -1
  158. package/examples/component-combobox.md +1 -1
  159. package/examples/component-command.md +1 -1
  160. package/examples/component-config-provider.md +3 -3
  161. package/examples/component-context-menu.md +1 -1
  162. package/examples/component-css-baseline.md +3 -3
  163. package/examples/component-date-picker.md +2 -2
  164. package/examples/component-descriptions.md +1 -1
  165. package/examples/component-dialog-actions.md +1 -1
  166. package/examples/component-dialog-content-text.md +1 -1
  167. package/examples/component-dialog-content.md +1 -1
  168. package/examples/component-dialog-title.md +1 -1
  169. package/examples/component-dialog.md +2 -2
  170. package/examples/component-divider.md +3 -3
  171. package/examples/component-drawer.md +3 -3
  172. package/examples/component-dropdown.md +3 -3
  173. package/examples/component-empty.md +2 -2
  174. package/examples/component-fade.md +1 -1
  175. package/examples/component-field.md +1 -1
  176. package/examples/component-filled-input.md +1 -1
  177. package/examples/component-flex.md +1 -1
  178. package/examples/component-float-button.md +2 -2
  179. package/examples/component-form-control-label.md +1 -1
  180. package/examples/component-form-control.md +1 -1
  181. package/examples/component-form-controls.md +1 -1
  182. package/examples/component-form-group.md +1 -1
  183. package/examples/component-form-helper-text.md +1 -1
  184. package/examples/component-form-label.md +1 -1
  185. package/examples/component-form.md +2 -2
  186. package/examples/component-grid.md +2 -2
  187. package/examples/component-grow.md +1 -1
  188. package/examples/component-hover-card.md +1 -1
  189. package/examples/component-icon-button.md +1 -1
  190. package/examples/component-icon.md +1 -1
  191. package/examples/component-image-list.md +1 -1
  192. package/examples/component-image.md +1 -1
  193. package/examples/component-input-adornment.md +1 -1
  194. package/examples/component-input-base.md +1 -1
  195. package/examples/component-input-number.md +1 -1
  196. package/examples/component-input-otp.md +2 -2
  197. package/examples/component-input.md +3 -3
  198. package/examples/component-item.md +1 -1
  199. package/examples/component-label.md +1 -1
  200. package/examples/component-layout.md +1 -1
  201. package/examples/component-link.md +1 -1
  202. package/examples/component-list-item-avatar.md +1 -1
  203. package/examples/component-list-item-button.md +1 -1
  204. package/examples/component-list-item-icon.md +1 -1
  205. package/examples/component-list-item-text.md +1 -1
  206. package/examples/component-list-item.md +1 -1
  207. package/examples/component-list-subheader.md +1 -1
  208. package/examples/component-list.md +2 -2
  209. package/examples/component-masonry.md +1 -1
  210. package/examples/component-mentions.md +1 -1
  211. package/examples/component-menu-item.md +1 -1
  212. package/examples/component-menu-list.md +1 -1
  213. package/examples/component-menu.md +1 -1
  214. package/examples/component-menubar.md +1 -1
  215. package/examples/component-message.md +1 -1
  216. package/examples/component-mobile-stepper.md +1 -1
  217. package/examples/component-modal.md +5 -5
  218. package/examples/component-navigation-menu.md +1 -1
  219. package/examples/component-notification.md +1 -1
  220. package/examples/component-outlined-input.md +1 -1
  221. package/examples/component-pagination.md +3 -3
  222. package/examples/component-paper.md +1 -1
  223. package/examples/component-popconfirm.md +1 -1
  224. package/examples/component-popover.md +3 -3
  225. package/examples/component-popper.md +1 -1
  226. package/examples/component-progress.md +2 -2
  227. package/examples/component-qr-code.md +1 -1
  228. package/examples/component-radio.md +3 -3
  229. package/examples/component-rate.md +2 -2
  230. package/examples/component-resizable.md +1 -1
  231. package/examples/component-result.md +1 -1
  232. package/examples/component-scroll-area.md +1 -1
  233. package/examples/component-segmented.md +3 -3
  234. package/examples/component-select.md +3 -3
  235. package/examples/component-separator.md +1 -1
  236. package/examples/component-sheet.md +1 -1
  237. package/examples/component-sidebar.md +1 -1
  238. package/examples/component-skeleton.md +3 -3
  239. package/examples/component-slide.md +1 -1
  240. package/examples/component-slider.md +3 -3
  241. package/examples/component-snackbar-content.md +1 -1
  242. package/examples/component-snackbar.md +1 -1
  243. package/examples/component-sonner.md +1 -1
  244. package/examples/component-space.md +1 -1
  245. package/examples/component-speed-dial-action.md +1 -1
  246. package/examples/component-speed-dial.md +1 -1
  247. package/examples/component-spin.md +2 -2
  248. package/examples/component-spinner.md +1 -1
  249. package/examples/component-splitter.md +2 -2
  250. package/examples/component-stack.md +1 -1
  251. package/examples/component-statistic.md +1 -1
  252. package/examples/component-step-button.md +4 -4
  253. package/examples/component-step-connector.md +4 -4
  254. package/examples/component-step-content.md +1 -1
  255. package/examples/component-step-icon.md +1 -1
  256. package/examples/component-step-label.md +1 -1
  257. package/examples/component-step.md +2 -2
  258. package/examples/component-steps.md +2 -2
  259. package/examples/component-swipeable-drawer.md +1 -1
  260. package/examples/component-switch.md +3 -3
  261. package/examples/component-tab-scroll-button.md +5 -5
  262. package/examples/component-tab.md +1 -1
  263. package/examples/component-table-body.md +1 -1
  264. package/examples/component-table-cell.md +1 -1
  265. package/examples/component-table-container.md +1 -1
  266. package/examples/component-table-footer.md +1 -1
  267. package/examples/component-table-head.md +1 -1
  268. package/examples/component-table-pagination.md +1 -1
  269. package/examples/component-table-row.md +1 -1
  270. package/examples/component-table-sort-label.md +1 -1
  271. package/examples/component-table.md +2 -2
  272. package/examples/component-tabs.md +3 -3
  273. package/examples/component-tag-badge.md +2 -2
  274. package/examples/component-tag.md +1 -1
  275. package/examples/component-textarea-autosize.md +1 -1
  276. package/examples/component-textarea.md +1 -1
  277. package/examples/component-time-picker.md +1 -1
  278. package/examples/component-timeline.md +1 -1
  279. package/examples/component-toast.md +4 -4
  280. package/examples/component-toggle-button.md +1 -1
  281. package/examples/component-toggle.md +1 -1
  282. package/examples/component-toolbar.md +1 -1
  283. package/examples/component-tooltip.md +3 -3
  284. package/examples/component-tour.md +1 -1
  285. package/examples/component-transfer.md +1 -1
  286. package/examples/component-tree-select.md +1 -1
  287. package/examples/component-tree.md +1 -1
  288. package/examples/component-typography.md +2 -2
  289. package/examples/component-upload.md +1 -1
  290. package/examples/component-watermark.md +1 -1
  291. package/examples/component-zoom.md +1 -1
  292. package/knowledge/COVERAGE.md +4 -3
  293. package/knowledge/components/INDEX.md +202 -202
  294. package/knowledge/patterns/brand-references.md +72 -72
  295. package/package.json +1 -1
  296. package/tools/audit/local-ci.py +16 -1
  297. package/tools/audit/package-smoke.py +717 -9
  298. package/tools/audit/registry-smoke.py +912 -10
  299. package/tools/audit/release-metadata.py +47 -1
  300. package/tools/audit/smoke_assertions.py +998 -35
  301. package/tools/migrations/refs-links-to-reference-pages.py +179 -0
@@ -0,0 +1,309 @@
1
+ // Website Improvement workflow graph helpers.
2
+
3
+ import {
4
+ buildSiteMcpCheckReport,
5
+ combineStatuses,
6
+ normalizeMcpKey,
7
+ } from "./site-mcp-report.mjs";
8
+ import { orderedRefactorTasks } from "./site-prompts.mjs";
9
+ import { markdownTable } from "./site-strings.mjs";
10
+ import {
11
+ AUDIT_CATEGORIES,
12
+ } from "./site-options.mjs";
13
+ import {
14
+ SITE_PROMPT_TEMPLATES,
15
+ } from "./site-content.mjs";
16
+ import { analyzeSiteWorkspace } from "./site-analysis.mjs";
17
+ import { generateSiteRefactorTasks } from "./site-tasks.mjs";
18
+
19
+ function workflowNode(id, type, label, status, data = {}) {
20
+ return {
21
+ id,
22
+ type,
23
+ label,
24
+ status,
25
+ data,
26
+ };
27
+ }
28
+
29
+ function workflowEdge(from, to, type, label) {
30
+ return {
31
+ id: `${from}->${to}:${type}`,
32
+ from,
33
+ to,
34
+ type,
35
+ label,
36
+ };
37
+ }
38
+
39
+ function siteProfileNodeId(profile) {
40
+ return `profile:${profile.id || "site"}`;
41
+ }
42
+
43
+ function workflowGraphMcpNodes(mcpReport) {
44
+ return mcpReport.items.map((item) => workflowNode(
45
+ `mcp:${item.key}`,
46
+ "mcp-readiness",
47
+ item.label,
48
+ item.level,
49
+ {
50
+ key: item.key,
51
+ requestedStatus: item.requestedStatus,
52
+ state: item.state,
53
+ evidence: item.evidence,
54
+ actions: item.actions,
55
+ },
56
+ ));
57
+ }
58
+
59
+ function workflowGraphTaskNode(task) {
60
+ return workflowNode(
61
+ `task:${task.id}`,
62
+ "refactor-task",
63
+ task.title,
64
+ "planned",
65
+ {
66
+ id: task.id,
67
+ category: task.category,
68
+ problem: task.problem,
69
+ evidence: task.evidence,
70
+ impact: task.impact,
71
+ effort: task.effort,
72
+ priority: task.priority,
73
+ pages: task.pages,
74
+ recommendedMcp: task.recommendedMcp,
75
+ codexPrompt: task.codexPrompt,
76
+ verification: task.verification,
77
+ risks: task.risks,
78
+ },
79
+ );
80
+ }
81
+
82
+ export function buildSiteWorkflowGraph(workspaceInput, summary = {}) {
83
+ const taskResult = generateSiteRefactorTasks(workspaceInput);
84
+ const workspace = taskResult.workspace;
85
+ const filePath = summary.filePath || "workspace.json";
86
+ const { summary: taskSummary } = analyzeSiteWorkspace(workspace, { filePath });
87
+ const mcpReport = buildSiteMcpCheckReport(workspace, taskSummary);
88
+ const profile = workspace.siteProfile;
89
+ const profileNodeId = siteProfileNodeId(profile);
90
+ const orderedTasks = orderedRefactorTasks(workspace);
91
+ const nodes = [];
92
+ const edges = [];
93
+
94
+ nodes.push(workflowNode(
95
+ "workspace:intake",
96
+ "workspace",
97
+ "Workspace intake",
98
+ taskSummary.status,
99
+ {
100
+ version: workspace.version,
101
+ updatedAt: workspace.updatedAt,
102
+ source: filePath,
103
+ workspaceStatus: taskSummary.status,
104
+ mcpStatus: mcpReport.status,
105
+ },
106
+ ));
107
+ nodes.push(workflowNode(
108
+ profileNodeId,
109
+ "site-profile",
110
+ profile.name,
111
+ taskSummary.status,
112
+ {
113
+ id: profile.id,
114
+ liveUrl: profile.liveUrl,
115
+ repoUrl: profile.repoUrl,
116
+ localPath: profile.localPath,
117
+ figmaUrl: profile.figmaUrl,
118
+ deployProvider: profile.deployProvider,
119
+ cms: profile.cms,
120
+ database: profile.database,
121
+ pages: profile.pages,
122
+ userFlows: profile.userFlows,
123
+ viewports: profile.viewports,
124
+ brandNotes: profile.brandNotes,
125
+ },
126
+ ));
127
+ edges.push(workflowEdge("workspace:intake", profileNodeId, "profile", "Workspace defines the target site profile"));
128
+
129
+ for (const category of AUDIT_CATEGORIES) {
130
+ const row = workspace.auditChecklist[category.id];
131
+ const nodeId = `audit:${category.id}`;
132
+ nodes.push(workflowNode(
133
+ nodeId,
134
+ "audit-category",
135
+ category.label,
136
+ row.status,
137
+ {
138
+ category: category.id,
139
+ notes: row.notes,
140
+ findings: row.findings,
141
+ findingCount: row.findings.length,
142
+ defaultVerification: category.defaultVerification,
143
+ },
144
+ ));
145
+ edges.push(workflowEdge(profileNodeId, nodeId, "audit-input", "Site context drives this audit category"));
146
+ }
147
+
148
+ const mcpNodes = workflowGraphMcpNodes(mcpReport);
149
+ nodes.push(...mcpNodes);
150
+ for (const node of mcpNodes) {
151
+ edges.push(workflowEdge(profileNodeId, node.id, "readiness-input", "Site profile provides MCP readiness evidence"));
152
+ }
153
+
154
+ for (const task of orderedTasks) {
155
+ const taskNode = workflowGraphTaskNode(task);
156
+ nodes.push(taskNode);
157
+ edges.push(workflowEdge(`audit:${task.category}`, taskNode.id, "finding-to-task", "Audit finding informs this refactor task"));
158
+ edges.push(workflowEdge(profileNodeId, taskNode.id, "site-context", "Site profile scopes this refactor task"));
159
+ for (const rawMcp of task.recommendedMcp) {
160
+ const key = normalizeMcpKey(rawMcp);
161
+ if (workspace.mcpReadiness[key]) {
162
+ edges.push(workflowEdge(`mcp:${key}`, taskNode.id, "mcp-support", "MCP readiness supports task execution"));
163
+ }
164
+ }
165
+ }
166
+
167
+ for (const template of SITE_PROMPT_TEMPLATES) {
168
+ const promptNodeId = `prompt:${template.id}`;
169
+ nodes.push(workflowNode(
170
+ promptNodeId,
171
+ "prompt-template",
172
+ template.label,
173
+ "ready",
174
+ {
175
+ id: template.id,
176
+ agent: template.agent,
177
+ output: template.output,
178
+ description: template.description,
179
+ taskSelectable: template.taskSelectable,
180
+ },
181
+ ));
182
+ edges.push(workflowEdge(profileNodeId, promptNodeId, "profile-context", "Prompt template receives site profile context"));
183
+ }
184
+
185
+ for (const task of orderedTasks) {
186
+ edges.push(workflowEdge(`task:${task.id}`, "prompt:codex-implementation", "implementation-prompt", "Task can be exported as a Codex implementation prompt"));
187
+ }
188
+
189
+ nodes.push(workflowNode(
190
+ "handoff:report",
191
+ "handoff-report",
192
+ "Handoff report",
193
+ "ready",
194
+ {
195
+ output: "website-handoff.md",
196
+ purpose: "Summarize site state, audit findings, priority improvements, verification, and remaining risk",
197
+ },
198
+ ));
199
+ nodes.push(workflowNode(
200
+ "handoff:bundle",
201
+ "handoff-bundle",
202
+ "Local handoff bundle",
203
+ "ready",
204
+ {
205
+ output: "website-handoff-bundle",
206
+ purpose: "Package the local Website Improvement plan without mutating the target repo",
207
+ },
208
+ ));
209
+ nodes.push(workflowNode(
210
+ "handoff:target-repo",
211
+ "target-repo",
212
+ "Target website repo",
213
+ "external",
214
+ {
215
+ repoUrl: profile.repoUrl,
216
+ localPath: profile.localPath,
217
+ boundary: "Implementation happens outside the design-ai repository",
218
+ },
219
+ ));
220
+ edges.push(workflowEdge(profileNodeId, "handoff:report", "handoff-input", "Site profile anchors the handoff report"));
221
+ for (const task of orderedTasks) {
222
+ edges.push(workflowEdge(`task:${task.id}`, "handoff:report", "handoff-input", "Refactor task is summarized in the handoff report"));
223
+ }
224
+ for (const item of mcpReport.items.filter((item) => item.requestedStatus !== "unused")) {
225
+ edges.push(workflowEdge(`mcp:${item.key}`, "handoff:report", "readiness-input", "MCP readiness is summarized in the handoff report"));
226
+ }
227
+ for (const template of SITE_PROMPT_TEMPLATES) {
228
+ edges.push(workflowEdge(`prompt:${template.id}`, "handoff:target-repo", "agent-prompt", "Prompt can be used in the target website workflow"));
229
+ }
230
+ edges.push(workflowEdge("handoff:report", "handoff:bundle", "bundle-input", "Handoff report can be packaged into a local bundle"));
231
+ edges.push(workflowEdge("handoff:bundle", "handoff:target-repo", "handoff", "Verified bundle can become target-repo implementation context"));
232
+
233
+ const status = combineStatuses(taskSummary.status, mcpReport.status);
234
+ return {
235
+ version: 1,
236
+ kind: "website-improvement-workflow-graph",
237
+ generatedAt: workspace.updatedAt,
238
+ filePath,
239
+ status,
240
+ workspaceStatus: taskSummary.status,
241
+ mcpStatus: mcpReport.status,
242
+ externalCalls: false,
243
+ site: {
244
+ id: profile.id,
245
+ name: profile.name,
246
+ liveUrl: profile.liveUrl,
247
+ repoUrl: profile.repoUrl,
248
+ localPath: profile.localPath,
249
+ },
250
+ summary: {
251
+ status,
252
+ workspaceStatus: taskSummary.status,
253
+ mcpStatus: mcpReport.status,
254
+ nodeCount: nodes.length,
255
+ edgeCount: edges.length,
256
+ auditCategoryCount: AUDIT_CATEGORIES.length,
257
+ taskCount: orderedTasks.length,
258
+ generatedTaskCount: taskResult.created.length,
259
+ requiredMcpCount: mcpReport.counts.required,
260
+ promptTemplateCount: SITE_PROMPT_TEMPLATES.length,
261
+ },
262
+ nodes,
263
+ edges,
264
+ boundaries: [
265
+ "deterministic-local",
266
+ "no-external-mcp-calls",
267
+ "no-target-repo-mutation",
268
+ "no-new-dependencies",
269
+ ],
270
+ };
271
+ }
272
+
273
+ export function formatSiteWorkflowGraphJson(graph) {
274
+ return JSON.stringify(graph, null, 2);
275
+ }
276
+
277
+ export function formatSiteWorkflowGraphMarkdown(graph) {
278
+ return [
279
+ `# Website improvement workflow graph: ${graph.site.name}`,
280
+ "",
281
+ "## Summary",
282
+ `- Source: ${graph.filePath}`,
283
+ `- Status: ${graph.status}`,
284
+ `- Workspace status: ${graph.workspaceStatus}`,
285
+ `- MCP status: ${graph.mcpStatus}`,
286
+ `- Nodes: ${graph.summary.nodeCount}`,
287
+ `- Edges: ${graph.summary.edgeCount}`,
288
+ `- Tasks: ${graph.summary.taskCount}`,
289
+ `- Prompt templates: ${graph.summary.promptTemplateCount}`,
290
+ `- External calls: ${graph.externalCalls ? "yes" : "no"}`,
291
+ "",
292
+ "## Nodes",
293
+ markdownTable(
294
+ ["ID", "Type", "Status", "Label"],
295
+ graph.nodes.map((node) => [node.id, node.type, node.status, node.label]),
296
+ ),
297
+ "",
298
+ "## Edges",
299
+ markdownTable(
300
+ ["From", "To", "Type", "Label"],
301
+ graph.edges.map((edge) => [edge.from, edge.to, edge.type, edge.label]),
302
+ ),
303
+ "",
304
+ "## Boundaries",
305
+ "- This graph is deterministic and local.",
306
+ "- No external MCP calls are made.",
307
+ "- It does not mutate the target website repo, run Lighthouse/axe, crawl pages, add dependencies, or write to external systems.",
308
+ ].join("\n");
309
+ }