Skip to content
Closed
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
10 changes: 10 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,16 @@ Entries are newest first. Keep their headings stable. Publish material correctio
new entries so readers who advanced their checkpoint see them. Entries explain what changed, why, when it applies,
and any useful small example or verification; they need not reproduce commit logs.

## 2026-10-04: Photo and file uploads

**Skills — released in plugin 0.8.4.** The authoring reference now says that `image` and `attachment` Fields
compile to Active Storage uploads instead of being skipped, what they generate, and what stays a gap. Generated apps
store uploads on Cloudinary, so the Skill tells the user to create a Cloudinary account and set `CLOUDINARY_URL` in
`.env.development.local` and in Render; setup works without it, and the first upload raises a `KeyError` naming it.
It applies once the First Draft service runs Compiler release
`foundation-plan-rails/compiler-application-2026-10-04-image-uploads` or later; until then the GapSet still lists
these Fields as skipped.

## 2026-10-03: An interview that asks your level first

**Skills — released in plugin 0.8.3.** The Skill's interview now follows one order. The agent clarifies your idea,
Expand Down
2 changes: 1 addition & 1 deletion evals/create-full-stack-app/cases.json
Original file line number Diff line number Diff line change
Expand Up @@ -316,7 +316,7 @@
"expectations": [
"Uses the supplied document without a redundant artifact invitation and models item-level return facts independently of the whole loan.",
"Does not turn four printed photo boxes into four fixed Fields or infer a fixed attachment limit.",
"Preserves attachment intent as structured meaning whose image or attachment Fields become service-support gaps skipped at import, separate from outside-grammar media/import work in notes; does not encode file paths as supported uploaded seed values.",
"Preserves attachment intent as structured meaning, such as a child Entity with one image Field per damage photo, separate from outside-grammar media/import work in notes; does not encode file paths as supported uploaded seed values.",
"Does not retain private filled-in content in Plan, notes, seed, archive or repository."
],
"artifacts": [
Expand Down
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@firstdraft/skills",
"version": "0.8.3",
"version": "0.8.4",
"description": "Portable Agent Skills for First Draft",
"license": "MIT",
"private": true,
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.8.3",
"version": "0.8.4",
"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.8.3",
"version": "0.8.4",
"description": "First Draft Foundation Plan authoring and Compilation for Claude Code and Codex",
"license": "MIT",
"type": "module",
Expand Down
4 changes: 2 additions & 2 deletions release/compatibility.json
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
{
"format": "firstdraft.release-compatibility/1",
"component": "skills",
"version": "0.8.3",
"version": "0.8.4",
"plugin_source": {
"package": "@firstdraft.com/claude-code",
"tarball_sha256": "f5639a83ac299dde1748635a16edff5148f1d8450003ba5cd6ce9b8611c27946"
"tarball_sha256": "0048a347a60dd1dc78bb4d7037720585cf10a851fd38026c271cfdefe4371b57"
},
"requires": {
"api_contract": [
Expand Down
2 changes: 1 addition & 1 deletion skills/create-full-stack-app/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ explicit handoff. Follow [writing notes](references/modeling-guide.md#retain-imp

## Current boundary

Targets plugin 0.8.3, CLI 0.8.1, API 0.7, Plan 0.23; catalog selection is separate.
Targets plugin 0.8.4, CLI 0.8.1, API 0.7, Plan 0.23; catalog selection is separate.

- Bounded generation includes Web Accounts/Policies/Scaffolds, development data, and selected iPhone/Android
clients. [Appearance](references/foundation-plan-023.md#application-and-clients) controls theme and native colors,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ interleaved output fail closed. Branch on the object's stable `error` and struct
human-readable `detail` or broad process exit status.

This plugin bundles `@firstdraft.com/cli@0.8.1`. Its exact reviewed revision and runtime digest are owned by
[the CLI contract configuration](https://github.com/firstdraft/skills/blob/claude-v0.8.3/script/cli-contract/config.mjs)
[the CLI contract configuration](https://github.com/firstdraft/skills/blob/claude-v0.8.4/script/cli-contract/config.mjs)
at this plugin's protected release tag. Check the command surface rather than assuming the version alone
establishes compatibility. These source checks do not prove plugin/catalog publication, service authentication,
staging compatibility, or a complete user journey.
Expand Down
23 changes: 14 additions & 9 deletions skills/create-full-stack-app/references/foundation-plan-023.md
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ The bundled schema was copied byte-for-byte from
release or execution evidence.

This plugin's bundled CLI and pinned contract check use the exact reviewed CLI revision and runtime digest in
[the CLI contract configuration](https://github.com/firstdraft/skills/blob/claude-v0.8.3/script/cli-contract/config.mjs)
[the CLI contract configuration](https://github.com/firstdraft/skills/blob/claude-v0.8.4/script/cli-contract/config.mjs)
at this plugin's protected release tag, as contract provenance rather than release or execution evidence. The CLI
exposes `generate uuid`, `generate application-key`, `plan init`, `plan push`,
`plan status`, local `plan compile` (equivalent to `--output .`), explicit `plan compile --github`,
Expand Down Expand Up @@ -326,11 +326,13 @@ descriptor terminates in a required emitted scalar or system Field. It preloads
The whole-graph analyzer rejects an optional Field descriptor; multi-target, longer-chain, optional-source, cyclic,
or otherwise unsupported Association descriptors remain exact gaps. A Field may use these types:

- `attachment`
- `boolean`
- `date`
- `datetime`
- `decimal`
- `enum`
- `image`
- `integer`
- `language_code`
- `long_text`
Expand All @@ -354,14 +356,17 @@ query `status_active` when the stored state is `active`. Check an affected appli
state; no generated workaround or namespace-based scope suppression is supplied. With `no_direct_assignment: true`,
a scoped builder can also raise even for the initial state. Use ordinary creation followed by the named event
when a transition is intended; constructing its destination state directly would bypass the event's effects.
`attachment` and `image` are schema-valid
Field types, but they are skipped from the admitted graph and recorded as service-support gaps; they cannot reach
the current Compiler. Active Storage and image-delivery prose describes target direction, not emitted support.
Keep requested image and attachment Fields in the Plan either way. When a Compiler generates them, so that the
matching GapSet no longer reports the Field skipped, it stores files with Active Storage on Cloudinary. Then tell
the user to sign up for Cloudinary and set `CLOUDINARY_URL` from its dashboard in `.env.development.local` for
local use and in the Render environment for the deployed app. The user sets it; never ask for, print, or commit
its value.
An `attachment` or `image` Field compiles to Active Storage `has_one_attached`, with a presence validation when
required, a Scaffold file input (images accept `image/*`), and an image or download link on show pages and list rows.
Development seeds attach a placeholder file on local disk to each required upload; development data cannot supply
upload bytes. A required upload on the Account Entity has no signup control, so signup stays a partial gap. An older
service may still report these Fields as skipped in the GapSet; keep them in the Plan either way.
Generated apps store uploads on Cloudinary in development and production. Tell the user to sign up for Cloudinary
and set `CLOUDINARY_URL` from its dashboard in `.env.development.local` for local use and in the Render environment
for the deployed app; setup works without it, but the first upload raises a `KeyError` naming it. The user sets
it; never ask for, print, or commit its value. Uploaded files have public URLs. Type and size limits, several files
per Field, direct uploads, and protected delivery are not generated; model several photos as a child Entity with
one `image` Field.

### Field capability matrix

Expand Down
Loading