feat(webapp): the Prep lane: pickers, notes, re-open, a steerable sheet, a front door, and clocks (phase 3 of v4.3.0) #528
Loading…
Reference in a new issue
No description provided.
Delete branch "feat/phase3-prep-workbench"
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?
Closes #302, closes #303, closes #304, closes #305, closes #374, closes #381. Phase 3 of the v4.3.0 build order (#514): the Prep workbench lane, six commits in dependency order. No migration, no contract change.
#302 One ordering rule (
utils/sessionOrder.js,soonestFirst): dated sessions ascending, undated last. The Session Prep picker, Beat Planner and the Name Generator (same bug, third picker) all default throughAddToShelf.defaultSessionId, which is re-expressed on the shared sort so the two rules cannot drift. API ordering unchanged. No existing test pinned the old behaviour, because the fixture sessions had no dates; the new ones would have caught it.#303 #454 had already put
beat_noteson the GM-gated session response (tested), so the issue's premise had moved. This adds the read the issue asks for,GET …/planning/sessions/{sid}/beat-notesmirroring the PATCH, with a test that the two reads agree, and keeps the response field (thetranscriptprecedent). The client marks the read uncached; oneBeatNotesEditoris used by Beat Planner and the prep panel; Save is disabled while the draft matches the server (the untouched-empty-draft guard); a failed read disables the box and the button, since an unseen empty draft is the worst thing to write back; Append reads at click time and fails closed. The test that pinned the broken append now asserts real concatenation.#304 Configs gain
restore: { toValues, matches }. Re-open hands the row to the panel keyed by run id; on mount a panel restores its tool's newest ready run only whenmatchessays it is still about the current selection.matchesexists only for session-keyed tools; wiki-article grounding is not restored (a run stores ids, the picker holds entry objects), documented in the file.#305 The notes editor lives inside the Session Prep panel; a one-shot
directionsteer is a newSessionPrepParamsfield with its own context block registered last; the prompt names what the recent summaries are for and makesloose_endsthe only backward section. Tests assert on the assembled prompt and system prompt, including that the steer block comes last.#374 "Prep this session" on the GM session page and on every upcoming row of the campaign page, via
?tool=session_prep&session=…, read once into state; Session Prep is the default tool; untitled sessions read as their date everywhere through onesessionPickerLabel; "Save to this session" and "Add to shelf" each report where the output went; Generation History refetches on arefreshKey. Palette 13 → 6 jobs with the tools as leaves (Session Prep: prep, Beat Planner, series titles; Story Arcs: board, suggester; Quests: tracker, rumor mill; NPCs: instant NPC, voice cues; Names; At the Table: description, random table, loot parcel); nothing removed andactiveToolIdstays a leaf id, so links, Re-open and history labels are untouched. Switching sessions inside the panel now confirms before discarding unsaved notes (#410's guard, in its new location).#381 One
ElapsedTimeron the session page, the recording page and the Prep button, each with a typical-duration hint. The audio pipeline records no start time, so it anchors onupdated_at, which can under-report but never over-report; an exact start column would be a migration and is noted as a follow-up. "history rail" → "Generation History".Frontend 667 passed (57 files, +51 on this lane), backend full 2476 passed / 13 skipped, ruff and eslint clean apart from the pre-existing warning,
vite buildgreen. Two follow-ups worth a decision rather than silent action: Beat Planner is now redundant with the in-panel editor, and anaudio_processing_started_atcolumn would make the timer exact.🤖 Generated with Claude Code
`GET /api/campaigns/{id}/sessions` returns sessions newest-first by `created_at`, and a recurring series materialises its occurrences in date order — so `sessions[0]` is the occurrence furthest in the future. Every picker that seeded from index 0 therefore defaulted the GM to the session they will prep last. One rule, in one place: `utils/sessionOrder.soonestFirst` orders dated sessions ascending and sends undated ones to the back. `GeneratorPanel`'s `sessionOptions` sorts with it (so `session_prep` and `series_titles` both list and default correctly), `autoSelectFirst` now means "the session `AddToShelf.defaultSessionId` would pick", and the Beat Planner and Name Generator seeds in `CampaignPlanning` use the same call. `AddToShelf`'s own rule is re-expressed on top of the shared sort rather than re-implementing it. The API ordering is unchanged — other screens depend on it. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>`GeneratorPanel` holds its result in local state and the shell unmounts it on every tool switch, so a generated sheet was gone the moment the GM looked at anything else — while the run itself sat persisted in `generation_results` and listed in Generation History. "Re-open" switched the active tool and stopped there, which is the least useful half of what the word promises. Restoring needs the inverse of `buildParams`, which only the tool knows, so configs gain `restore`: toValues(params, ctx) -> values | null rebuild the inputs; null = "I cannot show this faithfully" matches(params, values) -> boolean is this run about what the panel is currently pointed at? Re-open passes the row to the panel as `initialRun` (keyed by run id, so a second Re-open remounts) and uses `toValues`. On mount, a panel with `matches` asks history for its tool's newest ready run and restores it only if it still matches the current selection — the session-keyed tools declare that; the free-text ones do not, because "the last thing you generated" is not the same claim as "the sheet for this session". `session_prep`/`series_titles` return null from `toValues` when the run's session is no longer one the picker offers: every action on a prep sheet writes to the session it names, so a sheet shown against the wrong one is worse than no sheet. Wiki-article pickers are not restored — a run records ids and the picker holds entry objects — which is documented at the top of workbenchTools.jsx. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>