Skip to content

feat: reframe /prototype as the early exploration workflow - #59

Merged
sellke merged 2 commits into
mainfrom
feat/prototype-exploration-reframe
Oct 20, 2026
Merged

sellke merged 2 commits into
mainfrom
feat/prototype-exploration-reframe

Conversation

@sellke

@sellke sellke commented Oct 20, 2026

Copy link
Copy Markdown
Owner

/prototype now opens with divergence. An idea that needs looking at before it needs specifying gets a few genuinely different, code-portable drafts, a recorded choice, and then the chosen direction built — without ever writing a spec artifact.

Why

Writ had no pre-spec divergence step anywhere in 32 commands. /design could not provide one: every mode routes output into .writ/specs/<spec-name>/mockups/, so it structurally requires a spec that does not exist yet. /prototype was already positioned as the pre-spec front door — its own usage table claims "exploring an approach before committing to it" — but delivered one unexamined canvas mockup and nothing retained.

Evidence base: .writ/research/2026-10-19-prototype-visual-drafts-research.md (on docs/product-reconcile-and-research, not this branch).

What changed

The contract is amended, not stretched. The old outcome said the repository gained no planning artifact, which forbade retaining anything from an exploration. ADR-020 allows one outcome per command, so rather than bolting a second on, the outcome is now the idea made real — drafts to choose between, working code, or both — with shipped code as a terminal state rather than the definition of done. A run ending at three drafts, a decision and no code is complete, and Step 5 and ## Completion both say so. The spec boundary moves from "no planning artifact" to "no spec artifact", which is what exit_criteria[0] already said correctly.

Drafts are render-only and must port cheaply. A draft is a self-contained page built from the project's own component names, framework and tokens — never a screenshot, an abstract wireframe, or running code. The portability test is stated inline: a coding agent reading the draft can name the components to create or change without guessing, or the draft is a picture and not worth keeping. Step 3 hands the chosen draft to the coding agent as the direction to build.

Divergence is constructed, not requested. Asking one agent for "a few options" yields one idea three times — models fixate on their own early output and repeated samples converge (research F4). Step 2.5 declares two or three orthogonal axes before generating, runs one subagent per draft with no shared context, has each generator commit to its axis before rendering, uses ordinary rather than visionary personas, and caps at three.

Rendering delegates to the platform — native artboards, then an artifact/canvas pane, then a written structural description. Never degrades silently. Writ ships no renderer.

Gated, so cost stays proportional. UI surface or an unsettled direction turns Step 2.5 on; --diverge / --no-diverge override. A bug fix with one obvious shape runs exactly as it does today.

/create-spec --from-prototype reads the record. The chosen draft becomes the Deliverable; a new Directions Considered section carries one line per rejected draft and why it lost.

The correctness fix a reviewer should look at first

--from-prototype previously required a diff and marked Story 1 Completed ✅ unconditionally. A /prototype run can now end at a chosen direction with nothing built — so that path would have produced a spec claiming work was done because a mockup existed, sending /implement-spec past code nobody wrote.

Step 0 now crosses exploration-record against diff in a source matrix. Never mark Story 1 complete on an exploration record alone. Step 1's opening framing and Step 3's completion rules branch on the same matrix. create-spec.lean.md carries the identical change — this is a core flow correction, not an opt-in arm like Jev or the review panel, so the lean twin is not exempt.

Two judgment calls worth reviewing

Divergence rules are inline, not in skills/design-divergence/SKILL.md. Referencing a skill that does not exist is the dead-end-path defect the goldilocks assessment catalogued. Extraction is the follow-up, once a second caller exists. The research doc still describes it as a skill — a known, deliberate doc/code divergence.

create-spec.md grew, and it is already the tree's worst byte violator. test_governor_enforcement's ratchet blocked the first version of this change. Following the precedent recorded on that very entry ("two adjacent sentences were trimmed to offset"), 448 bytes were recovered by collapsing Step 1's five anchor questions to one sentence and Step 3's six bullets to the prose the lean twin already proves is sufficient. The residual is the matrix itself: recorded overage repinned 28123 → 29304 with disclosure, acknowledged and not exempted. That file wants a real reduction pass, which is not this change.

eval.sh gains a referenced_paths_allowlist row for exploration.md, which /prototype writes at runtime — the referenced-paths check caught the dangling reference before it landed. test_lean_commands sha and KEPT_HEADINGS repinned for the renamed Step 3 heading.

Verification

  • bash scripts/eval.sh — 0 findings, 0 run errors
  • uv run --python 3.9 pytest — 2275 passed, 2 skipped
  • All bash tests pass
  • prototype.md 18,234 bytes, 6,726 under the per-invocation budget

Not in this PR

  • skills/design-divergence/SKILL.md extraction
  • The two platform defects found during the research, filed as issues on docs/product-reconcile-and-research: cursor-ide-browser translated by no adapter, and Writ's /design colliding with Claude Code's native /design
  • Whether this warrants an ADR — a command's purpose changing is arguably a direction change

🤖 Generated with Claude Code

sellke and others added 2 commits October 20, 2026 12:39
/prototype now opens with divergence. An idea that needs looking at
before it needs specifying gets a few genuinely different, code-portable
drafts, a recorded choice, and then the chosen direction built — without
ever writing a spec artifact.

The contract is amended, not stretched. The old outcome said the
repository gained no planning artifact, which forbade retaining anything
from an exploration. ADR-020 allows one outcome per command, so rather
than bolting a second one on, the outcome is now the idea made real —
drafts to choose between, working code, or both — with shipped code as a
terminal state rather than the definition of done. A run that ends at
three drafts, a decision and no code is complete, and Step 5 and
Completion both say so in those words. exit_criteria splits into two
conditional rows so each path stays checkable, and the spec boundary
moves from "no planning artifact" to "no spec artifact", which is what
exit_criteria[0] already said correctly.

Drafts are render-only and must port cheaply. A draft is a self-contained
page built from the project's own component names, framework and tokens —
structurally accurate, not pixel-polished, and never a screenshot, an
abstract wireframe, or running code. The portability test is stated
inline: a coding agent reading the draft can name the components to
create or change without guessing, or the draft is a picture and not
worth keeping. Step 3 hands the chosen draft to the coding agent as the
direction to build, reusing the component names it labelled.

Divergence is constructed, not requested. Asking one agent for "a few
options" yields one idea three times — models fixate on their own early
output and repeated samples converge. Step 2.5 declares two or three
orthogonal axes before generating, runs one subagent per draft with no
shared context, has each generator commit to its axis before rendering,
uses ordinary rather than visionary personas, and caps at three.
Evidence: .writ/research/2026-10-19-prototype-visual-drafts-research.md
findings F3 and F4.

Rendering delegates to the platform — native artboards, then an artifact
or canvas pane, then a written structural description — and never
degrades silently. Writ ships no renderer.

The step is gated, so cost stays proportional: UI surface or an unsettled
direction turns it on, --diverge and --no-diverge override, and a bug fix
with one obvious shape runs exactly as it does today.

These rules are inline rather than in a skills/design-divergence/SKILL.md
because referencing a skill that does not exist yet is the dead-end-path
defect the goldilocks assessment flagged. Extraction is the follow-up,
once a second caller exists.

eval.sh gains a referenced_paths_allowlist row for exploration.md, which
/prototype writes at runtime under .writ/prototypes/<date>-<slug>/. The
referenced-paths check caught the dangling reference before this landed.

Full eval 0 findings; 2275 Python tests pass on the 3.9 floor; bash tests
pass. prototype.md is 18,050 bytes, 6,910 under the per-invocation
budget.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Wires the consumer for the artifact /prototype now writes, closing the
live-consumer gap the reframe opened.

Step 0 reads .writ/prototypes/<date>-<slug>/exploration.md before the git
diff and carries two things into the contract draft: the chosen draft
becomes the Deliverable, and a new Directions Considered section carries
one line per rejected draft and why it lost. Those rejected alternatives
are the durable half of an exploration — the "what else did we consider"
that Writ's ADRs demand everywhere else and that nobody can reconstruct
later. The section is omitted when there was no exploration; alternatives
that were never generated are never invented.

The correctness fix is the source matrix. --from-prototype previously
required a diff and marked Story 1 Complete unconditionally. A /prototype
run can now end at a chosen direction with nothing built, so the matrix
crosses exploration record against diff and marks Story 1 accordingly:
Complete when code exists, Not Started when only a direction was chosen.
Never mark Story 1 complete on an exploration record alone — a chosen
draft is a decision, not an implementation, and a spec claiming otherwise
sends /implement-spec past work nobody wrote. Step 1's opening framing
and Step 3's completion rules are conditional on the same matrix.

create-spec.lean.md carries the same contract change. This is a core flow
correction, not an opt-in arm, so the lean twin is not exempt.

Budget. create-spec.md is the tree's worst byte violator, and
test_governor_enforcement's ratchet blocked the first version of this
change for growing an existing violation. 448 bytes were offset by
collapsing Step 1's five anchor questions to one sentence and Step 3's
six bullets to the prose the lean twin already proves is sufficient. The
residual is the matrix itself: recorded overage repinned 28123 -> 29304
with disclosure, acknowledged and not exempted. The file wants a real
reduction pass, which is not this change.

test_lean_commands sha and KEPT_HEADINGS repinned for the renamed Step 3
heading.

Full eval 0 findings; 2275 Python tests pass on the 3.9 floor; bash tests
pass.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@sellke
sellke merged commit a997e01 into main Oct 20, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant