@bastani/atomic 0.9.16-alpha.7 → 0.9.16-alpha.8
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 +19 -0
- package/dist/builtin/intercom/CHANGELOG.md +6 -0
- package/dist/builtin/intercom/README.md +4 -4
- package/dist/builtin/intercom/broker/broker.ts +617 -22
- package/dist/builtin/intercom/broker/client-message-validation.ts +9 -0
- package/dist/builtin/intercom/broker/client.ts +200 -10
- package/dist/builtin/intercom/broker/pending-send-registry.ts +4 -0
- package/dist/builtin/intercom/broker/send-handler.ts +90 -36
- package/dist/builtin/intercom/broker/send-signature.ts +20 -8
- package/dist/builtin/intercom/group.ts +85 -0
- package/dist/builtin/intercom/index.bundle.mjs +680 -53
- package/dist/builtin/intercom/package.json +1 -1
- package/dist/builtin/intercom/session-target.ts +54 -0
- package/dist/builtin/intercom/skills/intercom/SKILL.md +18 -3
- package/dist/builtin/intercom/source-ownership.ts +31 -0
- package/dist/builtin/intercom/types.ts +115 -0
- package/dist/builtin/mcp/index.bundle.mjs +109 -35
- package/dist/builtin/mcp/package.json +1 -1
- package/dist/builtin/subagents/package.json +1 -1
- package/dist/builtin/subagents/src/extension/index.bundle.mjs +173 -51
- package/dist/builtin/web-access/index.bundle.mjs +109 -35
- package/dist/builtin/web-access/package.json +1 -1
- package/dist/builtin/workflows/CHANGELOG.md +15 -0
- package/dist/builtin/workflows/README.md +40 -37
- package/dist/builtin/workflows/builtin/adversarial-verification.js +13 -0
- package/dist/builtin/workflows/builtin/{shared-prompts.ts → chunk-0x6e303p.js} +133 -154
- package/dist/builtin/workflows/builtin/chunk-29wrp38a.js +199 -0
- package/dist/builtin/workflows/builtin/chunk-2dqb5s2q.js +602 -0
- package/dist/builtin/workflows/builtin/chunk-4febxsv4.js +264 -0
- package/dist/builtin/workflows/builtin/chunk-5n10x7j2.js +69730 -0
- package/dist/builtin/workflows/builtin/chunk-5wgwscd0.js +4 -0
- package/dist/builtin/workflows/builtin/chunk-6fqs7c01.js +155 -0
- package/dist/builtin/workflows/builtin/chunk-7430zyas.js +126 -0
- package/dist/builtin/workflows/builtin/chunk-7at6dnkr.js +33 -0
- package/dist/builtin/workflows/builtin/chunk-82ha8p41.js +175 -0
- package/dist/builtin/workflows/builtin/chunk-bfkmzv9h.js +156 -0
- package/dist/builtin/workflows/builtin/chunk-c53y8bdh.js +345 -0
- package/dist/builtin/workflows/builtin/chunk-cdtd3m3w.js +529 -0
- package/dist/builtin/workflows/builtin/chunk-cg9tmks0.js +206 -0
- package/dist/builtin/workflows/builtin/chunk-hdpj1dkw.js +2447 -0
- package/dist/builtin/workflows/builtin/chunk-hzzn6adg.js +221 -0
- package/dist/builtin/workflows/builtin/chunk-nqr34qp3.js +1061 -0
- package/dist/builtin/workflows/builtin/chunk-qwzvgxnq.js +404 -0
- package/dist/builtin/workflows/builtin/chunk-qx2ptjs3.js +215 -0
- package/dist/builtin/workflows/builtin/chunk-v04c5qmd.js +1207 -0
- package/dist/builtin/workflows/builtin/chunk-wpckd35c.js +12 -0
- package/dist/builtin/workflows/builtin/chunk-x2ghn0je.js +4110 -0
- package/dist/builtin/workflows/builtin/chunk-zf28603f.js +1080 -0
- package/dist/builtin/workflows/builtin/classify-and-act.js +12 -0
- package/dist/builtin/workflows/builtin/fan-out-and-synthesize.js +10 -0
- package/dist/builtin/workflows/builtin/generate-and-filter.js +12 -0
- package/dist/builtin/workflows/builtin/goal.js +16 -0
- package/dist/builtin/workflows/builtin/index.js +49 -0
- package/dist/builtin/workflows/builtin/loop-until-done.js +12 -0
- package/dist/builtin/workflows/builtin/open-claude-design.js +11 -0
- package/dist/builtin/workflows/builtin/ralph.js +16 -0
- package/dist/builtin/workflows/builtin/steering-context.d.ts +6 -0
- package/dist/builtin/workflows/builtin/steering-context.js +7 -0
- package/dist/builtin/workflows/builtin/tournament.js +13 -0
- package/dist/builtin/workflows/package.json +10 -7
- package/dist/builtin/workflows/src/authoring/typebox-defaults.d.ts +41 -0
- package/dist/builtin/workflows/src/extension/index.bundle.mjs +1228 -428
- package/dist/builtin/workflows/src/{index.bundle.mjs → index.js} +956 -427
- package/dist/builtin/workflows/src/shared/authoring-contract-stage.d.ts +403 -0
- package/dist/builtin/workflows/src/shared/authoring-contract-ui.d.ts +327 -0
- package/dist/builtin/workflows/src/shared/budget.d.ts +67 -0
- package/dist/builtin/workflows/src/shared/workflow-authoring-types.d.ts +60 -0
- package/dist/builtin/workflows/src/shared/workflow-heartbeat-contract.d.ts +21 -0
- package/dist/core/agent-session-custom-message-commit.d.ts.map +1 -1
- package/dist/core/agent-session-custom-message-commit.js +12 -5
- package/dist/core/agent-session-custom-message-commit.js.map +1 -1
- package/dist/core/agent-session-persistent-custom-messages.d.ts.map +1 -1
- package/dist/core/agent-session-persistent-custom-messages.js +2 -0
- package/dist/core/agent-session-persistent-custom-messages.js.map +1 -1
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +2 -1
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/auth-storage.d.ts +2 -0
- package/dist/core/auth-storage.d.ts.map +1 -1
- package/dist/core/auth-storage.js +4 -0
- package/dist/core/auth-storage.js.map +1 -1
- package/dist/core/builtin-install-layout.d.ts +1 -1
- package/dist/core/builtin-install-layout.d.ts.map +1 -1
- package/dist/core/builtin-install-layout.js +1 -1
- package/dist/core/builtin-install-layout.js.map +1 -1
- package/dist/core/codex-fast-mode.d.ts +10 -7
- package/dist/core/codex-fast-mode.d.ts.map +1 -1
- package/dist/core/codex-fast-mode.js +31 -13
- package/dist/core/codex-fast-mode.js.map +1 -1
- package/dist/core/extensions/context-types.d.ts +35 -0
- package/dist/core/extensions/context-types.d.ts.map +1 -1
- package/dist/core/extensions/context-types.js.map +1 -1
- package/dist/core/extensions/index.d.ts +1 -1
- package/dist/core/extensions/index.d.ts.map +1 -1
- package/dist/core/extensions/index.js.map +1 -1
- package/dist/core/extensions/loader-virtual-modules.d.ts.map +1 -1
- package/dist/core/extensions/loader-virtual-modules.js +6 -1
- package/dist/core/extensions/loader-virtual-modules.js.map +1 -1
- package/dist/core/model-runtime.d.ts +2 -0
- package/dist/core/model-runtime.d.ts.map +1 -1
- package/dist/core/model-runtime.js +4 -0
- package/dist/core/model-runtime.js.map +1 -1
- package/dist/core/runtime-credentials.d.ts +1 -0
- package/dist/core/runtime-credentials.d.ts.map +1 -1
- package/dist/core/runtime-credentials.js +8 -0
- package/dist/core/runtime-credentials.js.map +1 -1
- package/dist/core/sdk.d.ts.map +1 -1
- package/dist/core/sdk.js +5 -5
- package/dist/core/sdk.js.map +1 -1
- package/dist/core/session-manager-storage.d.ts +2 -0
- package/dist/core/session-manager-storage.d.ts.map +1 -1
- package/dist/core/session-manager-storage.js +4 -2
- package/dist/core/session-manager-storage.js.map +1 -1
- package/dist/core/slash-commands.js +1 -1
- package/dist/core/slash-commands.js.map +1 -1
- package/dist/core/workflow-stage-admission.d.ts +6 -1
- package/dist/core/workflow-stage-admission.d.ts.map +1 -1
- package/dist/core/workflow-stage-admission.js +8 -9
- package/dist/core/workflow-stage-admission.js.map +1 -1
- package/dist/index.d.ts +0 -1
- package/dist/modes/interactive/components/footer.d.ts.map +1 -1
- package/dist/modes/interactive/components/footer.js +1 -1
- package/dist/modes/interactive/components/footer.js.map +1 -1
- package/dist/modes/interactive/interactive-autocomplete.js +1 -1
- package/dist/modes/interactive/interactive-autocomplete.js.map +1 -1
- package/dist/modes/interactive/interactive-startup.js +1 -1
- package/dist/modes/interactive/interactive-startup.js.map +1 -1
- package/dist/modes/interactive-engine/isolated-runtime.d.ts +4 -0
- package/dist/modes/interactive-engine/isolated-runtime.d.ts.map +1 -1
- package/dist/modes/interactive-engine/isolated-runtime.js +69 -10
- package/dist/modes/interactive-engine/isolated-runtime.js.map +1 -1
- package/dist/modes/rpc/rpc-client-api.d.ts +18 -2
- package/dist/modes/rpc/rpc-client-api.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-client-api.js +33 -5
- package/dist/modes/rpc/rpc-client-api.js.map +1 -1
- package/dist/modes/rpc/rpc-command-handler.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-command-handler.js +8 -4
- package/dist/modes/rpc/rpc-command-handler.js.map +1 -1
- package/dist/modes/rpc/rpc-types.d.ts +13 -0
- package/dist/modes/rpc/rpc-types.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-types.js.map +1 -1
- package/docs/intercom.md +15 -6
- package/docs/packages.md +2 -2
- package/docs/providers.md +8 -3
- package/docs/quickstart.md +2 -2
- package/docs/rpc.md +21 -4
- package/docs/settings.md +6 -4
- package/docs/subagents.md +1 -1
- package/docs/usage.md +1 -1
- package/docs/workflows.md +108 -239
- package/npm-shrinkwrap.json +32 -32
- package/package.json +9 -13
- package/dist/builtin/workflows/ambient.d.ts +0 -61
- package/dist/builtin/workflows/builtin/adversarial-verification-prompts.ts +0 -26
- package/dist/builtin/workflows/builtin/adversarial-verification-runner.ts +0 -391
- package/dist/builtin/workflows/builtin/adversarial-verification.ts +0 -34
- package/dist/builtin/workflows/builtin/classify-and-act-prompts.ts +0 -14
- package/dist/builtin/workflows/builtin/classify-and-act-runner.ts +0 -108
- package/dist/builtin/workflows/builtin/classify-and-act.ts +0 -40
- package/dist/builtin/workflows/builtin/fan-out-and-synthesize-prompts.ts +0 -14
- package/dist/builtin/workflows/builtin/fan-out-and-synthesize-runner.ts +0 -96
- package/dist/builtin/workflows/builtin/fan-out-and-synthesize.ts +0 -37
- package/dist/builtin/workflows/builtin/generate-and-filter-prompts.ts +0 -41
- package/dist/builtin/workflows/builtin/generate-and-filter-runner.ts +0 -90
- package/dist/builtin/workflows/builtin/generate-and-filter.ts +0 -31
- package/dist/builtin/workflows/builtin/goal-artifacts.ts +0 -64
- package/dist/builtin/workflows/builtin/goal-convergence.ts +0 -87
- package/dist/builtin/workflows/builtin/goal-ledger.ts +0 -139
- package/dist/builtin/workflows/builtin/goal-models.ts +0 -72
- package/dist/builtin/workflows/builtin/goal-orchestrator-prompts.ts +0 -94
- package/dist/builtin/workflows/builtin/goal-prompts.ts +0 -217
- package/dist/builtin/workflows/builtin/goal-reducer.ts +0 -176
- package/dist/builtin/workflows/builtin/goal-reports.ts +0 -76
- package/dist/builtin/workflows/builtin/goal-reverify.ts +0 -305
- package/dist/builtin/workflows/builtin/goal-review.ts +0 -139
- package/dist/builtin/workflows/builtin/goal-runner.ts +0 -504
- package/dist/builtin/workflows/builtin/goal-schemas.ts +0 -89
- package/dist/builtin/workflows/builtin/goal-types.ts +0 -164
- package/dist/builtin/workflows/builtin/goal.ts +0 -78
- package/dist/builtin/workflows/builtin/index.ts +0 -16
- package/dist/builtin/workflows/builtin/loop-until-done-prompts.ts +0 -87
- package/dist/builtin/workflows/builtin/loop-until-done-runner.ts +0 -282
- package/dist/builtin/workflows/builtin/loop-until-done.ts +0 -51
- package/dist/builtin/workflows/builtin/open-claude-design-live-protocol.ts +0 -305
- package/dist/builtin/workflows/builtin/open-claude-design-phases.ts +0 -337
- package/dist/builtin/workflows/builtin/open-claude-design-runner.ts +0 -347
- package/dist/builtin/workflows/builtin/open-claude-design-setup.ts +0 -313
- package/dist/builtin/workflows/builtin/open-claude-design-utils.ts +0 -311
- package/dist/builtin/workflows/builtin/open-claude-design.ts +0 -57
- package/dist/builtin/workflows/builtin/pattern-artifact-root.ts +0 -28
- package/dist/builtin/workflows/builtin/progress-scoring.ts +0 -230
- package/dist/builtin/workflows/builtin/ralph-core.ts +0 -449
- package/dist/builtin/workflows/builtin/ralph-forked-prompts.ts +0 -100
- package/dist/builtin/workflows/builtin/ralph-models.ts +0 -183
- package/dist/builtin/workflows/builtin/ralph-review-gate.ts +0 -103
- package/dist/builtin/workflows/builtin/ralph-reviewer-prompt.ts +0 -104
- package/dist/builtin/workflows/builtin/ralph-runner.ts +0 -459
- package/dist/builtin/workflows/builtin/ralph.ts +0 -82
- package/dist/builtin/workflows/builtin/review-convergence.ts +0 -229
- package/dist/builtin/workflows/builtin/selection-math.ts +0 -156
- package/dist/builtin/workflows/builtin/steering-context.ts +0 -51
- package/dist/builtin/workflows/builtin/tournament-prompts.ts +0 -70
- package/dist/builtin/workflows/builtin/tournament-runner.ts +0 -400
- package/dist/builtin/workflows/builtin/tournament.ts +0 -73
- package/dist/builtin/workflows/builtin/verification-criteria.ts +0 -330
- package/dist/builtin/workflows/builtin/verification-prompts.ts +0 -206
- package/dist/builtin/workflows/builtin/verification-usage.ts +0 -44
|
@@ -1,347 +0,0 @@
|
|
|
1
|
-
import type { WorkflowParallelOptions, WorkflowTaskOptions, WorkflowTaskResult, WorkflowTaskStep } from "../src/shared/types.js";
|
|
2
|
-
import {
|
|
3
|
-
REFERENCE_PRECEDENCE,
|
|
4
|
-
buildPlaywrightCliBootstrapRules,
|
|
5
|
-
discoveryDecisionSchema,
|
|
6
|
-
ensurePlaywrightCli,
|
|
7
|
-
joinResults,
|
|
8
|
-
prepareArtifactDir,
|
|
9
|
-
shouldEarlyExitForBrowser,
|
|
10
|
-
taggedPrompt,
|
|
11
|
-
} from "./open-claude-design-utils.js";
|
|
12
|
-
import { exportOpenClaudeDesign, refineOpenClaudeDesign } from "./open-claude-design-phases.js";
|
|
13
|
-
import {
|
|
14
|
-
NO_REFERENCES_BRIEF,
|
|
15
|
-
buildReferenceDiscoveryPrompt,
|
|
16
|
-
designContextPath,
|
|
17
|
-
persistDesignContext,
|
|
18
|
-
persistReferencesBrief,
|
|
19
|
-
referencesBriefPath,
|
|
20
|
-
runDiscoveryAndInit,
|
|
21
|
-
type LiveReviewGateUi,
|
|
22
|
-
} from "./open-claude-design-setup.js";
|
|
23
|
-
|
|
24
|
-
const GROUNDED_REPORTING =
|
|
25
|
-
"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.";
|
|
26
|
-
const DELEGATION_RULE =
|
|
27
|
-
"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.";
|
|
28
|
-
|
|
29
|
-
type OpenClaudeDesignOutputs = {
|
|
30
|
-
readonly output_type?: string; readonly design_system?: string; readonly artifact?: string; readonly handoff?: string;
|
|
31
|
-
readonly import_context?: string; readonly run_id?: string;
|
|
32
|
-
readonly artifact_dir?: string; readonly preview_path?: string; readonly preview_file_url?: string; readonly spec_path?: string; readonly spec_file_url?: string;
|
|
33
|
-
readonly playwright_cli_status?: string;
|
|
34
|
-
};
|
|
35
|
-
|
|
36
|
-
type OpenClaudeDesignContext = {
|
|
37
|
-
readonly cwd?: string;
|
|
38
|
-
readonly inputs: { readonly prompt: string; readonly discover_references?: boolean };
|
|
39
|
-
exit?(options?: { readonly status?: string; readonly reason?: string; readonly outputs?: Partial<OpenClaudeDesignOutputs> }): never;
|
|
40
|
-
task(name: string, options: WorkflowTaskOptions): Promise<WorkflowTaskResult>;
|
|
41
|
-
parallel(steps: readonly WorkflowTaskStep[], options: WorkflowParallelOptions): Promise<WorkflowTaskResult[]>;
|
|
42
|
-
/** Durable tool node; the workflow-driven live review loop is built from these. */
|
|
43
|
-
tool<T>(name: string, args: object, fn: (handle: { readonly signal: AbortSignal }) => Promise<T>): Promise<T>;
|
|
44
|
-
readonly ui: LiveReviewGateUi;
|
|
45
|
-
};
|
|
46
|
-
|
|
47
|
-
export async function runOpenClaudeDesignWorkflow(ctx: OpenClaudeDesignContext): Promise<OpenClaudeDesignOutputs> {
|
|
48
|
-
const designContext = ctx;
|
|
49
|
-
|
|
50
|
-
// Initial deterministic setup step (no LLM): ensure the playwright-cli skill's
|
|
51
|
-
// `playwright-cli` command is installed before any design stage runs. Best-effort.
|
|
52
|
-
const playwrightCli = ensurePlaywrightCli();
|
|
53
|
-
const browserBootstrapRules = buildPlaywrightCliBootstrapRules(playwrightCli);
|
|
54
|
-
|
|
55
|
-
const inputs = designContext.inputs;
|
|
56
|
-
const prompt = inputs.prompt;
|
|
57
|
-
const discoverReferences = inputs.discover_references !== false;
|
|
58
|
-
|
|
59
|
-
const workflowCwd = designContext.cwd ?? process.cwd();
|
|
60
|
-
const { runId, artifactDir, previewPath, specPath } = prepareArtifactDir(
|
|
61
|
-
workflowCwd,
|
|
62
|
-
);
|
|
63
|
-
const previewFileUrl = `file://${previewPath}`;
|
|
64
|
-
const specFileUrl = `file://${specPath}`;
|
|
65
|
-
const partialArtifactOutputs = {
|
|
66
|
-
playwright_cli_status: playwrightCli.summary, run_id: runId, artifact_dir: artifactDir,
|
|
67
|
-
preview_path: previewPath, preview_file_url: previewFileUrl, spec_path: specPath, spec_file_url: specFileUrl,
|
|
68
|
-
};
|
|
69
|
-
|
|
70
|
-
// Browser-centric workflow: the discovery/preview review and the interactive
|
|
71
|
-
// `live` QA loop need the playwright-cli browser. If it is unavailable, exit
|
|
72
|
-
// cleanly up front (surfacing artifact paths) rather than generating a design
|
|
73
|
-
// no one can review. Gated off under NODE_ENV=test / runtimes without ctx.exit.
|
|
74
|
-
if (
|
|
75
|
-
shouldEarlyExitForBrowser(playwrightCli.available, process.env.NODE_ENV) &&
|
|
76
|
-
typeof designContext.exit === "function"
|
|
77
|
-
) {
|
|
78
|
-
designContext.exit({
|
|
79
|
-
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.`,
|
|
80
|
-
outputs: partialArtifactOutputs,
|
|
81
|
-
});
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
// design-context.md / references.md are required `reads` inputs for the
|
|
85
|
-
// reference-discovery, generate, and exporter stages. A failed write must
|
|
86
|
-
// not let those stages dispatch against nonexistent context: exit the run
|
|
87
|
-
// as `blocked` through ctx.exit (mirroring the browser early-exit) with the
|
|
88
|
-
// artifact paths surfaced, or propagate the error when ctx.exit is absent.
|
|
89
|
-
const persistRequiredContextOrExit = (persist: () => void): void => {
|
|
90
|
-
try {
|
|
91
|
-
persist();
|
|
92
|
-
} catch (error) {
|
|
93
|
-
const detail = error instanceof Error ? error.message : String(error);
|
|
94
|
-
if (typeof designContext.exit === "function") {
|
|
95
|
-
designContext.exit({
|
|
96
|
-
status: "blocked",
|
|
97
|
-
reason: `${detail} No design was generated.`,
|
|
98
|
-
outputs: partialArtifactOutputs,
|
|
99
|
-
});
|
|
100
|
-
}
|
|
101
|
-
throw error;
|
|
102
|
-
}
|
|
103
|
-
};
|
|
104
|
-
|
|
105
|
-
// Anthropic-heavy chain for design taste. Opus stays at :xhigh here because
|
|
106
|
-
// visual quality, rather than cost per task, is the primary objective.
|
|
107
|
-
const designModelConfig = {
|
|
108
|
-
model: "anthropic/claude-opus-5:high",
|
|
109
|
-
fallbackModels: [
|
|
110
|
-
"github-copilot/claude-opus-5:high",
|
|
111
|
-
"anthropic/claude-fable-5:high",
|
|
112
|
-
"github-copilot/claude-fable-5:high",
|
|
113
|
-
"kimi-coding/k3:max",
|
|
114
|
-
"moonshotai/kimi-k3:max",
|
|
115
|
-
"moonshotai-cn/kimi-k3:max",
|
|
116
|
-
"anthropic/claude-opus-4-8:high",
|
|
117
|
-
"github-copilot/claude-opus-4.8:high",
|
|
118
|
-
"openai-codex/gpt-5.6-sol:xhigh",
|
|
119
|
-
"github-copilot/gpt-5.6-sol:xhigh",
|
|
120
|
-
"openai/gpt-5.6-sol:xhigh",
|
|
121
|
-
"xai/grok-4.6:xhigh",
|
|
122
|
-
"github-copilot/grok-4.6:xhigh",
|
|
123
|
-
"zai/glm-5.3:high",
|
|
124
|
-
"zai-coding-cn/glm-5.3:high",
|
|
125
|
-
"openrouter/anthropic/claude-opus-5:high",
|
|
126
|
-
"openrouter/anthropic/claude-fable-5:high",
|
|
127
|
-
"openrouter/anthropic/claude-opus-4-8:high",
|
|
128
|
-
"openrouter/moonshotai/kimi-k3:max",
|
|
129
|
-
"openrouter/openai/gpt-5.6-sol:xhigh",
|
|
130
|
-
"openrouter/sakana/fugu-ultra:high",
|
|
131
|
-
"openrouter/x-ai/grok-4.6",
|
|
132
|
-
],
|
|
133
|
-
};
|
|
134
|
-
// Phase 1: combined discovery + init — one stage interviews the user via
|
|
135
|
-
// impeccable `shape`, then immediately runs impeccable `init` so PRODUCT.md /
|
|
136
|
-
// DESIGN.md are detected, created, or reconciled before design research.
|
|
137
|
-
const frontDoor = await runDiscoveryAndInit({
|
|
138
|
-
designContext,
|
|
139
|
-
prompt,
|
|
140
|
-
discoveryConfig: { ...designModelConfig, schema: discoveryDecisionSchema },
|
|
141
|
-
});
|
|
142
|
-
const discovery = frontDoor.discovery;
|
|
143
|
-
const designBrief = discovery.brief;
|
|
144
|
-
const outputType = discovery.output_type;
|
|
145
|
-
const references = discovery.references;
|
|
146
|
-
const projectContext = frontDoor.projectContext;
|
|
147
|
-
|
|
148
|
-
const userReferenceContext = references.length > 0
|
|
149
|
-
? references.map((ref, index) => `${index + 1}. ${ref}`).join("\n")
|
|
150
|
-
: "No user-provided references were collected during discovery.";
|
|
151
|
-
const referenceHandlingRules = references.length > 0
|
|
152
|
-
? [
|
|
153
|
-
REFERENCE_PRECEDENCE,
|
|
154
|
-
"For URL references, use browser/screenshot tooling when available and cite only observable traits.",
|
|
155
|
-
"For files, screenshots, or design docs, read or parse the source directly and quote concrete evidence.",
|
|
156
|
-
"Include a `Reference requirements` section so the generator receives the imported constraints.",
|
|
157
|
-
].join("\n")
|
|
158
|
-
: "No user references to import. Focus on project context and curated reference-discovery when present.";
|
|
159
|
-
|
|
160
|
-
// Phase 3 (combined): a single fan-out gathers project design-system evidence
|
|
161
|
-
// and references. The ds-* stages now also import user URLs/files directly.
|
|
162
|
-
const dsSteps: WorkflowTaskStep[] = [
|
|
163
|
-
{
|
|
164
|
-
name: "ds-locator",
|
|
165
|
-
task: taggedPrompt([
|
|
166
|
-
["user_references", userReferenceContext],
|
|
167
|
-
["reference_handling", referenceHandlingRules],
|
|
168
|
-
["browser_use_guidelines", browserBootstrapRules],
|
|
169
|
-
["role", "You are an opinionated staff design engineer."],
|
|
170
|
-
[
|
|
171
|
-
"objective",
|
|
172
|
-
`Find UI/design-system sources for: ${designBrief}. Apply impeccable \`extract\` to codebase evidence and user reference URLs/files that should steer generation.`,
|
|
173
|
-
],
|
|
174
|
-
["delegation_rule", DELEGATION_RULE],
|
|
175
|
-
[
|
|
176
|
-
"instructions",
|
|
177
|
-
[
|
|
178
|
-
"Locate UI components, stylesheets, tokens, Storybook/examples, screenshots, tests, design docs, and user references.",
|
|
179
|
-
"Report concrete file, URL, or artifact paths and why each informs generation; separate primary sources, supporting examples, and reference-only inspiration.",
|
|
180
|
-
"If no explicit system exists, report the strongest implicit evidence such as repeated literals and dominant component patterns.",
|
|
181
|
-
].join("\n"),
|
|
182
|
-
],
|
|
183
|
-
[
|
|
184
|
-
"output_format",
|
|
185
|
-
`In at most 500 words, return Markdown sections: Project sources table | User reference sources | Reference requirements | Confidence notes. ${GROUNDED_REPORTING}`,
|
|
186
|
-
],
|
|
187
|
-
]),
|
|
188
|
-
...designModelConfig,
|
|
189
|
-
},
|
|
190
|
-
{
|
|
191
|
-
name: "ds-analyzer",
|
|
192
|
-
task: taggedPrompt([
|
|
193
|
-
["user_references", userReferenceContext],
|
|
194
|
-
["reference_handling", referenceHandlingRules],
|
|
195
|
-
["browser_use_guidelines", browserBootstrapRules],
|
|
196
|
-
[
|
|
197
|
-
"impeccable_skill",
|
|
198
|
-
"audit — score 0–4 across Accessibility, Performance, Theming, Responsive, Anti-patterns. Tag every finding P0 (blocks release) → P3 (polish). Document, do not fix.",
|
|
199
|
-
],
|
|
200
|
-
["role", "You are an opinionated staff design engineer."],
|
|
201
|
-
[
|
|
202
|
-
"objective",
|
|
203
|
-
`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.`,
|
|
204
|
-
],
|
|
205
|
-
["delegation_rule", DELEGATION_RULE],
|
|
206
|
-
[
|
|
207
|
-
"instructions",
|
|
208
|
-
[
|
|
209
|
-
"Inspect the UI stack, styling, tokens, responsive behavior, accessibility conventions, and component APIs.",
|
|
210
|
-
"Ground each claim in exact paths, symbols, code examples, screenshots, URLs, or quoted reference excerpts.",
|
|
211
|
-
"Identify integration constraints the generated design must follow, and state uncertainty when evidence is incomplete.",
|
|
212
|
-
].join("\n"),
|
|
213
|
-
],
|
|
214
|
-
[
|
|
215
|
-
"output_format",
|
|
216
|
-
`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_REPORTING}`,
|
|
217
|
-
],
|
|
218
|
-
]),
|
|
219
|
-
...designModelConfig,
|
|
220
|
-
},
|
|
221
|
-
{
|
|
222
|
-
name: "ds-patterns",
|
|
223
|
-
task: taggedPrompt([
|
|
224
|
-
["user_references", userReferenceContext],
|
|
225
|
-
["reference_handling", referenceHandlingRules],
|
|
226
|
-
["browser_use_guidelines", browserBootstrapRules],
|
|
227
|
-
["role", "You are an opinionated staff design engineer."],
|
|
228
|
-
[
|
|
229
|
-
"objective",
|
|
230
|
-
`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.`,
|
|
231
|
-
],
|
|
232
|
-
["delegation_rule", DELEGATION_RULE],
|
|
233
|
-
[
|
|
234
|
-
"instructions",
|
|
235
|
-
[
|
|
236
|
-
"Find reusable naming, variant, composition, state, animation, and layout patterns.",
|
|
237
|
-
"Cite concrete paths, component/symbol names, reference URLs, or quoted file/screenshot evidence.",
|
|
238
|
-
"Identify generated-design anti-patterns using impeccable's 25 deterministic anti-patterns; do not generalize beyond repository or reference evidence.",
|
|
239
|
-
].join("\n"),
|
|
240
|
-
],
|
|
241
|
-
[
|
|
242
|
-
"output_format",
|
|
243
|
-
`In at most 600 words, return Markdown sections: Reusable patterns | Examples | Reference requirements | Anti-patterns | Generation implications. ${GROUNDED_REPORTING}`,
|
|
244
|
-
],
|
|
245
|
-
]),
|
|
246
|
-
...designModelConfig,
|
|
247
|
-
},
|
|
248
|
-
];
|
|
249
|
-
|
|
250
|
-
const onboardingAnalysis = await designContext.parallel(dsSteps, {
|
|
251
|
-
task: designBrief,
|
|
252
|
-
});
|
|
253
|
-
const onboardingSummary = joinResults(onboardingAnalysis);
|
|
254
|
-
|
|
255
|
-
// Large research context is handed to later stages as an artifact file plus
|
|
256
|
-
// `reads`, never as an inline prompt embed or `previous` payload, so one
|
|
257
|
-
// oversized research result cannot become one oversized prompt message
|
|
258
|
-
// (issue #2121; same failure class as the #1499 413).
|
|
259
|
-
const designSystem = [
|
|
260
|
-
"Project design context from `/skill:impeccable init` and PRODUCT.md/DESIGN.md:",
|
|
261
|
-
projectContext.summary,
|
|
262
|
-
"",
|
|
263
|
-
"Design-system and user-reference evidence:",
|
|
264
|
-
onboardingSummary,
|
|
265
|
-
].join("\n\n");
|
|
266
|
-
persistRequiredContextOrExit(() => persistDesignContext(artifactDir, designSystem));
|
|
267
|
-
const designContextFile = designContextPath(artifactDir);
|
|
268
|
-
|
|
269
|
-
const referenceResult = discoverReferences
|
|
270
|
-
? await designContext.task("reference-discovery", {
|
|
271
|
-
prompt: buildReferenceDiscoveryPrompt({
|
|
272
|
-
prompt: designBrief,
|
|
273
|
-
outputType,
|
|
274
|
-
designContextFile,
|
|
275
|
-
artifactDir,
|
|
276
|
-
browserBootstrapRules,
|
|
277
|
-
}),
|
|
278
|
-
reads: [designContextFile],
|
|
279
|
-
...designModelConfig,
|
|
280
|
-
})
|
|
281
|
-
: undefined;
|
|
282
|
-
|
|
283
|
-
const referencesBriefRaw = (referenceResult?.text ?? "").trim();
|
|
284
|
-
const referencesBrief =
|
|
285
|
-
referencesBriefRaw.length > 0 ? referencesBriefRaw : NO_REFERENCES_BRIEF;
|
|
286
|
-
// Always persist so the generate stages' `reads` target exists even when
|
|
287
|
-
// discovery is skipped or returned nothing.
|
|
288
|
-
persistRequiredContextOrExit(() => persistReferencesBrief(artifactDir, referencesBrief));
|
|
289
|
-
const referencesFile = referencesBriefPath(artifactDir);
|
|
290
|
-
|
|
291
|
-
const importContext = references.length > 0
|
|
292
|
-
? [
|
|
293
|
-
REFERENCE_PRECEDENCE,
|
|
294
|
-
"Reference sources:",
|
|
295
|
-
userReferenceContext,
|
|
296
|
-
"",
|
|
297
|
-
"Full design-system and reference evidence: read the design-context file.",
|
|
298
|
-
].join("\n")
|
|
299
|
-
: "No user reference was provided; infer the design direction from the brief, project design context, research, and curated reference inspiration.";
|
|
300
|
-
|
|
301
|
-
const refinement = await refineOpenClaudeDesign({
|
|
302
|
-
designContext,
|
|
303
|
-
prompt: designBrief,
|
|
304
|
-
outputType,
|
|
305
|
-
previewPath,
|
|
306
|
-
previewFileUrl,
|
|
307
|
-
browserBootstrapRules,
|
|
308
|
-
designContextFile,
|
|
309
|
-
referencesFile,
|
|
310
|
-
designModelConfig,
|
|
311
|
-
workflowCwd,
|
|
312
|
-
importContext,
|
|
313
|
-
ui: designContext.ui,
|
|
314
|
-
});
|
|
315
|
-
const latestDesign = refinement.latestDesign;
|
|
316
|
-
|
|
317
|
-
const exportResult = await exportOpenClaudeDesign({
|
|
318
|
-
designContext,
|
|
319
|
-
prompt: designBrief,
|
|
320
|
-
outputType,
|
|
321
|
-
previewPath,
|
|
322
|
-
previewFileUrl,
|
|
323
|
-
specPath,
|
|
324
|
-
specFileUrl,
|
|
325
|
-
browserBootstrapRules,
|
|
326
|
-
designContextFile,
|
|
327
|
-
referencesFile,
|
|
328
|
-
latestDesign,
|
|
329
|
-
designModelConfig,
|
|
330
|
-
});
|
|
331
|
-
const handoff = exportResult.handoff;
|
|
332
|
-
|
|
333
|
-
return {
|
|
334
|
-
output_type: outputType,
|
|
335
|
-
design_system: "project-derived design system",
|
|
336
|
-
artifact: latestDesign,
|
|
337
|
-
handoff: handoff.text,
|
|
338
|
-
import_context: importContext,
|
|
339
|
-
run_id: runId,
|
|
340
|
-
artifact_dir: artifactDir,
|
|
341
|
-
preview_path: previewPath,
|
|
342
|
-
preview_file_url: previewFileUrl,
|
|
343
|
-
spec_path: specPath,
|
|
344
|
-
spec_file_url: specFileUrl,
|
|
345
|
-
playwright_cli_status: playwrightCli.summary,
|
|
346
|
-
};
|
|
347
|
-
}
|
|
@@ -1,313 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* open-claude-design setup helpers.
|
|
3
|
-
*
|
|
4
|
-
* Capabilities that delegate to the accessible `impeccable` skill
|
|
5
|
-
* (`/skill:impeccable …`), factored into this module so the runner and phases
|
|
6
|
-
* files stay focused:
|
|
7
|
-
*
|
|
8
|
-
* 1. Discovery + init front door: one `discovery` stage runs
|
|
9
|
-
* `/skill:impeccable shape` and `/skill:impeccable init`, interviews the
|
|
10
|
-
* user for the design brief/output type/references, then lets impeccable
|
|
11
|
-
* detect/create/reconcile PRODUCT.md and DESIGN.md in the same stage.
|
|
12
|
-
* 2. Reference discovery: browse five curated galleries (Awwwards,
|
|
13
|
-
* recent.design, Dribbble, Monet, Motionsites) and synthesize a references
|
|
14
|
-
* brief the generator heavily emulates.
|
|
15
|
-
* 3. Live interactive QA prompt: drive `/skill:impeccable live` against the
|
|
16
|
-
* static preview.html so the user picks elements, annotates, and accepts
|
|
17
|
-
* on-brand variants in the browser. cross-ref: impeccable `reference/live.md`.
|
|
18
|
-
*/
|
|
19
|
-
|
|
20
|
-
import { mkdirSync, writeFileSync } from "node:fs";
|
|
21
|
-
import { join } from "node:path";
|
|
22
|
-
import type { WorkflowTaskResult } from "../src/shared/types.js";
|
|
23
|
-
import {
|
|
24
|
-
OUTPUT_TYPES,
|
|
25
|
-
discoveryDecisionFromResult,
|
|
26
|
-
taggedPrompt,
|
|
27
|
-
type DiscoveryDecision,
|
|
28
|
-
} from "./open-claude-design-utils.js";
|
|
29
|
-
|
|
30
|
-
type SetupModelConfig = Record<string, object | string | readonly string[]>;
|
|
31
|
-
type SetupDesignContext = {
|
|
32
|
-
task(name: string, options: object): Promise<WorkflowTaskResult>;
|
|
33
|
-
};
|
|
34
|
-
|
|
35
|
-
const GROUNDED_REPORTING =
|
|
36
|
-
"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.";
|
|
37
|
-
|
|
38
|
-
// ---------------------------------------------------------------------------
|
|
39
|
-
// 0. Discovery + init front door (one workflow stage)
|
|
40
|
-
// ---------------------------------------------------------------------------
|
|
41
|
-
|
|
42
|
-
export type ProjectDesignContextResult = {
|
|
43
|
-
readonly summary: string;
|
|
44
|
-
};
|
|
45
|
-
|
|
46
|
-
export function renderDiscoveryContext(discovery: DiscoveryDecision): string {
|
|
47
|
-
return [
|
|
48
|
-
`Confirmed design brief: ${discovery.brief}`,
|
|
49
|
-
`Output type: ${discovery.output_type}`,
|
|
50
|
-
discovery.references.length > 0
|
|
51
|
-
? `References to emulate (take precedence over DESIGN.md/PRODUCT.md): ${discovery.references.join(", ")}`
|
|
52
|
-
: "References to emulate: none provided.",
|
|
53
|
-
].join("\n");
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
function buildDiscoveryInitPrompt(prompt: string): string {
|
|
57
|
-
const outputTypes = OUTPUT_TYPES.join(", ");
|
|
58
|
-
return `/skill:impeccable shape
|
|
59
|
-
/skill:impeccable init
|
|
60
|
-
|
|
61
|
-
${taggedPrompt([
|
|
62
|
-
["role", "You are an opinionated staff designer running the open-claude-design front door."],
|
|
63
|
-
[
|
|
64
|
-
"objective",
|
|
65
|
-
`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.`,
|
|
66
|
-
],
|
|
67
|
-
[
|
|
68
|
-
"interview",
|
|
69
|
-
[
|
|
70
|
-
"Use `ask_user_question` for important gaps not inferable from the request or repository.",
|
|
71
|
-
`Cover the product and core jobs/screens, one output type (${outputTypes}), and references to emulate (URLs, local paths, screenshots, or design docs).`,
|
|
72
|
-
"Ask 2-3 questions per round and present inferred answers as options rather than facts.",
|
|
73
|
-
"User references are the PRIMARY visual authority and override conflicting DESIGN.md/PRODUCT.md guidance.",
|
|
74
|
-
].join("\n"),
|
|
75
|
-
],
|
|
76
|
-
[
|
|
77
|
-
"init_instructions",
|
|
78
|
-
[
|
|
79
|
-
"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.",
|
|
80
|
-
"Create missing files when needed and reconcile existing ones without silently overwriting them; ask only about genuine gaps.",
|
|
81
|
-
"When headless, infer the most defensible brief/register from the prompt and repository, record explicit `## Gaps / Assumptions`, and do not block.",
|
|
82
|
-
].join("\n"),
|
|
83
|
-
],
|
|
84
|
-
[
|
|
85
|
-
"output_format",
|
|
86
|
-
`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}`,
|
|
87
|
-
],
|
|
88
|
-
])}`;
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
export async function runDiscoveryAndInit(args: {
|
|
92
|
-
readonly designContext: SetupDesignContext;
|
|
93
|
-
readonly prompt: string;
|
|
94
|
-
readonly discoveryConfig: SetupModelConfig;
|
|
95
|
-
}): Promise<{
|
|
96
|
-
readonly discovery: DiscoveryDecision;
|
|
97
|
-
readonly discoveryContext: string;
|
|
98
|
-
readonly projectContext: ProjectDesignContextResult;
|
|
99
|
-
}> {
|
|
100
|
-
const result = await args.designContext.task("discovery", {
|
|
101
|
-
prompt: buildDiscoveryInitPrompt(args.prompt),
|
|
102
|
-
...args.discoveryConfig,
|
|
103
|
-
});
|
|
104
|
-
const discovery = discoveryDecisionFromResult(result, args.prompt);
|
|
105
|
-
return {
|
|
106
|
-
discovery,
|
|
107
|
-
discoveryContext: renderDiscoveryContext(discovery),
|
|
108
|
-
projectContext: {
|
|
109
|
-
summary: [
|
|
110
|
-
"Ran `/skill:impeccable shape` + `/skill:impeccable init` in the combined discovery stage.",
|
|
111
|
-
(result.text ?? "").trim(),
|
|
112
|
-
].filter((part) => part.length > 0).join("\n\n"),
|
|
113
|
-
},
|
|
114
|
-
};
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
// ---------------------------------------------------------------------------
|
|
118
|
-
// 1. Reference discovery
|
|
119
|
-
// ---------------------------------------------------------------------------
|
|
120
|
-
|
|
121
|
-
/** Curated galleries of beautiful, current reference designs. */
|
|
122
|
-
export const REFERENCE_DESIGN_SITES: readonly { readonly name: string; readonly url: string }[] = [
|
|
123
|
-
{ name: "Awwwards", url: "https://www.awwwards.com/websites/" },
|
|
124
|
-
{ name: "recent.design", url: "https://recent.design/" },
|
|
125
|
-
{ name: "Dribbble (recent shots)", url: "https://dribbble.com/shots/recent" },
|
|
126
|
-
{ name: "Monet", url: "https://www.monet.design/c" },
|
|
127
|
-
{ name: "Motionsites", url: "https://motionsites.ai/" },
|
|
128
|
-
];
|
|
129
|
-
|
|
130
|
-
export const NO_REFERENCES_BRIEF =
|
|
131
|
-
"Reference discovery was skipped. Generate from the project design system and the prompt; do not fabricate external references.";
|
|
132
|
-
|
|
133
|
-
/** Artifact filenames for large stage-to-stage context handoffs (issue #2121). */
|
|
134
|
-
export const DESIGN_CONTEXT_FILENAME = "design-context.md";
|
|
135
|
-
export const REFERENCES_BRIEF_FILENAME = "references.md";
|
|
136
|
-
|
|
137
|
-
export function designContextPath(artifactDir: string): string {
|
|
138
|
-
return join(artifactDir, DESIGN_CONTEXT_FILENAME);
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
export function referencesBriefPath(artifactDir: string): string {
|
|
142
|
-
return join(artifactDir, REFERENCES_BRIEF_FILENAME);
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
export function buildReferenceDiscoveryPrompt(args: {
|
|
146
|
-
readonly prompt: string;
|
|
147
|
-
readonly outputType: string;
|
|
148
|
-
readonly designContextFile: string;
|
|
149
|
-
readonly artifactDir: string;
|
|
150
|
-
readonly browserBootstrapRules: string;
|
|
151
|
-
}): string {
|
|
152
|
-
const siteList = REFERENCE_DESIGN_SITES.map(
|
|
153
|
-
(site, index) => `${index + 1}. ${site.name} — ${site.url}`,
|
|
154
|
-
).join("\n");
|
|
155
|
-
return taggedPrompt([
|
|
156
|
-
["reference_galleries", siteList],
|
|
157
|
-
[
|
|
158
|
-
"design_context_file",
|
|
159
|
-
`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.`,
|
|
160
|
-
],
|
|
161
|
-
["browser_use_guidelines", args.browserBootstrapRules],
|
|
162
|
-
["screenshot_dir", args.artifactDir],
|
|
163
|
-
[
|
|
164
|
-
"role",
|
|
165
|
-
"You are an opinionated staff design engineer curating current, best-in-class visual references.",
|
|
166
|
-
],
|
|
167
|
-
[
|
|
168
|
-
"objective",
|
|
169
|
-
`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.`,
|
|
170
|
-
],
|
|
171
|
-
[
|
|
172
|
-
"instructions",
|
|
173
|
-
[
|
|
174
|
-
"Use the playwright-cli skill to open each gallery; if `playwright-cli` reports a missing browser executable, follow the bootstrap rules and retry once.",
|
|
175
|
-
"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.",
|
|
176
|
-
`Capture motion across the entire page: start \`playwright-cli video-start ${join(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\`.`,
|
|
177
|
-
`Also run \`playwright-cli screenshot --full-page --filename=${join(args.artifactDir, "ref-<site>-<n>.png")}\`; this still is the minimum when video is unavailable.`,
|
|
178
|
-
"Record the actual destination URL, title, and author. For each reference, cite observed layout, typography, color, spacing, and motion traits rather than inferred traits.",
|
|
179
|
-
"Assess fit against DESIGN.md, PRODUCT.md, and the ds-* discovery evidence in the design-context file; prefer on-brand references and flag departures.",
|
|
180
|
-
"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.",
|
|
181
|
-
"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.",
|
|
182
|
-
].join("\n"),
|
|
183
|
-
],
|
|
184
|
-
[
|
|
185
|
-
"output_format",
|
|
186
|
-
[
|
|
187
|
-
"In at most 900 words, return these Markdown sections:",
|
|
188
|
-
"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?)",
|
|
189
|
-
"2. User preference check (selected direction, or none plus the requested/provided reference)",
|
|
190
|
-
"3. Synthesis (3-5 strongest directions ranked by fit, including motion to reproduce)",
|
|
191
|
-
"4. What to avoid (observed anti-references)",
|
|
192
|
-
"5. Verification notes (actual-page video/screenshot versus search-only)",
|
|
193
|
-
GROUNDED_REPORTING,
|
|
194
|
-
].join("\n"),
|
|
195
|
-
],
|
|
196
|
-
]);
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
/**
|
|
200
|
-
* Write a context artifact that downstream stages consume via `reads`.
|
|
201
|
-
* These files are required stage inputs, not best-effort durability copies:
|
|
202
|
-
* a swallowed write failure would let reference-discovery, generate, and
|
|
203
|
-
* exporter stages dispatch against nonexistent design/reference context, so
|
|
204
|
-
* a failure propagates and stops the workflow (issue #2121, Greptile P1).
|
|
205
|
-
*/
|
|
206
|
-
function writeRequiredContextArtifact(
|
|
207
|
-
artifactDir: string,
|
|
208
|
-
filePath: string,
|
|
209
|
-
content: string,
|
|
210
|
-
label: string,
|
|
211
|
-
): void {
|
|
212
|
-
try {
|
|
213
|
-
mkdirSync(artifactDir, { recursive: true });
|
|
214
|
-
writeFileSync(filePath, `${content}\n`);
|
|
215
|
-
} catch (error) {
|
|
216
|
-
const detail = error instanceof Error ? error.message : String(error);
|
|
217
|
-
throw new Error(
|
|
218
|
-
`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})`,
|
|
219
|
-
{ cause: error },
|
|
220
|
-
);
|
|
221
|
-
}
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
/**
|
|
225
|
-
* Persist the curated references brief to `<artifactDir>/references.md`.
|
|
226
|
-
* Downstream generate stages consume this file via `reads` instead of an
|
|
227
|
-
* inline prompt embed; a write failure propagates (issue #2121).
|
|
228
|
-
*/
|
|
229
|
-
export function persistReferencesBrief(artifactDir: string, brief: string): void {
|
|
230
|
-
writeRequiredContextArtifact(artifactDir, referencesBriefPath(artifactDir), brief, "references-brief");
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
/**
|
|
234
|
-
* Persist the composed project design context (impeccable init summary plus
|
|
235
|
-
* ds-* discovery evidence) to `<artifactDir>/design-context.md`.
|
|
236
|
-
* Reference-discovery, generate, and exporter stages consume this file via
|
|
237
|
-
* `reads` instead of an inline prompt embed, so one oversized research result
|
|
238
|
-
* cannot become an oversized single prompt message. A write failure
|
|
239
|
-
* propagates rather than letting those stages run without their design
|
|
240
|
-
* context (issue #2121).
|
|
241
|
-
*/
|
|
242
|
-
export function persistDesignContext(artifactDir: string, content: string): void {
|
|
243
|
-
writeRequiredContextArtifact(artifactDir, designContextPath(artifactDir), content, "design-context");
|
|
244
|
-
}
|
|
245
|
-
|
|
246
|
-
// ---------------------------------------------------------------------------
|
|
247
|
-
// 2. Live interactive QA prompt (the user-feedback review session)
|
|
248
|
-
// ---------------------------------------------------------------------------
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
// ---------------------------------------------------------------------------
|
|
252
|
-
// 3. Deterministic live-review gate (run-level HIL prompt, issue #2060)
|
|
253
|
-
// ---------------------------------------------------------------------------
|
|
254
|
-
|
|
255
|
-
/**
|
|
256
|
-
* Minimal structural slice of `ctx.ui` the live-review gate needs. Kept
|
|
257
|
-
* structural so the runner/phases modules stay decoupled from the full
|
|
258
|
-
* WorkflowRunContext type.
|
|
259
|
-
*/
|
|
260
|
-
export type LiveReviewGateUi = {
|
|
261
|
-
select<T extends string>(message: string, options: readonly T[]): Promise<T>;
|
|
262
|
-
};
|
|
263
|
-
|
|
264
|
-
/**
|
|
265
|
-
* Choices for the deterministic gate raised before the live review session.
|
|
266
|
-
* The first entry starts the session; the second accepts the current design
|
|
267
|
-
* and skips straight to export.
|
|
268
|
-
*/
|
|
269
|
-
export const LIVE_REVIEW_GATE_OPTIONS = [
|
|
270
|
-
"Start live review",
|
|
271
|
-
"Skip remaining review rounds and export as-is",
|
|
272
|
-
] as const;
|
|
273
|
-
|
|
274
|
-
/**
|
|
275
|
-
* Message for the deterministic run-level prompt raised before the live
|
|
276
|
-
* review session. The browser long-poll never sets `awaiting_input`, so
|
|
277
|
-
* without this gate the run is indistinguishable from active compute while it
|
|
278
|
-
* waits on a human (issue #2060). Raising a `ctx.ui` prompt sets the run-level
|
|
279
|
-
* pending prompt, which fires the needs-attention badge and carries the
|
|
280
|
-
* preview URL to the root session deterministically.
|
|
281
|
-
*/
|
|
282
|
-
export function buildLiveReviewGateMessage(args: {
|
|
283
|
-
readonly round: number;
|
|
284
|
-
readonly previewPath: string;
|
|
285
|
-
readonly previewFileUrl: string;
|
|
286
|
-
}): string {
|
|
287
|
-
return [
|
|
288
|
-
`Design review session ${args.round} is ready for your browser review.`,
|
|
289
|
-
"",
|
|
290
|
-
`Preview file: ${args.previewPath}`,
|
|
291
|
-
`Preview URL: ${args.previewFileUrl}`,
|
|
292
|
-
"",
|
|
293
|
-
`"${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).`,
|
|
294
|
-
"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.",
|
|
295
|
-
"",
|
|
296
|
-
"YOU end the review, and nothing else does. It keeps waiting through any amount of silence.",
|
|
297
|
-
"End it by clicking exit in the Impeccable overlay, closing the browser tab, or saying \"exit live\".",
|
|
298
|
-
"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.",
|
|
299
|
-
`"${LIVE_REVIEW_GATE_OPTIONS[1]}" accepts the current design and proceeds to export without opening a session.`,
|
|
300
|
-
].join("\n");
|
|
301
|
-
}
|
|
302
|
-
|
|
303
|
-
/**
|
|
304
|
-
* True only for the executor's unavailable-UI rejections (no UI adapter, or
|
|
305
|
-
* headless/non-interactive mode; see `executor-hil.ts` `makeRejectingUIContext`
|
|
306
|
-
* and the prompt-node unavailable errors). The live-review gate degrades to
|
|
307
|
-
* running the review for exactly these; every other rejection — interruption,
|
|
308
|
-
* durable checkpoint persistence failure, exit — must propagate so the
|
|
309
|
-
* workflow stops instead of opening a review against an invalid run state.
|
|
310
|
-
*/
|
|
311
|
-
export function isUiUnavailableRejection(error: unknown): boolean {
|
|
312
|
-
return error instanceof Error && /ctx\.ui\.\w+ (?:prompt node )?is unavailable/.test(error.message);
|
|
313
|
-
}
|