Studio files/play panes: follow-ups from #9/#10 closeout #28

Closed
opened 2026-07-27 11:07:11 -04:00 by cmoriarty · 2 comments
Owner

Follow-ups deliberately split out of #9/#10 when they closed — the core panes shipped (209f766, deployed, e2e-covered); these are the polish items named in the closing review:

Files pane (#10 residuals)

  • Cross-file/global search over the game repo (current search is CodeMirror's in-file ⌘F). Likely server-side: a GET /repo/{slug}/search?q= on the orchestrator walking the tree, plus a results panel. — done in b9b9332
  • Animated sprite sheets should animate in the viewer (CSS steps() from the sibling .json manifest — the review page already does this; lift the technique). — done in b9b9332
  • Tweak flow beyond images: animate re-generation from the viewer (re-run i2v with a new motion prompt against the committed base) — done in b9b9332, with base/motion provenance now written into the sheet manifest
  • …and audio tweak once the seat grows cover/repaint routes (the orchestrator 422 already documents that upstream blocker). Blocked: the audio seat still generates from text alone; #22 is closed, so this needs an audio-server ticket of its own

Play pane (#9 residuals)

  • Run-aware build selection: today the pane loads the picked game's mirror root; once production runs emit real builds (walking skeleton, #11), it should follow the newest build of the ACTIVE run, not just the game. Blocked on #11 — per-run builds don't exist yet; the drain mirrors per game
  • Optional: auto-run vitals after each drain and surface the verdict as a chip, so regressions greet you without a click. — done in b9b9332/5009e67
Follow-ups deliberately split out of #9/#10 when they closed — the core panes shipped (209f766, deployed, e2e-covered); these are the polish items named in the closing review: **Files pane (#10 residuals)** - [x] Cross-file/global search over the game repo (current search is CodeMirror's in-file ⌘F). Likely server-side: a `GET /repo/{slug}/search?q=` on the orchestrator walking the tree, plus a results panel. — done in b9b9332 - [x] Animated sprite sheets should animate in the viewer (CSS steps() from the sibling .json manifest — the review page already does this; lift the technique). — done in b9b9332 - [x] Tweak flow beyond images: animate re-generation from the viewer (re-run i2v with a new motion prompt against the committed base) — done in b9b9332, with `base`/`motion` provenance now written into the sheet manifest - [ ] …and audio tweak once the seat grows cover/repaint routes (the orchestrator 422 already documents that upstream blocker). **Blocked**: the audio seat still generates from text alone; #22 is closed, so this needs an audio-server ticket of its own **Play pane (#9 residuals)** - [ ] Run-aware build selection: today the pane loads the picked game's mirror root; once production runs emit real builds (walking skeleton, #11), it should follow the newest build of the ACTIVE run, not just the game. **Blocked on #11** — per-run builds don't exist yet; the drain mirrors per game - [x] Optional: auto-run vitals after each drain and surface the verdict as a chip, so regressions greet you without a click. — done in b9b9332/5009e67
Author
Owner

Four of the six follow-ups are done and deployed (b9b9332, 5009e67). The other two are blocked on work that hasn't landed — details below, and the checkboxes above are updated to match.

Files pane

Cross-file search. GET /repo/{slug}/search?q= greps the whole game repo server-side. Forgejo's code search needs the indexer enabled, so this walks the tree instead — resolving the head commit once and reading every blob at that sha. That is both consistent (no file read from a different commit than its neighbour) and half the API calls, since a branch-name read has to resolve the sha anyway; it also settles the follow-up noted on #31 about /repo/.../raw double-fetching. Binaries and blobs over 512KB are skipped, hits are capped at 20 per file and 200 overall, and the panel says when a result set was truncated. In the pane: a search box above the tree, results replacing it while a query is up, and clicking a hit opens the file and scrolls to the line.

Live against cycle-test: q=knight → 9 hits across 2 files from 4 searched, all read at ca62b356. Clicking docs/08-assets.md:22 opened the editor with the cursor on line 22, ### knight (sprite).

Sheets animate. An animated sprite now plays in the viewer using the review page's steps() technique, driven by the sibling manifest, with a pause toggle and the still sheet beside it. A missing or unreadable manifest falls back to the plain image — a still sheet beats a broken viewer.

Verified by driving the animation's own timeline: at t=375ms the background sits at −576px (frame 3 of 8), at t=875ms at −1344px (frame 7). 96×96 · 8 frames @ 8fps, matching the manifest.

Animate re-generation. The tweak box on a sheet becomes re-animate: it re-runs i2v against the committed base sprite with a new motion prompt, keeping frame count, fps and frame size from the manifest so the sheet keeps its shape.

Generation now writes base and motion into the manifest. Without that a sheet is a dead end — a record of frame counts with no memory of the sprite it animated. Sheets that predate it ask for their base once, from the repo's own committed sprites.

Verified with a real animate job on cycle-test: 411s, committed back to assets/animated_sprite/knight-walk.png, manifest now reading

{"frameWidth": 96, "frameHeight": 96, "frames": 8, "fps": 8,
 "base": "assets/sprite/knight.png", "motion": "slow idle breathing, slight sway"}

and reopening the sheet pre-fills both, with the note changing from "this sheet predates provenance" to "recorded when this sheet was generated".

Audio tweak — still blocked. Re-checked the seat while doing this: /music, /sfx and /vocal generate from text alone; there is no cover, repaint, or audio-to-audio route to condition on a source, and audio_item.produce is a single blocking call with no progress feed. The studio states this where the box would be rather than shipping a button that 422s (done under #31). #22 is closed, so the remaining blocker is audio-server model work with no ticket of its own — worth opening one if this is wanted soon.

Play pane

Auto-vitals after a drain — done. When a drain that touched the open game finishes, the pane reloads the build and runs vitals unprompted, tagged auto · drain finished. Verified by driving a fake drain transition (running → done) past the watcher: the run fired on its own, and the chip renders even when the playtest errors — live-caught, since an unasked-for run that fails is exactly when you need to know why it ran.

Run-aware build selection — blocked on #11. The pane can't follow "the newest build of the active run" because per-run builds don't exist yet: the drain mirrors per game ($FILES_URL/games/{game}/), and #11 (the E2E walking skeleton that would emit real builds) is still open. Implementing it now would mean inventing a concept the backend doesn't have. Left as-is, still pointing at the game mirror with the URL box as the override.

State

149 unit tests pass (new coverage for the search endpoint: text-only filtering, single-sha reads, line numbers, and the two-character floor), ruff and tsc --noEmit clean. Deployed and confirmed on the live bundle index-QRo1TZcJ.js.

Four of the six follow-ups are done and deployed (b9b9332, 5009e67). The other two are blocked on work that hasn't landed — details below, and the checkboxes above are updated to match. ## Files pane **Cross-file search.** `GET /repo/{slug}/search?q=` greps the whole game repo server-side. Forgejo's code search needs the indexer enabled, so this walks the tree instead — resolving the head commit **once** and reading every blob at that sha. That is both consistent (no file read from a different commit than its neighbour) and half the API calls, since a branch-name read has to resolve the sha anyway; it also settles the follow-up noted on #31 about `/repo/.../raw` double-fetching. Binaries and blobs over 512KB are skipped, hits are capped at 20 per file and 200 overall, and the panel says when a result set was truncated. In the pane: a search box above the tree, results replacing it while a query is up, and clicking a hit opens the file **and scrolls to the line**. Live against `cycle-test`: `q=knight` → 9 hits across 2 files from 4 searched, all read at `ca62b356`. Clicking `docs/08-assets.md:22` opened the editor with the cursor on line 22, `### knight (sprite)`. **Sheets animate.** An animated sprite now plays in the viewer using the review page's steps() technique, driven by the sibling manifest, with a pause toggle and the still sheet beside it. A missing or unreadable manifest falls back to the plain image — a still sheet beats a broken viewer. Verified by driving the animation's own timeline: at t=375ms the background sits at −576px (frame 3 of 8), at t=875ms at −1344px (frame 7). `96×96 · 8 frames @ 8fps`, matching the manifest. **Animate re-generation.** The tweak box on a sheet becomes *re-animate*: it re-runs i2v against the committed **base sprite** with a new motion prompt, keeping frame count, fps and frame size from the manifest so the sheet keeps its shape. Generation now writes `base` and `motion` into the manifest. Without that a sheet is a dead end — a record of frame counts with no memory of the sprite it animated. Sheets that predate it ask for their base once, from the repo's own committed sprites. Verified with a real animate job on `cycle-test`: 411s, committed back to `assets/animated_sprite/knight-walk.png`, manifest now reading ```json {"frameWidth": 96, "frameHeight": 96, "frames": 8, "fps": 8, "base": "assets/sprite/knight.png", "motion": "slow idle breathing, slight sway"} ``` and reopening the sheet pre-fills both, with the note changing from *"this sheet predates provenance"* to *"recorded when this sheet was generated"*. **Audio tweak — still blocked.** Re-checked the seat while doing this: `/music`, `/sfx` and `/vocal` generate from text alone; there is no cover, repaint, or audio-to-audio route to condition on a source, and `audio_item.produce` is a single blocking call with no progress feed. The studio states this where the box would be rather than shipping a button that 422s (done under #31). #22 is closed, so the remaining blocker is audio-server model work with no ticket of its own — worth opening one if this is wanted soon. ## Play pane **Auto-vitals after a drain — done.** When a drain that touched the open game finishes, the pane reloads the build and runs vitals unprompted, tagged `auto · drain finished`. Verified by driving a fake drain transition (running → done) past the watcher: the run fired on its own, and the chip renders even when the playtest *errors* — live-caught, since an unasked-for run that fails is exactly when you need to know why it ran. **Run-aware build selection — blocked on #11.** The pane can't follow "the newest build of the active run" because per-run builds don't exist yet: the drain mirrors per *game* (`$FILES_URL/games/{game}/`), and #11 (the E2E walking skeleton that would emit real builds) is still open. Implementing it now would mean inventing a concept the backend doesn't have. Left as-is, still pointing at the game mirror with the URL box as the override. ## State 149 unit tests pass (new coverage for the search endpoint: text-only filtering, single-sha reads, line numbers, and the two-character floor), ruff and `tsc --noEmit` clean. Deployed and confirmed on the live bundle `index-QRo1TZcJ.js`.
Author
Owner

Closing. Four of the six follow-ups shipped and are deployed; the two that remain are blocked on other work and now live in #33 rather than keeping this one open indefinitely.

Done here (b9b9332, 5009e67):

  • cross-file repo search, server-side, with results that open the file on the matching line
  • animated sprite sheets that actually animate in the viewer, with a pause toggle
  • animate re-generation from the viewer, plus base/motion provenance written into the sheet manifest so a sheet remembers what it was made from
  • vitals that run themselves after a drain touching the open game, tagged auto — including when the run errors, which is exactly when you need to know why it ran

Moved to #33: run-aware build selection (needs per-run builds from #11) and audio tweak (needs a source-conditioned route on the audio seat; #22 is closed, so that blocker had no ticket of its own until now).

Final state: working tree clean, CI green for HEAD, 149 unit tests pass, ruff and tsc --noEmit clean, and the full studio e2e suite — 10 tests including a live brain round-trip — passes against the deployed :2027. Stack healthy: brain up, no seats held, empty queue.

Closing. Four of the six follow-ups shipped and are deployed; the two that remain are blocked on other work and now live in #33 rather than keeping this one open indefinitely. **Done here** (b9b9332, 5009e67): - cross-file repo search, server-side, with results that open the file on the matching line - animated sprite sheets that actually animate in the viewer, with a pause toggle - animate re-generation from the viewer, plus `base`/`motion` provenance written into the sheet manifest so a sheet remembers what it was made from - vitals that run themselves after a drain touching the open game, tagged `auto` — including when the run errors, which is exactly when you need to know why it ran **Moved to #33**: run-aware build selection (needs per-run builds from #11) and audio tweak (needs a source-conditioned route on the audio seat; #22 is closed, so that blocker had no ticket of its own until now). **Final state**: working tree clean, CI green for HEAD, 149 unit tests pass, ruff and `tsc --noEmit` clean, and the full studio e2e suite — 10 tests including a live brain round-trip — passes against the deployed :2027. Stack healthy: brain up, no seats held, empty queue.
Sign in to join this conversation.
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
cmoriarty/trog#28
No description provided.