Integrate create-full-stack-app Skill - #6
Conversation
Establish a portable pre-Compilation workflow before the CLI and API support nonempty import. Keep deterministic operations in the CLI, bundle the exact provisional schema, and make concurrency, recovery, privacy, and capability stops explicit.
Make the public name and discovery copy describe the complete First Draft journey rather than the internal Foundation Plan stage. Keep the current pre-Compilation scaffold explicit, and refresh the vendored 0.19 schema to the merged Project-graph baseline.
Stage an existing Plan and opaque CLI state for diagnostic and recovery cases so their preservation behavior is observable. Bind the unsupported-content diagnostic to the exact staged Plan bytes.
Let the Skill exercise the first useful server-backed modeling slice. Keep unsupported product meaning fail-closed and bind the documented capability boundary to schema-valid eval fixtures.
Treat the bundled schema as validator input instead of prose so agents do not spend context reading it end to end. Define bounded behavior for named, absent, failing, and library-only validator cases. Keep identity and reporting boundaries explicit.
Document stable value identities and ordinal semantics. Add local and push evals to keep importer and recovery boundaries honest.
Field defaults are schema-valid tagged values, but the Skill still treated them as an unsupported capability. Teach agents to preserve identity, author canonical literal and environment forms, and distinguish omission from literal null. Extend examples and behavioral evals to cover enum/default coupling, canonical decimal strings, and recovery across multiple diagnostics. Pin the guidance to the reviewed API baseline.
The bounded authoring API has moved from its reviewed branch onto the First Draft mainline, while the required CLI remains unreleased. Pin the Skill to that merged evidence without expanding its authoring claims.\n\nMake server-backed eval prerequisites explicit and replace reusable-looking state with a synthetic, clearly named placeholder so manual evaluation fails toward review rather than accidental reuse.
Technical reviewThe five component PRs opened before this watcher's cutoff and were not reviewed here, so this is a first read of the whole Skill rather than an integration check. The branch is eight linear commits with no merge, so there is no conflict resolution to audit. Most of this PR is prose that instructs an agent, which usually makes verification hard. This one is an exception, because nearly every claim in the body is mechanically checkable. So I checked all of them. Every pinned claim holdsThe vendored schema is byte-identical to upstream, three ways. The claimed digest, the file on this branch, the file at the pinned revision That matters more than it looks. A vendored schema that has quietly drifted from the server enforcing it would teach agents to author Plans the server rejects, and the failure would surface as confusing diagnostics rather than as a version mismatch. Both pinned First Draft commits are ancestors of Both diagnostic fixtures match the implementation. Not approximately. The fixtures are also internally consistent. Each carries a The 412 contract checks out too.
The Skill's own discipline is goodTwo things stand out as more than boilerplate. The instruction never to read the bundled schema end to end is real engineering, not a style note. The file is 4,961 lines. An agent that reads it has spent most of its working memory before writing a single Entity. Routing it to a validator as a file path, and inspecting only the The reporting rules hold claims at their observed boundary, which is the same discipline the parent repository applies to itself:
That is the right instinct, and it is what makes the next section worth raising rather than pedantic. Finding: the discovery strings claim a product that does not exist yetThe SKILL.md body is careful. It says the Skill is experimental and that the slices "are not released end to end." The README goes further and says plainly: "Do not install this Skill for ordinary use yet." The strings an agent actually reads before deciding to invoke the Skill say something else entirely. The frontmatter description promises a workflow that "deterministically generates a high-quality Foundation" including "accessible web, iOS, and Android clients." The OpenAI manifest is more direct: short_description: "Create and deploy a Rails app for web, iOS, and Android"
default_prompt: "Use $create-full-stack-app to turn my software idea into a robust, deployed Rails application for web, iOS, and Android."None of that is hedged, and the Against the observed boundary: no generated application exists. First Draft's evidence ledger still lists filesystem materialization and a generated application as absent, which I confirmed while reviewing #235 earlier today. The Compiler is not implemented. The CLI these instructions depend on lives in an unmerged branch. And the parent repository's guardrails name this exact pattern, that "iOS is not Android; Simulator preview is not phone installation." The description is the one part of a Skill that gets loaded into an agent's context before any of the hedging does. An agent selecting from a list of Skills sees "Create and deploy a Rails app for web, iOS, and Android" and reasonably concludes the capability exists. It then reads the body and discovers it does not. The fix is cheap, because the body and README already contain the right language. Carrying "experimental" or "in development" into the three discovery strings would align them with everything else in the repository. Worth doing before the Skill is published anywhere discoverable, since a description is the hardest thing to walk back once agents have acted on it. Finding: two recovery branches depend on CLI prose that nothing pinsThe recovery rules tell the agent to branch on five distinct push outcomes. Three are keyed on machine-readable values: The other two are keyed on English sentences.
That is matching this exact string from the CLI's The damaged-local-files branch works the same way, keyed on "Could not read the local First Draft Plan or state." This happens because the CLI collapses five failure classes onto two exit codes and emits JSON for only some of them. I raised the CLI side of this on firstdraft/cli#5 as a design suggestion. Seeing the consumer makes it concrete rather than theoretical: the Skill genuinely needs to distinguish "retry is safe" from "stop, state is unrecoverable," and for two of the five cases the only available signal is a sentence. Nothing pins the two repositories together. A machine-readable Small note
|
Lesson: memory is a budget now, and other things this Skill gets rightMost of this PR is Markdown that tells an agent how to behave. That is a genuinely new kind of artifact, and it has engineering constraints that are not obvious until you hit them. Three of them show up here clearly. The 4,961-line file that must never be readThe Skill bundles the Foundation Plan JSON Schema, which is the authoritative definition of what a valid Plan looks like. It is 4,961 lines. The instructions are emphatic that the agent must not read it:
That looks backwards at first. Why ship a specification to something whose whole job is following specifications, then forbid it from looking? Because an agent has a fixed working memory, and everything competes for it: the user's request, the project's files, the Plan being written, and every tool result so far. Reading five thousand lines of schema spends most of that budget before any actual work begins. Worse, the useful signal gets buried. An agent that has just read 4,961 lines of nested The instructions route around it instead. Pass the schema as a file to a validator, which reads it properly and returns a short list of errors. Open the schema only to answer a specific structural question, and only the relevant definition. The schema stays authoritative without ever being in context. That is the move worth remembering: when a reference is large and precise, prefer a tool that consumes it over an agent that reads it. It is the same instinct as Tool output is untrusted inputThis line is doing more work than it appears to:
Think about what a validator error message contains. Some of it is the validator's own text. Some of it is your data, echoed back: the property name that failed, the value that was out of range. If a Plan contains a field named something like This is the injection problem, and it should feel familiar. It is the same shape as SQL injection and XSS. Data crosses into a place where instructions are interpreted, and nothing marks the boundary. The defense is also the same shape. In SQL you use bound parameters so user data can never be parsed as SQL. Here you cannot bind anything, because the whole interface is natural language, so the defense has to be a standing rule that output from tools is data and only the user and the Skill give instructions. Worth carrying into ordinary Rails work: anything you interpolate into a prompt is untrusted, including output from your own tools. A Pinning a copy, and proving the copy is honestThe Skill vendors its own copy of the schema rather than fetching it at runtime. That is the right call for something that must work offline and behave identically every time, but a vendored copy is a copy, and copies drift. A schema that has quietly diverged from the server is worse than no schema, because it teaches confident authoring of documents the server rejects. So the PR pins the copy with a digest: That single line is a claim anybody can check. I ran it three ways: against the file on the branch, against the upstream file at the pinned revision, and against upstream's current You use this constantly without thinking about it. The habit generalizes. When you copy something whose meaning is owned elsewhere, record where it came from and how to prove it is still the same. Copy a fixture from another repo, an error-code list from a vendor, a config from a sibling service, and it will be right on the day you paste it. Six months later nobody can tell whether it drifted. A pinned revision plus a digest turns "probably fine" into a check that fails on its own. Why this style of writing is hardThere is a pattern across all three. Each one is a rule the agent cannot verify from where it stands, written down because getting it wrong is expensive and invisible. The agent cannot tell that reading the schema cost it accuracy later, cannot tell that a validator message came from a hostile Plan, and cannot tell that a vendored file drifted. Writing this well is unlike writing documentation for people. A person reading a 5,000-line schema gets bored and skims, which is a crude but real defense. An agent reads all of it, dutifully, and is worse off for it. Instructions have to supply the judgment that experience would supply for a human. Which is also why the review of a file like this is mostly a matter of checking claims. Prose that instructs a machine can still be wrong in ways a digest, a fixture, or a pinned revision will catch. |
Discovery metadata is loaded before the body guardrails, so it must describe the workflow users can actually invoke today. Mark Plan authoring and diagnostics experimental and document the temporary CLI prose coupling until stable error codes exist.
|
Addressed both technical-review findings in
The remaining work belongs in firstdraft/cli#5: give those failures stable machine-readable error codes, then update this Skill to branch on the codes and remove the prose dependency. This change deliberately does not invent future codes. Final verification is green: 11 Skills tests, zero npm vulnerabilities, publishing dry run, unchanged schema digest, exact CLI-source sentence checks, 66 First Draft importer/API tests with 895 assertions, and hosted Node 22/24 CI. |
Summary
create-full-stack-appscaffold and its bounded authoring guidance intomain500d23eComponent reviews
This integration preserves the reviewed history of:
create-full-stack-appscaffoldThe component PRs remain open for review history until this integration PR is merged.
Boundaries
12fa2a6, with SHA-2565994c41f65eab52f92020fa24437e76b6957b7016ccf231dce06e8097f0b34b5.firstdraftCLI.Verification
npm ci --ignore-scriptssh script/check— 11 tests passnpm audit --audit-level=low— 0 vulnerabilitiesgh skill publish --dry-run .— structurally valid with the existing license and tag-protection advisoriesmaincontains API baseline500d23emainmain