06 · Create the intuitive trog command layer — one CLI, central orchestrator, retire make #21
Labels
No labels
bug
duplicate
enhancement
help wanted
invalid
question
wontfix
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
cmoriarty/trog#21
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
The make targets are accruing (asset-bench, assets-drain, cycle-test, critic-test, seat-up/run/down, hello, health…) on varying underlying scripting strategies — bash sourcing bash, python drivers, docker-exec'd python, heredocs — and it's getting unkept. Redesign the user-facing layer (user direction, 2026-07-24; supersedes much of the UX built in #17, whose plumbing stays).
The idea: one
trogcommand, obvious things trivially easy.Examples, not a final surface — subcommands take params for extra functionality, but the most useful case per command must be a one-liner with a plain-English prompt.
Requirements (from the direction):
What already exists to build on (don't rebuild, absorb):
assetq(Postgres queue) — already the handoff for batch drains; the orchestrator could be its standing consumerscripts/seat.sh+ profiles (#17) — the seat lifecycle the orchestrator would own; profiles stay the per-model truthDesign questions to settle first (proposal before code):
trog imageprint on success?trog test cycle/trog test critics?)trog critique: judge an arbitrary file against a prompt — needs a critic entrypoint decoupled from game-repo specs (brief comes from argv, file from path/repo)trog update: which update story does this wrap (check-updates/try-updates? deploy? both?)--repo,--out)?Decision output: a short design doc (docs/command-layer.md) answering the above, then implementation in phases — CLI skeleton + orchestrator MVP covering image/sfx/music one-offs first, drain/test/critique absorption after.
Related: #17 (tiers/plumbing this layer sits on), ticket 10 (E2E), studio UI (v2 milestone).
Phase 1 (MVP) is live (commits
f7ae09e,9381845; stack redeployed). Decisions honored: python everywhere, orchestrator in its own container, assetq as the reliable backing queue — Postgres, durable, transactional claims (FOR UPDATE SKIP LOCKED), one source of truth shared with the drain via anorigincolumn so the conductor and orchestrator can never double-consume.Install (laptop):
Working today, all smoked against the live stack:
Every job streams its progress events to the terminal and ends with the committed Forgejo URL. One-offs land in
trog-games/seat-scratch(--repooverrides).How it works: CLI → orchestrator API (:8200) →
assetqorigin='oneoff'→ single worker: brain idle-check → stop brain → seat container on the stack network (no host ports, no ssh, no laptop in the data path) → same drivers the conductor uses (now canonical introg_lib;scripts/keeps shims) → commit → always restore the brain (finally-block + boot-time reconcile that removes orphan seats and restarts a downed brain after a crash).SEAT_MODE=mockruns the whole path with the in-repo stub — both mock paths smoked too./critiqueis the spec-decoupled judge (brief from argv, file uploaded; brain vision or analyzer CLAP).Validation: 64 unit tests green (8 new for the CLI→spec mapping), lint clean,
make cycle-teststill PASSED (67s — conductor unaffected by the driver moves), orchestrator + brain + aegra healthy after all smokes.Not yet (phases in docs/command-layer.md): seat keep-warm TTL (consecutive one-offs currently bracket the brain each time),
trog drain/trog bench(conductor absorption),trog test *(make retirement completes there), SSE instead of polling,trog update's full story. Design doc + make-retirement map committed as docs/command-layer.md.Seat keep-warm TTL shipped and verified live (commit pushed, stack redeployed):
trog sfx "wooden door creaking open"→ 36s (brain hands over GPUs, seat up, generate, commit)trog sfx "heavy door slamming shut"→ 19s — event saysseat 'audio' already warm; generating, zero brain churnORCH_SEAT_TTLenv tunes the window (default 180s). Profile switches swap seats without bouncing the brain twice.trog statusshows the warm seat and its remaining window. Worker shutdown also releases — the brain can't be orphaned by a restart.Remaining phases unchanged:
trog drain/bench(conductor absorption),trog test *(make retirement completes), SSE,trog updatestory.Delivery redesign shipped (user direction: CLI one-offs are throwaways; git makes them permanent and they pile up):
produce()returns artifacts as bytes; the caller picks the destination. The conductor'srun_item(produce + git) is unchanged — cycle-test still PASSED (68s).--repo= throwaway: date-bucketed plain file under/mnt/output/oneoffs/<date>/, served at:3923/oneoffs/…— and trogdor-files grew a dedicated share with 14-day auto-expiry (same lifetime flag as intermediates), so throwaways literally clean themselves up.--repo owner/name= keeper: git delivery into that game repo, Forgejo URL printed. The game-design graph's drain always delivers to git — git stays truth for production.trog animategained--base-repofor one-offs whose base sprite lives in a repo the job isn't delivering to.Live smoke:
65 tests green, both stacks redeployed (trog + trogdor-files 8e99b83), brain restored by TTL sweep, queue empty.
Three more phase-2 features shipped and live-smoked in one session:
1 · Live queue position + spinner UX. One animated dots line narrates:
Job is #N in the queuecounts down live (N = your place among one-offs — the multiplayer-studio contract), thenSwapping brain for image stack→Generating sprite→ green done line. Phase events fire at phase START. The bigserial never shows: jobs surface as small per-day refs (trog job 10re-attaches), and a daily sweep prunes terminal one-offs older than 14 days.2 · Parallel seats on free GPUs. SeatManager is multi-seat with the GPU truth table (audio=1, animate=0/2/3, image=all): a submitted job starts in parallel whenever its cards are free; same-profile jobs share the warm seat. A blocked exclusive job preempts idle warm seats immediately (brain kept down — no thrash) instead of waiting out the TTL. Smoked: music + sfx ran together on the audio seat; the image job showed its countdown, preempted the idle audio seat, and took the rig.
3 ·
trog image --from <path-or-url>— tweak an existing image. Local path or any http URL (file-server links work). Newflux2-pixel-i2iworkflow re-runs the tail of the schedule over the encoded source (--denoise0=copy…1=ignore, default 0.55) through the same pixel post-pass. Smoked end-to-end: generated a blue hedgehog, then--fromits file-server URL with "make it red with white gloves" — same character, same pose, gloves added. Audio--fromis refused with an honest 422 until the seat's cover/repaint routes are wired.67 tests green, stack redeployed, brain restored by the TTL sweep after the smokes.
Closing: the command layer stands as a complete unit. Shipped, deployed, and live-smoked in this ticket:
trogCLI (uv/pip): image / music / sfx / animate / critique / job / status — plain-English one-liners with a dots-spinner narration, live#N in the queuecountdown, per-day job refs (bigserial never shows):3923/oneoffs/, 14-day auto-expiry both file- and queue-side);--repo→ git; drains stay git — git is truth for production--fromimage tweak (local path or URL,--denoiseknob, i2i workflow through the same pixel post-pass);/critiquedecoupled from game specsFollow-ups spun out: #22 (06.1 drain absorption — conductor + bash profiles retire,
trog drain/bench/update, audio--from) and #23 (06.2 testing absorption + make retirement —trog test *, seat.sh retires, SSE,--out). The make targets live until those land.