Skip to content

feat: a browsable index of the design spikes - #349

Draft
Yona-Appletree wants to merge 14 commits into
mainfrom
claude/nifty-lewin-fab52a
Draft

feat: a browsable index of the design spikes#349
Yona-Appletree wants to merge 14 commits into
mainfrom
claude/nifty-lewin-fab52a

Conversation

@Yona-Appletree

@Yona-Appletree Yona-Appletree commented Aug 5, 2026

Copy link
Copy Markdown
Collaborator

The spikes/ directory holds self-contained HTML design playgrounds, one per
exploration — but there was no way to see what exists short of listing the
directory. This adds the contact sheet and an entry point from Studio.

What's here

spikes/index.html — generated, not hand-maintained.
scripts/spikes-index.mjs reads each spike's own <title> and opening
paragraph, so the index cannot describe a spike wrongly for long. Cards link
relatively, so the page works over file:// as well as over the dev server.
The three cargo spikes list separately from their READMEs, unlinked — they are
not browsable, and an index that quietly omitted them would not be a list of
the spikes.

Dated, newest first. Dates live in spikes/dates.json rather than being
read from git on each run: CI checks out shallow (actions/checkout defaults
to depth 1), so git log -- <path> there answers for the tip commit alone and
would disagree with every full clone — the byte-compare gate would fail in CI
and pass everywhere else. Git is asked once, when a spike first appears; after
that the date is a committed fact, hand-editable when a spike gets a later
round. Verified: with git forced to fail, --check still passes.

A drift gate. just spikes-index writes it; just lint-spikes-index
joins check-lint. Without a gate the failure mode is silent — a new spike is
simply missing and nothing says so. Same reasoning as the vec and torture
corpus --check gates.

Serving, dev only. just studio-dev's existing 1 s sync loop copies the
spike pages into the served directory. It copies page by page rather than
cp -R spikes/., because the code spikes are cargo crates and one cargo test
in there would drag a target/ into a once-a-second copy. Copying only from
that loop is what keeps the spikes out of every build artifact — the loop runs
only while a dev server is up.

The Tools menu entry, gated on cfg!(debug_assertions). Not the stories
feature: the release Pages build turns stories on for the in-app design
library, so it is not a dev signal. Story capture builds --release, so the
card stays out of the story baselines too. It links /spikes/index.html
explicitly rather than /spikes/ — dx serve answers unknown paths with the SPA
fallback, so the directory form would have loaded Studio instead.

A smoke assertion. The studio Pages smoke check grows a forbidden list
naming spikes. Nothing in the deploy path copies them today; this states the
requirement out loud so a later "just add it to the asset dir" fails in CI
rather than publishing internal design records — several of which state gate
verdicts as settled fact. Verified both ways against a stub artifact.

No spike was modified.

Verified on the dev server

  • /spikes/index.html serves; all 11 spike pages return 200; the served
    directory contains exactly those pages — no code-spike dirs, no Cargo.toml,
    no target/.
  • Clicking a card from the index opens the spike and it renders live.
  • The Tools menu shows all three cards in a debug build.

Review gate

Visual gate on the index page — screenshots handed over in chat. Staying in
draft until then.

🤖 Generated with Claude Code

Yona-Appletree and others added 7 commits August 5, 2026 00:04
The spikes are self-contained HTML design records but there was no way
to see what exists short of listing the directory. This adds the contact
sheet, derived rather than hand-written: each card's title comes from the
spike's own <title> and its blurb from the spike's opening paragraph, so
the page cannot describe a spike wrongly for long. Code spikes (the cargo
ones) list separately from their README, unlinked — they are not
browsable, and an index that quietly omitted them would not be a list of
the spikes.

Output is deterministic (sorted, no timestamps, no git state) so the
--check mode in the next commit cannot flap.

Co-Authored-By: Claude Fable 5 <[email protected]>
`just spikes-index` rewrites the page; `just lint-spikes-index` joins
check-lint so a spike added without regenerating fails the gate. Without
it the failure mode is silent — the new spike is simply missing and
nothing says so, the same reason the vec and torture corpora carry
--check gates.

studio-dev's existing 1 s sync loop also copies the spike pages into the
served directory, so the Tools-menu entry has something to open. Page by
page rather than `cp -R spikes/.`: the code spikes are cargo crates, and
one `cargo test` in there would drag a target/ dir into a once-a-second
copy. Copying only from this loop is what keeps the spikes out of every
build artifact — the loop runs only while a dev server is up.

Co-Authored-By: Claude Fable 5 <[email protected]>
Nothing in the deploy path copies spikes/ today — the artifact builder
works from an allowlist. This states the requirement out loud so a later
"just add it to the asset dir" fails in CI rather than publishing
internal design records, several of which state gate verdicts as settled
fact.

Co-Authored-By: Claude Fable 5 <[email protected]>
The "…" menu is where the project-free tools already live, so the design
spikes belong there too. Gated on cfg!(debug_assertions) rather than the
`stories` feature — the release Pages build turns `stories` on for the
in-app design library, so it is not a dev signal. Story capture builds
--release, so the card stays out of the baselines as well.

Co-Authored-By: Claude Fable 5 <[email protected]>
The flask reads as "experiment", which is what a spike is. It renders the
same glyph as Test on purpose and stays a separate name: design
experiments and test runs are different meanings, and borrowing
MapUniverses (documented as DMX-universe coloring on the mapping lamp
view) would have been a worse kind of reuse.

Co-Authored-By: Claude Fable 5 <[email protected]>
The contact sheet is read for "what happened lately", so the order should
say it. Each card now carries the date the spike landed, and both sections
sort newest first.

Dates live in spikes/dates.json rather than being read from git on every
run. CI checks out shallow — actions/checkout defaults to depth 1 — so
`git log -- <path>` there answers for the tip commit alone and would
disagree with any full clone, which would make the byte-compare gate fail
in CI and pass everywhere else. Git is asked once, when a spike first
appears; after that the date is a committed fact, hand-editable when a
spike gets a later round.

Co-Authored-By: Claude Fable 5 <[email protected]>
@github-actions

github-actions Bot commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

CI refreshed the story baselines on this branch

The validate-stories job detected drift and committed the fresh set: 6 changed
in 0d01a28.

Review every PNG in the PR's Files changed view (swipe / onion-skin).
Your local branch is now behind — git pull before pushing again.

Story Before After
exploration__node-ui__status-indicators__sm.png exploration__node-ui__status-indicators__sm.png@13f02d179f exploration__node-ui__status-indicators__sm.png@0d01a283e4
studio__node__clock-face__crowd__md.png studio__node__clock-face__crowd__md.png@13f02d179f studio__node__clock-face__crowd__md.png@0d01a283e4
studio__node__clock-face__default__lg.png studio__node__clock-face__default__lg.png@13f02d179f studio__node__clock-face__default__lg.png@0d01a283e4
studio__node__clock-face__default__md.png studio__node__clock-face__default__md.png@13f02d179f studio__node__clock-face__default__md.png@0d01a283e4
studio__node__clock-face__shared__lg.png studio__node__clock-face__shared__lg.png@13f02d179f studio__node__clock-face__shared__lg.png@0d01a283e4
studio__node__clock-face__shared__md.png studio__node__clock-face__shared__md.png@13f02d179f studio__node__clock-face__shared__md.png@0d01a283e4

Yona-Appletree and others added 3 commits August 5, 2026 00:41
Two full-gate runs this session aborted in test-rust-core, each on a
different load-sensitive test, under a load average of 246 from a sibling
agent session. The perf test's own number (19.16 s vs the 10 s bound) is
the worst in its log.

The useful part is the correction to the workaround. The entry told you
to re-run the later recipes when THIS test fails; the first abort was a
different test entirely, so the rule belongs on the abort, not on the
test: whenever test-rust-core aborts, run test-studio-host and
test-xt-host explicitly. Both were run here and pass.

Co-Authored-By: Claude Fable 5 <[email protected]>
Two consecutive green CI runs on this PR each fired the baseline
auto-commit and moved the same clock-face stories back and forth, the
second restoring blob hashes byte-identical to main. Two runs in the same
pinned environment, no clock-face code in the diff, so the capture has two
reachable renderings rather than drift that is settling.

Filed open, not diagnosed: the debt entry's own lore is that this pipeline
produces "obviously a settling race" diagnoses the pixels then overturn, so
the entry records the evidence and the hypothesis separately.

The part worth carrying: auto-commit turns a nondeterministic capture into
silent churn instead of a red check, and the ADR's "merge with the green run
one commit back" assumes the bot commit settles something. Under oscillation
it never does, so judging a refresh means diffing blob hashes against the
PREVIOUS refresh, not just against main.

Co-Authored-By: Claude Fable 5 <[email protected]>
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