openuispec 0.2.18 → 0.2.20
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/README.md +2 -10
- package/dist/check/audit.js +392 -0
- package/dist/check/index.js +216 -0
- package/dist/cli/configure-target.js +391 -0
- package/dist/cli/index.js +510 -0
- package/dist/cli/init.js +1047 -0
- package/dist/drift/index.js +903 -0
- package/dist/mcp-server/index.js +886 -0
- package/dist/mcp-server/preview-render.js +1761 -0
- package/dist/mcp-server/preview.js +233 -0
- package/dist/mcp-server/screenshot-android.js +458 -0
- package/dist/mcp-server/screenshot-ios.js +639 -0
- package/dist/mcp-server/screenshot-shared.js +180 -0
- package/dist/mcp-server/screenshot.js +459 -0
- package/dist/prepare/index.js +1216 -0
- package/dist/runtime/package-paths.js +33 -0
- package/dist/schema/semantic-lint.js +564 -0
- package/dist/schema/validate.js +689 -0
- package/dist/status/index.js +194 -0
- package/docs/images/how-it-works.svg +56 -0
- package/docs/images/workflows.svg +76 -0
- package/package.json +12 -13
- package/check/audit.ts +0 -426
- package/check/index.ts +0 -320
- package/cli/configure-target.ts +0 -523
- package/cli/index.ts +0 -537
- package/cli/init.ts +0 -1253
- package/docs/images/how-it-works-dark.png +0 -0
- package/docs/images/how-it-works-light.png +0 -0
- package/docs/images/workflows-dark.png +0 -0
- package/docs/images/workflows-light.png +0 -0
- package/drift/index.ts +0 -1165
- package/mcp-server/index.ts +0 -1041
- package/mcp-server/preview-render.ts +0 -1922
- package/mcp-server/preview.ts +0 -292
- package/mcp-server/screenshot-android.ts +0 -621
- package/mcp-server/screenshot-ios.ts +0 -753
- package/mcp-server/screenshot-shared.ts +0 -237
- package/mcp-server/screenshot.ts +0 -563
- package/prepare/index.ts +0 -1530
- package/schema/semantic-lint.ts +0 -692
- package/schema/validate.ts +0 -870
- package/scripts/regenerate-previews.ts +0 -136
- package/scripts/take-all-screenshots.ts +0 -507
- package/status/index.ts +0 -275
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Cross-target status summary for OpenUISpec projects.
|
|
4
|
+
*
|
|
5
|
+
* Usage:
|
|
6
|
+
* openuispec status # summarize every target
|
|
7
|
+
* openuispec status --json # machine-readable output
|
|
8
|
+
*/
|
|
9
|
+
import { existsSync } from "node:fs";
|
|
10
|
+
import { computeDrift, computeSharedDrift, discoverTargets, explainDrift, findProjectDir, formatBaseline, hasDriftChanges, readOutputDirs, readProjectName, readSharedLayers, readSharedLayerState, resolveOutputDir, stateFilePath, } from "../drift/index.js";
|
|
11
|
+
import { readFileSync } from "node:fs";
|
|
12
|
+
function configuredTargets(projectDir) {
|
|
13
|
+
try {
|
|
14
|
+
const manifest = readOutputDirs(projectDir);
|
|
15
|
+
const keys = Object.keys(manifest);
|
|
16
|
+
if (keys.length > 0)
|
|
17
|
+
return keys.sort();
|
|
18
|
+
}
|
|
19
|
+
catch {
|
|
20
|
+
// ignore
|
|
21
|
+
}
|
|
22
|
+
// Fallback to common targets when manifest output_dir is absent.
|
|
23
|
+
return ["android", "ios", "web"];
|
|
24
|
+
}
|
|
25
|
+
function allTargets(projectDir, projectName) {
|
|
26
|
+
const seen = new Set(configuredTargets(projectDir));
|
|
27
|
+
for (const target of discoverTargets(projectDir, projectName)) {
|
|
28
|
+
seen.add(target);
|
|
29
|
+
}
|
|
30
|
+
return Array.from(seen).sort();
|
|
31
|
+
}
|
|
32
|
+
function readState(statePath) {
|
|
33
|
+
return JSON.parse(readFileSync(statePath, "utf-8"));
|
|
34
|
+
}
|
|
35
|
+
function buildTargetStatus(cwd, projectDir, projectName, target) {
|
|
36
|
+
const outputDir = resolveOutputDir(projectDir, projectName, target);
|
|
37
|
+
const outputExists = existsSync(outputDir);
|
|
38
|
+
const path = stateFilePath(projectDir, projectName, target);
|
|
39
|
+
if (!existsSync(path)) {
|
|
40
|
+
return {
|
|
41
|
+
target,
|
|
42
|
+
output_dir: outputDir,
|
|
43
|
+
output_exists: outputExists,
|
|
44
|
+
snapshot: false,
|
|
45
|
+
snapshot_at: null,
|
|
46
|
+
baseline: {
|
|
47
|
+
kind: null,
|
|
48
|
+
commit: null,
|
|
49
|
+
branch: null,
|
|
50
|
+
label: null,
|
|
51
|
+
},
|
|
52
|
+
changed: 0,
|
|
53
|
+
added: 0,
|
|
54
|
+
removed: 0,
|
|
55
|
+
behind: false,
|
|
56
|
+
explain_available: false,
|
|
57
|
+
status: outputExists ? "needs baseline" : "needs generation",
|
|
58
|
+
recommended_next_step: outputExists
|
|
59
|
+
? `Review the generated output, then run \`openuispec drift --snapshot --target ${target}\` to create the baseline.`
|
|
60
|
+
: `Run code generation for "${target}", then \`openuispec prepare --target ${target}\` to build the target work bundle.`,
|
|
61
|
+
note: outputExists
|
|
62
|
+
? "Baseline pending — generated code exists but user has not yet confirmed it with a snapshot."
|
|
63
|
+
: `Output directory not found. Run code generation for "${target}" first.`,
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
const state = readState(path);
|
|
67
|
+
const result = computeDrift(projectDir, state, false);
|
|
68
|
+
const explanation = explainDrift(projectDir, result);
|
|
69
|
+
const changed = result.drift.changed.length;
|
|
70
|
+
const added = result.drift.added.length;
|
|
71
|
+
const removed = result.drift.removed.length;
|
|
72
|
+
return {
|
|
73
|
+
target,
|
|
74
|
+
output_dir: outputDir,
|
|
75
|
+
output_exists: outputExists,
|
|
76
|
+
snapshot: true,
|
|
77
|
+
snapshot_at: state.snapshot_at,
|
|
78
|
+
baseline: {
|
|
79
|
+
kind: state.baseline?.kind ?? null,
|
|
80
|
+
commit: state.baseline?.commit ?? null,
|
|
81
|
+
branch: state.baseline?.branch ?? null,
|
|
82
|
+
label: formatBaseline(state.baseline),
|
|
83
|
+
},
|
|
84
|
+
changed,
|
|
85
|
+
added,
|
|
86
|
+
removed,
|
|
87
|
+
behind: changed + added + removed > 0,
|
|
88
|
+
explain_available: explanation.available,
|
|
89
|
+
status: changed + added + removed > 0 ? "behind" : "up to date",
|
|
90
|
+
recommended_next_step: changed + added + removed > 0
|
|
91
|
+
? `Run \`openuispec prepare --target ${target}\` to build the target work bundle for the pending spec changes.`
|
|
92
|
+
: `No immediate action required for "${target}". Re-run \`openuispec status\` after spec changes or after re-baselining.`,
|
|
93
|
+
note: explanation.available ? undefined : explanation.note,
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
function buildSharedLayerStatus(projectDir, layer) {
|
|
97
|
+
const state = readSharedLayerState(layer);
|
|
98
|
+
if (!state) {
|
|
99
|
+
return {
|
|
100
|
+
name: layer.name,
|
|
101
|
+
platforms: layer.platforms,
|
|
102
|
+
root: layer.root,
|
|
103
|
+
snapshot: false,
|
|
104
|
+
snapshot_at: null,
|
|
105
|
+
generated_by_target: null,
|
|
106
|
+
has_drift: false,
|
|
107
|
+
status: "needs generation",
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
let hasDrift = false;
|
|
111
|
+
if (layer.tracks.length > 0) {
|
|
112
|
+
hasDrift = hasDriftChanges(computeSharedDrift(projectDir, layer).drift);
|
|
113
|
+
}
|
|
114
|
+
return {
|
|
115
|
+
name: layer.name,
|
|
116
|
+
platforms: layer.platforms,
|
|
117
|
+
root: layer.root,
|
|
118
|
+
snapshot: true,
|
|
119
|
+
snapshot_at: state.snapshot_at,
|
|
120
|
+
generated_by_target: state.generated_by_target,
|
|
121
|
+
has_drift: hasDrift,
|
|
122
|
+
status: hasDrift ? "behind" : "up to date",
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
export function buildStatusResult(cwd = process.cwd()) {
|
|
126
|
+
const projectDir = findProjectDir(cwd);
|
|
127
|
+
const projectName = readProjectName(projectDir);
|
|
128
|
+
const targets = allTargets(projectDir, projectName).map((target) => buildTargetStatus(cwd, projectDir, projectName, target));
|
|
129
|
+
const sharedLayers = readSharedLayers(projectDir);
|
|
130
|
+
const sharedLayerStatuses = sharedLayers.length > 0
|
|
131
|
+
? sharedLayers.map((layer) => buildSharedLayerStatus(projectDir, layer))
|
|
132
|
+
: undefined;
|
|
133
|
+
return {
|
|
134
|
+
project: projectName,
|
|
135
|
+
targets,
|
|
136
|
+
...(sharedLayerStatuses ? { shared_layers: sharedLayerStatuses } : {}),
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
function printReport(result) {
|
|
140
|
+
console.log("OpenUISpec Status");
|
|
141
|
+
console.log("=================");
|
|
142
|
+
console.log(`Project: ${result.project}`);
|
|
143
|
+
console.log("");
|
|
144
|
+
for (const target of result.targets) {
|
|
145
|
+
const summary = target.snapshot
|
|
146
|
+
? `${target.changed} changed, ${target.added} added, ${target.removed} removed`
|
|
147
|
+
: target.output_exists
|
|
148
|
+
? "no snapshot"
|
|
149
|
+
: "output missing";
|
|
150
|
+
console.log(`${target.target}`);
|
|
151
|
+
console.log(` output: ${target.output_dir}`);
|
|
152
|
+
console.log(` output exists: ${target.output_exists ? "yes" : "no"}`);
|
|
153
|
+
console.log(` snapshot: ${target.snapshot ? target.snapshot_at : "missing"}`);
|
|
154
|
+
if (target.baseline.label) {
|
|
155
|
+
console.log(` baseline: ${target.baseline.label}`);
|
|
156
|
+
}
|
|
157
|
+
console.log(` drift: ${summary}`);
|
|
158
|
+
console.log(` status: ${target.status}`);
|
|
159
|
+
console.log(` explain: ${target.explain_available ? "available" : "unavailable"}`);
|
|
160
|
+
if (target.note) {
|
|
161
|
+
console.log(` note: ${target.note}`);
|
|
162
|
+
}
|
|
163
|
+
console.log(` next: ${target.recommended_next_step}`);
|
|
164
|
+
console.log("");
|
|
165
|
+
}
|
|
166
|
+
if (result.shared_layers && result.shared_layers.length > 0) {
|
|
167
|
+
console.log("Shared Layers");
|
|
168
|
+
console.log("─────────────");
|
|
169
|
+
for (const layer of result.shared_layers) {
|
|
170
|
+
console.log(`${layer.name} (${layer.platforms.join(", ")})`);
|
|
171
|
+
console.log(` root: ${layer.root}`);
|
|
172
|
+
console.log(` snapshot: ${layer.snapshot ? layer.snapshot_at : "missing"}`);
|
|
173
|
+
if (layer.generated_by_target) {
|
|
174
|
+
console.log(` generated by: ${layer.generated_by_target}`);
|
|
175
|
+
}
|
|
176
|
+
console.log(` status: ${layer.status}`);
|
|
177
|
+
console.log("");
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
export function runStatus(argv) {
|
|
182
|
+
const isJson = argv.includes("--json");
|
|
183
|
+
const result = buildStatusResult(process.cwd());
|
|
184
|
+
if (isJson) {
|
|
185
|
+
console.log(JSON.stringify(result, null, 2));
|
|
186
|
+
return;
|
|
187
|
+
}
|
|
188
|
+
printReport(result);
|
|
189
|
+
}
|
|
190
|
+
const isDirectRun = process.argv[1]?.endsWith("status/index.ts") ||
|
|
191
|
+
process.argv[1]?.endsWith("status/index.js");
|
|
192
|
+
if (isDirectRun) {
|
|
193
|
+
runStatus(process.argv.slice(2));
|
|
194
|
+
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
<svg width="100%" viewBox="0 0 680 470" xmlns="http://www.w3.org/2000/svg">
|
|
2
|
+
<defs>
|
|
3
|
+
<marker id="arrow" viewBox="0 0 10 10" refX="8" refY="5" markerWidth="6" markerHeight="6" orient="auto-start-reverse"><path d="M2 1L8 5L2 9" fill="none" stroke="context-stroke" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/></marker>
|
|
4
|
+
|
|
5
|
+
<mask id="imagine-text-gaps-o7de63" maskUnits="userSpaceOnUse"><rect x="0" y="0" width="680" height="470" fill="white"/><rect x="256.6324462890625" y="12.305379867553711" width="166.73512268066406" height="20.52798843383789" fill="black" rx="2"/><rect x="69.6505126953125" y="62.305381774902344" width="90.69898223876953" height="20.527990341186523" fill="black" rx="2"/><rect x="46.96881103515625" y="84.19429016113281" width="136.0624237060547" height="18.16684913635254" fill="black" rx="2"/><rect x="91.05573272705078" y="120.19429779052734" width="47.88853454589844" height="18.16684913635254" fill="black" rx="2"/><rect x="83.20494079589844" y="156.1942901611328" width="63.590126037597656" height="18.16684913635254" fill="black" rx="2"/><rect x="75.04055786132812" y="192.19430541992188" width="79.91889953613281" height="18.16684913635254" fill="black" rx="2"/><rect x="88.12275695800781" y="228.19430541992188" width="53.75449752807617" height="18.16684913635254" fill="black" rx="2"/><rect x="94.92210388183594" y="264.1943054199219" width="40.15579605102539" height="18.16684913635254" fill="black" rx="2"/><rect x="69.73905181884766" y="300.1943054199219" width="90.52189636230469" height="18.16684913635254" fill="black" rx="2"/><rect x="67.63247680664062" y="336.1943054199219" width="94.73506164550781" height="18.16684913635254" fill="black" rx="2"/><rect x="73.51688385009766" y="372.1943054199219" width="82.96624755859375" height="18.16684913635254" fill="black" rx="2"/><rect x="217" y="214.1942901611328" width="35.17526435852051" height="18.16684913635254" fill="black" rx="2"/><rect x="292.1412048339844" y="152.30538940429688" width="89.71763610839844" height="20.527990341186523" fill="black" rx="2"/><rect x="300.2318115234375" y="174.1942901611328" width="73.53643798828125" height="18.16684913635254" fill="black" rx="2"/><rect x="280.6084899902344" y="208.1942901611328" width="112.78303527832031" height="18.16684913635254" fill="black" rx="2"/><rect x="272.58062744140625" y="244.1942901611328" width="128.83879852294922" height="18.16684913635254" fill="black" rx="2"/><rect x="288.5773620605469" y="280.1943054199219" width="96.84532928466797" height="18.16684913635254" fill="black" rx="2"/><rect x="442.0000305175781" y="138.1942901611328" width="36.606706619262695" height="18.16684913635254" fill="black" rx="2"/><rect x="442.0000305175781" y="214.1942901611328" width="39.89016914367676" height="18.16684913635254" fill="black" rx="2"/><rect x="442.0000305175781" y="304.1943054199219" width="69.11670303344727" height="18.16684913635254" fill="black" rx="2"/><rect x="519.6734619140625" y="106.30538177490234" width="98.65308380126953" height="20.527990341186523" fill="black" rx="2"/><rect x="507.6279602050781" y="128.1942901611328" width="122.74410247802734" height="18.16684913635254" fill="black" rx="2"/><rect x="497.83660888671875" y="208.30538940429688" width="142.3268280029297" height="20.527990341186523" fill="black" rx="2"/><rect x="505.4365234375" y="230.1942901611328" width="127.12696838378906" height="18.16684913635254" fill="black" rx="2"/><rect x="521.5771484375" y="314.3053894042969" width="94.84574127197266" height="20.527990341186523" fill="black" rx="2"/><rect x="499.4488220214844" y="336.1943054199219" width="139.10238647460938" height="18.16684913635254" fill="black" rx="2"/><rect x="138.05886840820312" y="434.1943054199219" width="403.8822937011719" height="18.16684913635254" fill="black" rx="2"/></mask></defs>
|
|
6
|
+
|
|
7
|
+
<rect width="680" height="460" rx="12" fill="#F5F1E8" style="fill:rgb(245, 241, 232);stroke:none;color:rgb(0, 0, 0);stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;opacity:1;font-family:"Anthropic Sans", -apple-system, "system-ui", "Segoe UI", sans-serif;font-size:16px;font-weight:400;text-anchor:start;dominant-baseline:auto"/>
|
|
8
|
+
|
|
9
|
+
<text x="340" y="28" text-anchor="middle" style="fill:rgb(44, 44, 42);stroke:none;color:rgb(0, 0, 0);stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;opacity:1;font-family:system-ui, -apple-system, sans-serif;font-size:14px;font-weight:500;text-anchor:middle;dominant-baseline:auto">How OpenUISpec works</text>
|
|
10
|
+
|
|
11
|
+
<rect x="40" y="52" width="150" height="370" rx="12" fill="#FAEEDA" stroke="#EF9F27" stroke-width="0.5" style="fill:rgb(250, 238, 218);stroke:rgb(239, 159, 39);color:rgb(0, 0, 0);stroke-width:0.5px;stroke-linecap:butt;stroke-linejoin:miter;opacity:1;font-family:"Anthropic Sans", -apple-system, "system-ui", "Segoe UI", sans-serif;font-size:16px;font-weight:400;text-anchor:start;dominant-baseline:auto"/>
|
|
12
|
+
<text x="115" y="78" text-anchor="middle" fill="#633806" style="fill:rgb(44, 44, 42);stroke:none;color:rgb(0, 0, 0);stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;opacity:1;font-family:system-ui, -apple-system, sans-serif;font-size:14px;font-weight:500;text-anchor:middle;dominant-baseline:auto">OpenUISpec</text>
|
|
13
|
+
<text x="115" y="98" text-anchor="middle" fill="#854F0B" style="fill:rgb(95, 94, 90);stroke:none;color:rgb(0, 0, 0);stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;opacity:1;font-family:system-ui, -apple-system, sans-serif;font-size:12px;font-weight:400;text-anchor:middle;dominant-baseline:auto">Semantic spec (YAML)</text>
|
|
14
|
+
|
|
15
|
+
<rect x="56" y="116" width="118" height="28" rx="6" fill="#FAEEDA" stroke="#EF9F27" stroke-width="0.5" style="fill:rgb(250, 238, 218);stroke:rgb(239, 159, 39);color:rgb(0, 0, 0);stroke-width:0.5px;stroke-linecap:butt;stroke-linejoin:miter;opacity:1;font-family:"Anthropic Sans", -apple-system, "system-ui", "Segoe UI", sans-serif;font-size:16px;font-weight:400;text-anchor:start;dominant-baseline:auto"/><text x="115" y="134" text-anchor="middle" fill="#633806" style="fill:rgb(95, 94, 90);stroke:none;color:rgb(0, 0, 0);stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;opacity:1;font-family:system-ui, -apple-system, sans-serif;font-size:12px;font-weight:400;text-anchor:middle;dominant-baseline:auto">Tokens</text>
|
|
16
|
+
<rect x="56" y="152" width="118" height="28" rx="6" fill="#FAEEDA" stroke="#EF9F27" stroke-width="0.5" style="fill:rgb(250, 238, 218);stroke:rgb(239, 159, 39);color:rgb(0, 0, 0);stroke-width:0.5px;stroke-linecap:butt;stroke-linejoin:miter;opacity:1;font-family:"Anthropic Sans", -apple-system, "system-ui", "Segoe UI", sans-serif;font-size:16px;font-weight:400;text-anchor:start;dominant-baseline:auto"/><text x="115" y="170" text-anchor="middle" fill="#633806" style="fill:rgb(95, 94, 90);stroke:none;color:rgb(0, 0, 0);stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;opacity:1;font-family:system-ui, -apple-system, sans-serif;font-size:12px;font-weight:400;text-anchor:middle;dominant-baseline:auto">Contracts</text>
|
|
17
|
+
<rect x="56" y="188" width="118" height="28" rx="6" fill="#FAEEDA" stroke="#EF9F27" stroke-width="0.5" style="fill:rgb(250, 238, 218);stroke:rgb(239, 159, 39);color:rgb(0, 0, 0);stroke-width:0.5px;stroke-linecap:butt;stroke-linejoin:miter;opacity:1;font-family:"Anthropic Sans", -apple-system, "system-ui", "Segoe UI", sans-serif;font-size:16px;font-weight:400;text-anchor:start;dominant-baseline:auto"/><text x="115" y="206" text-anchor="middle" fill="#633806" style="fill:rgb(95, 94, 90);stroke:none;color:rgb(0, 0, 0);stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;opacity:1;font-family:system-ui, -apple-system, sans-serif;font-size:12px;font-weight:400;text-anchor:middle;dominant-baseline:auto">Components</text>
|
|
18
|
+
<rect x="56" y="224" width="118" height="28" rx="6" fill="#FAEEDA" stroke="#EF9F27" stroke-width="0.5" style="fill:rgb(250, 238, 218);stroke:rgb(239, 159, 39);color:rgb(0, 0, 0);stroke-width:0.5px;stroke-linecap:butt;stroke-linejoin:miter;opacity:1;font-family:"Anthropic Sans", -apple-system, "system-ui", "Segoe UI", sans-serif;font-size:16px;font-weight:400;text-anchor:start;dominant-baseline:auto"/><text x="115" y="242" text-anchor="middle" fill="#633806" style="fill:rgb(95, 94, 90);stroke:none;color:rgb(0, 0, 0);stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;opacity:1;font-family:system-ui, -apple-system, sans-serif;font-size:12px;font-weight:400;text-anchor:middle;dominant-baseline:auto">Screens</text>
|
|
19
|
+
<rect x="56" y="260" width="118" height="28" rx="6" fill="#FAEEDA" stroke="#EF9F27" stroke-width="0.5" style="fill:rgb(250, 238, 218);stroke:rgb(239, 159, 39);color:rgb(0, 0, 0);stroke-width:0.5px;stroke-linecap:butt;stroke-linejoin:miter;opacity:1;font-family:"Anthropic Sans", -apple-system, "system-ui", "Segoe UI", sans-serif;font-size:16px;font-weight:400;text-anchor:start;dominant-baseline:auto"/><text x="115" y="278" text-anchor="middle" fill="#633806" style="fill:rgb(95, 94, 90);stroke:none;color:rgb(0, 0, 0);stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;opacity:1;font-family:system-ui, -apple-system, sans-serif;font-size:12px;font-weight:400;text-anchor:middle;dominant-baseline:auto">Flows</text>
|
|
20
|
+
<rect x="56" y="296" width="118" height="28" rx="6" fill="#FAEEDA" stroke="#EF9F27" stroke-width="0.5" style="fill:rgb(250, 238, 218);stroke:rgb(239, 159, 39);color:rgb(0, 0, 0);stroke-width:0.5px;stroke-linecap:butt;stroke-linejoin:miter;opacity:1;font-family:"Anthropic Sans", -apple-system, "system-ui", "Segoe UI", sans-serif;font-size:16px;font-weight:400;text-anchor:start;dominant-baseline:auto"/><text x="115" y="314" text-anchor="middle" fill="#633806" style="fill:rgb(95, 94, 90);stroke:none;color:rgb(0, 0, 0);stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;opacity:1;font-family:system-ui, -apple-system, sans-serif;font-size:12px;font-weight:400;text-anchor:middle;dominant-baseline:auto">Actions & data</text>
|
|
21
|
+
<rect x="56" y="332" width="118" height="28" rx="6" fill="#FAEEDA" stroke="#EF9F27" stroke-width="0.5" style="fill:rgb(250, 238, 218);stroke:rgb(239, 159, 39);color:rgb(0, 0, 0);stroke-width:0.5px;stroke-linecap:butt;stroke-linejoin:miter;opacity:1;font-family:"Anthropic Sans", -apple-system, "system-ui", "Segoe UI", sans-serif;font-size:16px;font-weight:400;text-anchor:start;dominant-baseline:auto"/><text x="115" y="350" text-anchor="middle" fill="#633806" style="fill:rgb(95, 94, 90);stroke:none;color:rgb(0, 0, 0);stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;opacity:1;font-family:system-ui, -apple-system, sans-serif;font-size:12px;font-weight:400;text-anchor:middle;dominant-baseline:auto">Platform config</text>
|
|
22
|
+
<rect x="56" y="368" width="118" height="28" rx="6" fill="#FAEEDA" stroke="#EF9F27" stroke-width="0.5" style="fill:rgb(250, 238, 218);stroke:rgb(239, 159, 39);color:rgb(0, 0, 0);stroke-width:0.5px;stroke-linecap:butt;stroke-linejoin:miter;opacity:1;font-family:"Anthropic Sans", -apple-system, "system-ui", "Segoe UI", sans-serif;font-size:16px;font-weight:400;text-anchor:start;dominant-baseline:auto"/><text x="115" y="386" text-anchor="middle" fill="#633806" style="fill:rgb(95, 94, 90);stroke:none;color:rgb(0, 0, 0);stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;opacity:1;font-family:system-ui, -apple-system, sans-serif;font-size:12px;font-weight:400;text-anchor:middle;dominant-baseline:auto">Design intent</text>
|
|
23
|
+
|
|
24
|
+
<line x1="194" y1="237" x2="248" y2="237" stroke="#BA7517" stroke-width="1.5" stroke-dasharray="4 3" marker-end="url(#arrow)" style="fill:rgb(0, 0, 0);stroke:rgb(186, 117, 23);color:rgb(0, 0, 0);stroke-width:1.5px;stroke-dasharray:4px, 3px;stroke-linecap:butt;stroke-linejoin:miter;opacity:1;font-family:"Anthropic Sans", -apple-system, "system-ui", "Segoe UI", sans-serif;font-size:16px;font-weight:400;text-anchor:start;dominant-baseline:auto"/>
|
|
25
|
+
<text x="221" y="228" fill="#854F0B" style="fill:rgb(95, 94, 90);stroke:none;color:rgb(0, 0, 0);stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;opacity:1;font-family:system-ui, -apple-system, sans-serif;font-size:12px;font-weight:400;text-anchor:start;dominant-baseline:auto">spec</text>
|
|
26
|
+
|
|
27
|
+
<rect x="252" y="140" width="170" height="194" rx="12" fill="#EEEDFE" stroke="#7F77DD" stroke-width="0.5" style="fill:rgb(238, 237, 254);stroke:rgb(127, 119, 221);color:rgb(0, 0, 0);stroke-width:0.5px;stroke-linecap:butt;stroke-linejoin:miter;opacity:1;font-family:"Anthropic Sans", -apple-system, "system-ui", "Segoe UI", sans-serif;font-size:16px;font-weight:400;text-anchor:start;dominant-baseline:auto"/>
|
|
28
|
+
<text x="337" y="168" text-anchor="middle" fill="#26215C" style="fill:rgb(44, 44, 42);stroke:none;color:rgb(0, 0, 0);stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;opacity:1;font-family:system-ui, -apple-system, sans-serif;font-size:14px;font-weight:500;text-anchor:middle;dominant-baseline:auto">AI generator</text>
|
|
29
|
+
<text x="337" y="188" text-anchor="middle" fill="#534AB7" style="fill:rgb(95, 94, 90);stroke:none;color:rgb(0, 0, 0);stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;opacity:1;font-family:system-ui, -apple-system, sans-serif;font-size:12px;font-weight:400;text-anchor:middle;dominant-baseline:auto">MCP server</text>
|
|
30
|
+
|
|
31
|
+
<rect x="268" y="204" width="138" height="28" rx="6" fill="#EEEDFE" stroke="#7F77DD" stroke-width="0.5" style="fill:rgb(238, 237, 254);stroke:rgb(127, 119, 221);color:rgb(0, 0, 0);stroke-width:0.5px;stroke-linecap:butt;stroke-linejoin:miter;opacity:1;font-family:"Anthropic Sans", -apple-system, "system-ui", "Segoe UI", sans-serif;font-size:16px;font-weight:400;text-anchor:start;dominant-baseline:auto"/><text x="337" y="222" text-anchor="middle" fill="#3C3489" style="fill:rgb(95, 94, 90);stroke:none;color:rgb(0, 0, 0);stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;opacity:1;font-family:system-ui, -apple-system, sans-serif;font-size:12px;font-weight:400;text-anchor:middle;dominant-baseline:auto">Read spec context</text>
|
|
32
|
+
<rect x="268" y="240" width="138" height="28" rx="6" fill="#EEEDFE" stroke="#7F77DD" stroke-width="0.5" style="fill:rgb(238, 237, 254);stroke:rgb(127, 119, 221);color:rgb(0, 0, 0);stroke-width:0.5px;stroke-linecap:butt;stroke-linejoin:miter;opacity:1;font-family:"Anthropic Sans", -apple-system, "system-ui", "Segoe UI", sans-serif;font-size:16px;font-weight:400;text-anchor:start;dominant-baseline:auto"/><text x="337" y="258" text-anchor="middle" fill="#3C3489" style="fill:rgb(95, 94, 90);stroke:none;color:rgb(0, 0, 0);stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;opacity:1;font-family:system-ui, -apple-system, sans-serif;font-size:12px;font-weight:400;text-anchor:middle;dominant-baseline:auto">Generate native code</text>
|
|
33
|
+
<rect x="268" y="276" width="138" height="28" rx="6" fill="#EEEDFE" stroke="#7F77DD" stroke-width="0.5" style="fill:rgb(238, 237, 254);stroke:rgb(127, 119, 221);color:rgb(0, 0, 0);stroke-width:0.5px;stroke-linecap:butt;stroke-linejoin:miter;opacity:1;font-family:"Anthropic Sans", -apple-system, "system-ui", "Segoe UI", sans-serif;font-size:16px;font-weight:400;text-anchor:start;dominant-baseline:auto"/><text x="337" y="294" text-anchor="middle" fill="#3C3489" style="fill:rgb(95, 94, 90);stroke:none;color:rgb(0, 0, 0);stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;opacity:1;font-family:system-ui, -apple-system, sans-serif;font-size:12px;font-weight:400;text-anchor:middle;dominant-baseline:auto">Validate & audit</text>
|
|
34
|
+
|
|
35
|
+
<line x1="426" y1="198" x2="490" y2="134" stroke="#534AB7" stroke-width="1.5" marker-end="url(#arrow)" mask="url(#imagine-text-gaps-o7de63)" style="fill:rgb(0, 0, 0);stroke:rgb(83, 74, 183);color:rgb(0, 0, 0);stroke-width:1.5px;stroke-linecap:butt;stroke-linejoin:miter;opacity:1;font-family:"Anthropic Sans", -apple-system, "system-ui", "Segoe UI", sans-serif;font-size:16px;font-weight:400;text-anchor:start;dominant-baseline:auto"/>
|
|
36
|
+
<line x1="426" y1="237" x2="490" y2="237" stroke="#534AB7" stroke-width="1.5" marker-end="url(#arrow)" style="fill:rgb(0, 0, 0);stroke:rgb(83, 74, 183);color:rgb(0, 0, 0);stroke-width:1.5px;stroke-linecap:butt;stroke-linejoin:miter;opacity:1;font-family:"Anthropic Sans", -apple-system, "system-ui", "Segoe UI", sans-serif;font-size:16px;font-weight:400;text-anchor:start;dominant-baseline:auto"/>
|
|
37
|
+
<line x1="426" y1="276" x2="490" y2="340" stroke="#534AB7" stroke-width="1.5" marker-end="url(#arrow)" mask="url(#imagine-text-gaps-o7de63)" style="fill:rgb(0, 0, 0);stroke:rgb(83, 74, 183);color:rgb(0, 0, 0);stroke-width:1.5px;stroke-linecap:butt;stroke-linejoin:miter;opacity:1;font-family:"Anthropic Sans", -apple-system, "system-ui", "Segoe UI", sans-serif;font-size:16px;font-weight:400;text-anchor:start;dominant-baseline:auto"/>
|
|
38
|
+
|
|
39
|
+
<text x="446" y="152" fill="#5F5E5A" style="fill:rgb(95, 94, 90);stroke:none;color:rgb(0, 0, 0);stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;opacity:1;font-family:system-ui, -apple-system, sans-serif;font-size:12px;font-weight:400;text-anchor:start;dominant-baseline:auto">Swift</text>
|
|
40
|
+
<text x="446" y="228" fill="#5F5E5A" style="fill:rgb(95, 94, 90);stroke:none;color:rgb(0, 0, 0);stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;opacity:1;font-family:system-ui, -apple-system, sans-serif;font-size:12px;font-weight:400;text-anchor:start;dominant-baseline:auto">Kotlin</text>
|
|
41
|
+
<text x="446" y="318" fill="#5F5E5A" style="fill:rgb(95, 94, 90);stroke:none;color:rgb(0, 0, 0);stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;opacity:1;font-family:system-ui, -apple-system, sans-serif;font-size:12px;font-weight:400;text-anchor:start;dominant-baseline:auto">TypeScript</text>
|
|
42
|
+
|
|
43
|
+
<rect x="494" y="92" width="150" height="80" rx="10" fill="#E6F1FB" stroke="#85B7EB" stroke-width="0.5" style="fill:rgb(230, 241, 251);stroke:rgb(133, 183, 235);color:rgb(0, 0, 0);stroke-width:0.5px;stroke-linecap:butt;stroke-linejoin:miter;opacity:1;font-family:"Anthropic Sans", -apple-system, "system-ui", "Segoe UI", sans-serif;font-size:16px;font-weight:400;text-anchor:start;dominant-baseline:auto"/>
|
|
44
|
+
<text x="569" y="122" text-anchor="middle" fill="#042C53" style="fill:rgb(44, 44, 42);stroke:none;color:rgb(0, 0, 0);stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;opacity:1;font-family:system-ui, -apple-system, sans-serif;font-size:14px;font-weight:500;text-anchor:middle;dominant-baseline:auto">iOS — SwiftUI</text>
|
|
45
|
+
<text x="569" y="142" text-anchor="middle" fill="#185FA5" style="fill:rgb(95, 94, 90);stroke:none;color:rgb(0, 0, 0);stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;opacity:1;font-family:system-ui, -apple-system, sans-serif;font-size:12px;font-weight:400;text-anchor:middle;dominant-baseline:auto">Native, platform feel</text>
|
|
46
|
+
|
|
47
|
+
<rect x="494" y="198" width="150" height="80" rx="10" fill="#EAF3DE" stroke="#97C459" stroke-width="0.5" style="fill:rgb(234, 243, 222);stroke:rgb(151, 196, 89);color:rgb(0, 0, 0);stroke-width:0.5px;stroke-linecap:butt;stroke-linejoin:miter;opacity:1;font-family:"Anthropic Sans", -apple-system, "system-ui", "Segoe UI", sans-serif;font-size:16px;font-weight:400;text-anchor:start;dominant-baseline:auto"/>
|
|
48
|
+
<text x="569" y="224" text-anchor="middle" fill="#173404" style="fill:rgb(44, 44, 42);stroke:none;color:rgb(0, 0, 0);stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;opacity:1;font-family:system-ui, -apple-system, sans-serif;font-size:14px;font-weight:500;text-anchor:middle;dominant-baseline:auto">Android — Compose</text>
|
|
49
|
+
<text x="569" y="244" text-anchor="middle" fill="#3B6D11" style="fill:rgb(95, 94, 90);stroke:none;color:rgb(0, 0, 0);stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;opacity:1;font-family:system-ui, -apple-system, sans-serif;font-size:12px;font-weight:400;text-anchor:middle;dominant-baseline:auto">Material You theming</text>
|
|
50
|
+
|
|
51
|
+
<rect x="494" y="304" width="150" height="80" rx="10" fill="#FAECE7" stroke="#F0997B" stroke-width="0.5" style="fill:rgb(250, 236, 231);stroke:rgb(240, 153, 123);color:rgb(0, 0, 0);stroke-width:0.5px;stroke-linecap:butt;stroke-linejoin:miter;opacity:1;font-family:"Anthropic Sans", -apple-system, "system-ui", "Segoe UI", sans-serif;font-size:16px;font-weight:400;text-anchor:start;dominant-baseline:auto"/>
|
|
52
|
+
<text x="569" y="330" text-anchor="middle" fill="#4A1B0C" style="fill:rgb(44, 44, 42);stroke:none;color:rgb(0, 0, 0);stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;opacity:1;font-family:system-ui, -apple-system, sans-serif;font-size:14px;font-weight:500;text-anchor:middle;dominant-baseline:auto">Web — React</text>
|
|
53
|
+
<text x="569" y="350" text-anchor="middle" fill="#993C1D" style="fill:rgb(95, 94, 90);stroke:none;color:rgb(0, 0, 0);stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;opacity:1;font-family:system-ui, -apple-system, sans-serif;font-size:12px;font-weight:400;text-anchor:middle;dominant-baseline:auto">Responsive, accessible</text>
|
|
54
|
+
|
|
55
|
+
<text x="340" y="448" text-anchor="middle" fill="#888780" style="fill:rgb(95, 94, 90);stroke:none;color:rgb(0, 0, 0);stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;opacity:1;font-family:system-ui, -apple-system, sans-serif;font-size:12px;font-weight:400;text-anchor:middle;dominant-baseline:auto">Share the intent · generate native code · each platform feels like home</text>
|
|
56
|
+
</svg>
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
<svg width="100%" viewBox="0 0 680 530" xmlns="http://www.w3.org/2000/svg">
|
|
2
|
+
<defs>
|
|
3
|
+
<marker id="arrow" viewBox="0 0 10 10" refX="8" refY="5" markerWidth="6" markerHeight="6" orient="auto-start-reverse"><path d="M2 1L8 5L2 9" fill="none" stroke="context-stroke" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/></marker>
|
|
4
|
+
|
|
5
|
+
</defs>
|
|
6
|
+
|
|
7
|
+
<rect width="680" height="520" rx="12" fill="#F5F1E8" style="fill:rgb(245, 241, 232);stroke:none;color:rgb(0, 0, 0);stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;opacity:1;font-family:"Anthropic Sans", -apple-system, "system-ui", "Segoe UI", sans-serif;font-size:16px;font-weight:400;text-anchor:start;dominant-baseline:auto"/>
|
|
8
|
+
|
|
9
|
+
<text x="340" y="28" text-anchor="middle" style="fill:rgb(44, 44, 42);stroke:none;color:rgb(0, 0, 0);stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;opacity:1;font-family:system-ui, -apple-system, sans-serif;font-size:14px;font-weight:500;text-anchor:middle;dominant-baseline:auto">Workflows</text>
|
|
10
|
+
|
|
11
|
+
<rect x="40" y="48" width="106" height="26" rx="13" fill="#FAEEDA" stroke="#EF9F27" stroke-width="0.5" style="fill:rgb(250, 238, 218);stroke:rgb(239, 159, 39);color:rgb(0, 0, 0);stroke-width:0.5px;stroke-linecap:butt;stroke-linejoin:miter;opacity:1;font-family:"Anthropic Sans", -apple-system, "system-ui", "Segoe UI", sans-serif;font-size:16px;font-weight:400;text-anchor:start;dominant-baseline:auto"/><text x="93" y="65" text-anchor="middle" fill="#633806" style="fill:rgb(95, 94, 90);stroke:none;color:rgb(0, 0, 0);stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;opacity:1;font-family:system-ui, -apple-system, sans-serif;font-size:12px;font-weight:400;text-anchor:middle;dominant-baseline:auto">Design mode</text>
|
|
12
|
+
<text x="158" y="65" style="fill:rgb(95, 94, 90);stroke:none;color:rgb(0, 0, 0);stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;opacity:1;font-family:system-ui, -apple-system, sans-serif;font-size:12px;font-weight:400;text-anchor:start;dominant-baseline:auto">Spec-first — new features, design system changes</text>
|
|
13
|
+
|
|
14
|
+
<rect x="40" y="86" width="152" height="106" rx="10" fill="#FAEEDA" stroke="#EF9F27" stroke-width="0.5" style="fill:rgb(250, 238, 218);stroke:rgb(239, 159, 39);color:rgb(0, 0, 0);stroke-width:0.5px;stroke-linecap:butt;stroke-linejoin:miter;opacity:1;font-family:"Anthropic Sans", -apple-system, "system-ui", "Segoe UI", sans-serif;font-size:16px;font-weight:400;text-anchor:start;dominant-baseline:auto"/>
|
|
15
|
+
<text x="116" y="108" text-anchor="middle" fill="#633806" style="fill:rgb(44, 44, 42);stroke:none;color:rgb(0, 0, 0);stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;opacity:1;font-family:system-ui, -apple-system, sans-serif;font-size:14px;font-weight:500;text-anchor:middle;dominant-baseline:auto">1 · Define</text>
|
|
16
|
+
<text x="116" y="128" text-anchor="middle" fill="#854F0B" style="fill:rgb(95, 94, 90);stroke:none;color:rgb(0, 0, 0);stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;opacity:1;font-family:system-ui, -apple-system, sans-serif;font-size:12px;font-weight:400;text-anchor:middle;dominant-baseline:auto">Author spec YAML</text>
|
|
17
|
+
<text x="116" y="144" text-anchor="middle" fill="#854F0B" style="fill:rgb(95, 94, 90);stroke:none;color:rgb(0, 0, 0);stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;opacity:1;font-family:system-ui, -apple-system, sans-serif;font-size:12px;font-weight:400;text-anchor:middle;dominant-baseline:auto">Tokens, contracts,</text>
|
|
18
|
+
<text x="116" y="160" text-anchor="middle" fill="#854F0B" style="fill:rgb(95, 94, 90);stroke:none;color:rgb(0, 0, 0);stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;opacity:1;font-family:system-ui, -apple-system, sans-serif;font-size:12px;font-weight:400;text-anchor:middle;dominant-baseline:auto">screens, flows</text>
|
|
19
|
+
<text x="116" y="208" text-anchor="middle" fill="#888780" font-style="italic" style="fill:rgb(95, 94, 90);stroke:none;color:rgb(0, 0, 0);stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;opacity:1;font-family:system-ui, -apple-system, sans-serif;font-size:12px;font-weight:400;font-style:italic;text-anchor:middle;dominant-baseline:auto">openuispec validate</text>
|
|
20
|
+
|
|
21
|
+
<line x1="196" y1="139" x2="228" y2="139" stroke="#BA7517" stroke-width="1.5" marker-end="url(#arrow)" style="fill:rgb(0, 0, 0);stroke:rgb(186, 117, 23);color:rgb(0, 0, 0);stroke-width:1.5px;stroke-linecap:butt;stroke-linejoin:miter;opacity:1;font-family:"Anthropic Sans", -apple-system, "system-ui", "Segoe UI", sans-serif;font-size:16px;font-weight:400;text-anchor:start;dominant-baseline:auto"/>
|
|
22
|
+
|
|
23
|
+
<rect x="232" y="86" width="162" height="106" rx="10" fill="#EEEDFE" stroke="#7F77DD" stroke-width="0.5" style="fill:rgb(238, 237, 254);stroke:rgb(127, 119, 221);color:rgb(0, 0, 0);stroke-width:0.5px;stroke-linecap:butt;stroke-linejoin:miter;opacity:1;font-family:"Anthropic Sans", -apple-system, "system-ui", "Segoe UI", sans-serif;font-size:16px;font-weight:400;text-anchor:start;dominant-baseline:auto"/>
|
|
24
|
+
<text x="313" y="108" text-anchor="middle" fill="#26215C" style="fill:rgb(44, 44, 42);stroke:none;color:rgb(0, 0, 0);stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;opacity:1;font-family:system-ui, -apple-system, sans-serif;font-size:14px;font-weight:500;text-anchor:middle;dominant-baseline:auto">2 · Generate</text>
|
|
25
|
+
<text x="313" y="128" text-anchor="middle" fill="#534AB7" style="fill:rgb(95, 94, 90);stroke:none;color:rgb(0, 0, 0);stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;opacity:1;font-family:system-ui, -apple-system, sans-serif;font-size:12px;font-weight:400;text-anchor:middle;dominant-baseline:auto">AI reads spec via MCP</text>
|
|
26
|
+
<text x="313" y="144" text-anchor="middle" fill="#534AB7" style="fill:rgb(95, 94, 90);stroke:none;color:rgb(0, 0, 0);stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;opacity:1;font-family:system-ui, -apple-system, sans-serif;font-size:12px;font-weight:400;text-anchor:middle;dominant-baseline:auto">Produces native code</text>
|
|
27
|
+
<text x="313" y="160" text-anchor="middle" fill="#534AB7" style="fill:rgb(95, 94, 90);stroke:none;color:rgb(0, 0, 0);stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;opacity:1;font-family:system-ui, -apple-system, sans-serif;font-size:12px;font-weight:400;text-anchor:middle;dominant-baseline:auto">per platform target</text>
|
|
28
|
+
<text x="313" y="208" text-anchor="middle" fill="#888780" font-style="italic" style="fill:rgb(95, 94, 90);stroke:none;color:rgb(0, 0, 0);stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;opacity:1;font-family:system-ui, -apple-system, sans-serif;font-size:12px;font-weight:400;font-style:italic;text-anchor:middle;dominant-baseline:auto">openuispec prepare</text>
|
|
29
|
+
|
|
30
|
+
<line x1="398" y1="139" x2="430" y2="139" stroke="#BA7517" stroke-width="1.5" marker-end="url(#arrow)" style="fill:rgb(0, 0, 0);stroke:rgb(186, 117, 23);color:rgb(0, 0, 0);stroke-width:1.5px;stroke-linecap:butt;stroke-linejoin:miter;opacity:1;font-family:"Anthropic Sans", -apple-system, "system-ui", "Segoe UI", sans-serif;font-size:16px;font-weight:400;text-anchor:start;dominant-baseline:auto"/>
|
|
31
|
+
|
|
32
|
+
<rect x="434" y="86" width="152" height="106" rx="10" fill="#EAF3DE" stroke="#97C459" stroke-width="0.5" style="fill:rgb(234, 243, 222);stroke:rgb(151, 196, 89);color:rgb(0, 0, 0);stroke-width:0.5px;stroke-linecap:butt;stroke-linejoin:miter;opacity:1;font-family:"Anthropic Sans", -apple-system, "system-ui", "Segoe UI", sans-serif;font-size:16px;font-weight:400;text-anchor:start;dominant-baseline:auto"/>
|
|
33
|
+
<text x="510" y="108" text-anchor="middle" fill="#173404" style="fill:rgb(44, 44, 42);stroke:none;color:rgb(0, 0, 0);stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;opacity:1;font-family:system-ui, -apple-system, sans-serif;font-size:14px;font-weight:500;text-anchor:middle;dominant-baseline:auto">3 · Refine</text>
|
|
34
|
+
<text x="510" y="128" text-anchor="middle" fill="#3B6D11" style="fill:rgb(95, 94, 90);stroke:none;color:rgb(0, 0, 0);stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;opacity:1;font-family:system-ui, -apple-system, sans-serif;font-size:12px;font-weight:400;text-anchor:middle;dominant-baseline:auto">Platform teams adjust</text>
|
|
35
|
+
<text x="510" y="144" text-anchor="middle" fill="#3B6D11" style="fill:rgb(95, 94, 90);stroke:none;color:rgb(0, 0, 0);stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;opacity:1;font-family:system-ui, -apple-system, sans-serif;font-size:12px;font-weight:400;text-anchor:middle;dominant-baseline:auto">for native polish</text>
|
|
36
|
+
<text x="510" y="160" text-anchor="middle" fill="#3B6D11" style="fill:rgb(95, 94, 90);stroke:none;color:rgb(0, 0, 0);stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;opacity:1;font-family:system-ui, -apple-system, sans-serif;font-size:12px;font-weight:400;text-anchor:middle;dominant-baseline:auto">Snapshot baseline</text>
|
|
37
|
+
<text x="510" y="208" text-anchor="middle" fill="#888780" font-style="italic" style="fill:rgb(95, 94, 90);stroke:none;color:rgb(0, 0, 0);stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;opacity:1;font-family:system-ui, -apple-system, sans-serif;font-size:12px;font-weight:400;font-style:italic;text-anchor:middle;dominant-baseline:auto">openuispec drift --snapshot</text>
|
|
38
|
+
|
|
39
|
+
<line x1="590" y1="139" x2="610" y2="139" stroke="#B4B2A9" stroke-width="0.5" stroke-dasharray="3 2" style="fill:rgb(0, 0, 0);stroke:rgb(180, 178, 169);color:rgb(0, 0, 0);stroke-width:0.5px;stroke-dasharray:3px, 2px;stroke-linecap:butt;stroke-linejoin:miter;opacity:1;font-family:"Anthropic Sans", -apple-system, "system-ui", "Segoe UI", sans-serif;font-size:16px;font-weight:400;text-anchor:start;dominant-baseline:auto"/>
|
|
40
|
+
<rect x="614" y="115" width="52" height="48" rx="8" fill="#E1F5EE" stroke="#5DCAA5" stroke-width="0.5" style="fill:rgb(225, 245, 238);stroke:rgb(93, 202, 165);color:rgb(0, 0, 0);stroke-width:0.5px;stroke-linecap:butt;stroke-linejoin:miter;opacity:1;font-family:"Anthropic Sans", -apple-system, "system-ui", "Segoe UI", sans-serif;font-size:16px;font-weight:400;text-anchor:start;dominant-baseline:auto"/><text x="640" y="135" text-anchor="middle" fill="#085041" style="fill:rgb(95, 94, 90);stroke:none;color:rgb(0, 0, 0);stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;opacity:1;font-family:system-ui, -apple-system, sans-serif;font-size:12px;font-weight:400;text-anchor:middle;dominant-baseline:auto">Native</text><text x="640" y="149" text-anchor="middle" fill="#085041" style="fill:rgb(95, 94, 90);stroke:none;color:rgb(0, 0, 0);stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;opacity:1;font-family:system-ui, -apple-system, sans-serif;font-size:12px;font-weight:400;text-anchor:middle;dominant-baseline:auto">apps</text>
|
|
41
|
+
|
|
42
|
+
<line x1="40" y1="242" x2="640" y2="242" stroke="#D3D1C7" stroke-width="0.5" stroke-dasharray="6 4" style="fill:rgb(0, 0, 0);stroke:rgb(211, 209, 199);color:rgb(0, 0, 0);stroke-width:0.5px;stroke-dasharray:6px, 4px;stroke-linecap:butt;stroke-linejoin:miter;opacity:1;font-family:"Anthropic Sans", -apple-system, "system-ui", "Segoe UI", sans-serif;font-size:16px;font-weight:400;text-anchor:start;dominant-baseline:auto"/>
|
|
43
|
+
<text x="340" y="258" text-anchor="middle" fill="#888780" style="fill:rgb(95, 94, 90);stroke:none;color:rgb(0, 0, 0);stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;opacity:1;font-family:system-ui, -apple-system, sans-serif;font-size:12px;font-weight:400;text-anchor:middle;dominant-baseline:auto">or</text>
|
|
44
|
+
|
|
45
|
+
<rect x="40" y="274" width="132" height="26" rx="13" fill="#E6F1FB" stroke="#85B7EB" stroke-width="0.5" style="fill:rgb(230, 241, 251);stroke:rgb(133, 183, 235);color:rgb(0, 0, 0);stroke-width:0.5px;stroke-linecap:butt;stroke-linejoin:miter;opacity:1;font-family:"Anthropic Sans", -apple-system, "system-ui", "Segoe UI", sans-serif;font-size:16px;font-weight:400;text-anchor:start;dominant-baseline:auto"/><text x="106" y="291" text-anchor="middle" fill="#0C447C" style="fill:rgb(95, 94, 90);stroke:none;color:rgb(0, 0, 0);stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;opacity:1;font-family:system-ui, -apple-system, sans-serif;font-size:12px;font-weight:400;text-anchor:middle;dominant-baseline:auto">Development mode</text>
|
|
46
|
+
<text x="184" y="291" style="fill:rgb(95, 94, 90);stroke:none;color:rgb(0, 0, 0);stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;opacity:1;font-family:system-ui, -apple-system, sans-serif;font-size:12px;font-weight:400;text-anchor:start;dominant-baseline:auto">Platform-first — day-to-day iteration, fixes, polish</text>
|
|
47
|
+
|
|
48
|
+
<rect x="40" y="312" width="152" height="106" rx="10" fill="#EAF3DE" stroke="#97C459" stroke-width="0.5" style="fill:rgb(234, 243, 222);stroke:rgb(151, 196, 89);color:rgb(0, 0, 0);stroke-width:0.5px;stroke-linecap:butt;stroke-linejoin:miter;opacity:1;font-family:"Anthropic Sans", -apple-system, "system-ui", "Segoe UI", sans-serif;font-size:16px;font-weight:400;text-anchor:start;dominant-baseline:auto"/>
|
|
49
|
+
<text x="116" y="334" text-anchor="middle" fill="#173404" style="fill:rgb(44, 44, 42);stroke:none;color:rgb(0, 0, 0);stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;opacity:1;font-family:system-ui, -apple-system, sans-serif;font-size:14px;font-weight:500;text-anchor:middle;dominant-baseline:auto">1 · Code</text>
|
|
50
|
+
<text x="116" y="354" text-anchor="middle" fill="#3B6D11" style="fill:rgb(95, 94, 90);stroke:none;color:rgb(0, 0, 0);stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;opacity:1;font-family:system-ui, -apple-system, sans-serif;font-size:12px;font-weight:400;text-anchor:middle;dominant-baseline:auto">Edit native code</text>
|
|
51
|
+
<text x="116" y="370" text-anchor="middle" fill="#3B6D11" style="fill:rgb(95, 94, 90);stroke:none;color:rgb(0, 0, 0);stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;opacity:1;font-family:system-ui, -apple-system, sans-serif;font-size:12px;font-weight:400;text-anchor:middle;dominant-baseline:auto">Live preview, hot reload</text>
|
|
52
|
+
<text x="116" y="386" text-anchor="middle" fill="#3B6D11" style="fill:rgb(95, 94, 90);stroke:none;color:rgb(0, 0, 0);stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;opacity:1;font-family:system-ui, -apple-system, sans-serif;font-size:12px;font-weight:400;text-anchor:middle;dominant-baseline:auto">Fix, tweak, polish</text>
|
|
53
|
+
|
|
54
|
+
<line x1="196" y1="365" x2="228" y2="365" stroke="#185FA5" stroke-width="1.5" marker-end="url(#arrow)" style="fill:rgb(0, 0, 0);stroke:rgb(24, 95, 165);color:rgb(0, 0, 0);stroke-width:1.5px;stroke-linecap:butt;stroke-linejoin:miter;opacity:1;font-family:"Anthropic Sans", -apple-system, "system-ui", "Segoe UI", sans-serif;font-size:16px;font-weight:400;text-anchor:start;dominant-baseline:auto"/>
|
|
55
|
+
|
|
56
|
+
<rect x="232" y="312" width="162" height="106" rx="10" fill="#FAEEDA" stroke="#EF9F27" stroke-width="0.5" style="fill:rgb(250, 238, 218);stroke:rgb(239, 159, 39);color:rgb(0, 0, 0);stroke-width:0.5px;stroke-linecap:butt;stroke-linejoin:miter;opacity:1;font-family:"Anthropic Sans", -apple-system, "system-ui", "Segoe UI", sans-serif;font-size:16px;font-weight:400;text-anchor:start;dominant-baseline:auto"/>
|
|
57
|
+
<text x="313" y="334" text-anchor="middle" fill="#633806" style="fill:rgb(44, 44, 42);stroke:none;color:rgb(0, 0, 0);stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;opacity:1;font-family:system-ui, -apple-system, sans-serif;font-size:14px;font-weight:500;text-anchor:middle;dominant-baseline:auto">2 · Sync</text>
|
|
58
|
+
<text x="313" y="354" text-anchor="middle" fill="#854F0B" style="fill:rgb(95, 94, 90);stroke:none;color:rgb(0, 0, 0);stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;opacity:1;font-family:system-ui, -apple-system, sans-serif;font-size:12px;font-weight:400;text-anchor:middle;dominant-baseline:auto">AI reads code changes</text>
|
|
59
|
+
<text x="313" y="370" text-anchor="middle" fill="#854F0B" style="fill:rgb(95, 94, 90);stroke:none;color:rgb(0, 0, 0);stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;opacity:1;font-family:system-ui, -apple-system, sans-serif;font-size:12px;font-weight:400;text-anchor:middle;dominant-baseline:auto">Updates spec YAML</text>
|
|
60
|
+
<text x="313" y="386" text-anchor="middle" fill="#854F0B" style="fill:rgb(95, 94, 90);stroke:none;color:rgb(0, 0, 0);stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;opacity:1;font-family:system-ui, -apple-system, sans-serif;font-size:12px;font-weight:400;text-anchor:middle;dominant-baseline:auto">to match platform code</text>
|
|
61
|
+
<text x="313" y="434" text-anchor="middle" fill="#888780" font-style="italic" style="fill:rgb(95, 94, 90);stroke:none;color:rgb(0, 0, 0);stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;opacity:1;font-family:system-ui, -apple-system, sans-serif;font-size:12px;font-weight:400;font-style:italic;text-anchor:middle;dominant-baseline:auto">openuispec drift --explain</text>
|
|
62
|
+
|
|
63
|
+
<line x1="398" y1="365" x2="430" y2="365" stroke="#185FA5" stroke-width="1.5" marker-end="url(#arrow)" style="fill:rgb(0, 0, 0);stroke:rgb(24, 95, 165);color:rgb(0, 0, 0);stroke-width:1.5px;stroke-linecap:butt;stroke-linejoin:miter;opacity:1;font-family:"Anthropic Sans", -apple-system, "system-ui", "Segoe UI", sans-serif;font-size:16px;font-weight:400;text-anchor:start;dominant-baseline:auto"/>
|
|
64
|
+
|
|
65
|
+
<rect x="434" y="312" width="152" height="106" rx="10" fill="#EEEDFE" stroke="#7F77DD" stroke-width="0.5" style="fill:rgb(238, 237, 254);stroke:rgb(127, 119, 221);color:rgb(0, 0, 0);stroke-width:0.5px;stroke-linecap:butt;stroke-linejoin:miter;opacity:1;font-family:"Anthropic Sans", -apple-system, "system-ui", "Segoe UI", sans-serif;font-size:16px;font-weight:400;text-anchor:start;dominant-baseline:auto"/>
|
|
66
|
+
<text x="510" y="334" text-anchor="middle" fill="#26215C" style="fill:rgb(44, 44, 42);stroke:none;color:rgb(0, 0, 0);stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;opacity:1;font-family:system-ui, -apple-system, sans-serif;font-size:14px;font-weight:500;text-anchor:middle;dominant-baseline:auto">3 · Propagate</text>
|
|
67
|
+
<text x="510" y="354" text-anchor="middle" fill="#534AB7" style="fill:rgb(95, 94, 90);stroke:none;color:rgb(0, 0, 0);stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;opacity:1;font-family:system-ui, -apple-system, sans-serif;font-size:12px;font-weight:400;text-anchor:middle;dominant-baseline:auto">Other platforms see</text>
|
|
68
|
+
<text x="510" y="370" text-anchor="middle" fill="#534AB7" style="fill:rgb(95, 94, 90);stroke:none;color:rgb(0, 0, 0);stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;opacity:1;font-family:system-ui, -apple-system, sans-serif;font-size:12px;font-weight:400;text-anchor:middle;dominant-baseline:auto">spec diff and update</text>
|
|
69
|
+
<text x="510" y="386" text-anchor="middle" fill="#534AB7" style="fill:rgb(95, 94, 90);stroke:none;color:rgb(0, 0, 0);stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;opacity:1;font-family:system-ui, -apple-system, sans-serif;font-size:12px;font-weight:400;text-anchor:middle;dominant-baseline:auto">their code accordingly</text>
|
|
70
|
+
<text x="510" y="434" text-anchor="middle" fill="#888780" font-style="italic" style="fill:rgb(95, 94, 90);stroke:none;color:rgb(0, 0, 0);stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;opacity:1;font-family:system-ui, -apple-system, sans-serif;font-size:12px;font-weight:400;font-style:italic;text-anchor:middle;dominant-baseline:auto">openuispec status</text>
|
|
71
|
+
|
|
72
|
+
<line x1="590" y1="365" x2="610" y2="365" stroke="#B4B2A9" stroke-width="0.5" stroke-dasharray="3 2" style="fill:rgb(0, 0, 0);stroke:rgb(180, 178, 169);color:rgb(0, 0, 0);stroke-width:0.5px;stroke-dasharray:3px, 2px;stroke-linecap:butt;stroke-linejoin:miter;opacity:1;font-family:"Anthropic Sans", -apple-system, "system-ui", "Segoe UI", sans-serif;font-size:16px;font-weight:400;text-anchor:start;dominant-baseline:auto"/>
|
|
73
|
+
<rect x="614" y="341" width="52" height="48" rx="8" fill="#E1F5EE" stroke="#5DCAA5" stroke-width="0.5" style="fill:rgb(225, 245, 238);stroke:rgb(93, 202, 165);color:rgb(0, 0, 0);stroke-width:0.5px;stroke-linecap:butt;stroke-linejoin:miter;opacity:1;font-family:"Anthropic Sans", -apple-system, "system-ui", "Segoe UI", sans-serif;font-size:16px;font-weight:400;text-anchor:start;dominant-baseline:auto"/><text x="640" y="361" text-anchor="middle" fill="#085041" style="fill:rgb(95, 94, 90);stroke:none;color:rgb(0, 0, 0);stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;opacity:1;font-family:system-ui, -apple-system, sans-serif;font-size:12px;font-weight:400;text-anchor:middle;dominant-baseline:auto">All in</text><text x="640" y="375" text-anchor="middle" fill="#085041" style="fill:rgb(95, 94, 90);stroke:none;color:rgb(0, 0, 0);stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;opacity:1;font-family:system-ui, -apple-system, sans-serif;font-size:12px;font-weight:400;text-anchor:middle;dominant-baseline:auto">sync</text>
|
|
74
|
+
|
|
75
|
+
<text x="340" y="500" text-anchor="middle" fill="#888780" style="fill:rgb(95, 94, 90);stroke:none;color:rgb(0, 0, 0);stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;opacity:1;font-family:system-ui, -apple-system, sans-serif;font-size:12px;font-weight:400;text-anchor:middle;dominant-baseline:auto">Spec lives in version control · diffs are human-readable · drift is detected, not hidden</text>
|
|
76
|
+
</svg>
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "openuispec",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.20",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"description": "A semantic UI specification format for AI-native, platform-native app development",
|
|
@@ -10,27 +10,23 @@
|
|
|
10
10
|
"url": "https://github.com/rsktash/openuispec.git"
|
|
11
11
|
},
|
|
12
12
|
"files": [
|
|
13
|
-
"
|
|
14
|
-
"
|
|
15
|
-
"
|
|
16
|
-
"mcp-server/",
|
|
17
|
-
"prepare/",
|
|
18
|
-
"status/",
|
|
19
|
-
"schema/",
|
|
13
|
+
"dist/",
|
|
14
|
+
"cli/target-presets.json",
|
|
15
|
+
"schema/**/*.json",
|
|
20
16
|
"spec/",
|
|
21
17
|
"docs/",
|
|
22
18
|
"examples/*/openuispec/**",
|
|
23
19
|
"examples/*/openuispec.yaml",
|
|
24
20
|
"examples/*/README.md",
|
|
25
|
-
"scripts/",
|
|
26
21
|
"README.md",
|
|
27
22
|
"LICENSE"
|
|
28
23
|
],
|
|
29
24
|
"bin": {
|
|
30
|
-
"openuispec": "./cli/index.
|
|
31
|
-
"openuispec-mcp": "./mcp-server/index.
|
|
25
|
+
"openuispec": "./dist/cli/index.js",
|
|
26
|
+
"openuispec-mcp": "./dist/mcp-server/index.js"
|
|
32
27
|
},
|
|
33
28
|
"scripts": {
|
|
29
|
+
"build": "tsc -p tsconfig.build.json && node scripts/fix-dist-bins.mjs",
|
|
34
30
|
"test": "node --import tsx --test tests/check.test.ts tests/configure-target.test.ts tests/drift-prepare.test.ts tests/init.test.ts tests/mcp-tools.test.ts tests/semantic-lint.test.ts tests/status.test.ts",
|
|
35
31
|
"test:screenshot": "node --import tsx --test tests/mcp-screenshot.test.ts",
|
|
36
32
|
"test:all": "node --import tsx --test tests/*.test.ts",
|
|
@@ -45,6 +41,8 @@
|
|
|
45
41
|
"drift:snapshot": "tsx drift/index.ts --snapshot --target",
|
|
46
42
|
"prepare:target": "tsx prepare/index.ts",
|
|
47
43
|
"status": "tsx status/index.ts",
|
|
44
|
+
"prepare": "npm run build",
|
|
45
|
+
"prepack": "npm run build",
|
|
48
46
|
"postinstall": "echo \"\\n ✓ openuispec installed — if upgrading, run: openuispec update-rules\\n\"",
|
|
49
47
|
"cloc": "cloc --exclude-dir=$(tr '\n' ',' < .cloc-ignore) ."
|
|
50
48
|
},
|
|
@@ -52,14 +50,15 @@
|
|
|
52
50
|
"@modelcontextprotocol/sdk": "^1.27.1",
|
|
53
51
|
"ajv": "^8.17.1",
|
|
54
52
|
"ajv-formats": "^3.0.1",
|
|
55
|
-
"
|
|
56
|
-
"
|
|
53
|
+
"yaml": "^2.7.1",
|
|
54
|
+
"zod": "^3.25.76"
|
|
57
55
|
},
|
|
58
56
|
"optionalDependencies": {
|
|
59
57
|
"puppeteer": "^24.39.1"
|
|
60
58
|
},
|
|
61
59
|
"devDependencies": {
|
|
62
60
|
"@types/node": "^25.5.0",
|
|
61
|
+
"tsx": "^4.19.4",
|
|
63
62
|
"typescript": "^5.8.3"
|
|
64
63
|
}
|
|
65
64
|
}
|