@bastani/atomic 0.9.16-alpha.7 → 0.9.16-alpha.9

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 (226) hide show
  1. package/CHANGELOG.md +25 -0
  2. package/dist/builtin/intercom/CHANGELOG.md +6 -0
  3. package/dist/builtin/intercom/README.md +4 -4
  4. package/dist/builtin/intercom/broker/broker.ts +617 -22
  5. package/dist/builtin/intercom/broker/client-message-validation.ts +9 -0
  6. package/dist/builtin/intercom/broker/client.ts +200 -10
  7. package/dist/builtin/intercom/broker/pending-send-registry.ts +4 -0
  8. package/dist/builtin/intercom/broker/send-handler.ts +90 -36
  9. package/dist/builtin/intercom/broker/send-signature.ts +20 -8
  10. package/dist/builtin/intercom/group.ts +85 -0
  11. package/dist/builtin/intercom/index.bundle.mjs +746 -55
  12. package/dist/builtin/intercom/package.json +1 -1
  13. package/dist/builtin/intercom/session-target.ts +54 -0
  14. package/dist/builtin/intercom/skills/intercom/SKILL.md +18 -3
  15. package/dist/builtin/intercom/source-ownership.ts +31 -0
  16. package/dist/builtin/intercom/types.ts +115 -0
  17. package/dist/builtin/mcp/index.bundle.mjs +175 -37
  18. package/dist/builtin/mcp/package.json +1 -1
  19. package/dist/builtin/subagents/package.json +1 -1
  20. package/dist/builtin/subagents/src/extension/index.bundle.mjs +239 -53
  21. package/dist/builtin/web-access/index.bundle.mjs +175 -37
  22. package/dist/builtin/web-access/package.json +1 -1
  23. package/dist/builtin/workflows/CHANGELOG.md +15 -0
  24. package/dist/builtin/workflows/README.md +40 -37
  25. package/dist/builtin/workflows/builtin/adversarial-verification.js +13 -0
  26. package/dist/builtin/workflows/builtin/{shared-prompts.ts → chunk-0x6e303p.js} +133 -154
  27. package/dist/builtin/workflows/builtin/chunk-17zk6ffd.js +69794 -0
  28. package/dist/builtin/workflows/builtin/chunk-29wrp38a.js +199 -0
  29. package/dist/builtin/workflows/builtin/chunk-2dqb5s2q.js +602 -0
  30. package/dist/builtin/workflows/builtin/chunk-4febxsv4.js +264 -0
  31. package/dist/builtin/workflows/builtin/chunk-5wgwscd0.js +4 -0
  32. package/dist/builtin/workflows/builtin/chunk-6fqs7c01.js +155 -0
  33. package/dist/builtin/workflows/builtin/chunk-7430zyas.js +126 -0
  34. package/dist/builtin/workflows/builtin/chunk-7at6dnkr.js +33 -0
  35. package/dist/builtin/workflows/builtin/chunk-82ha8p41.js +175 -0
  36. package/dist/builtin/workflows/builtin/chunk-8v8wmb7z.js +529 -0
  37. package/dist/builtin/workflows/builtin/chunk-bfkmzv9h.js +156 -0
  38. package/dist/builtin/workflows/builtin/chunk-c53y8bdh.js +345 -0
  39. package/dist/builtin/workflows/builtin/chunk-cg9tmks0.js +206 -0
  40. package/dist/builtin/workflows/builtin/chunk-h5e65g7g.js +1080 -0
  41. package/dist/builtin/workflows/builtin/chunk-hzzn6adg.js +221 -0
  42. package/dist/builtin/workflows/builtin/chunk-nqr34qp3.js +1061 -0
  43. package/dist/builtin/workflows/builtin/chunk-qe6bfpbd.js +1207 -0
  44. package/dist/builtin/workflows/builtin/chunk-qwzvgxnq.js +404 -0
  45. package/dist/builtin/workflows/builtin/chunk-qx2ptjs3.js +215 -0
  46. package/dist/builtin/workflows/builtin/chunk-rbnj9621.js +2447 -0
  47. package/dist/builtin/workflows/builtin/chunk-wpckd35c.js +12 -0
  48. package/dist/builtin/workflows/builtin/chunk-x2ghn0je.js +4110 -0
  49. package/dist/builtin/workflows/builtin/classify-and-act.js +12 -0
  50. package/dist/builtin/workflows/builtin/fan-out-and-synthesize.js +10 -0
  51. package/dist/builtin/workflows/builtin/generate-and-filter.js +12 -0
  52. package/dist/builtin/workflows/builtin/goal.js +16 -0
  53. package/dist/builtin/workflows/builtin/index.js +49 -0
  54. package/dist/builtin/workflows/builtin/loop-until-done.js +12 -0
  55. package/dist/builtin/workflows/builtin/open-claude-design.js +11 -0
  56. package/dist/builtin/workflows/builtin/ralph.js +16 -0
  57. package/dist/builtin/workflows/builtin/steering-context.d.ts +6 -0
  58. package/dist/builtin/workflows/builtin/steering-context.js +7 -0
  59. package/dist/builtin/workflows/builtin/tournament.js +13 -0
  60. package/dist/builtin/workflows/package.json +10 -7
  61. package/dist/builtin/workflows/src/authoring/typebox-defaults.d.ts +41 -0
  62. package/dist/builtin/workflows/src/extension/index.bundle.mjs +1294 -430
  63. package/dist/builtin/workflows/src/{index.bundle.mjs → index.js} +1022 -429
  64. package/dist/builtin/workflows/src/shared/authoring-contract-stage.d.ts +403 -0
  65. package/dist/builtin/workflows/src/shared/authoring-contract-ui.d.ts +327 -0
  66. package/dist/builtin/workflows/src/shared/budget.d.ts +67 -0
  67. package/dist/builtin/workflows/src/shared/workflow-authoring-types.d.ts +60 -0
  68. package/dist/builtin/workflows/src/shared/workflow-heartbeat-contract.d.ts +21 -0
  69. package/dist/core/agent-session-custom-message-commit.d.ts.map +1 -1
  70. package/dist/core/agent-session-custom-message-commit.js +12 -5
  71. package/dist/core/agent-session-custom-message-commit.js.map +1 -1
  72. package/dist/core/agent-session-persistent-custom-messages.d.ts.map +1 -1
  73. package/dist/core/agent-session-persistent-custom-messages.js +2 -0
  74. package/dist/core/agent-session-persistent-custom-messages.js.map +1 -1
  75. package/dist/core/agent-session.d.ts.map +1 -1
  76. package/dist/core/agent-session.js +2 -1
  77. package/dist/core/agent-session.js.map +1 -1
  78. package/dist/core/auth-storage.d.ts +2 -0
  79. package/dist/core/auth-storage.d.ts.map +1 -1
  80. package/dist/core/auth-storage.js +4 -0
  81. package/dist/core/auth-storage.js.map +1 -1
  82. package/dist/core/builtin-install-layout.d.ts +1 -1
  83. package/dist/core/builtin-install-layout.d.ts.map +1 -1
  84. package/dist/core/builtin-install-layout.js +1 -1
  85. package/dist/core/builtin-install-layout.js.map +1 -1
  86. package/dist/core/codex-fast-mode.d.ts +10 -7
  87. package/dist/core/codex-fast-mode.d.ts.map +1 -1
  88. package/dist/core/codex-fast-mode.js +31 -13
  89. package/dist/core/codex-fast-mode.js.map +1 -1
  90. package/dist/core/extensions/agent-events.d.ts +15 -0
  91. package/dist/core/extensions/agent-events.d.ts.map +1 -1
  92. package/dist/core/extensions/agent-events.js.map +1 -1
  93. package/dist/core/extensions/api-types.d.ts +3 -1
  94. package/dist/core/extensions/api-types.d.ts.map +1 -1
  95. package/dist/core/extensions/api-types.js.map +1 -1
  96. package/dist/core/extensions/context-types.d.ts +35 -0
  97. package/dist/core/extensions/context-types.d.ts.map +1 -1
  98. package/dist/core/extensions/context-types.js.map +1 -1
  99. package/dist/core/extensions/event-types.d.ts +2 -2
  100. package/dist/core/extensions/event-types.d.ts.map +1 -1
  101. package/dist/core/extensions/event-types.js.map +1 -1
  102. package/dist/core/extensions/index.d.ts +1 -1
  103. package/dist/core/extensions/index.d.ts.map +1 -1
  104. package/dist/core/extensions/index.js.map +1 -1
  105. package/dist/core/extensions/loader-virtual-modules.d.ts.map +1 -1
  106. package/dist/core/extensions/loader-virtual-modules.js +6 -1
  107. package/dist/core/extensions/loader-virtual-modules.js.map +1 -1
  108. package/dist/core/extensions/runner.d.ts +6 -0
  109. package/dist/core/extensions/runner.d.ts.map +1 -1
  110. package/dist/core/extensions/runner.js +65 -1
  111. package/dist/core/extensions/runner.js.map +1 -1
  112. package/dist/core/model-runtime.d.ts +2 -0
  113. package/dist/core/model-runtime.d.ts.map +1 -1
  114. package/dist/core/model-runtime.js +4 -0
  115. package/dist/core/model-runtime.js.map +1 -1
  116. package/dist/core/runtime-credentials.d.ts +1 -0
  117. package/dist/core/runtime-credentials.d.ts.map +1 -1
  118. package/dist/core/runtime-credentials.js +8 -0
  119. package/dist/core/runtime-credentials.js.map +1 -1
  120. package/dist/core/sdk.d.ts.map +1 -1
  121. package/dist/core/sdk.js +5 -5
  122. package/dist/core/sdk.js.map +1 -1
  123. package/dist/core/session-manager-storage.d.ts +2 -0
  124. package/dist/core/session-manager-storage.d.ts.map +1 -1
  125. package/dist/core/session-manager-storage.js +4 -2
  126. package/dist/core/session-manager-storage.js.map +1 -1
  127. package/dist/core/slash-commands.js +1 -1
  128. package/dist/core/slash-commands.js.map +1 -1
  129. package/dist/core/workflow-stage-admission.d.ts +6 -1
  130. package/dist/core/workflow-stage-admission.d.ts.map +1 -1
  131. package/dist/core/workflow-stage-admission.js +8 -9
  132. package/dist/core/workflow-stage-admission.js.map +1 -1
  133. package/dist/index-extensions.d.ts +1 -1
  134. package/dist/index-extensions.d.ts.map +1 -1
  135. package/dist/index-extensions.js.map +1 -1
  136. package/dist/index.d.ts +0 -1
  137. package/dist/modes/interactive/components/footer.d.ts.map +1 -1
  138. package/dist/modes/interactive/components/footer.js +1 -1
  139. package/dist/modes/interactive/components/footer.js.map +1 -1
  140. package/dist/modes/interactive/interactive-autocomplete.js +1 -1
  141. package/dist/modes/interactive/interactive-autocomplete.js.map +1 -1
  142. package/dist/modes/interactive/interactive-extension-runtime.js +1 -1
  143. package/dist/modes/interactive/interactive-extension-runtime.js.map +1 -1
  144. package/dist/modes/interactive/interactive-startup.js +1 -1
  145. package/dist/modes/interactive/interactive-startup.js.map +1 -1
  146. package/dist/modes/interactive-engine/isolated-runtime.d.ts +4 -0
  147. package/dist/modes/interactive-engine/isolated-runtime.d.ts.map +1 -1
  148. package/dist/modes/interactive-engine/isolated-runtime.js +69 -10
  149. package/dist/modes/interactive-engine/isolated-runtime.js.map +1 -1
  150. package/dist/modes/rpc/rpc-client-api.d.ts +18 -2
  151. package/dist/modes/rpc/rpc-client-api.d.ts.map +1 -1
  152. package/dist/modes/rpc/rpc-client-api.js +33 -5
  153. package/dist/modes/rpc/rpc-client-api.js.map +1 -1
  154. package/dist/modes/rpc/rpc-command-handler.d.ts.map +1 -1
  155. package/dist/modes/rpc/rpc-command-handler.js +8 -4
  156. package/dist/modes/rpc/rpc-command-handler.js.map +1 -1
  157. package/dist/modes/rpc/rpc-types.d.ts +13 -0
  158. package/dist/modes/rpc/rpc-types.d.ts.map +1 -1
  159. package/dist/modes/rpc/rpc-types.js.map +1 -1
  160. package/docs/extensions.md +19 -0
  161. package/docs/intercom.md +15 -6
  162. package/docs/packages.md +2 -2
  163. package/docs/providers.md +8 -3
  164. package/docs/quickstart.md +2 -2
  165. package/docs/rpc.md +21 -4
  166. package/docs/settings.md +6 -4
  167. package/docs/subagents.md +1 -1
  168. package/docs/usage.md +1 -1
  169. package/docs/workflows.md +108 -239
  170. package/npm-shrinkwrap.json +32 -32
  171. package/package.json +9 -13
  172. package/dist/builtin/workflows/ambient.d.ts +0 -61
  173. package/dist/builtin/workflows/builtin/adversarial-verification-prompts.ts +0 -26
  174. package/dist/builtin/workflows/builtin/adversarial-verification-runner.ts +0 -391
  175. package/dist/builtin/workflows/builtin/adversarial-verification.ts +0 -34
  176. package/dist/builtin/workflows/builtin/classify-and-act-prompts.ts +0 -14
  177. package/dist/builtin/workflows/builtin/classify-and-act-runner.ts +0 -108
  178. package/dist/builtin/workflows/builtin/classify-and-act.ts +0 -40
  179. package/dist/builtin/workflows/builtin/fan-out-and-synthesize-prompts.ts +0 -14
  180. package/dist/builtin/workflows/builtin/fan-out-and-synthesize-runner.ts +0 -96
  181. package/dist/builtin/workflows/builtin/fan-out-and-synthesize.ts +0 -37
  182. package/dist/builtin/workflows/builtin/generate-and-filter-prompts.ts +0 -41
  183. package/dist/builtin/workflows/builtin/generate-and-filter-runner.ts +0 -90
  184. package/dist/builtin/workflows/builtin/generate-and-filter.ts +0 -31
  185. package/dist/builtin/workflows/builtin/goal-artifacts.ts +0 -64
  186. package/dist/builtin/workflows/builtin/goal-convergence.ts +0 -87
  187. package/dist/builtin/workflows/builtin/goal-ledger.ts +0 -139
  188. package/dist/builtin/workflows/builtin/goal-models.ts +0 -72
  189. package/dist/builtin/workflows/builtin/goal-orchestrator-prompts.ts +0 -94
  190. package/dist/builtin/workflows/builtin/goal-prompts.ts +0 -217
  191. package/dist/builtin/workflows/builtin/goal-reducer.ts +0 -176
  192. package/dist/builtin/workflows/builtin/goal-reports.ts +0 -76
  193. package/dist/builtin/workflows/builtin/goal-reverify.ts +0 -305
  194. package/dist/builtin/workflows/builtin/goal-review.ts +0 -139
  195. package/dist/builtin/workflows/builtin/goal-runner.ts +0 -504
  196. package/dist/builtin/workflows/builtin/goal-schemas.ts +0 -89
  197. package/dist/builtin/workflows/builtin/goal-types.ts +0 -164
  198. package/dist/builtin/workflows/builtin/goal.ts +0 -78
  199. package/dist/builtin/workflows/builtin/index.ts +0 -16
  200. package/dist/builtin/workflows/builtin/loop-until-done-prompts.ts +0 -87
  201. package/dist/builtin/workflows/builtin/loop-until-done-runner.ts +0 -282
  202. package/dist/builtin/workflows/builtin/loop-until-done.ts +0 -51
  203. package/dist/builtin/workflows/builtin/open-claude-design-live-protocol.ts +0 -305
  204. package/dist/builtin/workflows/builtin/open-claude-design-phases.ts +0 -337
  205. package/dist/builtin/workflows/builtin/open-claude-design-runner.ts +0 -347
  206. package/dist/builtin/workflows/builtin/open-claude-design-setup.ts +0 -313
  207. package/dist/builtin/workflows/builtin/open-claude-design-utils.ts +0 -311
  208. package/dist/builtin/workflows/builtin/open-claude-design.ts +0 -57
  209. package/dist/builtin/workflows/builtin/pattern-artifact-root.ts +0 -28
  210. package/dist/builtin/workflows/builtin/progress-scoring.ts +0 -230
  211. package/dist/builtin/workflows/builtin/ralph-core.ts +0 -449
  212. package/dist/builtin/workflows/builtin/ralph-forked-prompts.ts +0 -100
  213. package/dist/builtin/workflows/builtin/ralph-models.ts +0 -183
  214. package/dist/builtin/workflows/builtin/ralph-review-gate.ts +0 -103
  215. package/dist/builtin/workflows/builtin/ralph-reviewer-prompt.ts +0 -104
  216. package/dist/builtin/workflows/builtin/ralph-runner.ts +0 -459
  217. package/dist/builtin/workflows/builtin/ralph.ts +0 -82
  218. package/dist/builtin/workflows/builtin/review-convergence.ts +0 -229
  219. package/dist/builtin/workflows/builtin/selection-math.ts +0 -156
  220. package/dist/builtin/workflows/builtin/steering-context.ts +0 -51
  221. package/dist/builtin/workflows/builtin/tournament-prompts.ts +0 -70
  222. package/dist/builtin/workflows/builtin/tournament-runner.ts +0 -400
  223. package/dist/builtin/workflows/builtin/tournament.ts +0 -73
  224. package/dist/builtin/workflows/builtin/verification-criteria.ts +0 -330
  225. package/dist/builtin/workflows/builtin/verification-prompts.ts +0 -206
  226. package/dist/builtin/workflows/builtin/verification-usage.ts +0 -44
@@ -0,0 +1,1061 @@
1
+ import {
2
+ createChildProcessEnvironment
3
+ } from "./chunk-x2ghn0je.js";
4
+ import {
5
+ workflow
6
+ } from "./chunk-bfkmzv9h.js";
7
+ import {
8
+ withSteeringPropagationContext
9
+ } from "./chunk-0x6e303p.js";
10
+
11
+ // dist/builtin/workflows/builtin/open-claude-design.ts
12
+ import { Type as Type2 } from "typebox";
13
+
14
+ // dist/builtin/workflows/builtin/open-claude-design-utils.ts
15
+ import { spawnSync } from "node:child_process";
16
+ import { mkdirSync } from "node:fs";
17
+ import { tmpdir, userInfo } from "node:os";
18
+ import { join } from "node:path";
19
+ import { Type } from "typebox";
20
+ var OUTPUT_TYPES = [
21
+ "prototype",
22
+ "wireframe",
23
+ "page",
24
+ "component",
25
+ "theme",
26
+ "tokens"
27
+ ];
28
+ var DEFAULT_OUTPUT_TYPE = "prototype";
29
+ function taggedPrompt(sections) {
30
+ return sections.map(([tag, content]) => {
31
+ const trimmed = content.trim();
32
+ return `<${tag}>
33
+ ${trimmed}
34
+ </${tag}>`;
35
+ }).join(`
36
+
37
+ `);
38
+ }
39
+ function normalizeOutputType(value) {
40
+ return value !== undefined && OUTPUT_TYPES.includes(value) ? value : DEFAULT_OUTPUT_TYPE;
41
+ }
42
+ function shouldEarlyExitForBrowser(browserAvailable, nodeEnv) {
43
+ return !browserAvailable && nodeEnv !== "test";
44
+ }
45
+ var discoveryDecisionSchema = Type.Object({
46
+ brief: Type.String(),
47
+ output_type: Type.Union([...OUTPUT_TYPES].map((value) => Type.Literal(value))),
48
+ references: Type.Array(Type.String())
49
+ }, { additionalProperties: false });
50
+ function discoveryDecisionFromResult(result, fallbackBrief) {
51
+ const decision = result.structured;
52
+ const brief = typeof decision?.brief === "string" && decision.brief.trim().length > 0 ? decision.brief.trim() : fallbackBrief;
53
+ const references = Array.isArray(decision?.references) ? decision.references.filter((ref) => typeof ref === "string").map((ref) => ref.trim()).filter((ref) => ref.length > 0) : [];
54
+ return {
55
+ brief,
56
+ output_type: normalizeOutputType(decision?.output_type),
57
+ references
58
+ };
59
+ }
60
+ function joinResults(results) {
61
+ return results.map((result) => `### ${result.name}
62
+
63
+ ${result.text}`).join(`
64
+
65
+ ---
66
+
67
+ `);
68
+ }
69
+ function tmpArtifactBase() {
70
+ let user = "default";
71
+ try {
72
+ user = userInfo().username.replace(/[^A-Za-z0-9._-]/g, "_") || "default";
73
+ } catch {}
74
+ return join(tmpdir(), `open-claude-design-${user}`);
75
+ }
76
+ function prepareArtifactDir(cwd = process.cwd()) {
77
+ const runId = `${new Date().toISOString().replace(/[:.]/g, "-")}-${Math.random().toString(36).slice(2, 8)}`;
78
+ const tmpCandidates = [
79
+ join(tmpArtifactBase(), runId),
80
+ join(tmpdir(), "open-claude-design", runId)
81
+ ];
82
+ const candidates = [join(cwd, "specs", "design", runId), ...tmpCandidates];
83
+ for (const candidate of candidates) {
84
+ try {
85
+ mkdirSync(candidate, { recursive: true });
86
+ return {
87
+ runId,
88
+ artifactDir: candidate,
89
+ previewPath: join(candidate, "preview.html"),
90
+ specPath: join(candidate, "spec.html")
91
+ };
92
+ } catch {}
93
+ }
94
+ const fallback = join(tmpArtifactBase(), runId);
95
+ return {
96
+ runId,
97
+ artifactDir: fallback,
98
+ previewPath: join(fallback, "preview.html"),
99
+ specPath: join(fallback, "spec.html")
100
+ };
101
+ }
102
+ var HTML_PREVIEW_RULES = [
103
+ "Produce one self-contained HTML document: inline CSS in <style> and JS in <script>; make no external requests except explicitly required Google Fonts.",
104
+ "Use realistic brief-specific content, not Lorem ipsum or obvious placeholders.",
105
+ "Render well from 360px to 1440px with sensible container or media-query breakpoints.",
106
+ "Include default and hover/focus states for every interactive element, plus empty, loading, and error states where relevant.",
107
+ "Use semantic landmarks, labeled controls, WCAG AA contrast, visible focus, and prefers-reduced-motion.",
108
+ "Add HTML comments marking sections, states, and design-system token references for engineering handoff."
109
+ ].join(`
110
+ `);
111
+ var ANTI_SLOP_RULES = [
112
+ "Avoid generic AI palettes and structures: purple/indigo or blue-to-pink gradients, neon glassmorphism stacks, and nested card grids.",
113
+ "Avoid impeccable catalog clichés: gradient emphasis text, side-tab borders, three-font headers, and decorative shadows in flat-by-default systems.",
114
+ "Commit to a specific aesthetic rather than generic SaaS defaults."
115
+ ].join(`
116
+ `);
117
+ var REFERENCE_PRECEDENCE = "User references in <reference_context> are the PRIMARY visual authority and override conflicting DESIGN.md/PRODUCT.md guidance. DESIGN.md governs uncovered design decisions; PRODUCT.md still governs strategic register/voice.";
118
+ function ensurePlaywrightCli() {
119
+ const isWindows = process.platform === "win32";
120
+ const onPath = () => {
121
+ try {
122
+ const probe = spawnSync(isWindows ? "where" : "which", ["playwright-cli"], {
123
+ stdio: "ignore",
124
+ timeout: 15000,
125
+ shell: isWindows,
126
+ env: createChildProcessEnvironment()
127
+ });
128
+ return probe.status === 0;
129
+ } catch {
130
+ return false;
131
+ }
132
+ };
133
+ if (onPath()) {
134
+ return {
135
+ available: true,
136
+ alreadyPresent: true,
137
+ installed: false,
138
+ summary: "playwright-cli already on PATH; skipped install."
139
+ };
140
+ }
141
+ if (false) {}
142
+ try {
143
+ const install = spawnSync("npm", ["install", "-g", "@playwright/cli@latest"], {
144
+ stdio: "ignore",
145
+ timeout: 180000,
146
+ shell: isWindows,
147
+ env: createChildProcessEnvironment()
148
+ });
149
+ if (install.status === 0) {
150
+ return {
151
+ available: true,
152
+ alreadyPresent: false,
153
+ installed: true,
154
+ summary: "Installed playwright-cli via `npm install -g @playwright/cli@latest`."
155
+ };
156
+ }
157
+ const reason = install.error?.message ?? (typeof install.status === "number" ? `npm install -g @playwright/cli@latest exited with code ${install.status}` : "npm install -g @playwright/cli@latest did not complete");
158
+ return {
159
+ available: false,
160
+ alreadyPresent: false,
161
+ installed: false,
162
+ summary: `Could not install playwright-cli (${reason}); stages will degrade gracefully.`,
163
+ error: reason
164
+ };
165
+ } catch (error) {
166
+ const reason = error instanceof Error ? error.message : String(error);
167
+ return {
168
+ available: false,
169
+ alreadyPresent: false,
170
+ installed: false,
171
+ summary: `Could not install playwright-cli (${reason}); stages will degrade gracefully.`,
172
+ error: reason
173
+ };
174
+ }
175
+ }
176
+ function buildPlaywrightCliBootstrapRules(status) {
177
+ const probeRule = status.available ? "The playwright-cli skill's `playwright-cli` command is on PATH. Do not reinstall it unless a command reports it missing; then probe with `which playwright-cli` (or `npx --no-install playwright-cli --version`), run `npm install -g @playwright/cli@latest` once, and retry. Do not add project dependencies." : `The playwright-cli skill's \`playwright-cli\` command failed setup: "${status.error ?? "unknown error"}". Probe with \`which playwright-cli\` (or \`npx --no-install playwright-cli --version\`) and retry once with \`npm install -g @playwright/cli@latest\`. For permission errors, use a user-writable global prefix; report missing npm/Node or network/registry errors plainly. If still unavailable, surface the manual file path / URL. Do not add project dependencies.`;
178
+ return [
179
+ probeRule,
180
+ "Use `playwright-cli open <url>` to show a local preview; use `playwright-cli snapshot` and `playwright-cli screenshot --filename=<file>` for review evidence.",
181
+ "If a `playwright-cli` command reports a missing browser executable, run `npx playwright install chromium` once and retry.",
182
+ "If `playwright-cli` is unavailable after three attempts or the browser runtime still fails, surface the manual file path / URL."
183
+ ].join(`
184
+ `);
185
+ }
186
+
187
+ // dist/builtin/workflows/builtin/open-claude-design-live-protocol.ts
188
+ import { spawn } from "node:child_process";
189
+ import { fileURLToPath } from "node:url";
190
+ var MODEL_EVENTS = new Set(["generate", "steer", "manual_edit_apply", "variant_mount_failed"]);
191
+ function needsModel(event) {
192
+ return MODEL_EVENTS.has(event.type);
193
+ }
194
+ function replyTokenFor(event) {
195
+ if (event.type === "steer")
196
+ return "steer_done";
197
+ return "done";
198
+ }
199
+ var LEGACY_REPLY_STATUSES = new Set(["done", "error", "complete", "discard", "discarded"]);
200
+ function isJsonObject(value) {
201
+ return typeof value === "object" && value !== null && !Array.isArray(value);
202
+ }
203
+ function parseLiveEvent(stdout) {
204
+ const lines = stdout.split(/\r?\n/).filter((line) => line.trim().startsWith("{"));
205
+ for (const line of [...lines].reverse()) {
206
+ try {
207
+ const parsed = JSON.parse(line);
208
+ if (!isJsonObject(parsed) || typeof parsed.type !== "string")
209
+ continue;
210
+ return { ...parsed, type: parsed.type, raw: line };
211
+ } catch {}
212
+ }
213
+ return { type: "timeout", raw: stdout };
214
+ }
215
+ function assertSuccessfulScript(result, operation) {
216
+ if (result.code !== 0) {
217
+ const details = result.stderr.length > 0 ? `: ${result.stderr}` : "";
218
+ throw new Error(`${operation} failed with exit code ${result.code}${details}`);
219
+ }
220
+ return result;
221
+ }
222
+ async function pollLiveEvent(input) {
223
+ const script = liveScriptPath("live-poll.mjs");
224
+ const run = input.deps?.run ?? runNodeScript;
225
+ for (;; ) {
226
+ if (input.signal?.aborted === true)
227
+ return { type: "exit", raw: "aborted" };
228
+ const result = assertSuccessfulScript(await run(script, [], input.workflowCwd, input.signal), "live poll");
229
+ const event = parseLiveEvent(result.stdout);
230
+ if (event.type !== "timeout")
231
+ return event;
232
+ }
233
+ }
234
+ async function replyLiveEvent(input) {
235
+ const id = input.event.id;
236
+ if (typeof id !== "string" || id.length === 0 || id.startsWith("--")) {
237
+ throw new Error(`Cannot reply to ${input.event.type}: live event id is missing`);
238
+ }
239
+ if (LEGACY_REPLY_STATUSES.has(id)) {
240
+ throw new Error(`Cannot reply to live event ${id}: expected an event id before the reply status`);
241
+ }
242
+ const status = input.status ?? replyTokenFor(input.event);
243
+ if (status.length === 0 || status.startsWith("--")) {
244
+ throw new Error(`Cannot reply to live event ${id}: reply status is missing`);
245
+ }
246
+ const args = ["--reply", id, status];
247
+ const file = input.file ?? input.event.file;
248
+ const message = input.message ?? input.event.message;
249
+ const data = input.data ?? input.event.data;
250
+ if (file !== undefined)
251
+ args.push("--file", file);
252
+ if (data !== undefined)
253
+ args.push("--data", JSON.stringify(data));
254
+ if (message !== undefined)
255
+ args.push(message);
256
+ const script = liveScriptPath("live-poll.mjs");
257
+ const run = input.deps?.run ?? runNodeScript;
258
+ return assertSuccessfulScript(await run(script, args, input.workflowCwd, input.signal), "live reply");
259
+ }
260
+ function liveScriptPath(script) {
261
+ return fileURLToPath(new URL(`../skills/impeccable/scripts/${script}`, import.meta.url));
262
+ }
263
+ function runNodeScript(scriptPath, args, cwd, signal) {
264
+ return new Promise((resolve, reject) => {
265
+ const child = spawn(process.execPath, [scriptPath, ...args], {
266
+ cwd,
267
+ env: { ...process.env, GH_PAGER: "cat" },
268
+ stdio: ["ignore", "pipe", "pipe"]
269
+ });
270
+ let stdout = "";
271
+ let stderr = "";
272
+ let settled = false;
273
+ const onAbort = () => child.kill("SIGTERM");
274
+ signal?.addEventListener("abort", onAbort, { once: true });
275
+ child.stdout.on("data", (chunk) => {
276
+ stdout += chunk.toString();
277
+ });
278
+ child.stderr.on("data", (chunk) => {
279
+ stderr += chunk.toString();
280
+ });
281
+ child.on("error", (error) => {
282
+ if (settled)
283
+ return;
284
+ settled = true;
285
+ signal?.removeEventListener("abort", onAbort);
286
+ reject(error);
287
+ });
288
+ child.on("close", (code) => {
289
+ if (settled)
290
+ return;
291
+ settled = true;
292
+ signal?.removeEventListener("abort", onAbort);
293
+ resolve({ code: code ?? -1, stdout: stdout.trim(), stderr: stderr.trim() });
294
+ });
295
+ });
296
+ }
297
+ function buildLiveEventPrompt(input) {
298
+ const shared = [
299
+ `<live_event>
300
+ ${input.event.raw}
301
+ </live_event>`,
302
+ `<preview_path>${input.previewPath}</preview_path>`,
303
+ "<role>You are an opinionated staff design engineer inside an impeccable `live` session. The workflow owns the poll loop; handle exactly this one event and stop.</role>"
304
+ ];
305
+ if (input.event.type === "generate") {
306
+ return [
307
+ ...shared,
308
+ [
309
+ "<instructions>",
310
+ "Follow the live contract for a `generate` event:",
311
+ "1. Reuse `event.scaffold` when present and read the annotation screenshot when one is attached.",
312
+ "2. Extract the page identity FIRST, then produce three DISTINCT on-brand variants and publish them for the user to preview.",
313
+ "3. Apply the craft floors by construction as you write. Do not screenshot, re-render, or QA between generate and accept; the overlay preview is the verification channel.",
314
+ "Do not poll, do not reply, and do not exit the session: the workflow does that. Stop as soon as the variants are published.",
315
+ "</instructions>"
316
+ ].join(`
317
+ `)
318
+ ].join(`
319
+
320
+ `);
321
+ }
322
+ if (input.event.type === "steer") {
323
+ return [
324
+ ...shared,
325
+ [
326
+ "<instructions>",
327
+ "Follow the live contract for a `steer` event: read the message and pageUrl, then do the work — page edits, navigation help, or a short answer.",
328
+ "Do not poll, do not reply, and do not exit the session: the workflow does that. Stop when the steer is handled.",
329
+ "</instructions>"
330
+ ].join(`
331
+ `)
332
+ ].join(`
333
+
334
+ `);
335
+ }
336
+ if (input.event.type === "variant_mount_failed") {
337
+ return [
338
+ ...shared,
339
+ [
340
+ "<instructions>",
341
+ "The browser could not mount the published variant. Inspect the reported variant source/module, fix the compile or runtime failure, and stop after the repair.",
342
+ "Do not poll, do not reply, and do not exit the session: the workflow does that."
343
+ ].join(`
344
+ `)
345
+ ].join(`
346
+
347
+ `);
348
+ }
349
+ return [
350
+ ...shared,
351
+ [
352
+ "<instructions>",
353
+ "Apply this manual edit event per the live contract, then stop. Do not poll, reply, or exit; the workflow does that.",
354
+ "</instructions>"
355
+ ].join(`
356
+ `)
357
+ ].join(`
358
+
359
+ `);
360
+ }
361
+ function buildLiveSessionStartPrompt(input) {
362
+ return [
363
+ `<preview_path>${input.previewPath}</preview_path>`,
364
+ `<preview_file_url>${input.previewFileUrl}</preview_file_url>`,
365
+ `<browser_use_guidelines>${input.browserBootstrapRules}</browser_use_guidelines>`,
366
+ "<role>You are an opinionated staff design engineer opening an impeccable `live` review session.</role>",
367
+ [
368
+ "<objective>",
369
+ `Start review session ${input.round}: boot live against the static preview and open it in the user's browser. Then STOP.`,
370
+ "</objective>"
371
+ ].join(`
372
+ `),
373
+ [
374
+ "<instructions>",
375
+ "1. Drive `/skill:impeccable live` against the static preview: run `live.mjs` with `--target` pointed at the preview file, or the equivalent `.impeccable/live/config.json` entry, and open the URL that serves it.",
376
+ "2. Print the live `http://` review URL in plain text, plus the preview file URL as the manual fallback, so anyone attaching to this run can find the review.",
377
+ "3. Directly under the URL, print how the user ends the review, in plain text: click exit in the Impeccable overlay, close the browser tab, or say `exit live`. State that the review waits indefinitely until they do, and that ending it exports the design as it then stands, with no further round.",
378
+ "4. Do NOT start a poll loop. The workflow owns polling and will call you back for each event that needs you. Ending your turn does not end the review.",
379
+ "</instructions>"
380
+ ].join(`
381
+ `),
382
+ "<output_format>Under 150 words: the live review URL, the manual fallback path, how to end the review, and whether the browser opened.</output_format>"
383
+ ].join(`
384
+
385
+ `);
386
+ }
387
+
388
+ // dist/builtin/workflows/builtin/open-claude-design-setup.ts
389
+ import { mkdirSync as mkdirSync2, writeFileSync } from "node:fs";
390
+ import { join as join2 } from "node:path";
391
+ var GROUNDED_REPORTING = "Before reporting progress, audit each claim against a tool result from this session. Report only work you can point to evidence for; say so explicitly when something is unverified.";
392
+ function renderDiscoveryContext(discovery) {
393
+ return [
394
+ `Confirmed design brief: ${discovery.brief}`,
395
+ `Output type: ${discovery.output_type}`,
396
+ discovery.references.length > 0 ? `References to emulate (take precedence over DESIGN.md/PRODUCT.md): ${discovery.references.join(", ")}` : "References to emulate: none provided."
397
+ ].join(`
398
+ `);
399
+ }
400
+ function buildDiscoveryInitPrompt(prompt) {
401
+ const outputTypes = OUTPUT_TYPES.join(", ");
402
+ return `/skill:impeccable shape
403
+ /skill:impeccable init
404
+
405
+ ${taggedPrompt([
406
+ ["role", "You are an opinionated staff designer running the open-claude-design front door."],
407
+ [
408
+ "objective",
409
+ `In one stage, confirm the design brief, output type, and references for: ${prompt}. Then run impeccable's \`init\` so PRODUCT.md and DESIGN.md are detected, created, or reconciled before design research; do not wait for another init stage.`
410
+ ],
411
+ [
412
+ "interview",
413
+ [
414
+ "Use `ask_user_question` for important gaps not inferable from the request or repository.",
415
+ `Cover the product and core jobs/screens, one output type (${outputTypes}), and references to emulate (URLs, local paths, screenshots, or design docs).`,
416
+ "Ask 2-3 questions per round and present inferred answers as options rather than facts.",
417
+ "User references are the PRIMARY visual authority and override conflicting DESIGN.md/PRODUCT.md guidance."
418
+ ].join(`
419
+ `)
420
+ ],
421
+ [
422
+ "init_instructions",
423
+ [
424
+ "After confirmation, run `/skill:impeccable init` in this stage. Let impeccable init perform its own PRODUCT.md/DESIGN.md detection rather than relying on runner detection.",
425
+ "Create missing files when needed and reconcile existing ones without silently overwriting them; ask only about genuine gaps.",
426
+ "When headless, infer the most defensible brief/register from the prompt and repository, record explicit `## Gaps / Assumptions`, and do not block."
427
+ ].join(`
428
+ `)
429
+ ],
430
+ [
431
+ "output_format",
432
+ `Return the structured fields \`brief\`, \`output_type\` (one of ${outputTypes}), and \`references\` (verbatim URL/path array, empty when none). In at most 250 words, summarize PRODUCT.md/DESIGN.md changes and assumptions. ${GROUNDED_REPORTING}`
433
+ ]
434
+ ])}`;
435
+ }
436
+ async function runDiscoveryAndInit(args) {
437
+ const result = await args.designContext.task("discovery", {
438
+ prompt: buildDiscoveryInitPrompt(args.prompt),
439
+ ...args.discoveryConfig
440
+ });
441
+ const discovery = discoveryDecisionFromResult(result, args.prompt);
442
+ return {
443
+ discovery,
444
+ discoveryContext: renderDiscoveryContext(discovery),
445
+ projectContext: {
446
+ summary: [
447
+ "Ran `/skill:impeccable shape` + `/skill:impeccable init` in the combined discovery stage.",
448
+ (result.text ?? "").trim()
449
+ ].filter((part) => part.length > 0).join(`
450
+
451
+ `)
452
+ }
453
+ };
454
+ }
455
+ var REFERENCE_DESIGN_SITES = [
456
+ { name: "Awwwards", url: "https://www.awwwards.com/websites/" },
457
+ { name: "recent.design", url: "https://recent.design/" },
458
+ { name: "Dribbble (recent shots)", url: "https://dribbble.com/shots/recent" },
459
+ { name: "Monet", url: "https://www.monet.design/c" },
460
+ { name: "Motionsites", url: "https://motionsites.ai/" }
461
+ ];
462
+ var NO_REFERENCES_BRIEF = "Reference discovery was skipped. Generate from the project design system and the prompt; do not fabricate external references.";
463
+ var DESIGN_CONTEXT_FILENAME = "design-context.md";
464
+ var REFERENCES_BRIEF_FILENAME = "references.md";
465
+ function designContextPath(artifactDir) {
466
+ return join2(artifactDir, DESIGN_CONTEXT_FILENAME);
467
+ }
468
+ function referencesBriefPath(artifactDir) {
469
+ return join2(artifactDir, REFERENCES_BRIEF_FILENAME);
470
+ }
471
+ function buildReferenceDiscoveryPrompt(args) {
472
+ const siteList = REFERENCE_DESIGN_SITES.map((site, index) => `${index + 1}. ${site.name} — ${site.url}`).join(`
473
+ `);
474
+ return taggedPrompt([
475
+ ["reference_galleries", siteList],
476
+ [
477
+ "design_context_file",
478
+ `Read the file at ${args.designContextFile} for the project design context (PRODUCT.md/DESIGN.md summary) and the ds-* discovery evidence before curating. Do not proceed from assumptions when the file is readable; if it is missing, say so and curate from the brief alone.`
479
+ ],
480
+ ["browser_use_guidelines", args.browserBootstrapRules],
481
+ ["screenshot_dir", args.artifactDir],
482
+ [
483
+ "role",
484
+ "You are an opinionated staff design engineer curating current, best-in-class visual references."
485
+ ],
486
+ [
487
+ "objective",
488
+ `Curate references for a ${args.outputType} serving: ${args.prompt}. Open actual design pages, capture motion with scroll-through video when possible and a full-page screenshot as fallback, record destination URLs, and apply impeccable \`extract\` to report concrete observed traits.`
489
+ ],
490
+ [
491
+ "instructions",
492
+ [
493
+ "Use the playwright-cli skill to open each gallery; if `playwright-cli` reports a missing browser executable, follow the bootstrap rules and retry once.",
494
+ "From each gallery, choose 1-3 fitting designs and CLICK INTO each actual live or project-detail page; do not capture only the grid or thumbnail.",
495
+ `Capture motion across the entire page: start \`playwright-cli video-start ${join2(args.artifactDir, "ref-<site>-<n>.webm")}\`, scroll smoothly in small increments with waits (using \`playwright-cli run-code\` or repeated \`playwright-cli mousewheel 0 600\`) so animations fire and lazy content loads, then run \`playwright-cli video-stop\`.`,
496
+ `Also run \`playwright-cli screenshot --full-page --filename=${join2(args.artifactDir, "ref-<site>-<n>.png")}\`; this still is the minimum when video is unavailable.`,
497
+ "Record the actual destination URL, title, and author. For each reference, cite observed layout, typography, color, spacing, and motion traits rather than inferred traits.",
498
+ "Assess fit against DESIGN.md, PRODUCT.md, and the ds-* discovery evidence in the design-context file; prefer on-brand references and flag departures.",
499
+ "Use ask_user_question to ask which reference direction they prefer, offering 2-4 strongest options plus `None of these fit`. If none fit, ask them to provide a reference image, screenshot, URL, or local file path and record the answer.",
500
+ "If `playwright-cli` is unavailable or automation is blocked, use web search / page fetch to reach actual pages and mark missing recordings or screenshots. Never fabricate references or visual claims; report galleries with no usable result."
501
+ ].join(`
502
+ `)
503
+ ],
504
+ [
505
+ "output_format",
506
+ [
507
+ "In at most 900 words, return these Markdown sections:",
508
+ "1. Curated references (table: Source gallery | Work (title/author) | Full page URL (destination) | Scroll-through video path | Full-page screenshot path | Transferable trait (incl. motion) | On-brand?)",
509
+ "2. User preference check (selected direction, or none plus the requested/provided reference)",
510
+ "3. Synthesis (3-5 strongest directions ranked by fit, including motion to reproduce)",
511
+ "4. What to avoid (observed anti-references)",
512
+ "5. Verification notes (actual-page video/screenshot versus search-only)",
513
+ GROUNDED_REPORTING
514
+ ].join(`
515
+ `)
516
+ ]
517
+ ]);
518
+ }
519
+ function writeRequiredContextArtifact(artifactDir, filePath, content, label) {
520
+ try {
521
+ mkdirSync2(artifactDir, { recursive: true });
522
+ writeFileSync(filePath, `${content}
523
+ `);
524
+ } catch (error) {
525
+ const detail = error instanceof Error ? error.message : String(error);
526
+ throw new Error(`open-claude-design: failed to write the required ${label} artifact at ${filePath}. Downstream stages read this file via \`reads\` and must not run without it (${detail})`, { cause: error });
527
+ }
528
+ }
529
+ function persistReferencesBrief(artifactDir, brief) {
530
+ writeRequiredContextArtifact(artifactDir, referencesBriefPath(artifactDir), brief, "references-brief");
531
+ }
532
+ function persistDesignContext(artifactDir, content) {
533
+ writeRequiredContextArtifact(artifactDir, designContextPath(artifactDir), content, "design-context");
534
+ }
535
+ var LIVE_REVIEW_GATE_OPTIONS = [
536
+ "Start live review",
537
+ "Skip remaining review rounds and export as-is"
538
+ ];
539
+ function buildLiveReviewGateMessage(args) {
540
+ return [
541
+ `Design review session ${args.round} is ready for your browser review.`,
542
+ "",
543
+ `Preview file: ${args.previewPath}`,
544
+ `Preview URL: ${args.previewFileUrl}`,
545
+ "",
546
+ `"${LIVE_REVIEW_GATE_OPTIONS[0]}" opens an interactive browser session; the session-start stage prints the live http:// review URL as soon as its server is up (attach with /workflow connect to see it, or open the preview URL above directly).`,
547
+ "The session is unbounded: pick elements, accept variants, and steer for as long as you like, and everything you accept lands in the preview as you go.",
548
+ "",
549
+ "YOU end the review, and nothing else does. It keeps waiting through any amount of silence.",
550
+ 'End it by clicking exit in the Impeccable overlay, closing the browser tab, or saying "exit live".',
551
+ "The moment you do, the design you are looking at is exported. There is no further round and no confirmation, so end the session only when the preview is what you want handed off.",
552
+ `"${LIVE_REVIEW_GATE_OPTIONS[1]}" accepts the current design and proceeds to export without opening a session.`
553
+ ].join(`
554
+ `);
555
+ }
556
+ function isUiUnavailableRejection(error) {
557
+ return error instanceof Error && /ctx\.ui\.\w+ (?:prompt node )?is unavailable/.test(error.message);
558
+ }
559
+
560
+ // dist/builtin/workflows/builtin/open-claude-design-phases.ts
561
+ var GROUNDED_REPORTING2 = "Before reporting progress, audit each claim against a tool result from this session. Report only work you can point to evidence for; say so explicitly when something is unverified.";
562
+ function forkContinuationOptions(sessionFile) {
563
+ return sessionFile === undefined || sessionFile.length === 0 ? {} : { context: "fork", forkFromSessionFile: sessionFile };
564
+ }
565
+ async function refineOpenClaudeDesign(options) {
566
+ const { designContext, prompt, outputType, previewPath, previewFileUrl, browserBootstrapRules, designContextFile, referencesFile, designModelConfig, workflowCwd } = options;
567
+ const importContext = options.importContext ?? "";
568
+ const generated = await designContext.task("generate-1", {
569
+ prompt: buildInitialGeneratePrompt({
570
+ prompt,
571
+ outputType,
572
+ previewPath,
573
+ designContextFile,
574
+ referencesFile,
575
+ importContext
576
+ }),
577
+ reads: [designContextFile, referencesFile],
578
+ ...designModelConfig
579
+ });
580
+ const gateChoice = await options.ui.select(buildLiveReviewGateMessage({ round: 1, previewPath, previewFileUrl }), LIVE_REVIEW_GATE_OPTIONS).catch((error) => {
581
+ if (isUiUnavailableRejection(error))
582
+ return LIVE_REVIEW_GATE_OPTIONS[0];
583
+ throw error;
584
+ });
585
+ if (gateChoice === LIVE_REVIEW_GATE_OPTIONS[0]) {
586
+ await runLiveReviewSession({
587
+ designContext,
588
+ round: 1,
589
+ reviewStageName: "user-feedback-1",
590
+ previewPath,
591
+ previewFileUrl,
592
+ browserBootstrapRules,
593
+ designModelConfig,
594
+ workflowCwd
595
+ });
596
+ }
597
+ return { latestDesign: generated.text };
598
+ }
599
+ async function runLiveReviewSession(options) {
600
+ const { designContext, round, reviewStageName, previewPath, previewFileUrl, browserBootstrapRules, designModelConfig, workflowCwd } = options;
601
+ let sessionFile;
602
+ const start = await designContext.task(`${reviewStageName}-start`, {
603
+ prompt: buildLiveSessionStartPrompt({ previewPath, previewFileUrl, browserBootstrapRules, round }),
604
+ ...designModelConfig
605
+ });
606
+ sessionFile = start.sessionFile;
607
+ for (let index = 1;; index += 1) {
608
+ const event = await designContext.tool(`live-poll-${round}-${index}`, { round, index }, async ({ signal }) => pollLiveEvent({ workflowCwd, signal }));
609
+ if (event.type === "exit")
610
+ break;
611
+ if (!needsModel(event))
612
+ continue;
613
+ if (event.id === undefined || event.id.length === 0) {
614
+ throw new Error(`Live ${event.type} event is missing its id`);
615
+ }
616
+ const response = await designContext.task(`live-${event.type}-${round}-${index}`, {
617
+ prompt: buildLiveEventPrompt({ event, previewPath }),
618
+ ...designModelConfig,
619
+ ...forkContinuationOptions(sessionFile)
620
+ });
621
+ sessionFile = response.sessionFile ?? sessionFile;
622
+ const status = replyTokenFor(event);
623
+ await designContext.tool(`live-reply-${round}-${index}`, { round, index, eventId: event.id, status }, async ({ signal }) => replyLiveEvent({ workflowCwd, event, status, signal }));
624
+ }
625
+ }
626
+ function buildInitialGeneratePrompt(args) {
627
+ return taggedPrompt([
628
+ ["design_brief", args.prompt],
629
+ [
630
+ "design_context_file",
631
+ `Read the file at ${args.designContextFile} for the project design context (PRODUCT.md/DESIGN.md summary) and the ds-* design-system evidence before designing.`
632
+ ],
633
+ ["reference_context", args.importContext],
634
+ [
635
+ "reference_inspiration_file",
636
+ `Read the file at ${args.referencesFile} for the curated reference inspiration to heavily emulate.`
637
+ ],
638
+ ["reference_precedence", REFERENCE_PRECEDENCE],
639
+ ["preview_artifact_path", args.previewPath],
640
+ ["html_rules", HTML_PREVIEW_RULES],
641
+ ["anti_design_slop_rules", ANTI_SLOP_RULES],
642
+ ["role", "You are an opinionated staff design engineer."],
643
+ [
644
+ "objective",
645
+ `Create the first production-ready ${args.outputType} for: ${args.prompt}. Write an interactive browser preview and apply impeccable \`craft\`; each decision must trace to the brief, references, design system, or reference context.`
646
+ ],
647
+ [
648
+ "instructions",
649
+ [
650
+ `First read the design-context and reference-inspiration files named above; they are the design system and reference authority for every decision. If a file is missing, say so and proceed from the brief.`,
651
+ `Create the HTML artifact exactly at ${args.previewPath}.`,
652
+ "Follow <reference_precedence>; heavily reference the reference-inspiration file without copying wholesale or inventing traits.",
653
+ `Build the requested output_type (${args.outputType}): render full realistic layouts for prototypes/pages, or the component in at least three representative contexts.`,
654
+ "Include structure, states, accessibility, responsive behavior, and integration notes as HTML comments so the preview stays clean.",
655
+ "Use project language rather than generic placeholders when conventions exist. Add no features or abstractions beyond this design brief."
656
+ ].join(`
657
+ `)
658
+ ],
659
+ [
660
+ "output_format",
661
+ [
662
+ "In at most 500 words, return Markdown, not the HTML body:",
663
+ "1. Artifact overview",
664
+ "2. Files written (including the absolute preview.html path)",
665
+ "3. UI structure and states (by HTML section ID)",
666
+ "4. Accessibility and responsive behavior",
667
+ "5. Implementation notes",
668
+ "6. Assumptions / open questions",
669
+ GROUNDED_REPORTING2
670
+ ].join(`
671
+ `)
672
+ ]
673
+ ]);
674
+ }
675
+ async function exportOpenClaudeDesign(options) {
676
+ const { designContext, prompt, outputType, previewPath, previewFileUrl, specPath, specFileUrl, browserBootstrapRules, designContextFile, referencesFile, designModelConfig } = options;
677
+ const latestDesign = options.latestDesign;
678
+ const handoff = await designContext.task("exporter", {
679
+ reads: [designContextFile, referencesFile],
680
+ prompt: taggedPrompt([
681
+ [
682
+ "design_context_file",
683
+ `Read the file at ${designContextFile} for the project design context (PRODUCT.md/DESIGN.md summary) and the ds-* design-system evidence to document.`
684
+ ],
685
+ [
686
+ "reference_inspiration_file",
687
+ `Read the file at ${referencesFile} for the curated reference research that informed the final design; use it wherever the spec cites visual direction or reference provenance.`
688
+ ],
689
+ ["preview_artifact_path", previewPath],
690
+ ["spec_artifact_path", specPath],
691
+ ["final_design_summary", "{previous}"],
692
+ ["html_rules", HTML_PREVIEW_RULES],
693
+ ["anti_design_slop_rules", ANTI_SLOP_RULES],
694
+ ["role", "You are an opinionated staff design engineer."],
695
+ [
696
+ "objective",
697
+ `Export the final ${outputType} for "${prompt}" as a rich browser-readable HTML spec. Apply impeccable \`document\` and embed or link the final preview so implementation reviewers see the design as exported.`
698
+ ],
699
+ [
700
+ "instructions",
701
+ [
702
+ "First read the design-context file named above, then read preview_artifact_path as the canonical final design, and use the Write tool to create one self-contained HTML5 file at spec_artifact_path.",
703
+ 'In order, include: sticky header with title/status/run id; Executive Summary; Live Preview embedding the full preview via `<iframe srcdoc="...">` or a side-by-side rendered copy in `<article class="preview-frame">`; the six DESIGN.md sections (Overview, Colors, Typography, Elevation, Components, Do\'s and Don\'ts) rendered with swatches, tables, and code blocks; Implementation handoff (Recommended files + components, Implementation steps, Usage example, Accessibility & responsive checklist, Validation commands, Known limitations); and an appendix linking the raw preview path.',
704
+ "Use dense legible typography, generous whitespace, monospaced code, rendered hex/oklch swatches, and copy-to-clipboard hints in HTML comments.",
705
+ `Show the absolute preview path (${previewPath}) and file URL (${previewFileUrl}) prominently. Preserve assumptions and limitations; introduce no requirement absent from the final design or DESIGN.md.`
706
+ ].join(`
707
+ `)
708
+ ],
709
+ [
710
+ "output_format",
711
+ [
712
+ "In at most 600 words, return Markdown, not the HTML:",
713
+ "1. Spec written to (absolute path)",
714
+ "2. Sections included",
715
+ "3. How to open the spec (playwright-cli command + manual fallback path)",
716
+ "4. Recommended files and components",
717
+ "5. Implementation steps",
718
+ "6. Usage example",
719
+ "7. Accessibility / responsive checklist",
720
+ "8. Validation commands",
721
+ "9. Known limitations",
722
+ GROUNDED_REPORTING2
723
+ ].join(`
724
+ `)
725
+ ]
726
+ ]),
727
+ previous: { name: "final-design", text: latestDesign },
728
+ ...designModelConfig
729
+ });
730
+ await designContext.task("final-display", {
731
+ prompt: taggedPrompt([
732
+ ["spec_path", specPath],
733
+ ["spec_file_url", specFileUrl],
734
+ ["preview_path", previewPath],
735
+ ["preview_file_url", previewFileUrl],
736
+ ["browser_use_guidelines", browserBootstrapRules],
737
+ ["role", "You are an opinionated staff design engineer."],
738
+ [
739
+ "objective",
740
+ "Show the exported spec with the playwright-cli skill's `playwright-cli` command. Export is complete, so do not solicit changes; direct further changes to a new `/workflow open-claude-design` run and degrade gracefully when browser automation is unavailable."
741
+ ],
742
+ [
743
+ "instructions",
744
+ [
745
+ `Use the bootstrap rules, run \`playwright-cli open ${specFileUrl}\`, and if a browser executable is missing follow those rules and retry once before \`playwright-cli snapshot\`.`,
746
+ "Do not run `show --annotate` or invite changes because the review session has ended.",
747
+ `Prominently print the manual paths:
748
+ - Final spec: ${specPath}
749
+ - Preview: ${previewPath}`,
750
+ "Unavailable tooling must not block the workflow; return the structured summary."
751
+ ].join(`
752
+ `)
753
+ ],
754
+ [
755
+ "output_format",
756
+ `Under 250 words, return Markdown with: \`display_method\` | \`spec_path\` | \`preview_path\` | \`manual_open_instructions\` | \`next_action_hint\` (how to re-run the workflow). ${GROUNDED_REPORTING2}`
757
+ ]
758
+ ]),
759
+ ...designModelConfig
760
+ }).catch(() => {
761
+ return;
762
+ });
763
+ return { latestDesign, handoff };
764
+ }
765
+
766
+ // dist/builtin/workflows/builtin/open-claude-design-runner.ts
767
+ var GROUNDED_REPORTING3 = "Before reporting progress, audit each claim against a tool result from this session. Report only work you can point to evidence for; say so explicitly when something is unverified.";
768
+ var DELEGATION_RULE = "Delegate further only work genuinely independent and too large for a handful of tool calls; do not delegate self-verification, and prefer one subagent over several.";
769
+ async function runOpenClaudeDesignWorkflow(ctx) {
770
+ const designContext = ctx;
771
+ const playwrightCli = ensurePlaywrightCli();
772
+ const browserBootstrapRules = buildPlaywrightCliBootstrapRules(playwrightCli);
773
+ const inputs = designContext.inputs;
774
+ const prompt = inputs.prompt;
775
+ const discoverReferences = inputs.discover_references !== false;
776
+ const workflowCwd = designContext.cwd ?? process.cwd();
777
+ const { runId, artifactDir, previewPath, specPath } = prepareArtifactDir(workflowCwd);
778
+ const previewFileUrl = `file://${previewPath}`;
779
+ const specFileUrl = `file://${specPath}`;
780
+ const partialArtifactOutputs = {
781
+ playwright_cli_status: playwrightCli.summary,
782
+ run_id: runId,
783
+ artifact_dir: artifactDir,
784
+ preview_path: previewPath,
785
+ preview_file_url: previewFileUrl,
786
+ spec_path: specPath,
787
+ spec_file_url: specFileUrl
788
+ };
789
+ if (shouldEarlyExitForBrowser(playwrightCli.available, "development") && typeof designContext.exit === "function") {
790
+ designContext.exit({
791
+ reason: `open-claude-design needs the playwright-cli skill's browser for interactive design review, which is unavailable (${playwrightCli.error ?? playwrightCli.summary}). No design was generated. Install it (\`npm install -g @playwright/cli@latest\` + \`npx playwright install chromium\`) and re-run.`,
792
+ outputs: partialArtifactOutputs
793
+ });
794
+ }
795
+ const persistRequiredContextOrExit = (persist) => {
796
+ try {
797
+ persist();
798
+ } catch (error) {
799
+ const detail = error instanceof Error ? error.message : String(error);
800
+ if (typeof designContext.exit === "function") {
801
+ designContext.exit({
802
+ status: "blocked",
803
+ reason: `${detail} No design was generated.`,
804
+ outputs: partialArtifactOutputs
805
+ });
806
+ }
807
+ throw error;
808
+ }
809
+ };
810
+ const designModelConfig = {
811
+ model: "anthropic/claude-opus-5:high",
812
+ fallbackModels: [
813
+ "github-copilot/claude-opus-5:high",
814
+ "anthropic/claude-fable-5:high",
815
+ "github-copilot/claude-fable-5:high",
816
+ "kimi-coding/k3:max",
817
+ "moonshotai/kimi-k3:max",
818
+ "moonshotai-cn/kimi-k3:max",
819
+ "anthropic/claude-opus-4-8:high",
820
+ "github-copilot/claude-opus-4.8:high",
821
+ "openai-codex/gpt-5.6-sol:xhigh",
822
+ "github-copilot/gpt-5.6-sol:xhigh",
823
+ "openai/gpt-5.6-sol:xhigh",
824
+ "xai/grok-4.6:xhigh",
825
+ "github-copilot/grok-4.6:xhigh",
826
+ "zai/glm-5.3:high",
827
+ "zai-coding-cn/glm-5.3:high",
828
+ "openrouter/anthropic/claude-opus-5:high",
829
+ "openrouter/anthropic/claude-fable-5:high",
830
+ "openrouter/anthropic/claude-opus-4-8:high",
831
+ "openrouter/moonshotai/kimi-k3:max",
832
+ "openrouter/openai/gpt-5.6-sol:xhigh",
833
+ "openrouter/sakana/fugu-ultra:high",
834
+ "openrouter/x-ai/grok-4.6"
835
+ ]
836
+ };
837
+ const frontDoor = await runDiscoveryAndInit({
838
+ designContext,
839
+ prompt,
840
+ discoveryConfig: { ...designModelConfig, schema: discoveryDecisionSchema }
841
+ });
842
+ const discovery = frontDoor.discovery;
843
+ const designBrief = discovery.brief;
844
+ const outputType = discovery.output_type;
845
+ const references = discovery.references;
846
+ const projectContext = frontDoor.projectContext;
847
+ const userReferenceContext = references.length > 0 ? references.map((ref, index) => `${index + 1}. ${ref}`).join(`
848
+ `) : "No user-provided references were collected during discovery.";
849
+ const referenceHandlingRules = references.length > 0 ? [
850
+ REFERENCE_PRECEDENCE,
851
+ "For URL references, use browser/screenshot tooling when available and cite only observable traits.",
852
+ "For files, screenshots, or design docs, read or parse the source directly and quote concrete evidence.",
853
+ "Include a `Reference requirements` section so the generator receives the imported constraints."
854
+ ].join(`
855
+ `) : "No user references to import. Focus on project context and curated reference-discovery when present.";
856
+ const dsSteps = [
857
+ {
858
+ name: "ds-locator",
859
+ task: taggedPrompt([
860
+ ["user_references", userReferenceContext],
861
+ ["reference_handling", referenceHandlingRules],
862
+ ["browser_use_guidelines", browserBootstrapRules],
863
+ ["role", "You are an opinionated staff design engineer."],
864
+ [
865
+ "objective",
866
+ `Find UI/design-system sources for: ${designBrief}. Apply impeccable \`extract\` to codebase evidence and user reference URLs/files that should steer generation.`
867
+ ],
868
+ ["delegation_rule", DELEGATION_RULE],
869
+ [
870
+ "instructions",
871
+ [
872
+ "Locate UI components, stylesheets, tokens, Storybook/examples, screenshots, tests, design docs, and user references.",
873
+ "Report concrete file, URL, or artifact paths and why each informs generation; separate primary sources, supporting examples, and reference-only inspiration.",
874
+ "If no explicit system exists, report the strongest implicit evidence such as repeated literals and dominant component patterns."
875
+ ].join(`
876
+ `)
877
+ ],
878
+ [
879
+ "output_format",
880
+ `In at most 500 words, return Markdown sections: Project sources table | User reference sources | Reference requirements | Confidence notes. ${GROUNDED_REPORTING3}`
881
+ ]
882
+ ]),
883
+ ...designModelConfig
884
+ },
885
+ {
886
+ name: "ds-analyzer",
887
+ task: taggedPrompt([
888
+ ["user_references", userReferenceContext],
889
+ ["reference_handling", referenceHandlingRules],
890
+ ["browser_use_guidelines", browserBootstrapRules],
891
+ [
892
+ "impeccable_skill",
893
+ "audit — score 0–4 across Accessibility, Performance, Theming, Responsive, Anti-patterns. Tag every finding P0 (blocks release) → P3 (polish). Document, do not fix."
894
+ ],
895
+ ["role", "You are an opinionated staff design engineer."],
896
+ [
897
+ "objective",
898
+ `Independently audit UI constraints for: ${designBrief}. Scan the repository, assess evidence across impeccable's six quality dimensions, and capture or parse user references without relying on another stage's output.`
899
+ ],
900
+ ["delegation_rule", DELEGATION_RULE],
901
+ [
902
+ "instructions",
903
+ [
904
+ "Inspect the UI stack, styling, tokens, responsive behavior, accessibility conventions, and component APIs.",
905
+ "Ground each claim in exact paths, symbols, code examples, screenshots, URLs, or quoted reference excerpts.",
906
+ "Identify integration constraints the generated design must follow, and state uncertainty when evidence is incomplete."
907
+ ].join(`
908
+ `)
909
+ ],
910
+ [
911
+ "output_format",
912
+ `In at most 700 words, return Markdown sections in this order: Stack | Tokens | Components | Layout / responsiveness | Accessibility | Audit scores (per dimension, 0–4) | Reference requirements | Hard constraints for generation. ${GROUNDED_REPORTING3}`
913
+ ]
914
+ ]),
915
+ ...designModelConfig
916
+ },
917
+ {
918
+ name: "ds-patterns",
919
+ task: taggedPrompt([
920
+ ["user_references", userReferenceContext],
921
+ ["reference_handling", referenceHandlingRules],
922
+ ["browser_use_guidelines", browserBootstrapRules],
923
+ ["role", "You are an opinionated staff design engineer."],
924
+ [
925
+ "objective",
926
+ `Extract reusable patterns and anti-patterns for: ${designBrief}. Apply impeccable \`extract\` to repository evidence and user references, translating them into generation guidance without relying on another stage's output.`
927
+ ],
928
+ ["delegation_rule", DELEGATION_RULE],
929
+ [
930
+ "instructions",
931
+ [
932
+ "Find reusable naming, variant, composition, state, animation, and layout patterns.",
933
+ "Cite concrete paths, component/symbol names, reference URLs, or quoted file/screenshot evidence.",
934
+ "Identify generated-design anti-patterns using impeccable's 25 deterministic anti-patterns; do not generalize beyond repository or reference evidence."
935
+ ].join(`
936
+ `)
937
+ ],
938
+ [
939
+ "output_format",
940
+ `In at most 600 words, return Markdown sections: Reusable patterns | Examples | Reference requirements | Anti-patterns | Generation implications. ${GROUNDED_REPORTING3}`
941
+ ]
942
+ ]),
943
+ ...designModelConfig
944
+ }
945
+ ];
946
+ const onboardingAnalysis = await designContext.parallel(dsSteps, {
947
+ task: designBrief
948
+ });
949
+ const onboardingSummary = joinResults(onboardingAnalysis);
950
+ const designSystem = [
951
+ "Project design context from `/skill:impeccable init` and PRODUCT.md/DESIGN.md:",
952
+ projectContext.summary,
953
+ "",
954
+ "Design-system and user-reference evidence:",
955
+ onboardingSummary
956
+ ].join(`
957
+
958
+ `);
959
+ persistRequiredContextOrExit(() => persistDesignContext(artifactDir, designSystem));
960
+ const designContextFile = designContextPath(artifactDir);
961
+ const referenceResult = discoverReferences ? await designContext.task("reference-discovery", {
962
+ prompt: buildReferenceDiscoveryPrompt({
963
+ prompt: designBrief,
964
+ outputType,
965
+ designContextFile,
966
+ artifactDir,
967
+ browserBootstrapRules
968
+ }),
969
+ reads: [designContextFile],
970
+ ...designModelConfig
971
+ }) : undefined;
972
+ const referencesBriefRaw = (referenceResult?.text ?? "").trim();
973
+ const referencesBrief = referencesBriefRaw.length > 0 ? referencesBriefRaw : NO_REFERENCES_BRIEF;
974
+ persistRequiredContextOrExit(() => persistReferencesBrief(artifactDir, referencesBrief));
975
+ const referencesFile = referencesBriefPath(artifactDir);
976
+ const importContext = references.length > 0 ? [
977
+ REFERENCE_PRECEDENCE,
978
+ "Reference sources:",
979
+ userReferenceContext,
980
+ "",
981
+ "Full design-system and reference evidence: read the design-context file."
982
+ ].join(`
983
+ `) : "No user reference was provided; infer the design direction from the brief, project design context, research, and curated reference inspiration.";
984
+ const refinement = await refineOpenClaudeDesign({
985
+ designContext,
986
+ prompt: designBrief,
987
+ outputType,
988
+ previewPath,
989
+ previewFileUrl,
990
+ browserBootstrapRules,
991
+ designContextFile,
992
+ referencesFile,
993
+ designModelConfig,
994
+ workflowCwd,
995
+ importContext,
996
+ ui: designContext.ui
997
+ });
998
+ const latestDesign = refinement.latestDesign;
999
+ const exportResult = await exportOpenClaudeDesign({
1000
+ designContext,
1001
+ prompt: designBrief,
1002
+ outputType,
1003
+ previewPath,
1004
+ previewFileUrl,
1005
+ specPath,
1006
+ specFileUrl,
1007
+ browserBootstrapRules,
1008
+ designContextFile,
1009
+ referencesFile,
1010
+ latestDesign,
1011
+ designModelConfig
1012
+ });
1013
+ const handoff = exportResult.handoff;
1014
+ return {
1015
+ output_type: outputType,
1016
+ design_system: "project-derived design system",
1017
+ artifact: latestDesign,
1018
+ handoff: handoff.text,
1019
+ import_context: importContext,
1020
+ run_id: runId,
1021
+ artifact_dir: artifactDir,
1022
+ preview_path: previewPath,
1023
+ preview_file_url: previewFileUrl,
1024
+ spec_path: specPath,
1025
+ spec_file_url: specFileUrl,
1026
+ playwright_cli_status: playwrightCli.summary
1027
+ };
1028
+ }
1029
+
1030
+ // dist/builtin/workflows/builtin/open-claude-design.ts
1031
+ var open_claude_design_default = workflow({
1032
+ name: "open-claude-design",
1033
+ description: "AI-powered design workflow: combined discovery/init → design-system/reference research → curated reference discovery → HTML generation → one live review session → rich HTML handoff. The discovery stage asks what to build, the output type, and which references to emulate, then runs impeccable init for PRODUCT.md/DESIGN.md (references take precedence over project context). The user reviews the generated HTML in one live session.",
1034
+ heartbeatIntervalMinutes: 0,
1035
+ inputs: {
1036
+ prompt: Type2.String({
1037
+ description: "What to design (for example, a dashboard, page, component, or prototype). The discovery stage refines this into a confirmed brief and asks for the output type and references."
1038
+ }),
1039
+ discover_references: Type2.Boolean({
1040
+ default: true,
1041
+ description: "Discover beautiful, current reference designs from notable design websites (Awwwards, recent.design, Dribbble, Monet, Motionsites) and feed them to generation. Set false to skip the network/browser reference pass."
1042
+ })
1043
+ },
1044
+ outputs: {
1045
+ output_type: Type2.Optional(Type2.String({ description: "Kind of design artifact produced." })),
1046
+ design_system: Type2.Optional(Type2.String({ description: "Design system source used for generation: the project-derived design system." })),
1047
+ artifact: Type2.Optional(Type2.String({ description: "Latest final design summary from the final preview artifact." })),
1048
+ handoff: Type2.Optional(Type2.String({ description: "Final rich HTML spec and implementation handoff summary." })),
1049
+ import_context: Type2.Optional(Type2.String({ description: "Reference-import context used during generation." })),
1050
+ run_id: Type2.Optional(Type2.String({ description: "Per-run design workflow artifact identifier." })),
1051
+ artifact_dir: Type2.Optional(Type2.String({ description: "Directory containing preview and spec artifacts." })),
1052
+ preview_path: Type2.Optional(Type2.String({ description: "Absolute path to the generated preview.html file." })),
1053
+ preview_file_url: Type2.Optional(Type2.String({ description: "file:// URL for the generated preview.html file." })),
1054
+ spec_path: Type2.Optional(Type2.String({ description: "Absolute path to the generated spec.html file." })),
1055
+ spec_file_url: Type2.Optional(Type2.String({ description: "file:// URL for the generated spec.html file." })),
1056
+ playwright_cli_status: Type2.Optional(Type2.String({ description: "Outcome of the initial deterministic step that ensures the playwright-cli skill's `playwright-cli` command is installed." }))
1057
+ },
1058
+ run: async (ctx) => await runOpenClaudeDesignWorkflow(withSteeringPropagationContext(ctx))
1059
+ });
1060
+
1061
+ export { open_claude_design_default };