fix: correct tool shapes, installer hang, and the half-built non-Stitch source paths - #23
Merged
Conversation
added 3 commits
July 20, 2026 21:34
A review pass caught that several documented tool shapes no longer match the
live server. Anyone following these docs would build calls the API rejects.
Verified every one of the 15 tools against the live schemas rather than
patching only what was reported — which turned up two more nobody had flagged.
apply_design_system was the worst of it. Docs said `selectedScreenIds:
["abc123"]`; the API takes `selectedScreenInstances: [{id, sourceScreen}]`.
Both new DESIGN.md skills route into it, so the feature this release is built
around dead-ended. The instance id is not the source screen id, and swapping
them fails — the skill now says so explicitly.
update_design_system was structurally wrong: `name` was nested inside
`designSystem` and `projectId` was absent entirely. The live tool takes all
three as siblings, all required.
Found by the sweep, not the review:
- generate_variants documented `prompt` and `variantOptions` as optional;
both are required
- get_screen omitted `name` altogether — it's the current identifier and
takes the full resource path, while projectId/screenId are deprecated but
still mandatory
Also corrected:
- assetId goes BARE to apply_design_system but PREFIXED to
generate_screen_from_text and update_design_system. Three skills taught the
wrong form; each now states which tool wants which.
- generate_screen_from_text was missing its `designSystem` param. Here the
skills were right and our schema was stale — that param is what makes
DESIGN.md -> design system -> generation actually hold together.
- Input payloads sent `font`, `backgroundLight`, `backgroundDark`,
`description`, `designTokens`, `styleGuidelines`. None exist on the live
input. The output examples that show `font` stay — it is returned, just not
settable.
- DesignTheme had `required: null` despite requiring five fields
- `ROBOTO` was offered as a font value; it isn't in the enum (`ROBOTO_FLEX`
is). Same class as the fictional names caught earlier.
- Skill/tool counts and the two new wrappers were missing from AGENTS.md and
the agent definition, so the shipped agent didn't know its own new skills
existed.
All 15 schemas now match the live server on properties and required fields,
checked programmatically.
`npx @booplex/stitch-kit < /dev/null`, or any run without a TTY — CI, Docker, a piped install — printed the API-key prompt and then died with "Detected unsettled top-level await". readline's question callback never fires on EOF, so the promise never settled and node exited partway through. The user got a silently failed install, no error, no skills. prompt() now returns '' when stdin isn't a TTY, and listens for readline's `close` event so EOF resolves instead of hanging. Callers already treat empty as "skipped", so the install continues and prints the manual MCP config. Verified against a scratch HOME seeded with all seven client marker directories: exits 0, installs the agent and 36 skills to Codex/OpenCode, 36 skills to Crush, agent-only to Claude Code (skills ship via the plugin), and MCP-only config for Cursor and VS Code — which matches the "Works with" table in the README exactly.
Accepting local HTML and URLs was bolted onto Step 1 without touching the rest of each skill, so the new routes were a door with no room behind it. Design tokens assumed a Stitch-emitted `tailwind.config` in `<head>`. Ordinary HTML doesn't have one, so the two routes we just advertised had no way to resolve colors, fonts, radii or dark mode. All six skills now resolve tokens in order — inline tailwind.config, then CSS custom properties, then a linked or inline stylesheet, then inferring from the most frequent computed values and telling the user what was inferred. They also state that the URL route only fetches the single HTML response, so linked stylesheets may not come along, and to say so rather than invent a palette. React Native and SwiftUI promised three sources then demanded a Stitch design with `deviceType: MOBILE` in five places each — including telling users to "regenerate with deviceType: MOBILE", which is meaningless to someone who handed over a local file. The constraint was always a mobile *layout*, not a Stitch artefact. Stitch screens are still checked via deviceType; local files and URLs are checked by viewport meta, mobile-first media queries, narrow root widths and touch-sized targets. The mobile-only requirement is unchanged. Also: - README no longer claims every target ships TypeScript and ARIA. Dark mode and tokens are universal; TS/ARIA are web-target only, SwiftUI emits Swift with native accessibility APIs, and the HTML target has no build step. - `create_design_system_from_design_md.json` had `$defs` outside the `arguments` fragment the schema README calls the complete input schema, so its `$ref` didn't resolve when validated standalone. Moved inside.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Three review passes plus an exhaustive schema comparison and an actual install test. Everything here would have shipped broken in 1.12.0.
Would have failed every call
apply_design_systemdocumentedselectedScreenIds: ["abc"]; the live API takesselectedScreenInstances: [{id, sourceScreen}]. Both new DESIGN.md skills route into it, so the release's headline feature dead-ended.update_design_systemwas structurally wrong —namenested insidedesignSystem,projectIdabsent entirely. Live takes all three as siblings, all required.Found by comparing all 15 tools against live rather than only the reported ones:
generate_variants—promptandvariantOptionsdocumented optional, actually requiredget_screen—namemissing entirely; it's the current identifier and takes the full resource path, whileprojectId/screenIdare deprecated but still mandatoryAll 15 schemas now match live on properties and required fields, checked programmatically.
Installer died in any non-TTY context
npx @booplex/stitch-kitunder CI, Docker, or piped input printed the API-key prompt then exited withDetected unsettled top-level await. readline's callback never fires on EOF, so the promise never settled — a silently failed install.Verified fixed against a scratch
HOMEseeded with all seven client markers: exits 0, agent + 36 skills to Codex and OpenCode, 36 skills to Crush, agent-only to Claude Code (skills ship via plugin), MCP-only for Cursor and VS Code. That also makes the README's "Works with" table a measured fact rather than an unverified claim.The non-Stitch routes were a door with no room
PR #21 made six conversion skills accept local HTML and URLs, but only edited Step 1:
tailwind.config. Arbitrary HTML has none, so the new routes couldn't resolve colors, fonts, radii or dark mode at all. Now a four-step chain — tailwind.config → CSS custom properties → linked/inline stylesheet → infer from dominant computed values and say what was inferred. Plus an explicit note that the URL route fetches only the single HTML response.deviceType: MOBILE" — meaningless to someone who supplied a local file. The constraint was always a mobile layout. Stitch screens still checkdeviceType; local files and URLs check viewport meta, mobile-first media queries, narrow root widths, touch targets. Mobile-only requirement unchanged.Smaller corrections
assetIdgoes bare toapply_design_systembut prefixed togenerate_screen_from_textandupdate_design_system— three skills taught the wrong formgenerate_screen_from_textwas missing itsdesignSystemparam. Here the skills were right and our schema was stale — that param is what makes DESIGN.md → design system → generation hold togetherfont,backgroundLight,backgroundDark,description,designTokens,styleGuidelines— none exist on the live input. Output examples showingfontstay; it's returned, just not settableDesignThemehadrequired: nulldespite requiring five fieldsROBOTOoffered as a font value; not in the enum (ROBOTO_FLEXis)create_design_system_from_design_md.jsonhad$defsoutside theargumentsfragment, so its$refdidn't resolve standaloneAGENTS.mdand the agent definition, so the shipped agent didn't know its own new skills existedValidator:
Passed with 30 warning(s) — no errors.