Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,8 @@ jobs:
fetch-depth: 0
path: tmp/firstdraft-cli
persist-credentials: false
- run: git -C tmp/firstdraft-cli merge-base --is-ancestor 799a184cb2453ceadf5575f7b46ba975e084f192 HEAD
- run: git -C tmp/firstdraft-cli checkout --detach 799a184cb2453ceadf5575f7b46ba975e084f192
- run: git -C tmp/firstdraft-cli merge-base --is-ancestor 137ef9ceff7469e43f072009e3bba941abc6cd4c HEAD
- run: git -C tmp/firstdraft-cli checkout --detach 137ef9ceff7469e43f072009e3bba941abc6cd4c
- run: node script/check-cli-contract.mjs tmp/firstdraft-cli
- run: node script/check-claude-plugin-package.mjs --cli-root tmp/firstdraft-cli
- name: Check Codex installation and Skill discovery
Expand Down
8 changes: 4 additions & 4 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,8 @@ jobs:
fetch-depth: 0
path: tmp/firstdraft-cli
persist-credentials: false
- run: git -C tmp/firstdraft-cli merge-base --is-ancestor 799a184cb2453ceadf5575f7b46ba975e084f192 HEAD
- run: git -C tmp/firstdraft-cli checkout --detach 799a184cb2453ceadf5575f7b46ba975e084f192
- run: git -C tmp/firstdraft-cli merge-base --is-ancestor 137ef9ceff7469e43f072009e3bba941abc6cd4c HEAD
- run: git -C tmp/firstdraft-cli checkout --detach 137ef9ceff7469e43f072009e3bba941abc6cd4c
- run: node script/check-cli-registry-package.mjs --cli-root tmp/firstdraft-cli
- run: node script/check-claude-plugin-package.mjs --cli-root tmp/firstdraft-cli

Expand Down Expand Up @@ -118,8 +118,8 @@ jobs:
fetch-depth: 0
path: tmp/firstdraft-cli
persist-credentials: false
- run: git -C tmp/firstdraft-cli merge-base --is-ancestor 799a184cb2453ceadf5575f7b46ba975e084f192 HEAD
- run: git -C tmp/firstdraft-cli checkout --detach 799a184cb2453ceadf5575f7b46ba975e084f192
- run: git -C tmp/firstdraft-cli merge-base --is-ancestor 137ef9ceff7469e43f072009e3bba941abc6cd4c HEAD
- run: git -C tmp/firstdraft-cli checkout --detach 137ef9ceff7469e43f072009e3bba941abc6cd4c
- run: node script/check-cli-registry-package.mjs --cli-root tmp/firstdraft-cli
- run: node script/claude-plugin-package.mjs pack "$RUNNER_TEMP/plugin" --cli-root tmp/firstdraft-cli
- name: Verify publication bytes
Expand Down
7 changes: 4 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,10 @@ canonical Skills and bundled CLI are packaged once for Claude Code and Codex. UI
app's own design and components. The public catalog and Drawing Board pins determine what an installed workspace
actually receives.

Plugin `0.2.5` documents default Account settings and observed service release identities, with its digest in
[release compatibility](release/compatibility.json). It packages only `create-full-stack-app`. The UI Skill
auditions remain deferred source.
Source candidate `0.3.0` requires CLI `0.3.0` and preserves the planning workspace under `.firstdraft/design/` after
root adoption. Its identities belong in [release compatibility](release/compatibility.json); it is unpublished.
The public catalog remains on plugin `0.2.5`. Only `create-full-stack-app` is packaged; the UI Skill auditions remain
deferred source.

Trying First Draft as a tester? Start with the
[Drawing Board guide](https://github.com/firstdraft/drawing-board#build-an-app-with-first-draft).
Expand Down
12 changes: 6 additions & 6 deletions RELEASING.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ Coordinate the service, CLI, and Skills. [History](evidence/release-history.md)
|---|---|
| Released plugin source | `@firstdraft.com/claude-code@0.2.5`, tag `claude-v0.2.5` |
| Qualified packed SHA-256 | `d9f466076a05e867019bc3e20c35b89076cc83195e781d9203c039d166becde6` |
| Public plugin package | `@firstdraft.com/claude-code@0.2.5` |
| Catalog manifest | Plugin `0.2.5` in `.claude-plugin/marketplace.json` |
| Plugin npm `next` / `latest` | `0.2.5` / `0.2.5` |
| Compatible CLI | `@firstdraft.com/cli@0.2.2` |
Expand All @@ -18,7 +17,12 @@ Coordinate the service, CLI, and Skills. [History](evidence/release-history.md)

[`release/compatibility.json`](release/compatibility.json) owns candidate compatibility; the shared
marketplace manifest owns public catalog selection. Drawing Board's source-Skill pin is separate.
API 0.3.1 permits omitted return overrides; CLI accepts 0.3.

Unpublished candidate `@firstdraft.com/claude-code@0.3.0` requires `@firstdraft.com/cli@0.3.0` for `.firstdraft/design/`.
The breaking root-adoption contract needs both minor bumps; API/Plan ranges and public selections stay unchanged.
Packed SHA-256 `9648469aea9a3f0959e1e4eabde6626edc381d2f3b24ac3cb99be26176edf41b` does not prove registry parity
or hosted root adoption.

[Release evidence](evidence/2026-09-15-account-authoring-0.2.5.md) records each completed qualification and
distribution step. Recheck before mutations.

Expand Down Expand Up @@ -75,10 +79,6 @@ syntax; do not add compatibility aliases.
and service identities. Candidate compatibility and local validation never prove authentication, service
compatibility, a fresh public install, a successful Compile, or GitHub Publication.

Source `@firstdraft.com/claude-code@0.2.5` has SHA-256
`d9f466076a05e867019bc3e20c35b89076cc83195e781d9203c039d166becde6`.
[Qualification](evidence/2026-09-15-account-authoring-0.2.5.md) covers Account guidance; UI Skills stay deferred.

Plugin 0.2.4's [Qualification](evidence/2026-09-14-ui-authoring-skill-0.2.4-qualification.md) records the
[defined checks](evals/create-full-stack-app/ui-foundation-release.md) and limits.
The procedure below records 0.2.2 smokes.
Expand Down
11 changes: 6 additions & 5 deletions evals/create-full-stack-app/cases.json
Original file line number Diff line number Diff line change
Expand Up @@ -1024,16 +1024,17 @@
{
"id": "compile-prepared-current-root",
"should_trigger": true,
"prompt": "I approve the unchanged staged Movie Catalog with SHA-256 52cdb2900607023ad9a10456af35231369bd27c3bf32786297fe3d3eea017a3f and its reviewed support result. Put the generated application at this current workspace root, moving my existing design materials under design. Do not create a GitHub repository. Tell me how to boot it and add features here afterward.",
"prompt": "I approve the unchanged staged Movie Catalog with SHA-256 52cdb2900607023ad9a10456af35231369bd27c3bf32786297fe3d3eea017a3f and its reviewed support result. Use the coordinated archive CLI source candidate to put the generated application at this current workspace root, preserving my existing planning materials directly under .firstdraft/design. Do not create a GitHub repository. Tell me how to boot it and add features here afterward.",
"expectations": [
"Treats the explicit current-root request as selection of firstdraft plan compile --output . and never substitutes an absent application directory or zero-flag Publication without another user decision.",
"Rereads the staged Plan, verifies the approved SHA-256 and semantic model remain unchanged, and runs the selected Compile exactly once without another command-level confirmation or preparatory push or status command.",
"Before mutation, applies the CLI-owned POSIX current-root preconditions: the physical current directory is writable, has no reserved design or .firstdraft-root-output entry, contains only eligible top-level entries, and is not nested inside another worktree; an existing Git root must be clean, nonsparse, operation-free, and have no submodule metadata.",
"Before mutation, verifies the identified CLI candidate supports the requested archive layout instead of assuming published CLI 0.2.2 implements it. Applies the CLI-owned POSIX current-root preconditions: the physical current directory is writable, has no reserved .firstdraft/design or top-level .firstdraft-root-output entry, contains only eligible top-level entries, and is not nested inside another worktree; an existing Git root must be clean, nonsparse, operation-free, and have no submodule metadata.",
"Lets the CLI own the root transaction, artifact verification, same-filesystem moves, rollback journal, and installation instead of moving, deleting, archiving, or overwriting workspace material itself.",
"On success, reports the validated output path, file count, manifest digest, Compilation status, and root_adoption result; prior non-Git top-level material is under design and an existing root .git and history are preserved with the transformation staged.",
"Recognizes that the approved Plan and private CLI state moved to design/.firstdraft, runs any later First Draft plan or compilation command from design, and never initializes a replacement Project in the generated application root.",
"On success, reports the validated output path, file count, manifest digest, Compilation status, and root_adoption result; prior non-Git top-level material is directly under .firstdraft/design and an existing root .git and history are preserved with the transformation staged.",
"Recognizes that the approved Plan and private CLI state moved to .firstdraft/design/.firstdraft, runs any later First Draft plan or compilation command from .firstdraft/design, and never initializes a replacement Project in the generated application root. Keeps that private state separate from the artifact-verified generated .firstdraft/submitted-foundation-plan.json and .firstdraft/gaps.json.",
"Hands off setup, boot, tests, and feature development at the generated Rails workspace root using its README, preserving the same existing .git, history, and remotes rather than initializing a nested repository or changing remotes.",
"Does not run the moved design/script/initialize-application or design/script/application-smoke helpers after root adoption; they belong to the optional nested application mode, which this prompt did not select.",
"Does not run the moved .firstdraft/design/script/initialize-application or .firstdraft/design/script/application-smoke helpers after root adoption; they belong to the optional nested application mode, which this prompt did not select.",
"Treats the archive as optional planning context: ordinary setup, preview, browser tests, and source development use the generated root and platform commands without requiring archived helpers or copying those helpers into the application. Does not remove the archive without a user request or migrate already materialized applications automatically.",
"Explains that requested features can be implemented directly in ordinary Rails source without First Draft Capabilities, Plan edits, or another Compile, and does not restart the First Draft workflow just to continue application development.",
"Recognizes that a non-Git root stays non-Git and makes no Publication, GitHub repository, repository URL, deployment, or newly created Git repository claim.",
"On invalid_output_path or incomplete rollback, preserves owner material and follows the structured recovery reason rather than deleting a conflicting path, running Git restoration blindly, or retrying an outcome-unknown mutation."
Expand Down
2 changes: 1 addition & 1 deletion packages/claude-plugin/.claude-plugin/plugin.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"$schema": "https://json.schemastore.org/claude-code-plugin-manifest.json",
"name": "firstdraft",
"displayName": "First Draft",
"version": "0.2.5",
"version": "0.3.0",
"description": "Author a Foundation Plan and compile a bounded Rails, iPhone, and Android application",
"author": {
"name": "First Draft",
Expand Down
2 changes: 1 addition & 1 deletion packages/claude-plugin/package.template.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@firstdraft.com/claude-code",
"version": "0.2.5",
"version": "0.3.0",
"description": "First Draft Foundation Plan authoring and UI development for Claude Code and Codex",
"license": "MIT",
"type": "module",
Expand Down
6 changes: 3 additions & 3 deletions release/compatibility.json
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
{
"format": "firstdraft.release-compatibility/1",
"component": "skills",
"version": "0.2.5",
"version": "0.3.0",
"plugin_source": {
"package": "@firstdraft.com/claude-code",
"tarball_sha256": "d9f466076a05e867019bc3e20c35b89076cc83195e781d9203c039d166becde6"
"tarball_sha256": "9648469aea9a3f0959e1e4eabde6626edc381d2f3b24ac3cb99be26176edf41b"
},
"requires": {
"api_contract": [
">= 0.3.1",
"< 0.4.0"
],
"cli": [
"= 0.2.2"
"= 0.3.0"
],
"foundation_plan_formats": [
"firstdraft.foundation-plan.sketch/0.19"
Expand Down
6 changes: 3 additions & 3 deletions script/cli-contract/config.mjs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
export const cliRevision = "799a184cb2453ceadf5575f7b46ba975e084f192";
export const cliRevision = "137ef9ceff7469e43f072009e3bba941abc6cd4c";
export const cliRuntimeSha256 =
"e48e4b583e6f06a1d7a50aa19a87da2b24b225eaa5806f3130b9ad4ba6c43a72";
"7e9fdcf42dd887a6e8f6d9f17755600aa3b841a282f7fcdfaff638fe4467cb28";
export const cliPackageName = "@firstdraft.com/cli";
export const cliPackageVersion = "0.2.2";
export const cliPackageVersion = "0.3.0";

export const safeGithubReasonCodes = Object.freeze([
"github.configuration_missing",
Expand Down
6 changes: 4 additions & 2 deletions script/cli-contract/fixtures.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -324,6 +324,7 @@ export function compilationArtifact(
provenanceAnalysisId = compilationAnalysisId,
provenanceCompilerRelease = compilerRelease,
provenanceTarget = compilationTarget,
additionalFiles = [],
} = {},
) {
const modelFile = artifactFile(
Expand All @@ -336,7 +337,8 @@ export function compilationArtifact(
const files = [
modelFile,
artifactFile("ios/bin/ios", "#!/bin/sh\nexit 0\n", "core:ios", 0o755),
];
...additionalFiles,
].sort((left, right) => left.path < right.path ? -1 : left.path > right.path ? 1 : 0);
const metadata = {
files: files.map(
({ path, sha256, mode, owner, source_subject_uuids }) => ({
Expand Down Expand Up @@ -422,7 +424,7 @@ export function problemResponse(
);
}

function artifactFile(path, contents, owner, mode = 0o644) {
export function artifactFile(path, contents, owner, mode = 0o644) {
const source = Buffer.from(contents);
return {
path,
Expand Down
Loading
Loading