[GM Workbench] Loot parcel generator (A4) #149
Loading…
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?
Motivation / Context
GMs need itemized loot parcels scaled by party level, wealth, and source ("dragon hoard," "pickpocketed noble") constantly during prep — a classic, table-stakes generative tool (§3, Group A). No loot/item model exists in the schema today (confirmed by the report's grep for
loot/quest_loginwebapp/backend/app), and issue #112 (loot ledger + XP tracking, v3.7.0) is specifying theLootEntry/XpAward/GoldLedgerEntrytracking models. This generator produces forward content (new parcels from a prompt), which #112 explicitly flags as a complementary follow-up, distinct from #112's own noted future scope of "LLM extraction proposing loot from transcripts" (retroactive, from session text — not this tool).Tagged TT in the report — sequence alongside or after #112 so the "send to ledger" action has a real destination, though the generator itself has no hard schema dependency on #112.
Approach
loot_parceltool inGENERATOR_TOOLS(generation_service.py, #136).game_system. Usescampaign_contextfrom #136.generate_structured_textin JSON mode. Small output → runs inline (sync_allowed=True).GenerationResult(scratch, #138) by default.LoreEntrywithentry_type=artifact(per §3's "Output lands" column) for items worth wiki tracking.LootEntry-shaped fields (name,qty,est_value,currency,notes) directly into #112'sPOST /api/campaigns/{campaign_id}/lootendpoint. Until #112 ships, this action is simply absent — the tool still works standalone (scratch + artifact lore entries).name,qty,est_valuefree-text,currencyfree-text,notes) to match #112'sLootEntryfield names from the start, even before #112 lands, so the later integration is a thin mapping rather than a reshape.Dependencies
LootEntry,XpAward,GoldLedgerEntry) and the/api/campaigns/{campaign_id}/lootendpoint. This issue does not require #112 to ship first — the generator works standalone — but the "add to loot ledger" action is a no-op/hidden until #112's endpoint exists. Recommend implementing this issue's ledger-integration action in the same PR as or immediately after #112, per the report's "sequence after or alongside #112" guidance.Out of scope
LootEntry; parcel output is scratch/lore-entry only until #112 exists, then maps ontoLootEntryfields.game_systemhint only, matching #130's locked stance).Acceptance criteria
loot_parceltool registered and reachable viaPOST /api/campaigns/{campaign_id}/workbench/loot_parcel/generate, GM-only.game_system, returns an itemized parcel with name/qty/est_value/currency/notes per item.GenerationResulthistory.artifact-typeLoreEntryrows individually.LootEntryrows; if not, the action is absent and the rest of the tool functions normally.Moved from v3.7.0 Table Tools → v3.10.0 GM Workbench (2026-07-18).
Rationale: same as #144 — this issue is specified as a
loot_parceltool registered into the Phase 0 Workbench foundation (#134/#136/#138), which is unbuilt and lives in v3.10.0. Building it standalone now would mean re-homing it into the registry later. Note #112 (the loot ledger this feeds via "add to loot ledger") has now shipped in v3.7.0, so when this is built on the Workbench foundation, the ledger-integration action has a livePOST /api/campaigns/{id}/lootdestination and correctly-namedLootEntryfields (name/qty/est_value/currency/notes) to map onto — a thin mapping, as intended.Done — merged to
feat/v3.10-gm-workbenchvia PR #220 (batched with #144 + #147).loot_parceltool registered on the #136 engine: an itemized parcel scaled to source + optional party level, persisting aGenerationResult(#138). Item field names are exactlyname/qty/est_value/currency/notes— matchingLootEntry. FrontendLootParcelGeneratorrenders the parcel + flavor; per item, "Save as artifact" →LoreEntry(entry_type=artifact), and "Add to ledger" → the #112 loot ledger viacreateLoot(a thin mapping, as intended — #112 has shipped). Tolerant parser. No new API/models/migrations.Verified: backend 712 passed (incl.
test_workbench_loot.py), frontend 372 passed, ruff + eslint clean.