Teach Skill to publish valid Plans - #14
Conversation
Technical review
The digest is exactly rightI reimplemented Independent implementation, same value, so the length-prefixed framing is precise enough that a second reading of the spec reproduces it. That is the third time this digest definition has survived that test in this series. The digest identifies the right bytes. My finding is about whether anyone will be able to find those bytes later. Finding: the pin is a branch head, and CI checks it out
That matters more than usual because of where the value appears. Of the five tracked-source occurrences, one is a checkout: # .github/workflows/ci.yml:33
ref: 527c7875dc83f2d391978b352d88c340db79fd59If cli#14 is rebased before merging, that commit stops being reachable and this repository's CI fails at checkout with a reference error. Not a stale link in a document, a red build with a confusing cause. Rebasing before merge is the norm across these repositories rather than a hypothetical. Working through this series I have watched it happen to firstdraft #264, #265, #270, #273, #277, #278, #279, and #280, and cli#12 itself was rebased between my review and its merge. On that record the pin is more likely to rot than not. This is also the same failure that produced cli#12. There the pin was The check is one API call, and it is the same one that would have caught
On the deliberate partThe body is explicit that this depends on cli#14 and that the endpoint is unreleased, so the dependency is disclosed rather than hidden, and repinning after the CLI merges is clearly the plan. Nothing here is a surprise. The gap between "we will repin" and "CI keeps working until we do" is what I am pointing at. If the intent is to land this before cli#14, the workflow The rest holds upThe contract check grew from 7 lines to 841 and now covers replay, reconciliation, privacy, personal-account ownership, Project and source identity, and each outer lifecycle status, exercised against both the source runner and the packed executable. Keeping the provisional publication contract distinct from the earlier local Compilation evidence pin is the right separation, and the body states plainly that there is no live endpoint, no npm availability, and no real repository mutation behind any of it. One findingPin a reachable revision, or accept that |
Lesson: a commit SHA is immutable, which is not the same as permanentThese two properties get conflated constantly, and the difference is where a whole class of broken builds comes from. Immutable means the bytes at that hash will never be different bytes. Guaranteed by the hash. Permanent means the object will still be there when you go looking. Guaranteed by nothing, unless something references it. Git keeps an object alive because a branch, a tag, or a reachable ancestor points at it. Cut every path to a commit and it becomes garbage, and eventually the collector agrees. How a pull request branch head evaporatesYou pin the head of an open PR, because a SHA feels like the careful choice: - uses: actions/checkout@v7
with:
repository: myorg/other-repo
ref: 527c7875dc83f2d391978b352d88c340db79fd59Then the PR is rebased. Rebasing does not move commits, it creates new ones with the same changes and different parents. The originals are now unreferenced. The branch is deleted on merge, garbage collection runs, and your Your build fails with a reference error in a repository nobody touched. The commit that "can never change" cannot be found. Squash-merging does the same thing, and it is the default on a lot of repositories. The one-call checkRead
Locally the same question is Ten seconds, and it is the difference between a citation and a time bomb. The wider patternThis is one instance of something more general: a reference is only as durable as the thing keeping its target alive.
In every case, ask what is keeping the target alive, and whether that thing outlives the reference. When you must cite something impermanentSometimes the honest answer is that the thing you ran genuinely is not on Two options that stay honest: Anchor by content. If you can hash what you depend on, cite the hash alongside the revision. A digest over the source tree still identifies the exact bytes even after the commit is collected, and anyone with a copy can verify it. Make the dependency explicit and ordered. If the pin cannot be permanent yet, say so and sequence the merges, so the thing being pinned lands first and the pin is rewritten to its merged revision before anything depends on it. The rule worth carrying: before pinning a SHA, ask whether |
Define the one-publication authorization and recovery boundaries for the prepared GitHub publication path. Pin and black-box the reviewed CLI contract while keeping local compilation and execution evidence distinct.
1eb976f to
9813085
Compare
|
Addressed in
Verification after the correction:
|
Follow-up on
|
Summary
create-full-stack-appthat an explicit request to create or publish an app authorizes exactly one singleton private GitHub Publication after observed valid analysisplan compile --outputas a separate development pathContract and evidence boundary
This pins the reviewed, merged CLI revision
2d792f20424ae4fcc312d05be6201efb86b1f93band its full runtime-source digest7157b01e556d1c8a9eadf591995e251fe96b703bd612d15d991a304cea794e37. CI proves that the pin is reachable from CLImain, detaches to the exact revision, and then exercises the contract. This deliberately keeps the prepared contract distinct from the earlier local Compilation evidence pin.The Publication endpoint and joined server-to-GitHub path remain unreleased and lack a completed staging smoke. This change does not claim npm availability, a live endpoint, or a real GitHub repository mutation.
Depends on the now-merged firstdraft/cli#14.
Review
Local review on Opus/high completed five passes. All worthwhile feedback was incorporated; the final pass reported no action items.
Verification
npm ci --ignore-scriptssh script/check— 17 tests passednode script/check-cli-contract.mjs /Users/sandbox2/code/firstdraft/cli— source runner and packed executable passed against the exact merged commit7157b01e556d1c8a9eadf591995e251fe96b703bd612d15d991a304cea794e37uv run --with pyyaml python /Users/sandbox2/.codex/skills/.system/skill-creator/scripts/quick_validate.py skills/create-full-stack-app— Skill is validnpm audit --audit-level=high— 0 vulnerabilitiesgit diff --check