Commit Graph
7 Commits
Author SHA1 Message Date
Paul BakausandClaude Fable 5 ac4c3200db Surface rounds deal three structures, draw wireframes, and anchor comps on a reference screenshot
- concept-seed --scope surface deals three grounded-list indices (dice-picked,
  primary leads) instead of one: a single card is not a choice, and the
  no-lineup rule stays direction-only, where it was written for worlds
- serve-question renders a new per-card wireframe field as a layout schematic
  in the media slot: the code-led channel's visualization, no image
  generation needed, no card back, no salience weight
- generate-image gains --ref (repeatable): routes through the edits endpoint
  with input images, so an established world's comp inherits identity from a
  captured screenshot of a real page instead of a prose paraphrase; tested
  against impeccable.style, where the reference-anchored comp reproduced the
  live site's chrome and the prose-only comp drifted
- new-work rung two rewritten around the dealt hand: lock-in is the
  approval, a locked comp builds comp-led and discharges the visualize.md
  three-option round, a locked wireframe builds code-led; visualize.md
  records the exemption and the reference-image discipline, including the
  reference-leak caveat (chrome carries, the reference page's content
  does not)

Written with AI assistance (Claude Code).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-12 16:28:15 -04:00
Paul BakausandClaude Fable 5 f66eace20d Decision page: plain-language raises, IMPECCABLE'S PICK, sticky footer, short-viewport fit
- The raise block drops the side-tab left border for a quiet patina panel,
  and drops the poker jargon: "Improved by Impeccable's worlds" with
  per-line "From <world>" donors, on single raises too; tooltip, aria, and
  screen-reader copy follow
- The pick-card kicker convention renames MY PICK to IMPECCABLE'S PICK at
  every definition site, so users stop reading "my" as themselves
- The footer (steer, registers, canon exit) is a sticky full-bleed bar on
  wide viewports, sharing one --page-inset with the content column; portrait
  keeps it in flow where the deck scrolls internally
- Short landscape viewports compact the headline and narrow the cards so a
  full round fits 1440x800

Written with AI assistance (Claude Code).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-12 15:26:34 -04:00
Paul BakausandClaude Fable 5 248a4a699a Retire the sketch era's wire name: the field is comp, sketch is an alias
The deliverable died in #545; the word survived as the decision-page
payload's field name, annotated everywhere it appeared with the same
compatibility apology. The page and the skill text ship together and
payloads are per-session, so the compatibility burden is one input alias,
not a frozen name.

serve-question.mjs: the card field, the answer key, the schema docs, the
--schema example, the help text, and every internal identifier (compSrc,
data-comp, .media.comp-pending, img.comp, comp-note) now say comp; a
payload declaring the legacy sketch key still renders and answers
identically. new-work.md and the asset producer drop their wire-name
parentheticals. The unit suite covers the canonical answer key coming
back from a legacy-key payload; the new-work e2e's declined-card stray
comp stays declared as sketch, which doubles as alias coverage.

AI-assisted (Claude Fable 5), prepared for maintainer review.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-11 15:53:25 -04:00
dbff0880e6 Decision page: full-fidelity comps, raise cycler, declined sizing, canon order, full card anatomy (#545)
* Polish the decision page: raise cycler, declined height, canon order, full card anatomy

Field feedback from the first real rolls of the verdict-routed hand:

- Several raises stacked on the assigned card blew it out of proportion.
  More than one raise now renders as a compact cycler: one visible, a
  counter, click or Enter advances. A single raise stays inline.
- Declined cards inherited the row's stretch alignment, so a narrow card
  stood at the tallest contender's height, a strange stilt beside the
  hand. They now size to their content.
- Deck order becomes a gradient of standing: contenders, then the canon,
  then declined dead last. The canon between full alternates and the
  demoted row reads as the familiar door rather than the last resort
  after the rejects.
- Root cause of bare-bones challenger and canon cards in the field: the
  --schema example only gave the assigned card palette, materials, and
  risk, and models author payloads by imitating the example, so the
  "same anatomy on every card" instruction lost to it every time. The
  example now carries full anatomy on every card and the schema note says
  a card with no palette chips is an authoring gap, not a data gap.

AI-assisted change.

Co-Authored-By: Claude Code <noreply@anthropic.com>

* Decision cards carry full-fidelity comps instead of sketches

Field verdict on the sketch contract: the sketches came back too simple
to inform the choice, and generation takes the same time at any
fidelity, so the deliberately-unfinished frame paid comp cost for sketch
quality. The decision card's image is now that direction's north-star
comp, produced under visualize.md's comp discipline (structure-led
prompt, real name and content, no invented commercial claims), saved
under .impeccable/mocks/ with its prompt sidecar. Fairness between cards
comes from equal fidelity in each card's own grammar rather than shared
unfinishedness.

The chosen card's comp is never spent by the choice: on a comp-led build
it enters the comp round as compositional option one (visualize.md now
generates two variations beside it; a round arriving with no decision
comp still renders all three), and on a code-led build it returns at the
finish review as the critique reference. Produce order still front-loads
a re-roll's spend onto the cards read first.

serve-question keeps the sketch field's wire name for payload
compatibility; docs, schema paths, shimmer labels, and the answer
directive (CHOSEN COMP) speak comp.

AI-assisted change.

Co-Authored-By: Claude Code <noreply@anthropic.com>

* fix: address PR review bot findings on the comp round

- Producer still forced sketches (cursor, high): the asset producer's
  Decision Sketches contract still mandated deliberately unfinished matte
  sketches, so the parallel path would keep shipping sketch-era images.
  The section is now Decision Comps: full-fidelity north-star comp,
  structure-led prompt, equal commitment across siblings, no invented
  claims, sidecar written.
- Mocks collided with the approval check (cursor, high): decision comps
  now live under .impeccable/mocks/decision/, visualize.md scopes the
  no-approval finding to comp-round output, new-work.md states the
  unchosen hand implies no approval, and the code-led finish packet names
  the chosen decision comp as the critique reference in the approved-comp
  slot.
- Raise cycler announces (greptile, both P1s): a visually hidden
  aria-live region reads out the newly active raise and its position on
  advance; initial render stays quiet.
- Declined width in the vertical deck (cursor, medium): align-self:
  flex-start shrank declined cards to content width in the portrait
  column layout, where the cross axis is horizontal; they stretch there
  and keep content height in the row layout.

AI-assisted change.

Co-Authored-By: Claude Code <noreply@anthropic.com>

* fix: raise cycler tooltip and label name both input modes

Copilot: the tooltip said Click while the control also answers Enter and
Space; the title and a new aria-label now say activate/press Enter.

AI-assisted change.

Co-Authored-By: Claude Code <noreply@anthropic.com>

* fix: finish reviewer exempts decision comps from the approval check

cursor[bot] follow-through: the reviewer's Persistence check still
treated any comps under .impeccable/mocks/ as approval-gated, and the
reviewer never reads visualize.md by design, so code-led and spent-hand
rounds could draw a false skipped-approval finding. The check now scopes
to comp-round comps, exempts .impeccable/mocks/decision/ as the direction
round's dealt hand, and defines how a code-led build's decision comp is
judged in the approved-comp slot: the critique reference, under the
no-approved-comp fidelity rules plus what the image dared that the build
did not.

AI-assisted change.

Co-Authored-By: Claude Code <noreply@anthropic.com>

* fix: the critique reference is its own reviewer input, not the approved-comp slot

cursor[bot]: passing the code-led decision comp through the approved-comp
slot dragged in that slot's obligations (inventory-first reading, the
fidelity matrix, Truth's shipped-asset demand for every image-native
region), which contradicts code-led's premise. The input contract now
names it a separate labeled critique-reference input that nothing binding
"the approved comp" touches, and Fidelity defines its treatment where the
no-approved-comp rules live: provocation, not spec; no matrix, citations,
or asset obligations; its dares enter material_fixes as ordinary fixes.

AI-assisted change.

Co-Authored-By: Claude Code <noreply@anthropic.com>

---------

Co-authored-by: Claude Code <noreply@anthropic.com>
2026-08-08 15:47:11 -07:00
c70bcbf6b4 Direction round: verdict-routed hand, MY PICK card, salience parity, Safer/Bolder registers (#531)
* Route the direction hand by verdict, add the pick card, enforce salience parity

The decision round previously rendered every dealt challenger as an equal
full card whatever the weighing said, so a world that fused poorly (an
underwater world dealt to a flower shop) sat at the same visual weight as
the assigned direction, and concept-level fusion had no surviving output.
Three changes, all presentation-layer; the dice, the assignment, and the
two-axis weighing are untouched:

- Verdict routing: the weighing closes with wins / competitive / declined
  per challenger, decided before any borrowing. Declined challengers render
  demoted (narrow, quiet, catalog art as a labeled thumb, "Adopt anyway"),
  reordered to the end of the deck by the page itself, still adoptable,
  never silently dropped. Donations return as named "raised by" lines on
  the assigned card: a declined challenger donates ambition and system
  discipline, never its clothes.

- The pick card: one card for the model's top-ranked grounded candidate
  when the dice assigned another, kicker MY PICK, honest familiarity risk
  on its face. One card, never a ranked list, never the lead position; the
  anti-menu rule survives with exactly this carve-out.

- Salience parity: a card's imagery weight is capped by the assigned
  card's. With a text-only assigned card (no image generation in the
  harness), full-bleed catalog heroes demote to labeled thumbs, so what
  looks important is the verdict's call, never rendering luck.

serve-question payload gains additive fields (verdict, kept, raised); old
payloads render unchanged. concept-seed's rendered instructions carry the
verdict/donation contract and the pick-card carve-out. Covered by two
Playwright tests in the new-work e2e suite (verdict routing + parity).

Design exploration and rationale were worked through with the maintainer;
research grounding is impeccable.style/research lessons 3-5.

AI-assisted change.

Co-Authored-By: Claude Code <noreply@anthropic.com>

* Add Safer/Bolder re-roll registers to the direction round

The re-roll gains the user's steering wheel on the familiar-to-bold axis.
The decision page renders two register buttons beside the plain re-roll
(payload: reroll: { registers: ["safer", "bolder"] }; booleans still work),
the answer carries the chosen register, and concept-seed gains --register.

The design constraint that shaped the implementation: a register changes
only what a round INSTRUCTS, never what it DEALT. The same key and reroll
count reproduce the same deal whatever the register, so the exclusion chain
never forks and the reproduction contract holds with no API change.

- bolder: the dealt foreign forms become the whole hand, every challenger a
  full card; the first-dealt challenger leads (assignment by deal order, so
  the dice still choose). The pick card sits out; the canon stays.
- safer: the round's dealt hand is spent unseen and stays excluded; the
  model presents its remaining conventional grounded candidates (at most
  three) plus the canon executed against named competitors. This is the one
  sanctioned lineup of the model's own ranked list, existing only by
  explicit user request. Works degraded (needs no catalog); bolder degrades
  to a plain grounded round, disclosed.

Registers are user steering, never the model's to pre-select. Covered by a
concept-seed unit test (same-deal invariant, validation) and a Playwright
test (button, answer field, REGISTER directive).

AI-assisted change.

Co-Authored-By: Claude Code <noreply@anthropic.com>

* Add the execution-contract round: comp-led or code-led, chosen after the direction

The build previously went comp-led for everyone, silently: a generated comp
led and the build chased it, which produces the boldest compositions and
also the measured worst-of-both-worlds failure (ambitious design landed
poorly, no motion, fix rounds after). Models already defect from it by
quietly skipping comp generation, which is unsanctioned code-led with no
contract to catch it. This makes the fork explicit and both paths
defection-proof:

- Comp-led: the comp is law and non-optional once chosen; visualize.md and
  the comp-is-king build phases run as today.
- Code-led: no comp of this page, skipped by contract rather than drift.
  The QUALITY BAR boards still calibrate finish, and the ambition moves
  into the written direction contract (FIRST VIEWPORT plus a named
  signature interaction and motion grammar), audited by the finish
  reviewer in behavior. Not a discount on commitment.

Placement: a second round on the same open table, right after the
direction lands. Sketches stay in the direction round (they pick the
world); comps are what code-led skips (they bind the composition). The
chosen world sets the default lead; the user flips freely; a standing
preference recorded in PRODUCT.md skips the round on later surfaces; with
no image generation there is no fork, code-led is the only path.

Mechanism: serve-question gains payload-level followup: true, which keeps
the detached server alive after a pick (exactly like re-roll), swaps the
page to the loading hand instead of goodbye, marks the answer with
followup: true so --wait keeps the table, and prints a FOLLOWUP OPEN
directive telling the agent to deliver the next round via --update.
Covered by a Playwright test driving the full two-round flow.

AI-assisted change.

Co-Authored-By: Claude Code <noreply@anthropic.com>

* fix: address PR review bot findings

- Degraded safer register no longer contradicts itself (greptile,
  Copilot, cursor): the degraded template previously said "the assigned
  index is suspended; the user picks" and then emitted ASSIGNED INDEX,
  the mandatory build instruction, and the restated footer anyway. The
  degraded safer path now suppresses the assignment machinery entirely,
  matching the non-degraded safer round, and restates the user-picks
  behavior for truncated readers instead.
- A declined card's declared sketch no longer renders a full media face
  (Copilot): the renderer ignores sketch slots on declined cards
  outright, so a stray sketch cannot buy back the salience the verdict
  took away.
- Bolder rounds no longer carry the generic weighing instruction
  (cursor): it measures against the assigned grounded direction, which
  the bolder register suspends; a leader-relative variant weighs the
  fused challengers against the first-dealt leader instead.

All three pinned by new assertions in tests/concept-seed.test.mjs and
tests/new-work-e2e.test.mjs.

AI-assisted change.

Co-Authored-By: Claude Code <noreply@anthropic.com>

* fix: followup never arms the loading hand in blocking serve mode

cursor[bot] caught a client/server disagreement: the page interpolated its
FOLLOWUP constant from the payload alone, so a followup: true payload served
in blocking mode (no --start) would leave the browser on a loading hand that
nothing resolves, since a blocking server exits on any pick and has no
update channel. The page constant is now armed only when the server is
detached, blocking rounds get the goodbye screen as before, and new-work.md
states that followup belongs only on a detached round; blocking and
structured-tool channels run the build-path round as its own second
question. Pinned in tests/serve-question.test.mjs.

AI-assisted change.

Co-Authored-By: Claude Code <noreply@anthropic.com>

* Add card-kind choice telemetry and the bolder routing disambiguation

The choice ping previously fired only when a dealt catalog challenger won,
so pick-share and canon-share had no denominator and the decision page's
new spectrum could not be measured. The ping now fires once per resolved
attended round on API-dealt rolls: --kind names which card class won
(assigned / pick / challenger / canon), --chosen carries the catalog id
only when a dealt challenger won, and --register rides along when the
round came from a steered hand. Grounded candidates' names never leave the
machine (the ping carries the kind alone), the legacy id-only shape stays
valid, and DO_NOT_TRACK / IMPECCABLE_NO_TELEMETRY still disable the ping
entirely. The seed's TELEMETRY block teaches the new invocation.

Also the naming-collision guard: "bolder" said while a direction round is
open routes to the Bolder hand register, never the bolder refinement
command; one line each in bolder.md and new-work.md.

The /api/chosen field additions land in a sister impeccable-site PR; the
API ignores unknown fields meanwhile, so this is safe to ship first.

AI-assisted change.

Co-Authored-By: Claude Code <noreply@anthropic.com>

* fix: ping test survives a DO_NOT_TRACK shell

cursor[bot]: the pingChosen unit test cleared only IMPECCABLE_NO_TELEMETRY,
so a developer shell with DO_NOT_TRACK set failed the success-path
assertions. The test now clears both, restores prior values in finally,
and passes under DO_NOT_TRACK=1.

AI-assisted change.

Co-Authored-By: Claude Code <noreply@anthropic.com>

---------

Co-authored-by: Claude Code <noreply@anthropic.com>
2026-08-08 14:17:21 -07:00
1045c6ca98 Gracefully handle the no-image decision page (#502)
* Gracefully handle the no-image decision page

Tested the new-work path without image generation and fixed what broke:

- A text-only card's back face (First viewport, The case) was unreachable:
  the Details flip chip only rendered inside the media block. Cards with no
  imagery now render their full read on the front and skip the back face.
- A hero/board that fails to load (retired catalog URL, offline shell) sat
  as a dark void with a zoom cursor. The slot now collapses to a field
  painted from the card's own palette with an "artwork unavailable" pill;
  broken inspiration PIPs remove themselves.
- Sketchless catalog art rendered unlabeled as the card's face, reading as
  the promise of the build. It now carries the same "inspiration" label and
  hover title the PIP uses.
- The --schema example pointed at catalog URLs that 404 (missing family
  prefix); updated to the real asset paths and noted the text-only front
  behavior in the schema prose.

Extends e2e test (e) with the front-read and label assertions and adds
test (f) for the broken-image fallback.

AI-assisted (Claude Code).

Co-Authored-By: Claude Code <noreply@anthropic.com>

* fix: address PR review bot findings

- cursor[bot]: the unavailable-art scrim painted over the flip chips and
  swallowed their clicks; it now passes pointer events through and the
  chips render above it.
- Copilot: a palette-less card whose art failed still read as a dark void
  and kept the stale Inspiration tooltip; the slot now falls back to the
  graphite field in CSS and the tooltip is removed with the art.

Test (f) now covers both: a broken card with back facts must still flip
via Details, and a palette-less broken card gets the labeled fallback.

AI-assisted (Claude Code).

Co-Authored-By: Claude Code <noreply@anthropic.com>

---------

Co-authored-by: Claude Code <noreply@anthropic.com>
2026-08-03 18:45:32 -07:00
Paul BakausandClaude Fable 5 6ece0e588f Add deterministic new-work interactive smoke suite
A cheap, LLM-free E2E tier for the interactive parts of new-work, mirroring
the two-layer live-e2e pattern (deterministic now, opt-in LLM tier later).

- generate-image.mjs: IMPECCABLE_IMAGE_GEN_FAKE=1 writes a deterministic
  offline image (SVG with wrapped prompt + SYNTHETIC COMP label, or a valid
  palette-stripe PNG carrying the prompt/marker in a tEXt chunk). Same CLI
  contract, no key, no network, $0.00 cost line.
- tests/new-work-e2e/user-bot.mjs: scripted user bot (module + CLI) that
  resolves the serve-question daemon from the workspace and drives the real
  page via Playwright (pick, re-roll + steer, canon, tab close).
- tests/new-work-e2e.test.mjs: node --test coverage of the serve-question
  cycles (pick + CHOSEN CARD, re-roll + --update re-deal, canon + CANON
  CHOSEN, tab-close exit-4, text-only card) plus fake image determinism.
- Registered as the opt-in new-work-e2e suite; added test:new-work-e2e.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-22 12:23:07 -07:00