feat: correction notes on every sprite regeneration surface, not just turnaround and anchors#3147
Merged
Conversation
… 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
force-pushed
the
claim/issue-3134
branch
from
July 27, 2026 08:00
6f83c1e to
dc34a89
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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.jsgrows one sharedcorrectionClause(text, subject)that every builder appends last, replacing the two hand-inlined copies.buildMainReferencePrompt,buildAmbientReferencePrompt,buildWalkVideoPrompt, andbuildAmbientVideoPrompteach take an optionalcorrectionPrompt.scannerPromptis promoted out ofservices/sprites/scanner.jsintoprompts.jsasbuildScannerPrompt(wording unchanged, so an existing scanner run's rebuilt provenance still matches what was sent). That also fixes a latent provenance bug:assetPrompt.jswas rebuilding scanner runs with the walk builder, reporting a prompt that was never sent. Each track now rebuilds with its own builder and reportssource: 'scanner'.spriteWalkGenerateSchema/spriteScannerGenerateSchema/spriteAmbientGenerateSchematakecorrectionPrompt: 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.jsthreadscorrectionPromptthrough both the candidate-sidecar rebuild and the animation-run rebuild, so a corrected re-roll's provenance shows the correction that produced it.Client
client/src/lib/spriteCorrections.jsowns the correction-map key vocabulary pluscorrectionPromptPayload(moved fromCorrectionNote.jsx, which re-exports it), so the pure gating layer can share the keys without importing a component. Barrel + README rows added.CorrectionNote.jsxgainsCorrectionNoteToggle/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, andAmbientWorkflow.jsx(both its reference and loop actions) render the shared note;AssetCollection.jsx's note is no longer gated tokind === 'reference';Sprites.jsxspreadscorrectionPromptPayloadinto 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, andambient-loopprefix. Relatedly,buildCollectionActions()returns acorrectionKey(mirroring the existingdirection) instead of taking acorrectionPromptpass-through, soSprites.jsxassembles the payload in exactly one place — the waygenerateAnchoralready 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 thatundefined/null/''/' '/'\n\t '/non-string all produce a prompt byte-identical to the blind regenerate (the hard acceptance criterion), plus directcorrectionClauseunit 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-replacedesignPrompt.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 test— 470 files / 5202 tests passed (full suite). New coverage inCorrectionNote.test.jsx(key namespacing + no cross-surface leakage + the toggle),WalkWorkflow.test.jsx,ScannerWorkflow.test.jsx, a newAmbientWorkflow.test.jsx,AssetCollection.test.jsx(walk-card note),spriteCollectionActions.test.js(correctionKeyis walk-namespaced, never the bare direction), andReferenceWorkflow.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 cleanorigin/mainworktree: 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'sdata/tree, not to this change.npx eslintclean on every touched client file.Closes #3134