Skip to content

feat: correction notes on every sprite regeneration surface, not just turnaround and anchors#3147

Merged
atomantic merged 3 commits into
mainfrom
claim/issue-3134
Jul 27, 2026
Merged

feat: correction notes on every sprite regeneration surface, not just turnaround and anchors#3147
atomantic merged 3 commits into
mainfrom
claim/issue-3134

Conversation

@atomantic

Copy link
Copy Markdown
Owner

Summary

Extends the sprite correction-prompt pattern (shipped for the turnaround sheet and the 7 directional anchors in #2964/#2979) to the five regeneration surfaces that could still only be re-rolled blind: the main reference, a place/object's ambient reference, and the walk-cycle / scanner-action / ambient-loop videos.

Server

  • services/sprites/prompts.js grows one shared correctionClause(text, subject) that every builder appends last, replacing the two hand-inlined copies. buildMainReferencePrompt, buildAmbientReferencePrompt, buildWalkVideoPrompt, and buildAmbientVideoPrompt each take an optional correctionPrompt.
  • scannerPrompt is promoted out of services/sprites/scanner.js into prompts.js as buildScannerPrompt (wording unchanged, so an existing scanner run's rebuilt provenance still matches what was sent). That also fixes a latent provenance bug: assetPrompt.js was rebuilding scanner runs with the walk builder, reporting a prompt that was never sent. Each track now rebuilds with its own builder and reports source: 'scanner'.
  • spriteWalkGenerateSchema / spriteScannerGenerateSchema / spriteAmbientGenerateSchema take correctionPrompt: z.string().max(4000).optional() (the reference schema already had it). Each service trims it, threads it into the prompt, and stamps it on the run record / job tag only when non-empty, mirroring the existing anchor branch.
  • assetPrompt.js threads correctionPrompt through both the candidate-sidecar rebuild and the animation-run rebuild, so a corrected re-roll's provenance shows the correction that produced it.

Client

  • New pure client/src/lib/spriteCorrections.js owns the correction-map key vocabulary plus correctionPromptPayload (moved from CorrectionNote.jsx, which re-exports it), so the pure gating layer can share the keys without importing a component. Barrel + README rows added.
  • CorrectionNote.jsx gains CorrectionNoteToggle / CorrectionToggleButton — the collapsed-pill-plus-note affordance the new surfaces use, and the same button the asset card was hand-rolling.
  • ReferenceWorkflow.jsx (main branch, previously hardcoded to {}), WalkWorkflow.jsx, ScannerWorkflow.jsx, and AmbientWorkflow.jsx (both its reference and loop actions) render the shared note; AssetCollection.jsx's note is no longer gated to kind === 'reference'; Sprites.jsx spreads correctionPromptPayload into all four generators.

One decision recorded on the issue

The plan said to reuse the page-owned map for the walk card. Reusing the bare direction key across surfaces would mean an anchor note ("no pocket on the right sleeve" — a still-image fix) silently riding the next walk video re-roll for that direction. So the map stays single and page-owned (still reset on record switch), but keys are namespaced per surface: anchors keep the bare direction (existing state resolves unchanged), while walk:<dir>, scanner:<dir>, main, ambient-reference, and ambient-loop prefix. Relatedly, buildCollectionActions() returns a correctionKey (mirroring the existing direction) instead of taking a correctionPrompt pass-through, so Sprites.jsx assembles the payload in exactly one place — the way generateAnchor already worked.

Test plan

  • cd server && npx vitest run services/sprites — 231 passed. New coverage:
    • prompts.test.js: a table-driven block over all 8 builders asserting one trimmed clause appended last with the right subject noun, and that undefined/null/''/' '/'\n\t '/non-string all produce a prompt byte-identical to the blind regenerate (the hard acceptance criterion), plus direct correctionClause unit tests.
    • walk.test.js / scanner.test.js / ambient.test.js: non-empty case threads into the TUI prompt and stamps the run record; blank case leaves the motion prompt identical and the run record without the key.
    • reference.test.js: main-reference derive (correction + blank), and the ambient main composing an additive correction alongside the full-replace designPrompt.
    • assetPrompt.test.js: each track rebuilds with its own builder (scanner no longer reports the walk prompt), and both a corrected run record and a corrected candidate sidecar rebuild with their clause.
  • cd client && npm test470 files / 5202 tests passed (full suite). New coverage in CorrectionNote.test.jsx (key namespacing + no cross-surface leakage + the toggle), WalkWorkflow.test.jsx, ScannerWorkflow.test.jsx, a new AmbientWorkflow.test.jsx, AssetCollection.test.jsx (walk-card note), spriteCollectionActions.test.js (correctionKey is walk-namespaced, never the bare direction), and ReferenceWorkflow.test.jsx (main sends the note, omits the field when blank, and does not pick up an anchor note).
  • cd server && npm test — 1311 pre-existing failures, all from the absent Postgres in this environment (… requires PostgreSQL). Verified against a clean origin/main worktree: 1309 identical failures, and the 2-file difference (lib/dataRoot.test.js, services/installState.test.js) reproduces in this worktree with the diff stashed — those two are sensitive to the worktree living under the primary repo's data/ tree, not to this change.
  • npx eslint clean on every touched client file.

Closes #3134

… turnaround and anchors (#3134)

Five Sprite Manager surfaces could only be re-rolled blind: the main
reference, a place/object's ambient reference, and the walk / scanner /
ambient-loop videos. Each now accepts the same additive correction note the
turnaround sheet and the 7 directional anchors already take, so a bad result
can be described instead of re-rolled and hoped over.

- prompts.js grows one shared correctionClause(text, subject) that every
  builder appends last, and buildScannerPrompt moves in from scanner.js so all
  stage prompts live in the one pure module. That also lets assetPrompt.js
  rebuild a scanner run's provenance with the builder that actually produced
  it, rather than reporting the walk prompt it never sent.
- The three animation-generate schemas take an optional correctionPrompt, and
  each service trims it, threads it into the prompt, and stamps it on the run
  record only when non-empty — so a blank note leaves both the prompt and the
  persisted run byte-identical to today's blind regenerate.
- Client notes share ONE page-owned map, but keyed per SURFACE
  (lib/spriteCorrections.js): anchors keep the bare direction so existing state
  still resolves, while walk/scanner/main/ambient prefix. Without that, an
  anchor's still-image note ("no pocket on the right sleeve") would silently
  ride the next walk VIDEO re-roll for that direction.
…only regenerate is not rejected (#3134)

The ambient main requires a design input server-side (DESIGN_INPUT_REQUIRED).
The field started blank on every mount, so after a page reload a user typing
only a correction note had the Regenerate button disabled — and the correction
affordance the surface just gained was unreachable. The server already persists
manifest.designPrompt on each ambient-main render, so seed from it.
@atomantic
atomantic merged commit 1c63a88 into main Jul 27, 2026
6 checks passed
@atomantic
atomantic deleted the claim/issue-3134 branch July 27, 2026 08:06
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.

Extend the sprite correction-prompt pattern to main reference, walk, scanner, and ambient regeneration

1 participant