@bastani/atomic 0.9.0-alpha.2 → 0.9.0-alpha.4
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.
- package/CHANGELOG.md +21 -0
- package/dist/builtin/cursor/package.json +2 -2
- package/dist/builtin/intercom/package.json +1 -1
- package/dist/builtin/mcp/package.json +1 -1
- package/dist/builtin/subagents/package.json +1 -1
- package/dist/builtin/web-access/package.json +1 -1
- package/dist/builtin/workflows/CHANGELOG.md +24 -0
- package/dist/builtin/workflows/README.md +12 -12
- package/dist/builtin/workflows/builtin/goal-ledger.ts +2 -0
- package/dist/builtin/workflows/builtin/goal-prompts.ts +8 -0
- package/dist/builtin/workflows/builtin/goal-reports.ts +5 -0
- package/dist/builtin/workflows/builtin/goal-runner.ts +103 -4
- package/dist/builtin/workflows/builtin/goal-types.ts +4 -0
- package/dist/builtin/workflows/builtin/goal.d.ts +4 -0
- package/dist/builtin/workflows/builtin/goal.ts +14 -2
- package/dist/builtin/workflows/builtin/index.d.ts +8 -8
- package/dist/builtin/workflows/builtin/open-claude-design-feedback.ts +359 -0
- package/dist/builtin/workflows/builtin/open-claude-design-phases.ts +254 -352
- package/dist/builtin/workflows/builtin/open-claude-design-runner.ts +256 -414
- package/dist/builtin/workflows/builtin/open-claude-design-setup.ts +272 -0
- package/dist/builtin/workflows/builtin/open-claude-design-utils.ts +58 -68
- package/dist/builtin/workflows/builtin/open-claude-design.d.ts +5 -9
- package/dist/builtin/workflows/builtin/open-claude-design.ts +14 -26
- package/dist/builtin/workflows/builtin/prompt-refinement.ts +102 -0
- package/dist/builtin/workflows/builtin/ralph-core.ts +6 -4
- package/dist/builtin/workflows/builtin/ralph-runner.ts +22 -24
- package/dist/builtin/workflows/builtin/ralph.d.ts +2 -0
- package/dist/builtin/workflows/builtin/ralph.ts +3 -1
- package/dist/builtin/workflows/package.json +1 -1
- package/dist/builtin/workflows/skills/impeccable/SKILL.md +14 -23
- package/dist/builtin/workflows/skills/impeccable/reference/brand.md +2 -2
- package/dist/builtin/workflows/skills/impeccable/reference/live.md +25 -4
- package/dist/builtin/workflows/skills/impeccable/scripts/context-signals.mjs +1 -1
- package/dist/builtin/workflows/skills/impeccable/scripts/context.mjs +724 -29
- package/dist/builtin/workflows/skills/impeccable/scripts/critique-storage.mjs +1 -1
- package/dist/builtin/workflows/skills/impeccable/scripts/detector/browser/injected/index.mjs +219 -7
- package/dist/builtin/workflows/skills/impeccable/scripts/detector/cli/main.mjs +57 -11
- package/dist/builtin/workflows/skills/impeccable/scripts/detector/design-system.mjs +750 -0
- package/dist/builtin/workflows/skills/impeccable/scripts/detector/detect-antipatterns-browser.js +648 -53
- package/dist/builtin/workflows/skills/impeccable/scripts/detector/detect-antipatterns.mjs +7 -0
- package/dist/builtin/workflows/skills/impeccable/scripts/detector/engines/browser/detect-url.mjs +29 -4
- package/dist/builtin/workflows/skills/impeccable/scripts/detector/engines/regex/detect-text.mjs +44 -11
- package/dist/builtin/workflows/skills/impeccable/scripts/detector/engines/static-html/css-cascade.mjs +29 -0
- package/dist/builtin/workflows/skills/impeccable/scripts/detector/engines/static-html/detect-html.mjs +27 -1
- package/dist/builtin/workflows/skills/impeccable/scripts/detector/node/file-system.mjs +1 -1
- package/dist/builtin/workflows/skills/impeccable/scripts/detector/registry/antipatterns.mjs +29 -0
- package/dist/builtin/workflows/skills/impeccable/scripts/detector/rules/checks.mjs +401 -46
- package/dist/builtin/workflows/skills/impeccable/scripts/detector/shared/inline-ignores.mjs +148 -0
- package/dist/builtin/workflows/skills/impeccable/scripts/detector/shared/page.mjs +6 -6
- package/dist/builtin/workflows/skills/impeccable/scripts/{design-parser.mjs → lib/design-parser.mjs} +8 -1
- package/dist/builtin/workflows/skills/impeccable/scripts/lib/impeccable-config.mjs +638 -0
- package/dist/builtin/workflows/skills/impeccable/scripts/lib/impeccable-paths.mjs +128 -0
- package/dist/builtin/workflows/skills/impeccable/scripts/{is-generated.mjs → lib/is-generated.mjs} +2 -2
- package/dist/builtin/workflows/skills/impeccable/scripts/lib/target-args.mjs +42 -0
- package/dist/builtin/workflows/skills/impeccable/scripts/live/browser-script-parts.mjs +49 -0
- package/dist/builtin/workflows/skills/impeccable/scripts/{live-completion.mjs → live/completion.mjs} +1 -0
- package/dist/builtin/workflows/skills/impeccable/scripts/{live-event-validation.mjs → live/event-validation.mjs} +6 -5
- package/dist/builtin/workflows/skills/impeccable/scripts/live/manual-apply.mjs +939 -0
- package/dist/builtin/workflows/skills/impeccable/scripts/live/manual-edit-routes.mjs +357 -0
- package/dist/builtin/workflows/skills/impeccable/scripts/{live-manual-edits-buffer.mjs → live/manual-edits-buffer.mjs} +1 -1
- package/dist/builtin/workflows/skills/impeccable/scripts/{live-session-store.mjs → live/session-store.mjs} +21 -3
- package/dist/builtin/workflows/skills/impeccable/scripts/live/svelte-component.mjs +835 -0
- package/dist/builtin/workflows/skills/impeccable/scripts/live/sveltekit-adapter.mjs +274 -0
- package/dist/builtin/workflows/skills/impeccable/scripts/live/ui-core.mjs +180 -0
- package/dist/builtin/workflows/skills/impeccable/scripts/live/vocabulary.mjs +36 -0
- package/dist/builtin/workflows/skills/impeccable/scripts/live-accept.mjs +185 -60
- package/dist/builtin/workflows/skills/impeccable/scripts/live-browser-dom.js +146 -0
- package/dist/builtin/workflows/skills/impeccable/scripts/live-browser.js +3369 -1026
- package/dist/builtin/workflows/skills/impeccable/scripts/live-commit-manual-edits.mjs +2 -2
- package/dist/builtin/workflows/skills/impeccable/scripts/live-complete.mjs +2 -2
- package/dist/builtin/workflows/skills/impeccable/scripts/live-discard-manual-edits.mjs +1 -1
- package/dist/builtin/workflows/skills/impeccable/scripts/live-inject.mjs +133 -9
- package/dist/builtin/workflows/skills/impeccable/scripts/live-insert.mjs +42 -2
- package/dist/builtin/workflows/skills/impeccable/scripts/live-manual-edit-evidence.mjs +4 -4
- package/dist/builtin/workflows/skills/impeccable/scripts/live-poll.mjs +21 -15
- package/dist/builtin/workflows/skills/impeccable/scripts/live-resume.mjs +1 -1
- package/dist/builtin/workflows/skills/impeccable/scripts/live-server.mjs +205 -1269
- package/dist/builtin/workflows/skills/impeccable/scripts/live-status.mjs +2 -2
- package/dist/builtin/workflows/skills/impeccable/scripts/live-target.mjs +30 -0
- package/dist/builtin/workflows/skills/impeccable/scripts/live-wrap.mjs +69 -26
- package/dist/builtin/workflows/skills/impeccable/scripts/live.mjs +73 -22
- package/dist/builtin/workflows/src/extension/workflow-prompts.ts +3 -1
- package/dist/core/atomic-guide-command.d.ts.map +1 -1
- package/dist/core/atomic-guide-command.js +5 -5
- package/dist/core/atomic-guide-command.js.map +1 -1
- package/dist/core/system-prompt.d.ts.map +1 -1
- package/dist/core/system-prompt.js +0 -1
- package/dist/core/system-prompt.js.map +1 -1
- package/docs/index.md +2 -2
- package/docs/quickstart.md +9 -9
- package/docs/workflows.md +816 -47
- package/package.json +2 -2
- package/dist/builtin/workflows/skills/impeccable/scripts/cleanup-deprecated.mjs +0 -284
- package/dist/builtin/workflows/skills/impeccable/scripts/impeccable-paths.mjs +0 -126
- /package/dist/builtin/workflows/skills/impeccable/scripts/{live-insert-ui.mjs → live/insert-ui.mjs} +0 -0
|
@@ -1,12 +1,19 @@
|
|
|
1
|
-
import { join } from "node:path";
|
|
2
1
|
import type { WorkflowTaskResult } from "../src/shared/types.js";
|
|
3
2
|
import {
|
|
4
3
|
ANTI_SLOP_RULES,
|
|
5
4
|
HTML_PREVIEW_RULES,
|
|
6
|
-
|
|
7
|
-
refinementDecisionFromResult,
|
|
5
|
+
REFERENCE_PRECEDENCE,
|
|
8
6
|
taggedPrompt,
|
|
9
7
|
} from "./open-claude-design-utils.js";
|
|
8
|
+
import {
|
|
9
|
+
assertUserAnnotationsThreaded,
|
|
10
|
+
hasMeaningfulFeedback,
|
|
11
|
+
persistPreviewFeedback,
|
|
12
|
+
toPreviewFeedback,
|
|
13
|
+
userAnnotationsBlock,
|
|
14
|
+
type PreviewFeedback,
|
|
15
|
+
} from "./open-claude-design-feedback.js";
|
|
16
|
+
import { buildLivePreviewDisplayPrompt } from "./open-claude-design-setup.js";
|
|
10
17
|
|
|
11
18
|
type DesignContext = {
|
|
12
19
|
task(name: string, options: object): Promise<WorkflowTaskResult>;
|
|
@@ -15,6 +22,19 @@ type DesignContext = {
|
|
|
15
22
|
|
|
16
23
|
type ModelConfig = Record<string, object | string | readonly string[]>;
|
|
17
24
|
|
|
25
|
+
type ForkContinuationOptions = {
|
|
26
|
+
readonly context?: "fork";
|
|
27
|
+
readonly forkFromSessionFile?: string;
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
function forkContinuationOptions(
|
|
31
|
+
sessionFile: string | undefined,
|
|
32
|
+
): ForkContinuationOptions {
|
|
33
|
+
return sessionFile === undefined || sessionFile.length === 0
|
|
34
|
+
? {}
|
|
35
|
+
: { context: "fork", forkFromSessionFile: sessionFile };
|
|
36
|
+
}
|
|
37
|
+
|
|
18
38
|
type RefineOptions = {
|
|
19
39
|
readonly designContext: DesignContext;
|
|
20
40
|
readonly prompt: string;
|
|
@@ -25,230 +45,195 @@ type RefineOptions = {
|
|
|
25
45
|
readonly artifactDir: string;
|
|
26
46
|
readonly browserBootstrapRules: string;
|
|
27
47
|
readonly designSystem: string;
|
|
28
|
-
readonly
|
|
48
|
+
readonly generationContext: readonly WorkflowTaskResult[];
|
|
29
49
|
readonly designModelConfig: ModelConfig;
|
|
30
|
-
readonly
|
|
50
|
+
readonly workflowCwd: string;
|
|
51
|
+
readonly referencesBrief?: string;
|
|
52
|
+
readonly importContext?: string;
|
|
31
53
|
};
|
|
32
54
|
|
|
33
55
|
export async function refineOpenClaudeDesign(options: RefineOptions): Promise<{ readonly latestDesign: string; readonly approvedForExport: boolean; readonly refinementCount: number; }> {
|
|
34
|
-
const { designContext, prompt, outputType, maxRefinements, previewPath, previewFileUrl, artifactDir, browserBootstrapRules, designSystem, designModelConfig,
|
|
35
|
-
|
|
56
|
+
const { designContext, prompt, outputType, maxRefinements, previewPath, previewFileUrl, artifactDir, browserBootstrapRules, designSystem, designModelConfig, workflowCwd } = options;
|
|
57
|
+
const referencesBrief = options.referencesBrief ?? "";
|
|
58
|
+
const importContext = options.importContext ?? "";
|
|
59
|
+
let latestDesign = "";
|
|
60
|
+
let latestGenerateSessionFile: string | undefined;
|
|
61
|
+
let latestUserFeedbackSessionFile: string | undefined;
|
|
62
|
+
let pendingFeedback: PreviewFeedback | undefined;
|
|
36
63
|
let approvedForExport = false;
|
|
37
64
|
let refinementCount = 0;
|
|
38
|
-
for (let iteration = 1; iteration <= maxRefinements; iteration += 1) {
|
|
39
|
-
refinementCount = iteration;
|
|
40
65
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
[
|
|
65
|
-
"output_format",
|
|
66
|
-
[
|
|
67
|
-
"Set ready_for_export=true only when the current preview needs no further refinement before export.",
|
|
68
|
-
"Set ready_for_export=false and populate required_changes when another polish iteration is needed.",
|
|
69
|
-
].join("\n"),
|
|
70
|
-
],
|
|
71
|
-
]),
|
|
72
|
-
previous: { name: "current-design", text: latestDesign },
|
|
73
|
-
...refinementDecisionConfig,
|
|
74
|
-
});
|
|
75
|
-
|
|
76
|
-
const feedbackDecision = refinementDecisionFromResult(feedback);
|
|
77
|
-
if (feedbackDecision.ready_for_export) {
|
|
78
|
-
approvedForExport = true;
|
|
79
|
-
break;
|
|
66
|
+
for (let iteration = 1; iteration <= maxRefinements; iteration += 1) {
|
|
67
|
+
const generateStageName = `generate-${iteration}`;
|
|
68
|
+
const generatePrompt = pendingFeedback === undefined
|
|
69
|
+
? buildInitialGeneratePrompt({
|
|
70
|
+
prompt,
|
|
71
|
+
outputType,
|
|
72
|
+
previewPath,
|
|
73
|
+
designSystem,
|
|
74
|
+
referencesBrief,
|
|
75
|
+
importContext,
|
|
76
|
+
})
|
|
77
|
+
: buildGenerateRevisionPrompt({
|
|
78
|
+
prompt,
|
|
79
|
+
outputType,
|
|
80
|
+
previewPath,
|
|
81
|
+
designSystem,
|
|
82
|
+
latestDesign,
|
|
83
|
+
referencesBrief,
|
|
84
|
+
importContext,
|
|
85
|
+
feedback: pendingFeedback,
|
|
86
|
+
});
|
|
87
|
+
if (pendingFeedback !== undefined) {
|
|
88
|
+
assertUserAnnotationsThreaded(generatePrompt, [pendingFeedback], generateStageName);
|
|
80
89
|
}
|
|
81
90
|
|
|
82
|
-
const
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
[
|
|
88
|
-
"role",
|
|
89
|
-
"You are a staff product manager with deep design and engineering empathy collecting actionable refinement feedback from the user about the rendered HTML preview. You call out bs because the user is your partner, not your boss; you want to get to a great design together, and that means being honest about what you don't like and what the user won't like. You are user-experience-obsessed.",
|
|
90
|
-
],
|
|
91
|
-
[
|
|
92
|
-
"objective",
|
|
93
|
-
`Critique the current ${outputType} for: ${prompt}. Produce the formal impeccable critique report. Apply the impeccable \`critique\` sub-skill to run the formal two-pass review against the live HTML preview.`,
|
|
94
|
-
],
|
|
95
|
-
["preview_path", previewPath],
|
|
96
|
-
["current_design_and_feedback", "{previous}"],
|
|
97
|
-
[
|
|
98
|
-
"instructions",
|
|
99
|
-
[
|
|
100
|
-
"1. Read the HTML at preview_path and ground every finding in concrete element/selector references.",
|
|
101
|
-
"2. Return concrete fixes only; avoid generic praise or non-actionable subjective notes.",
|
|
102
|
-
"3. Call out every DESIGN.md conflict and every missing state explicitly.",
|
|
103
|
-
].join("\n"),
|
|
104
|
-
],
|
|
105
|
-
[
|
|
106
|
-
"output_format",
|
|
107
|
-
[
|
|
108
|
-
"Markdown with sections in this order:",
|
|
109
|
-
"1. AI-slop verdict (PASS or FAIL with the specific tells)",
|
|
110
|
-
"2. Heuristic scores (table: heuristic | 0–4)",
|
|
111
|
-
"3. Cognitive load failure count (0–8) with named failures",
|
|
112
|
-
"4. Issues table: Issue | Evidence (selector/line) | Impact | Recommended fix | Severity P0–P3",
|
|
113
|
-
"5. Questions worth answering before shipping",
|
|
114
|
-
].join("\n"),
|
|
115
|
-
],
|
|
116
|
-
]),
|
|
117
|
-
previous: [
|
|
118
|
-
{ name: "current-design", text: latestDesign },
|
|
119
|
-
feedback,
|
|
120
|
-
],
|
|
121
|
-
...designModelConfig,
|
|
122
|
-
},
|
|
123
|
-
{
|
|
124
|
-
name: `screenshot-${iteration}`,
|
|
125
|
-
task: taggedPrompt([
|
|
126
|
-
[
|
|
127
|
-
"role",
|
|
128
|
-
"You are a staff QA engineer with design expertise.",
|
|
129
|
-
],
|
|
130
|
-
[
|
|
131
|
-
"objective",
|
|
132
|
-
`Validate visual implementation risks for: ${prompt}. Apply the impeccable \`audit + live\` sub-skills to run a live audit against the rendered HTML preview, validating or invalidating every visual risk with evidence from the actual rendered page in a real browser, not just the source code.`,
|
|
133
|
-
],
|
|
134
|
-
["preview_path", previewPath],
|
|
135
|
-
["preview_file_url", previewFileUrl],
|
|
136
|
-
["current_design_and_feedback", "{previous}"],
|
|
137
|
-
[
|
|
138
|
-
"browser_use_guidelines",
|
|
139
|
-
browserBootstrapRules,
|
|
140
|
-
],
|
|
141
|
-
[
|
|
142
|
-
"instructions",
|
|
143
|
-
[
|
|
144
|
-
`1. Attempt rendering verification via the playwright-cli skill: \`playwright-cli open ${previewFileUrl}\`. If that reports a missing browser executable, follow the bootstrap rules and retry once.`,
|
|
145
|
-
`2. Then run \`playwright-cli resize 360 800\`, \`playwright-cli screenshot --filename=${join(artifactDir, `mobile-${iteration}.png`)}\`, \`playwright-cli resize 1440 900\`, \`playwright-cli screenshot --filename=${join(artifactDir, `desktop-${iteration}.png`)}\`.`,
|
|
146
|
-
"3. Check: contrast (WCAG AA), overflow, spacing rhythm, alignment, breakpoint behavior, empty/loading/error states, keyboard/pointer affordances, focus rings, prefers-reduced-motion.",
|
|
147
|
-
"4. If `playwright-cli` is unavailable or browser bootstrap fails, perform a static design review of the HTML source and mark every finding as `needs-rendering-verification`.",
|
|
148
|
-
"5. Distinguish confirmed visual issues from risks that need rendering verification. Never fabricate rendered evidence.",
|
|
149
|
-
].join("\n"),
|
|
150
|
-
],
|
|
151
|
-
[
|
|
152
|
-
"output_format",
|
|
153
|
-
"Markdown sections: Tooling used | Confirmed issues (with screenshot refs) | Needs rendering verification | Suggested fixes | Audit scores (0–4 per impeccable audit dimension).",
|
|
154
|
-
],
|
|
155
|
-
]),
|
|
156
|
-
previous: [
|
|
157
|
-
{ name: "current-design", text: latestDesign },
|
|
158
|
-
feedback,
|
|
159
|
-
],
|
|
160
|
-
...designModelConfig,
|
|
161
|
-
},
|
|
162
|
-
],
|
|
163
|
-
{ task: prompt },
|
|
164
|
-
);
|
|
165
|
-
|
|
166
|
-
const applied = await designContext.task(`apply-changes-${iteration}`, {
|
|
167
|
-
prompt: taggedPrompt([
|
|
168
|
-
[
|
|
169
|
-
"role",
|
|
170
|
-
"You are an opinionated staff design engineer.",
|
|
171
|
-
],
|
|
172
|
-
[
|
|
173
|
-
"objective",
|
|
174
|
-
`Produce the next ${outputType} revision for: ${prompt}. Update the HTML file in place; do not branch the artifact. Apply the impeccable \`polish\` sub-skill to methodically apply the required changes, addressing every critique finding and screenshot-validated issue with surgical precision. This is not a redesign; it's a focused polish iteration to get from the current design to an export-ready state in one step.`,
|
|
175
|
-
],
|
|
176
|
-
["design_system", designSystem],
|
|
177
|
-
["preview_artifact_path", previewPath],
|
|
178
|
-
["revision_context", "{previous}"],
|
|
179
|
-
[
|
|
180
|
-
"instructions",
|
|
181
|
-
[
|
|
182
|
-
"1. Read the current HTML at preview_artifact_path with your file-read tool.",
|
|
183
|
-
`2. Apply user feedback, critique findings, screenshot/visual QA findings, and DESIGN.md constraints together. Overwrite ${previewPath} with the revised HTML (full file rewrite, not patches — the artifact must always be self-contained).`,
|
|
184
|
-
"3. Preserve strong existing design decisions unless a finding requires change.",
|
|
185
|
-
"4. Resolve conflicting feedback explicitly; choose the safest DESIGN.md-aligned option and note the trade-off.",
|
|
186
|
-
"5. Update states, accessibility, responsiveness, and HTML implementation comments when changes affect them.",
|
|
187
|
-
"6. After writing, return a short markdown summary listing the changes, trade-offs, and remaining questions — do NOT paste the HTML body.",
|
|
188
|
-
].join("\n"),
|
|
189
|
-
],
|
|
190
|
-
[
|
|
191
|
-
"output_format",
|
|
192
|
-
[
|
|
193
|
-
"Markdown with headings:",
|
|
194
|
-
"1. Revised artifact (path only)",
|
|
195
|
-
"2. Changes applied (bullet list, each tied to a critique or screenshot finding)",
|
|
196
|
-
"3. Trade-offs / conflicts resolved",
|
|
197
|
-
"4. Remaining questions",
|
|
198
|
-
].join("\n"),
|
|
199
|
-
],
|
|
200
|
-
]),
|
|
201
|
-
previous: [
|
|
202
|
-
{ name: "current-design", text: latestDesign },
|
|
203
|
-
feedback,
|
|
204
|
-
...validation,
|
|
205
|
-
],
|
|
91
|
+
const generated = await designContext.task(generateStageName, {
|
|
92
|
+
prompt: generatePrompt,
|
|
93
|
+
previous: pendingFeedback === undefined
|
|
94
|
+
? options.generationContext
|
|
95
|
+
: { name: "current-design", text: latestDesign },
|
|
206
96
|
...designModelConfig,
|
|
97
|
+
...forkContinuationOptions(latestGenerateSessionFile),
|
|
207
98
|
});
|
|
208
|
-
latestDesign =
|
|
99
|
+
latestDesign = generated.text;
|
|
100
|
+
latestGenerateSessionFile = generated.sessionFile ?? latestGenerateSessionFile;
|
|
101
|
+
refinementCount = iteration;
|
|
209
102
|
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
"role",
|
|
216
|
-
"You are a staff product manager with expertise in design. Re-open the revised HTML preview so the user can review the latest iteration.",
|
|
217
|
-
],
|
|
218
|
-
[
|
|
219
|
-
"objective",
|
|
220
|
-
`Show the user the revised preview after iteration ${iteration}/${maxRefinements} and capture any new annotated feedback for the next loop.`,
|
|
221
|
-
],
|
|
222
|
-
["preview_path", previewPath],
|
|
223
|
-
["preview_file_url", previewFileUrl],
|
|
224
|
-
[
|
|
225
|
-
"browser_use_bootstrap",
|
|
103
|
+
const userFeedbackResult = await designContext
|
|
104
|
+
.task(`user-feedback-${iteration}`, {
|
|
105
|
+
prompt: buildLivePreviewDisplayPrompt({
|
|
106
|
+
previewPath,
|
|
107
|
+
previewFileUrl,
|
|
226
108
|
browserBootstrapRules,
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
[
|
|
231
|
-
`1. If \`playwright-cli\` is available, run \`playwright-cli open ${previewFileUrl}\`. If that reports a missing browser executable, follow the bootstrap rules and retry once.`,
|
|
232
|
-
"2. Then run `playwright-cli snapshot` and, for interactive review, `playwright-cli show --annotate`; otherwise ask the user to provide feedback inline.",
|
|
233
|
-
`3. If \`playwright-cli\` is unavailable or browser bootstrap fails, surface the path clearly: ${previewPath} (URL: ${previewFileUrl}).`,
|
|
234
|
-
"4. Return any captured annotations as structured notes the next user-feedback step can read.",
|
|
235
|
-
"5. Do not block on unavailable tooling.",
|
|
236
|
-
].join("\n"),
|
|
237
|
-
],
|
|
238
|
-
[
|
|
239
|
-
"output_format",
|
|
240
|
-
"Markdown with: `display_method`, `preview_path`, `annotated_snapshot` (if any), `user_notes` (if any), `next_action_hint`.",
|
|
241
|
-
],
|
|
242
|
-
]),
|
|
109
|
+
iteration,
|
|
110
|
+
maxRefinements,
|
|
111
|
+
}),
|
|
243
112
|
...designModelConfig,
|
|
113
|
+
...forkContinuationOptions(
|
|
114
|
+
latestUserFeedbackSessionFile ?? latestGenerateSessionFile,
|
|
115
|
+
),
|
|
244
116
|
})
|
|
245
117
|
.catch(() => undefined);
|
|
246
|
-
}
|
|
247
118
|
|
|
119
|
+
latestUserFeedbackSessionFile =
|
|
120
|
+
userFeedbackResult?.sessionFile ?? latestUserFeedbackSessionFile;
|
|
121
|
+
const feedback = toPreviewFeedback({
|
|
122
|
+
iteration,
|
|
123
|
+
stageName: `user-feedback-${iteration}`,
|
|
124
|
+
result: userFeedbackResult,
|
|
125
|
+
});
|
|
126
|
+
persistPreviewFeedback({ artifactDir, workflowCwd, feedback });
|
|
127
|
+
|
|
128
|
+
if (!hasMeaningfulFeedback(feedback)) {
|
|
129
|
+
approvedForExport = true;
|
|
130
|
+
break;
|
|
131
|
+
}
|
|
132
|
+
pendingFeedback = feedback;
|
|
133
|
+
}
|
|
248
134
|
|
|
249
135
|
return { latestDesign, approvedForExport, refinementCount };
|
|
250
136
|
}
|
|
251
137
|
|
|
138
|
+
function buildInitialGeneratePrompt(args: {
|
|
139
|
+
readonly prompt: string;
|
|
140
|
+
readonly outputType: string;
|
|
141
|
+
readonly previewPath: string;
|
|
142
|
+
readonly designSystem: string;
|
|
143
|
+
readonly referencesBrief: string;
|
|
144
|
+
readonly importContext: string;
|
|
145
|
+
}): string {
|
|
146
|
+
return taggedPrompt([
|
|
147
|
+
["role", "You are an opinionated staff design engineer."],
|
|
148
|
+
[
|
|
149
|
+
"objective",
|
|
150
|
+
`Generate the first revision of a production-ready ${args.outputType} for: ${args.prompt}. Write it to disk as an interactive HTML preview the user can open in a browser. Apply the impeccable \`craft\` sub-skill to build the design with deliberate ordering and impeccable attention to detail. Every design decision must trace back to the brief, and every visual trait must be justified by the references, design system, or reference context.`,
|
|
151
|
+
],
|
|
152
|
+
["design_brief", args.prompt],
|
|
153
|
+
["design_system", args.designSystem],
|
|
154
|
+
["reference_context", args.importContext],
|
|
155
|
+
["reference_inspiration", args.referencesBrief],
|
|
156
|
+
["reference_precedence", REFERENCE_PRECEDENCE],
|
|
157
|
+
["preview_artifact_path", args.previewPath],
|
|
158
|
+
["html_rules", HTML_PREVIEW_RULES],
|
|
159
|
+
["anti_design_slop_rules", ANTI_SLOP_RULES],
|
|
160
|
+
[
|
|
161
|
+
"instructions",
|
|
162
|
+
[
|
|
163
|
+
`1. Create the HTML artifact at exactly this path: ${args.previewPath}.`,
|
|
164
|
+
"2. Follow the `<reference_precedence>` rule: user-provided references in `<reference_context>` win over DESIGN.md/PRODUCT.md where they conflict; DESIGN.md fills gaps the references do not cover.",
|
|
165
|
+
"3. Heavily reference the `<reference_inspiration>` block while staying consistent with the imported user references; never copy a reference wholesale or invent traits it does not contain.",
|
|
166
|
+
`4. Build the artifact as the requested output_type (${args.outputType}). For prototypes/pages, render full layouts with realistic content. For components, render the component in 3+ representative contexts.`,
|
|
167
|
+
"5. Include structure, states, accessibility behavior, responsive behavior, and integration notes — but keep them in HTML comments inside the file so the rendered preview stays clean.",
|
|
168
|
+
"6. Do not use generic placeholder language when project conventions are available.",
|
|
169
|
+
"7. After writing the file, return a short markdown summary (NOT the HTML body) describing what you built, decisions made, and assumptions left for the user to confirm.",
|
|
170
|
+
].join("\n"),
|
|
171
|
+
],
|
|
172
|
+
[
|
|
173
|
+
"output_format",
|
|
174
|
+
[
|
|
175
|
+
"Return markdown with the headings below. DO NOT paste the HTML; the file at preview_artifact_path is the artifact.",
|
|
176
|
+
"1. Artifact overview",
|
|
177
|
+
"2. Files written (must include the absolute path to preview.html)",
|
|
178
|
+
"3. UI structure and states (referenced by HTML section IDs)",
|
|
179
|
+
"4. Accessibility and responsive behavior",
|
|
180
|
+
"5. Implementation notes",
|
|
181
|
+
"6. Assumptions / open questions",
|
|
182
|
+
].join("\n"),
|
|
183
|
+
],
|
|
184
|
+
]);
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
function buildGenerateRevisionPrompt(args: {
|
|
188
|
+
readonly prompt: string;
|
|
189
|
+
readonly outputType: string;
|
|
190
|
+
readonly previewPath: string;
|
|
191
|
+
readonly designSystem: string;
|
|
192
|
+
readonly latestDesign: string;
|
|
193
|
+
readonly referencesBrief: string;
|
|
194
|
+
readonly importContext: string;
|
|
195
|
+
readonly feedback: PreviewFeedback;
|
|
196
|
+
}): string {
|
|
197
|
+
const annotations = userAnnotationsBlock([args.feedback]);
|
|
198
|
+
return taggedPrompt([
|
|
199
|
+
["role", "You are an opinionated staff design engineer."],
|
|
200
|
+
[
|
|
201
|
+
"objective",
|
|
202
|
+
`Generate the next ${args.outputType} revision for: ${args.prompt}. Update the HTML preview in place using only the user's captured feedback from the latest live review. Apply the impeccable \`craft\` and \`polish\` sub-skills with deliberate restraint: this is a focused revision, not an internal critique pass.`,
|
|
203
|
+
],
|
|
204
|
+
["design_system", args.designSystem],
|
|
205
|
+
["reference_inspiration", args.referencesBrief],
|
|
206
|
+
["reference_context", args.importContext],
|
|
207
|
+
["reference_precedence", REFERENCE_PRECEDENCE],
|
|
208
|
+
["preview_artifact_path", args.previewPath],
|
|
209
|
+
["user_feedback", annotations.text],
|
|
210
|
+
["current_design_summary", args.latestDesign],
|
|
211
|
+
["html_rules", HTML_PREVIEW_RULES],
|
|
212
|
+
["anti_design_slop_rules", ANTI_SLOP_RULES],
|
|
213
|
+
[
|
|
214
|
+
"instructions",
|
|
215
|
+
[
|
|
216
|
+
"1. Read the current HTML at preview_artifact_path with your file-read tool.",
|
|
217
|
+
"2. Treat `<user_feedback>` as the only refinement brief. Do not invent separate critique, screenshot, audit, or gate findings.",
|
|
218
|
+
"3. Every user note or accepted live change MUST be visibly addressed in the revised preview, or explicitly explained as a conflict with DESIGN.md/reference precedence in your summary.",
|
|
219
|
+
`4. Overwrite ${args.previewPath} with the revised self-contained HTML file. Do not branch the artifact and do not create extra preview files.`,
|
|
220
|
+
"5. Preserve strong existing design decisions unless the user feedback requires a change.",
|
|
221
|
+
"6. After writing, return a concise markdown summary of what changed and any user feedback you could not apply. Do NOT paste the HTML body.",
|
|
222
|
+
].join("\n"),
|
|
223
|
+
],
|
|
224
|
+
[
|
|
225
|
+
"output_format",
|
|
226
|
+
[
|
|
227
|
+
"Markdown with headings:",
|
|
228
|
+
"1. Revised artifact (path only)",
|
|
229
|
+
"2. User feedback addressed (each note/live change → how it was applied, or why it was deferred/conflicts)",
|
|
230
|
+
"3. Changes applied",
|
|
231
|
+
"4. Trade-offs / unresolved user feedback",
|
|
232
|
+
].join("\n"),
|
|
233
|
+
],
|
|
234
|
+
]);
|
|
235
|
+
}
|
|
236
|
+
|
|
252
237
|
type ExportOptions = {
|
|
253
238
|
readonly designContext: DesignContext;
|
|
254
239
|
readonly prompt: string;
|
|
@@ -261,172 +246,89 @@ type ExportOptions = {
|
|
|
261
246
|
readonly designSystem: string;
|
|
262
247
|
readonly latestDesign: string;
|
|
263
248
|
readonly designModelConfig: ModelConfig;
|
|
264
|
-
readonly exportGateDecisionConfig: ModelConfig;
|
|
265
249
|
};
|
|
266
250
|
|
|
267
251
|
export async function exportOpenClaudeDesign(options: ExportOptions): Promise<{ readonly latestDesign: string; readonly handoff: WorkflowTaskResult; }> {
|
|
268
|
-
const { designContext, prompt, outputType, previewPath, previewFileUrl, specPath, specFileUrl, browserBootstrapRules, designSystem, designModelConfig
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
252
|
+
const { designContext, prompt, outputType, previewPath, previewFileUrl, specPath, specFileUrl, browserBootstrapRules, designSystem, designModelConfig } = options;
|
|
253
|
+
const latestDesign = options.latestDesign;
|
|
254
|
+
|
|
255
|
+
const handoff = await designContext.task("exporter", {
|
|
256
|
+
prompt: taggedPrompt([
|
|
257
|
+
["role", "You are an opinionated staff design engineer."],
|
|
258
|
+
[
|
|
259
|
+
"objective",
|
|
260
|
+
`Export the final ${outputType} for "${prompt}" as a rich HTML spec the engineering team can read directly in a browser. The spec must embed or link the approved preview so reviewers see exactly what is being implemented. Apply the impeccable \`document\` sub-skill to produce a rich HTML spec that bundles the approved preview together with implementation guidance for another design/frontend engineer to implement.`,
|
|
261
|
+
],
|
|
262
|
+
["design_system", designSystem],
|
|
263
|
+
["preview_artifact_path", previewPath],
|
|
264
|
+
["spec_artifact_path", specPath],
|
|
265
|
+
["final_design_summary", "{previous}"],
|
|
266
|
+
[
|
|
267
|
+
"instructions",
|
|
282
268
|
[
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
],
|
|
269
|
+
`1. Read the approved HTML at preview_artifact_path. Use it as the canonical source of truth for the agreed design.`,
|
|
270
|
+
`2. Use the Write tool to create a rich HTML document at exactly: ${specPath}. The spec must be a single self-contained HTML5 file.`,
|
|
271
|
+
"3. The spec MUST contain, in order: (a) a sticky header with the design title + status + run id, (b) an Executive Summary section, (c) a 'Live Preview' section that EMBEDS the approved design via either an `<iframe srcdoc=\"...\">` containing the full preview HTML or a side-by-side rendered copy of the preview inside an `<article class=\"preview-frame\">` container, (d) the six DESIGN.md sections (Overview, Colors, Typography, Elevation, Components, Do's and Don'ts) rendered with swatches/tables/code blocks, (e) Implementation handoff (Recommended files + components | Implementation steps | Usage example | Accessibility & responsive checklist | Validation commands | Known limitations), (f) Appendix linking to the raw preview file path.",
|
|
272
|
+
"4. Style the spec itself with care: high-density legible typography, generous whitespace, code blocks with monospaced font, swatches that render with the actual hex/oklch values, copy-to-clipboard hints in HTML comments.",
|
|
273
|
+
`5. Embed the absolute preview path (${previewPath}) and file URL (${previewFileUrl}) prominently so the user can open the live preview separately.`,
|
|
274
|
+
"6. Preserve assumptions and known limitations so implementers do not treat uncertain items as facts.",
|
|
275
|
+
"7. Do not introduce design requirements that were absent from the final design or DESIGN.md.",
|
|
276
|
+
"8. After writing, return a concise markdown summary of what is in the spec (NOT the HTML).",
|
|
277
|
+
].join("\n"),
|
|
278
|
+
],
|
|
279
|
+
["html_rules", HTML_PREVIEW_RULES],
|
|
280
|
+
["anti_design_slop_rules", ANTI_SLOP_RULES],
|
|
281
|
+
[
|
|
282
|
+
"output_format",
|
|
292
283
|
[
|
|
293
|
-
"
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
"role",
|
|
310
|
-
"You are an opinionated staff design engineer. Apply the impeccable `harden` sub-skill to remove blocking findings without redesigning.",
|
|
311
|
-
],
|
|
312
|
-
[
|
|
313
|
-
"objective",
|
|
314
|
-
`Remove the blocking findings from the HTML preview without broad redesign. Output: ${prompt}.`,
|
|
315
|
-
],
|
|
316
|
-
[
|
|
317
|
-
"impeccable_skill",
|
|
318
|
-
"harden — make the artifact production-ready against real-world data extremes, error scenarios, internationalization, and device/context variability. Fix only what is broken; do not redesign.",
|
|
319
|
-
],
|
|
320
|
-
["blocking_findings", preExport.text],
|
|
321
|
-
["design_system", designSystem],
|
|
322
|
-
["preview_artifact_path", previewPath],
|
|
323
|
-
["current_final_design_summary", "{previous}"],
|
|
324
|
-
[
|
|
325
|
-
"instructions",
|
|
326
|
-
[
|
|
327
|
-
"1. Read the HTML at preview_artifact_path and apply only the fixes needed to clear the blocking findings.",
|
|
328
|
-
`2. Overwrite ${previewPath} with the corrected HTML (full file rewrite, still self-contained).`,
|
|
329
|
-
"3. Preserve DESIGN.md alignment and previously approved decisions.",
|
|
330
|
-
"4. Explain each forced change and how it resolves a specific blocking finding.",
|
|
331
|
-
"5. If a blocker cannot be resolved with available context, state the remaining risk plainly and propose a follow-up.",
|
|
332
|
-
].join("\n"),
|
|
333
|
-
],
|
|
334
|
-
[
|
|
335
|
-
"output_format",
|
|
336
|
-
"Markdown with sections: Corrected final design (path) | Forced fixes applied (table: finding → fix) | Remaining risk.",
|
|
337
|
-
],
|
|
338
|
-
]),
|
|
339
|
-
previous: { name: "final-design", text: latestDesign },
|
|
340
|
-
...designModelConfig,
|
|
341
|
-
});
|
|
342
|
-
latestDesign = forcedFix.text;
|
|
343
|
-
}
|
|
284
|
+
"Return markdown with headings (NOT the HTML):",
|
|
285
|
+
"1. Spec written to (absolute path)",
|
|
286
|
+
"2. Sections included",
|
|
287
|
+
"3. How to open the spec (playwright-cli command + manual fallback path)",
|
|
288
|
+
"4. Recommended files and components",
|
|
289
|
+
"5. Implementation steps",
|
|
290
|
+
"6. Usage example",
|
|
291
|
+
"7. Accessibility / responsive checklist",
|
|
292
|
+
"8. Validation commands",
|
|
293
|
+
"9. Known limitations",
|
|
294
|
+
].join("\n"),
|
|
295
|
+
],
|
|
296
|
+
]),
|
|
297
|
+
previous: { name: "final-design", text: latestDesign },
|
|
298
|
+
...designModelConfig,
|
|
299
|
+
});
|
|
344
300
|
|
|
345
|
-
|
|
301
|
+
await designContext
|
|
302
|
+
.task("final-display", {
|
|
346
303
|
prompt: taggedPrompt([
|
|
347
|
-
[
|
|
348
|
-
"role",
|
|
349
|
-
"You are an opinionated staff design engineer.",
|
|
350
|
-
],
|
|
304
|
+
["role", "You are an opinionated staff design engineer."],
|
|
351
305
|
[
|
|
352
306
|
"objective",
|
|
353
|
-
|
|
307
|
+
"Make the rich HTML spec visible to the user. Open the final spec.html with the playwright-cli skill's `playwright-cli` command so the user can review the agreed design and implementation handoff. This is post-export — do NOT solicit change requests; if the user wants more changes, tell them to re-run the workflow. Degrade gracefully if browser automation is unavailable.",
|
|
354
308
|
],
|
|
355
|
-
["
|
|
356
|
-
["
|
|
357
|
-
["
|
|
358
|
-
["
|
|
309
|
+
["spec_path", specPath],
|
|
310
|
+
["spec_file_url", specFileUrl],
|
|
311
|
+
["preview_path", previewPath],
|
|
312
|
+
["preview_file_url", previewFileUrl],
|
|
313
|
+
["browser_use_guidelines", browserBootstrapRules],
|
|
359
314
|
[
|
|
360
315
|
"instructions",
|
|
361
316
|
[
|
|
362
|
-
|
|
363
|
-
`2.
|
|
364
|
-
"3.
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
"6. Preserve assumptions and known limitations so implementers do not treat uncertain items as facts.",
|
|
368
|
-
"7. Do not introduce design requirements that were absent from the final design or DESIGN.md.",
|
|
369
|
-
"8. After writing, return a concise markdown summary of what is in the spec (NOT the HTML).",
|
|
317
|
+
"1. Probe for `playwright-cli` availability using the bootstrap rules above.",
|
|
318
|
+
`2. If available, run \`playwright-cli open ${specFileUrl}\`. If that reports a missing browser executable, follow the bootstrap rules and retry once, then \`playwright-cli snapshot\`.`,
|
|
319
|
+
"3. Do NOT run `show --annotate` or otherwise invite change requests: export is done and there is no further refinement pass. If the user wants changes, tell them to re-run `/workflow open-claude-design`.",
|
|
320
|
+
`4. Always print, prominently, the absolute paths so the user can open them manually:\n - Final spec: ${specPath}\n - Approved preview: ${previewPath}`,
|
|
321
|
+
"5. Do not block the workflow; return a structured summary even if no tooling worked.",
|
|
370
322
|
].join("\n"),
|
|
371
323
|
],
|
|
372
|
-
["html_rules", HTML_PREVIEW_RULES],
|
|
373
|
-
["anti_design_slop_rules", ANTI_SLOP_RULES],
|
|
374
324
|
[
|
|
375
325
|
"output_format",
|
|
376
|
-
|
|
377
|
-
"Return markdown with headings (NOT the HTML):",
|
|
378
|
-
"1. Spec written to (absolute path)",
|
|
379
|
-
"2. Sections included",
|
|
380
|
-
"3. How to open the spec (playwright-cli command + manual fallback path)",
|
|
381
|
-
"4. Recommended files and components",
|
|
382
|
-
"5. Implementation steps",
|
|
383
|
-
"6. Usage example",
|
|
384
|
-
"7. Accessibility / responsive checklist",
|
|
385
|
-
"8. Validation commands",
|
|
386
|
-
"9. Known limitations",
|
|
387
|
-
].join("\n"),
|
|
326
|
+
"Markdown with: `display_method` | `spec_path` | `preview_path` | `manual_open_instructions` | `next_action_hint` (how to re-run the workflow for further changes).",
|
|
388
327
|
],
|
|
389
328
|
]),
|
|
390
|
-
previous: { name: "final-design", text: latestDesign },
|
|
391
329
|
...designModelConfig,
|
|
392
|
-
})
|
|
393
|
-
|
|
394
|
-
// Final display attempt: open the spec.html for the user (or surface its path).
|
|
395
|
-
await designContext
|
|
396
|
-
.task("final-display", {
|
|
397
|
-
prompt: taggedPrompt([
|
|
398
|
-
[
|
|
399
|
-
"role",
|
|
400
|
-
"You are an opinionated staff design engineer.",
|
|
401
|
-
],
|
|
402
|
-
[
|
|
403
|
-
"objective",
|
|
404
|
-
"Make the rich HTML spec visible to the user. Open the final spec.html with the playwright-cli skill's `playwright-cli` command so the user can review the agreed design and implementation handoff. Degrade gracefully if browser automation is unavailable.",
|
|
405
|
-
],
|
|
406
|
-
["spec_path", specPath],
|
|
407
|
-
["spec_file_url", specFileUrl],
|
|
408
|
-
["preview_path", previewPath],
|
|
409
|
-
["preview_file_url", previewFileUrl],
|
|
410
|
-
["browser_use_guidelines", browserBootstrapRules],
|
|
411
|
-
[
|
|
412
|
-
"instructions",
|
|
413
|
-
[
|
|
414
|
-
"1. Probe for `playwright-cli` availability using the bootstrap rules above.",
|
|
415
|
-
`2. If available, run \`playwright-cli open ${specFileUrl}\`. If that reports a missing browser executable, follow the bootstrap rules and retry once.`,
|
|
416
|
-
"3. Then run `playwright-cli snapshot` and, for interactive review, `playwright-cli show --annotate` so the user can capture any final notes.",
|
|
417
|
-
`4. Always print, prominently, the absolute paths so the user can open them manually:\n - Final spec: ${specPath}\n - Approved preview: ${previewPath}`,
|
|
418
|
-
"5. Do not block the workflow; return a structured summary even if no tooling worked.",
|
|
419
|
-
].join("\n"),
|
|
420
|
-
],
|
|
421
|
-
[
|
|
422
|
-
"output_format",
|
|
423
|
-
"Markdown with: `display_method` | `spec_path` | `preview_path` | `annotated_snapshot` (if any) | `user_notes` (if any) | `manual_open_instructions`.",
|
|
424
|
-
],
|
|
425
|
-
]),
|
|
426
|
-
...designModelConfig,
|
|
427
|
-
})
|
|
428
|
-
.catch(() => undefined);
|
|
429
|
-
|
|
330
|
+
})
|
|
331
|
+
.catch(() => undefined);
|
|
430
332
|
|
|
431
333
|
return { latestDesign, handoff };
|
|
432
334
|
}
|