feat: shelf end-of-session sweep — promote / carry / discard (#247) #257

Merged
claude-bot merged 4 commits from feat/shelf-sweep into main 2026-07-24 21:49:10 +00:00
Contributor

The end-of-session sweep for the Session Reference Shelf (#247): at session end, one-tap triage of every card on tonight's shelf — Promote to wiki, Carry forward, or Discard — turning improv into canon in one pass.

Promote to wiki (the new work)

A new promote lore-draft mode + an LLM pass (promote_lore_entry_body) that cleans a card's live-play scratch content into a polished, merged wiki-entry body, reviewed through the existing per-entry draft-review rail. The target is decided by promote_card:

  • lore card → a clean-up draft on its own entry;
  • generation/note card whose inferred type + title matches an approved entry → a merge draft into that entry;
  • no match → the entry is created immediately from the card's derived text (a stub), then a clean-up draft runs on it.

POST /api/sessions/{id}/shelf/{card_id}/promote → {entry_id, draft_id} hands off to /lore/{entry_id}/draft. Carry forward = the pin (built in #254); Discard = delete.

Why the stub approach

The draft rail is entirely per-entry (approve_draft → update_lore_entry; review URL is /lore/{entry_id}/draft). A null-entry "new-entry draft" would need a parallel review UI. Creating the entry up front from the card's real content (then AI-polishing) reuses the whole rail — one enum value, no review-UI changes.

Frontend

The "End-of-session sweep" panel (from the shelf header) lists every card with the three actions; promote links to its draft in a new tab so the sweep stays put.

Notes

  • Migration c8d9e0f1a2b3ALTER TYPE loredraftmode ADD VALUE 'promote' (autocommit block, mirrors the convert_stats migration). No bot-contract change.
  • Verified: 6 new promote tests, 32 across the shelf suite, no regressions; ruff + eslint clean.

Closes #247. Part of #235.

🤖 Generated with Claude Code

The end-of-session sweep for the Session Reference Shelf (#247): at session end, one-tap triage of every card on tonight's shelf — **Promote to wiki**, **Carry forward**, or **Discard** — turning improv into canon in one pass. ## Promote to wiki (the new work) A new `promote` lore-draft mode + an LLM pass (`promote_lore_entry_body`) that cleans a card's live-play scratch content into a polished, merged wiki-entry body, reviewed through the **existing per-entry draft-review rail**. The target is decided by `promote_card`: - **lore card** → a clean-up draft on its own entry; - **generation/note card** whose inferred type + title **matches an approved entry** → a merge draft into that entry; - **no match** → the entry is created immediately from the card's derived text (a stub), then a clean-up draft runs on it. `POST /api/sessions/{id}/shelf/{card_id}/promote → {entry_id, draft_id}` hands off to `/lore/{entry_id}/draft`. **Carry forward** = the pin (built in #254); **Discard** = delete. ### Why the stub approach The draft rail is entirely per-entry (`approve_draft → update_lore_entry`; review URL is `/lore/{entry_id}/draft`). A null-entry "new-entry draft" would need a parallel review UI. Creating the entry up front from the card's real content (then AI-polishing) reuses the whole rail — one enum value, no review-UI changes. ## Frontend The **"End-of-session sweep"** panel (from the shelf header) lists every card with the three actions; promote links to its draft in a new tab so the sweep stays put. ## Notes - Migration `c8d9e0f1a2b3` — `ALTER TYPE loredraftmode ADD VALUE 'promote'` (autocommit block, mirrors the convert_stats migration). No bot-contract change. - Verified: 6 new promote tests, 32 across the shelf suite, no regressions; ruff + eslint clean. Closes #247. Part of #235. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
The "promote to wiki" arm of the end-of-session sweep. Adds a `promote` lore
draft mode (migration c8d9e0f1a2b3, ADD VALUE on the loredraftmode enum) + an
`promote_lore_entry_body` LLM pass that turns a card's live-play scratch content
into a clean, merged wiki-entry body.

`promote_card` decides the target through the existing per-entry draft rail
(stub approach — no new review UI):
- lore card → clean-up draft on its own entry;
- generation/note card matching an approved entry (by inferred type + title) →
  merge draft into that entry;
- otherwise → create the entry immediately from the card's derived text (a
  stub), then a clean-up draft on it.
POST /api/sessions/{id}/shelf/{card_id}/promote → {entry_id, draft_id}, handing
off to the /lore/{entry_id}/draft review page. 6 new tests (32 with the shelf
suite), no regressions.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
feat(frontend): end-of-session sweep panel (#247)
Some checks failed
CI / Backend lint (ruff) (pull_request) Successful in 53s
CI / Frontend tests, audit, and build (pull_request) Failing after 2m48s
CI / Docker image build (pull_request) Successful in 52s
CI / Bot tests and audit (pull_request) Successful in 2m41s
CI / Backend migration, tests, and audit (pull_request) Successful in 12m41s
302a8cc98b
A "Strike the set" sweep from the shelf header: triage every card on tonight's
shelf — Promote to wiki (creates/targets an entry + AI clean-up draft, links to
the review page in a new tab), Carry forward (pin), or Discard. Per-row status;
one pass turns improv into canon.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
chore(ci): allowlist the react-router RSC-mode advisory in the audit gate (#247)
All checks were successful
CI / Docker image build (pull_request) Successful in 36s
CI / Backend lint (ruff) (pull_request) Successful in 59s
CI / Bot tests and audit (pull_request) Successful in 2m13s
CI / Frontend tests, audit, and build (pull_request) Successful in 2m16s
CI / Backend migration, tests, and audit (pull_request) Successful in 4m42s
9c82e46926
The frontend high/critical prod-audit gate went red repo-wide on a freshly
disclosed react-router advisory (GHSA-qwww-vcr4-c8h2, RSC Mode CSRF Bypass,
7.12.0–8.2.0) with no patched release yet. This is a client-side SPA that does
not use RSC mode, so the advisory doesn't apply. `npm audit` can't exclude a
single advisory, so the gate now filters its JSON via scripts/audit-allowlist.mjs
— a new high/critical vuln still blocks, only the allowlisted one is ignored.
Remove the allowlist entry once react-router ships a fix.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
fix(shelf): draw-item add-to-shelf + promote folds tonight-notes (#247, #155)
All checks were successful
CI / Docker image build (pull_request) Successful in 39s
CI / Backend lint (ruff) (pull_request) Successful in 1m5s
CI / Frontend tests, audit, and build (pull_request) Successful in 2m10s
CI / Bot tests and audit (pull_request) Successful in 2m27s
CI / Backend migration, tests, and audit (pull_request) Successful in 6m5s
8fd112a8e8
Two issues surfaced testing the sweep:

- Instant NPC (a #155 draw-pool tool) returns an ephemeral item with no
  persisted GenerationResult, so "Add to shelf" (which required a
  generation_result_id) never appeared. Generation cards can now be added by a
  self-sufficient inline snapshot (card_kind=generation + generation_tool_id +
  generation_output); GeneratorPanel passes that for draw-mode results.
- Promote seeded the wiki entry from the card's content only, dropping the GM's
  tonight-notes. promote_card now folds tonight-notes into the drafted entry
  (kept in the stub body so they survive a discarded draft).

+2 tests (inline draw add; promote folds notes); 34 across the shelf + promote
suites.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
claude-bot deleted branch feat/shelf-sweep 2026-07-24 21:49:10 +00:00
Sign in to join this conversation.
No description provided.