@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,444 @@
1
+ import {
2
+ getStageActionAffordance,
3
+ getStageActionButtonLabel,
4
+ getStageActionDisabledReason,
5
+ getStageActionDisabledReasonCode,
6
+ getStageActionEnabled,
7
+ getStageActionEvidenceTarget,
8
+ getStageActionEvidenceTargetLabel,
9
+ getStageActionInstruction,
10
+ getStageActionLabel,
11
+ getStageActionStatus,
12
+ getStageActionStatusLabel,
13
+ getStageActionStatusTone,
14
+ getStageActionType,
15
+ } from "./site-bundle-handoff-runbook-actions.mjs";
16
+ import {
17
+ buildEvidenceCaptureInitialValidationChecklist,
18
+ buildEvidenceCaptureInitialValidationChecklistSummary,
19
+ buildEvidenceCaptureInitialValidationDisplayMetadata,
20
+ buildEvidenceCaptureInitialValidationStates,
21
+ buildEvidenceCaptureInitialValidationSummary,
22
+ buildEvidenceCapturePayloadBindings,
23
+ buildEvidenceCapturePayloadFlatTemplate,
24
+ buildEvidenceCapturePayloadTemplate,
25
+ buildEvidenceCaptureValidationSpecs,
26
+ uniqueValues,
27
+ } from "./site-bundle-handoff-runbook-evidence.mjs";
28
+ import {
29
+ getStageActionEvidenceCaptureFields,
30
+ } from "./site-bundle-handoff-runbook-evidence-fields.mjs";
31
+ import {
32
+ formatBundleHandoffOperatorRunbookStageLine,
33
+ } from "./site-bundle-handoff-runbook-format.mjs";
34
+ import {
35
+ getStageActionBlockedStageKeys,
36
+ getStageActionCompletionCriteria,
37
+ getStageActionDependencyReason,
38
+ getStageActionDependencyReasonCode,
39
+ getStageActionEvidenceRequirements,
40
+ getStageActionPrerequisiteKeys,
41
+ getStageActionPrerequisiteLabels,
42
+ getStageLabel,
43
+ } from "./site-bundle-handoff-runbook-stage-metadata.mjs";
44
+
45
+ import { buildActionSummary } from "./site-bundle-handoff-runbook-action-summary.mjs";
46
+ import { buildStageHumanLineMaps } from "./site-bundle-handoff-runbook-human-lines.mjs";
47
+ import {
48
+ buildStageActionDependencyMaps,
49
+ buildStageActionEvidenceCaptureMaps,
50
+ buildStageActionEvidenceMaps,
51
+ buildStageActionStatusMaps,
52
+ buildStageExecutionMaps,
53
+ buildStageIdentityMaps,
54
+ callsExternalSystem,
55
+ hasCommands,
56
+ isManualStage,
57
+ isOptionalStage,
58
+ isRequiredStage,
59
+ mutatesTargetRepo,
60
+ usesLocalOutputRunPolicy,
61
+ usesReadOnlyRunPolicy,
62
+ } from "./site-bundle-handoff-runbook-maps.mjs";
63
+ import { buildNextStepState } from "./site-bundle-handoff-runbook-next-step.mjs";
64
+
65
+ export function buildBundleHandoffCommandManifest({
66
+ sourceBundle,
67
+ taskCatalog,
68
+ defaultTask = null,
69
+ selectedTask = null,
70
+ effectiveTask = null,
71
+ } = {}) {
72
+ const commands = [];
73
+ const pushCommand = (entry) => {
74
+ if (!entry || !entry.command || !Array.isArray(entry.commandArgs) || entry.commandArgs.length === 0) return;
75
+ commands.push(entry);
76
+ };
77
+ const sourceValue = (field, fallback = "") => sourceBundle?.[field] || fallback;
78
+ const pushSourceCommand = (key, label, commandKey, argsKey, policyKey, safetyKey) => {
79
+ const safety = sourceValue(safetyKey, null);
80
+ pushCommand({
81
+ key,
82
+ scope: "source-bundle",
83
+ label,
84
+ command: sourceValue(commandKey),
85
+ commandArgs: sourceValue(argsKey, []),
86
+ runPolicy: sourceValue(policyKey),
87
+ safety,
88
+ strict: Boolean(safety?.strict),
89
+ taskId: "",
90
+ outputFile: "",
91
+ defaultTask: false,
92
+ selectedTask: false,
93
+ effectiveTask: false,
94
+ });
95
+ };
96
+ const pushTaskCommand = (task, { strict = false } = {}) => {
97
+ if (!task?.id) return;
98
+ const commandKey = strict ? "strictHandoffCommand" : "handoffCommand";
99
+ const argsKey = strict ? "strictHandoffCommandArgs" : "handoffCommandArgs";
100
+ const policyKey = strict ? "strictHandoffCommandRunPolicy" : "handoffCommandRunPolicy";
101
+ const safetyKey = strict ? "strictHandoffCommandSafety" : "handoffCommandSafety";
102
+ const taskValue = (field, fallback = "") => task[field] || fallback;
103
+ const safety = taskValue(safetyKey, null);
104
+ pushCommand({
105
+ key: `task.${task.id}.handoff.${strict ? "strict" : "default"}`,
106
+ scope: "task-handoff",
107
+ label: `${strict ? "Strict " : ""}Task handoff: ${task.id}`,
108
+ command: taskValue(commandKey),
109
+ commandArgs: taskValue(argsKey, []),
110
+ runPolicy: taskValue(policyKey),
111
+ safety,
112
+ strict,
113
+ taskId: task.id,
114
+ taskNumber: Number.isInteger(task.number) ? task.number : null,
115
+ outputFile: task.handoffOutFile || safety?.outputFile || "",
116
+ defaultTask: task.id === defaultTask?.id,
117
+ selectedTask: task.id === selectedTask?.id,
118
+ effectiveTask: task.id === effectiveTask?.id,
119
+ });
120
+ };
121
+
122
+ pushSourceCommand("source.bundleCheck", "Bundle check JSON", "checkCommand", "checkCommandArgs", "checkCommandRunPolicy", "checkCommandSafety");
123
+ pushSourceCommand("source.bundleCheck.strict", "Strict bundle check JSON", "strictCheckCommand", "strictCheckCommandArgs", "strictCheckCommandRunPolicy", "strictCheckCommandSafety");
124
+ pushSourceCommand("source.bundleHandoff", "Bundle handoff JSON", "handoffCommand", "handoffCommandArgs", "handoffCommandRunPolicy", "handoffCommandSafety");
125
+ pushSourceCommand("source.bundleHandoff.strict", "Strict bundle handoff JSON", "strictHandoffCommand", "strictHandoffCommandArgs", "strictHandoffCommandRunPolicy", "strictHandoffCommandSafety");
126
+ for (const task of taskCatalog?.items || []) {
127
+ pushTaskCommand(task);
128
+ pushTaskCommand(task, { strict: true });
129
+ }
130
+
131
+ const countBy = (predicate) => commands.filter(predicate).length;
132
+ const isSourceBundleCommand = (command) => command.scope === "source-bundle";
133
+ const isTaskHandoffCommand = (command) => command.scope === "task-handoff";
134
+ const usesReadOnlyRunPolicy = (command) => command.runPolicy === "read-only";
135
+ const usesLocalOutputRunPolicy = (command) => command.runPolicy === "writes-local-file";
136
+ const hasExternalCallSafety = (command) => command.safety?.externalCalls === true;
137
+ const hasTargetRepoMutationSafety = (command) => command.safety?.targetRepoMutation === true;
138
+ const requiresCleanWorkspaceSafety = (command) => command.safety?.requiresCleanWorkspace === true;
139
+ const requiresReviewBeforeMutationSafety = (command) => command.safety?.requiresReviewBeforeMutation === true;
140
+ const effectiveTaskId = effectiveTask?.id || "";
141
+ const selectedTaskId = selectedTask?.id || "";
142
+ const defaultTaskId = defaultTask?.id || "";
143
+ const manifestCountSummary = {
144
+ commandCount: commands.length,
145
+ sourceCommandCount: countBy(isSourceBundleCommand),
146
+ taskCommandCount: countBy(isTaskHandoffCommand),
147
+ readOnlyCount: countBy(usesReadOnlyRunPolicy),
148
+ localOutputFileCount: countBy(usesLocalOutputRunPolicy),
149
+ externalCallCount: countBy(hasExternalCallSafety),
150
+ targetRepoMutationCount: countBy(hasTargetRepoMutationSafety),
151
+ requiresCleanWorkspaceCount: countBy(requiresCleanWorkspaceSafety),
152
+ requiresReviewBeforeMutationCount: countBy(requiresReviewBeforeMutationSafety),
153
+ };
154
+ const manifestTaskSelection = {
155
+ defaultTaskId,
156
+ selectedTaskId,
157
+ effectiveTaskId,
158
+ };
159
+ const manifestStrictCommandKeys = {
160
+ defaultStrictTaskCommandKey: defaultTaskId ? `task.${defaultTaskId}.handoff.strict` : "",
161
+ selectedStrictTaskCommandKey: selectedTaskId ? `task.${selectedTaskId}.handoff.strict` : "",
162
+ effectiveStrictTaskCommandKey: effectiveTaskId ? `task.${effectiveTaskId}.handoff.strict` : "",
163
+ };
164
+ return {
165
+ version: 1,
166
+ source: "bundle-handoff",
167
+ ...manifestCountSummary,
168
+ ...manifestTaskSelection,
169
+ ...manifestStrictCommandKeys,
170
+ commands,
171
+ };
172
+ }
173
+
174
+ export function buildBundleHandoffOperatorRunbook(commandManifest) {
175
+ const commands = Array.isArray(commandManifest?.commands) ? commandManifest.commands : [];
176
+ const commandByKey = new Map(commands.map((command) => [command.key, command]));
177
+ const buildStage = ({
178
+ step,
179
+ key,
180
+ label,
181
+ kind,
182
+ required,
183
+ commandKeys = [],
184
+ reason,
185
+ manual = false,
186
+ }) => {
187
+ const stageCommands = commandKeys
188
+ .map((commandKey) => commandByKey.get(commandKey))
189
+ .filter(Boolean);
190
+ const firstCommand = stageCommands[0] || null;
191
+ const firstCommandSafety = firstCommand?.safety || null;
192
+ const commandHasSafetyFlag = (command, field) => command.safety?.[field] === true;
193
+ const commandCount = stageCommands.length;
194
+ const stageIdentity = {
195
+ step,
196
+ key,
197
+ label,
198
+ kind,
199
+ required,
200
+ };
201
+ const stageCommandSummary = {
202
+ commandKeys,
203
+ commands: stageCommands,
204
+ commandCount,
205
+ runPolicy: manual ? "manual-target-repo" : (firstCommand?.runPolicy || ""),
206
+ safetyLevel: manual ? "operator-controlled-target-repo" : (firstCommandSafety?.safetyLevel || ""),
207
+ };
208
+ const stageSafetySummary = {
209
+ writesLocalFile: stageCommands.some((command) => commandHasSafetyFlag(command, "writesLocalFile")),
210
+ outputFiles: stageCommands.map((command) => command.outputFile).filter(Boolean),
211
+ externalCalls: stageCommands.some((command) => commandHasSafetyFlag(command, "externalCalls")),
212
+ targetRepoMutation: stageCommands.some((command) => commandHasSafetyFlag(command, "targetRepoMutation")),
213
+ };
214
+ return {
215
+ ...stageIdentity,
216
+ ...stageCommandSummary,
217
+ ...stageSafetySummary,
218
+ reason,
219
+ };
220
+ };
221
+ const effectiveStrictTaskCommandKey = commandManifest?.effectiveStrictTaskCommandKey || "";
222
+ const stages = [
223
+ buildStage({
224
+ step: 1,
225
+ key: "verifySourceBundle",
226
+ label: "Verify source bundle integrity",
227
+ kind: "read-only-gate",
228
+ required: true,
229
+ commandKeys: ["source.bundleCheck.strict"],
230
+ reason: "Confirm the bundle still matches its checksum and generated-file contract before handoff execution.",
231
+ }),
232
+ buildStage({
233
+ step: 2,
234
+ key: "refreshHandoffSnapshot",
235
+ label: "Refresh strict handoff JSON snapshot",
236
+ kind: "read-only-preview",
237
+ required: false,
238
+ commandKeys: ["source.bundleHandoff.strict"],
239
+ reason: "Regenerate the machine-readable handoff snapshot when a wrapper or GUI needs the latest JSON contract.",
240
+ }),
241
+ buildStage({
242
+ step: 3,
243
+ key: "writeEffectiveTaskPrompt",
244
+ label: "Write effective task handoff prompt",
245
+ kind: "local-output",
246
+ required: true,
247
+ commandKeys: effectiveStrictTaskCommandKey ? [effectiveStrictTaskCommandKey] : [],
248
+ reason: "Create the selected task prompt as a local file before moving into the target website repository.",
249
+ }),
250
+ buildStage({
251
+ step: 4,
252
+ key: "executeInTargetRepo",
253
+ label: "Execute the task in the target website repo",
254
+ kind: "manual-target-repo",
255
+ required: true,
256
+ manual: true,
257
+ reason: "Open the generated task prompt in the target repo, inspect architecture first, then implement and verify there.",
258
+ }),
259
+ buildStage({
260
+ step: 5,
261
+ key: "recordEvidence",
262
+ label: "Record implementation evidence",
263
+ kind: "manual-reporting",
264
+ required: true,
265
+ manual: true,
266
+ reason: "Return changed files, verification commands, browser/viewport checks, remaining risks, and the bundle digest.",
267
+ }),
268
+ ];
269
+ const commandStages = stages.filter(hasCommands);
270
+ const stageActionRows = stages.map((stage) => {
271
+ const prerequisiteKeys = getStageActionPrerequisiteKeys(stage);
272
+ const blockedStageKeys = getStageActionBlockedStageKeys(stage, stages);
273
+ const completionCriteria = getStageActionCompletionCriteria(stage);
274
+ const evidenceRequirements = getStageActionEvidenceRequirements(stage);
275
+ const evidenceCaptureFields = getStageActionEvidenceCaptureFields(stage);
276
+ const evidenceFieldValues = (field) => evidenceCaptureFields.map((evidenceField) => evidenceField[field]);
277
+ const evidenceCaptureSectionKeys = uniqueValues(evidenceFieldValues("sectionKey"));
278
+ const evidenceCaptureSectionLabels = uniqueValues(evidenceFieldValues("sectionLabel"));
279
+ const evidenceCapturePayloadNamespaces = uniqueValues(evidenceFieldValues("payloadNamespace"));
280
+ const requiredEvidenceCaptureFields = evidenceCaptureFields.filter((field) => field.required);
281
+ const optionalEvidenceCaptureFields = evidenceCaptureFields.filter((field) => !field.required);
282
+ const actionEvidenceSummary = {
283
+ actionEvidenceRequirements: evidenceRequirements,
284
+ actionEvidenceRequirementCount: evidenceRequirements.length,
285
+ actionRequiresEvidence: evidenceRequirements.length > 0,
286
+ actionEvidenceTarget: getStageActionEvidenceTarget(stage),
287
+ actionEvidenceTargetLabel: getStageActionEvidenceTargetLabel(stage),
288
+ };
289
+ const actionIdentity = {
290
+ step: stage.step,
291
+ key: stage.key,
292
+ label: stage.label,
293
+ };
294
+ const actionStatusSummary = {
295
+ actionType: getStageActionType(stage),
296
+ actionLabel: getStageActionLabel(stage),
297
+ actionInstruction: getStageActionInstruction(stage),
298
+ actionButtonLabel: getStageActionButtonLabel(stage),
299
+ actionAffordance: getStageActionAffordance(stage),
300
+ actionEnabled: getStageActionEnabled(stage),
301
+ actionStatus: getStageActionStatus(stage),
302
+ actionStatusLabel: getStageActionStatusLabel(stage),
303
+ actionStatusTone: getStageActionStatusTone(stage),
304
+ actionDisabledReasonCode: getStageActionDisabledReasonCode(stage),
305
+ actionDisabledReason: getStageActionDisabledReason(stage),
306
+ };
307
+ const actionDependencySummary = {
308
+ actionPrerequisiteKeys: prerequisiteKeys,
309
+ actionPrerequisiteLabels: getStageActionPrerequisiteLabels(stage, stages),
310
+ actionPrerequisiteCount: prerequisiteKeys.length,
311
+ actionHasPrerequisites: prerequisiteKeys.length > 0,
312
+ actionDependencyReasonCode: getStageActionDependencyReasonCode(stage),
313
+ actionDependencyReason: getStageActionDependencyReason(stage),
314
+ actionBlockedStageKeys: blockedStageKeys,
315
+ actionBlockedStageLabels: blockedStageKeys.map((stageKey) => getStageLabel(stages, stageKey)),
316
+ actionBlockedStageCount: blockedStageKeys.length,
317
+ actionBlocksStages: blockedStageKeys.length > 0,
318
+ actionCompletionCriteria: completionCriteria,
319
+ actionCompletionCriteriaCount: completionCriteria.length,
320
+ actionHasCompletionCriteria: completionCriteria.length > 0,
321
+ };
322
+ const actionEvidenceCaptureSummary = {
323
+ actionEvidenceCaptureFields: evidenceCaptureFields,
324
+ actionEvidenceCaptureFieldKeys: evidenceFieldValues("key"),
325
+ actionEvidenceCaptureFieldLabels: evidenceFieldValues("label"),
326
+ actionEvidenceCaptureFieldPlaceholders: evidenceFieldValues("placeholder"),
327
+ actionEvidenceCaptureFieldRequirementLabels: evidenceFieldValues("requirementLabel"),
328
+ actionEvidenceCaptureFieldAriaLabels: evidenceFieldValues("ariaLabel"),
329
+ actionEvidenceCaptureFieldHelpTexts: evidenceFieldValues("helpText"),
330
+ actionEvidenceCaptureFieldSectionKeys: evidenceFieldValues("sectionKey"),
331
+ actionEvidenceCaptureFieldSectionLabels: evidenceFieldValues("sectionLabel"),
332
+ actionEvidenceCaptureSectionKeys: evidenceCaptureSectionKeys,
333
+ actionEvidenceCaptureSectionLabels: evidenceCaptureSectionLabels,
334
+ actionEvidenceCaptureSectionCount: evidenceCaptureSectionKeys.length,
335
+ actionEvidenceCaptureFieldPayloadNamespaces: evidenceFieldValues("payloadNamespace"),
336
+ actionEvidenceCaptureFieldPayloadPaths: evidenceFieldValues("payloadPath"),
337
+ actionEvidenceCapturePayloadNamespaces: evidenceCapturePayloadNamespaces,
338
+ actionEvidenceCapturePayloadNamespaceCount: evidenceCapturePayloadNamespaces.length,
339
+ actionEvidenceCapturePayloadTemplate: buildEvidenceCapturePayloadTemplate(evidenceCaptureFields),
340
+ actionEvidenceCapturePayloadFlatTemplate: buildEvidenceCapturePayloadFlatTemplate(evidenceCaptureFields),
341
+ actionEvidenceCapturePayloadBindings: buildEvidenceCapturePayloadBindings(evidenceCaptureFields),
342
+ actionEvidenceCaptureValidationSpecs: buildEvidenceCaptureValidationSpecs(evidenceCaptureFields),
343
+ actionEvidenceCaptureInitialValidationStates: buildEvidenceCaptureInitialValidationStates(evidenceCaptureFields),
344
+ actionEvidenceCaptureInitialValidationDisplayMetadata: buildEvidenceCaptureInitialValidationDisplayMetadata(evidenceCaptureFields),
345
+ actionEvidenceCaptureInitialValidationChecklist: buildEvidenceCaptureInitialValidationChecklist(evidenceCaptureFields),
346
+ actionEvidenceCaptureInitialValidationChecklistSummary: buildEvidenceCaptureInitialValidationChecklistSummary(evidenceCaptureFields),
347
+ actionEvidenceCaptureInitialValidationSummary: buildEvidenceCaptureInitialValidationSummary(evidenceCaptureFields),
348
+ actionEvidenceCaptureFieldInputTypes: evidenceFieldValues("inputType"),
349
+ actionEvidenceCaptureFieldValueShapes: evidenceFieldValues("valueShape"),
350
+ actionEvidenceCaptureFieldAcceptsMultiple: evidenceFieldValues("acceptsMultiple"),
351
+ actionEvidenceCaptureFieldDefaultValues: evidenceFieldValues("defaultValue"),
352
+ actionEvidenceCaptureFieldEmptyValues: evidenceFieldValues("emptyValue"),
353
+ actionEvidenceCaptureFieldValidationRules: evidenceFieldValues("validationRule"),
354
+ actionEvidenceCaptureFieldMinLengths: evidenceFieldValues("minLength"),
355
+ actionEvidenceCaptureFieldExamples: evidenceFieldValues("example"),
356
+ actionEvidenceCaptureFieldValidationHints: evidenceFieldValues("validationHint"),
357
+ actionRequiredEvidenceCaptureFieldKeys: requiredEvidenceCaptureFields.map((field) => field.key),
358
+ actionOptionalEvidenceCaptureFieldKeys: optionalEvidenceCaptureFields.map((field) => field.key),
359
+ actionEvidenceCaptureFieldCount: evidenceCaptureFields.length,
360
+ actionRequiredEvidenceCaptureFieldCount: requiredEvidenceCaptureFields.length,
361
+ actionOptionalEvidenceCaptureFieldCount: optionalEvidenceCaptureFields.length,
362
+ actionHasEvidenceCaptureFields: evidenceCaptureFields.length > 0,
363
+ };
364
+ const actionExecutionSummary = {
365
+ required: stage.required,
366
+ runPolicy: stage.runPolicy,
367
+ safetyLevel: stage.safetyLevel,
368
+ commandKeys: stage.commandKeys,
369
+ commandCount: stage.commandCount,
370
+ outputFiles: stage.outputFiles,
371
+ manual: isManualStage(stage),
372
+ writesLocalFile: stage.writesLocalFile,
373
+ externalCalls: stage.externalCalls,
374
+ targetRepoMutation: stage.targetRepoMutation,
375
+ };
376
+
377
+ return {
378
+ ...actionIdentity,
379
+ ...actionStatusSummary,
380
+ ...actionDependencySummary,
381
+ ...actionEvidenceSummary,
382
+ ...actionEvidenceCaptureSummary,
383
+ ...actionExecutionSummary,
384
+ };
385
+ });
386
+ const stageIdentityMaps = buildStageIdentityMaps(stages);
387
+ const stageActionStatusMaps = buildStageActionStatusMaps(stageActionRows);
388
+ const stageActionDependencyMaps = buildStageActionDependencyMaps(stageActionRows);
389
+ const stageActionEvidenceMaps = buildStageActionEvidenceMaps(stageActionRows);
390
+ const stageActionEvidenceCaptureMaps = buildStageActionEvidenceCaptureMaps(stageActionRows);
391
+ const stageHumanLineMaps = buildStageHumanLineMaps(
392
+ stages,
393
+ stageActionRows,
394
+ stageActionEvidenceCaptureMaps.stageActionEvidenceCaptureInitialValidationChecklistSummaryByKey,
395
+ );
396
+ const stageExecutionMaps = buildStageExecutionMaps(stages);
397
+ const { nextActionSummary, nextStepSummary } = buildNextStepState({
398
+ stageByKey: stageIdentityMaps.stageByKey,
399
+ commandByKey,
400
+ stageActionRows,
401
+ stageHumanLineByKey: stageHumanLineMaps.stageHumanLineByKey,
402
+ stageHumanLineDisplayRowByKey: stageHumanLineMaps.stageHumanLineDisplayRowByKey,
403
+ });
404
+ const actionSummary = buildActionSummary({
405
+ stages,
406
+ commandStages,
407
+ stageActionRows,
408
+ stageHumanLineMaps,
409
+ nextActionSummary,
410
+ });
411
+ const countBy = (predicate) => stages.filter(predicate).length;
412
+ const runbookCountSummary = {
413
+ stageCount: stages.length,
414
+ commandStageCount: commandStages.length,
415
+ manualStageCount: countBy(isManualStage),
416
+ requiredStageCount: countBy(isRequiredStage),
417
+ optionalStageCount: countBy(isOptionalStage),
418
+ readOnlyCommandStageCount: countBy(usesReadOnlyRunPolicy),
419
+ localOutputCommandStageCount: countBy(usesLocalOutputRunPolicy),
420
+ externalCallCommandStageCount: countBy(callsExternalSystem),
421
+ targetRepoMutationCommandStageCount: countBy(mutatesTargetRepo),
422
+ effectiveTaskId: commandManifest?.effectiveTaskId || "",
423
+ effectiveStrictTaskCommandKey,
424
+ };
425
+ return {
426
+ version: 1,
427
+ source: "bundle-handoff",
428
+ ...runbookCountSummary,
429
+ ...stageIdentityMaps,
430
+ ...stageHumanLineMaps,
431
+ ...stageActionStatusMaps,
432
+ ...stageActionDependencyMaps,
433
+ ...stageActionEvidenceMaps,
434
+ ...stageActionEvidenceCaptureMaps,
435
+ actionSummary,
436
+ ...stageExecutionMaps,
437
+ ...nextStepSummary,
438
+ stages,
439
+ };
440
+ }
441
+
442
+ export {
443
+ formatBundleHandoffOperatorRunbookLines,
444
+ } from "./site-bundle-handoff-runbook-format.mjs";
@@ -0,0 +1,183 @@
1
+ import {
2
+ buildBundleCheckCommand,
3
+ buildBundleCheckCommandArgs,
4
+ buildBundleHandoffCommand,
5
+ buildBundleHandoffCommandArgs,
6
+ buildBundleSourceCommandSafety,
7
+ buildBundleTaskHandoffCommand,
8
+ buildBundleTaskHandoffCommandArgs,
9
+ buildBundleTaskHandoffCommandSafety,
10
+ taskHandoffOutFile,
11
+ } from "./site-bundle-commands.mjs";
12
+ import { orderedRefactorTasks } from "./site-prompts.mjs";
13
+ import { normalizeStringArray } from "./site-strings.mjs";
14
+
15
+ export const SITE_TARGET_REPO_EXECUTION_CHECKLIST = [
16
+ {
17
+ id: "confirm-target-repo",
18
+ label: "Confirm target repo working directory",
19
+ required: true,
20
+ evidence: "State the target repo path and confirm it is not the design-ai repo before editing.",
21
+ },
22
+ {
23
+ id: "inspect-architecture",
24
+ label: "Inspect existing architecture and design system",
25
+ required: true,
26
+ evidence: "Name the routing, component, styling, token, and test/build surfaces inspected before implementation.",
27
+ },
28
+ {
29
+ id: "apply-focused-task",
30
+ label: "Apply one focused Website Improvement task",
31
+ required: true,
32
+ evidence: "Identify the completed task id/title, changed files, and why the scope stayed limited.",
33
+ },
34
+ {
35
+ id: "verify-quality-gates",
36
+ label: "Run target repo quality gates",
37
+ required: true,
38
+ evidence: "Record lint/typecheck/build/test results plus browser, viewport, accessibility, and deployment checks that were available.",
39
+ },
40
+ {
41
+ id: "record-handoff-evidence",
42
+ label: "Record implementation evidence and remaining risks",
43
+ required: true,
44
+ evidence: "Return executed work, verification results, remaining risks, next actions, and the bundle digest used.",
45
+ },
46
+ ];
47
+
48
+ function summarizeBundleTaskItem(task, index, directory) {
49
+ return {
50
+ number: index + 1,
51
+ id: task.id,
52
+ title: task.title,
53
+ category: task.category,
54
+ priority: task.priority,
55
+ impact: task.impact,
56
+ effort: task.effort,
57
+ pages: normalizeStringArray(task.pages),
58
+ recommendedMcp: normalizeStringArray(task.recommendedMcp),
59
+ handoffTaskArg: task.id,
60
+ handoffOutFile: taskHandoffOutFile(task),
61
+ handoffCommand: buildBundleTaskHandoffCommand(directory, task),
62
+ handoffCommandArgs: buildBundleTaskHandoffCommandArgs(directory, task),
63
+ handoffCommandRunPolicy: "writes-local-file",
64
+ handoffCommandSafety: buildBundleTaskHandoffCommandSafety(task),
65
+ strictHandoffCommand: buildBundleTaskHandoffCommand(directory, task, { strict: true }),
66
+ strictHandoffCommandArgs: buildBundleTaskHandoffCommandArgs(directory, task, { strict: true }),
67
+ strictHandoffCommandRunPolicy: "writes-local-file",
68
+ strictHandoffCommandSafety: buildBundleTaskHandoffCommandSafety(task, { strict: true }),
69
+ };
70
+ }
71
+
72
+ export function summarizeBundleTaskCatalog(workspace, directory, selectedTask = null) {
73
+ const items = orderedRefactorTasks(workspace).map((task, index) => summarizeBundleTaskItem(task, index, directory));
74
+ const selectedTaskId = selectedTask?.id || "";
75
+ return {
76
+ source: "website-workspace.tasks.json",
77
+ count: items.length,
78
+ defaultTaskId: items[0]?.id || "",
79
+ selectedTaskId,
80
+ selectionMode: selectedTaskId ? "explicit" : "bundled-default",
81
+ items,
82
+ };
83
+ }
84
+
85
+ export function emptyBundleTaskCatalog(error = "") {
86
+ return {
87
+ source: "website-workspace.tasks.json",
88
+ count: 0,
89
+ defaultTaskId: "",
90
+ selectedTaskId: "",
91
+ selectionMode: "unavailable",
92
+ items: [],
93
+ error,
94
+ };
95
+ }
96
+
97
+ export function summarizeSelectedTask(task, taskSelector, source, directory = "") {
98
+ if (!task) return null;
99
+ return {
100
+ id: task.id,
101
+ title: task.title,
102
+ category: task.category,
103
+ priority: task.priority,
104
+ impact: task.impact,
105
+ effort: task.effort,
106
+ selector: String(taskSelector || "").trim(),
107
+ source,
108
+ handoffTaskArg: task.id,
109
+ handoffOutFile: taskHandoffOutFile(task),
110
+ handoffCommand: directory ? buildBundleTaskHandoffCommand(directory, task) : "",
111
+ handoffCommandArgs: directory ? buildBundleTaskHandoffCommandArgs(directory, task) : [],
112
+ handoffCommandRunPolicy: directory ? "writes-local-file" : "",
113
+ handoffCommandSafety: directory ? buildBundleTaskHandoffCommandSafety(task) : null,
114
+ strictHandoffCommand: directory ? buildBundleTaskHandoffCommand(directory, task, { strict: true }) : "",
115
+ strictHandoffCommandArgs: directory ? buildBundleTaskHandoffCommandArgs(directory, task, { strict: true }) : [],
116
+ strictHandoffCommandRunPolicy: directory ? "writes-local-file" : "",
117
+ strictHandoffCommandSafety: directory ? buildBundleTaskHandoffCommandSafety(task, { strict: true }) : null,
118
+ };
119
+ }
120
+
121
+ export function formatBundleHandoffTaskCatalogLines(taskCatalog) {
122
+ if (!taskCatalog || !Array.isArray(taskCatalog.items) || taskCatalog.items.length === 0) {
123
+ const reason = taskCatalog?.error ? ` ${taskCatalog.error}` : "";
124
+ return [`- No bundle task catalog is available.${reason}`];
125
+ }
126
+ return taskCatalog.items.map((task) => {
127
+ const pages = task.pages.length ? task.pages.join(", ") : "all pages";
128
+ const mcps = task.recommendedMcp.length ? task.recommendedMcp.join(", ") : "none";
129
+ const command = task.strictHandoffCommand || task.handoffCommand || `design-ai site <bundle-dir> --bundle-handoff --task ${task.handoffTaskArg}`;
130
+ return `- ${task.number}. [${task.priority}/${task.impact}/${task.effort}] ${task.id}: ${task.title} (pages: ${pages}; MCP: ${mcps}; command: \`${command}\`)`;
131
+ });
132
+ }
133
+
134
+ export function formatBundleHandoffIssueLines(issues) {
135
+ const actionable = issues.filter((issue) => issue.level !== "pass");
136
+ if (actionable.length === 0) return "- No blocking bundle-check issues were found.";
137
+ return actionable.map((issue) => `- [${issue.level}] ${issue.id}: ${issue.message}`).join("\n");
138
+ }
139
+
140
+ export function buildSiteBundleHandoffBoundaries(checkReport) {
141
+ return Array.from(new Set([
142
+ ...normalizeStringArray(checkReport?.boundaries),
143
+ "target-repo-work-after-handoff",
144
+ ]));
145
+ }
146
+
147
+ export function summarizeSiteBundleHandoffSource(checkReport) {
148
+ return {
149
+ directory: checkReport.directory,
150
+ sourceWorkspace: checkReport.summary.source || "",
151
+ siteName: checkReport.summary.siteName || "",
152
+ status: checkReport.status,
153
+ valid: checkReport.valid,
154
+ workspaceStatus: checkReport.workspaceStatus || "unknown",
155
+ mcpStatus: checkReport.mcpStatus || "unknown",
156
+ mcpProbeStatus: checkReport.mcpProbeStatus || "unknown",
157
+ checksumAlgorithm: checkReport.summary.checksumAlgorithm || "",
158
+ checksumBundleDigest: checkReport.summary.checksumBundleDigest || "",
159
+ verifiedChecksumFiles: checkReport.counts.verifiedChecksumFiles,
160
+ expectedChecksumFiles: checkReport.counts.expectedChecksumFiles,
161
+ verifiedGeneratedFiles: checkReport.counts.verifiedGeneratedFiles,
162
+ expectedGeneratedFiles: checkReport.counts.expectedGeneratedFiles,
163
+ issueCount: checkReport.issues.length,
164
+ warningCount: checkReport.counts.warnings,
165
+ failureCount: checkReport.counts.failures,
166
+ checkCommand: buildBundleCheckCommand(checkReport.directory),
167
+ checkCommandArgs: buildBundleCheckCommandArgs(checkReport.directory),
168
+ checkCommandRunPolicy: "read-only",
169
+ checkCommandSafety: buildBundleSourceCommandSafety(),
170
+ strictCheckCommand: buildBundleCheckCommand(checkReport.directory, { strict: true }),
171
+ strictCheckCommandArgs: buildBundleCheckCommandArgs(checkReport.directory, { strict: true }),
172
+ strictCheckCommandRunPolicy: "read-only",
173
+ strictCheckCommandSafety: buildBundleSourceCommandSafety({ strict: true }),
174
+ handoffCommand: buildBundleHandoffCommand(checkReport.directory),
175
+ handoffCommandArgs: buildBundleHandoffCommandArgs(checkReport.directory),
176
+ handoffCommandRunPolicy: "read-only",
177
+ handoffCommandSafety: buildBundleSourceCommandSafety(),
178
+ strictHandoffCommand: buildBundleHandoffCommand(checkReport.directory, { strict: true }),
179
+ strictHandoffCommandArgs: buildBundleHandoffCommandArgs(checkReport.directory, { strict: true }),
180
+ strictHandoffCommandRunPolicy: "read-only",
181
+ strictHandoffCommandSafety: buildBundleSourceCommandSafety({ strict: true }),
182
+ };
183
+ }