ledger - xopherdeep/do-it-for-the-xp GitHub Wiki

SDD ledger — plan: docs/superpowers/plans/2026-10-19-classic-dungeon-temples.md

Recovered 2026-10-21 from the lead session after the feat+classic-temples worktree (which held this git-ignored file) was removed. Part 1 (plan Tasks 1, 4, 5) merged as PR #155. Resume at plan Task 2 on a fresh branch off master; the briefs for Tasks 2 and 3 are on board #1455, Task 6 on #1456, the handoff on #1453. Builder reports are beside this file.

Spec: docs/superpowers/specs/2026-10-18-classic-dungeon-temples-design.md (docs 25be956) Worktree: .claude/worktrees/feat+classic-temples, branch feat/classic-temples, base 61d7b718 (origin/master) — removed after the merge Baseline: ShippedTemplesAudit 218 pass; TempleSolver|wakeOnEntry|RoomInteractions|MinibossBossKey|templeAudit|WindTemple 281 pass, 1 skipped. Owner (2026-10-19): open a PR and merge into master when done (merge once the PR's Tests check is green). Board: plan T1-T3 -> #1455, T4 -> #1468, T5-T6 -> #1456, T7 -> #1457, T8 -> #1458..#1464, T9 -> #1465, T10 -> #1466. Briefs go in board comments (owner rule).

Pre-flight scan

Pair / task Produces vs consumes Finding
T1 -> T2 RoomDrops, FIGHT_ROOM_TYPES consistent
T1 -> T3 roomDrops, dropKey, BOMB_ITEM; both edit FightDrops.spec.ts sequential, consistent
T1 -> T7 isBombSource + solver bomb lock vs dress Bomb-chest rule CONFLICT with spec: plan adds a Bomb chest only when the solver fails, but every temple gets a shop near the entrance (a Bomb source), so no chest would ever be placed; spec says a Bomb chest sits before any cracked wall on the only way forward
T1 -> T9 ShippedTemplesAudit Wind no longer blown by hand consistent
T1, T7 both edit ShippedTemplesAudit.spec.ts sequential
T3, T4 both may touch TempleGrounds wiring (T3 templeReveals/useRoomOutcomes, T4 TempleGrounds.ts/.vue) sequential
T4 -> T7 per-floor wake reads monsterTemplateCells by floor; T7 side rooms reuse floor's must-clear beasts consistent
T5 -> T6 ClassicDungeon schema, convert.py (T6 edits it) T6 after T5
T5 -> T7 dungeons/*.json, classicDungeon.ts consistent
T5 vs T6 ClassicDungeonJson.spec requires one Big Key and one big-chest in every JSON CONFLICT: Zelda 1 Level 1 has no Big Key and two key items (boomerang, bow)
T6 -> T9 Wind JSON (17 Eagle cells) + override re-adds the owner's 4 rooms consistent
T7 -> T8 ClassicPlan, dressClassic, renderClassicModule consistent
T7 -> T9 Wind joins CLASSIC_IDS; must-clear rules apply to JSON cells only consistent
T1 self tests vs code consistent
T2 self tests vs code consistent
T3 self sheet line as raw string vs Global Constraint "in-world text from the copy catalogue" CONFLICT (minor)
T4 self consistent
T5 self "map and compass present" vs randomizer data: location names do not always name the vanilla item (TR's map is "Roller Room - Left"); the pinned randomizer has no vanilla placement table GAP
T6 self consistent once the T5/T6 ruling applies
T7 self "today's quests must all stay" vs "side rooms reuse must-clear beasts" and "must-clear beasts distinct" vs "a plan short of beasts repeats one" CONFLICT x2
T8 self consistent
T9 self consistent
T10 self consistent
Process skill says never parallel implementers; T5 (converter) is long and shares no file see ruling

Rulings

  • Ruling: the dress step puts a Bomb chest (loot { chest: 'consumable', items: ['Bomb'] }) in the nearest reachable empty cell before every cracked wall whose blocking (bombable read as wall) cuts the boss off, whether or not a shop is reachable — the spec is binding ("a Bomb chest sits before any cracked wall on the only way forward") and kids should not need GP to pass — cost if wrong: a few extra Bomb chests, harmless.
  • Ruling: ClassicDungeonJson.spec's "one Big Key, one big-chest" checks apply to LTTP JSON (source starts with "LTTP"); the Wind JSON has no Big Key (the owner's east room holds it), and of Level 1's two I items the one reached by the stairway (the bow basement) is the big-chest, the other is chest: 'other' — Zelda 1 has no Big Key and the plan's Wind task already re-adds the owner's Boss Key room — cost if wrong: the Wind JSON shape differs from LTTP's in two fields, contained in one spec branch.
  • Ruling: the room sheet's drop line stays a raw string like every other line in RoomInteractions/vocabulary — the surrounding code's idiom wins for one line; the floor-wake reveal (new UI) uses the catalogue — cost if wrong: one line not in three voices, a one-line follow-up.
  • Ruling: vanilla chest contents come from sporchia/alttp_vt_randomizer's region classes (app/Region/Standard/*.php, setVanilla()), pinned by commit with its licence copied into sources/ (the T5 builder verifies the licence; if it is not permissive, hand-write the eight dungeons' vanilla tables into overrides/ from the same data) — the pinned door randomizer has no vanilla placement table and location names are not reliable — cost if wrong: one more source file to swap.
  • Ruling: must-clear plans are built from today's beasts first (starter-quest beasts guaranteed a must-clear room), topped up with other theme beasts to the must-clear count; when today's plan has more beasts than must-clear rooms, the extras leave that temple (they stay in the library) — the spec's side-room rule (reuse the floor's must-clear beasts) is binding and the plan's "all stay" serves only the starter quests — cost if wrong: a few beasts no longer in their temple; the GM can still place them.
  • Ruling: ClassicTemples.spec's "must-clear beasts distinct" exempts the beasts listed in classicReport(id).repeats — the spec allows repeats until art lands — cost if wrong: none; the repeats list is the art task.
  • Ruling: T5 (converter) and then T6 run in their own isolated worktree (Agent isolation) in parallel with T1-T4, merged into feat/classic-temples after review — they add only new files under tools/temples/classic and one new spec, so no conflicts; the skill's no-parallel rule exists for a shared tree — cost if wrong: a merge to resolve by hand.

Progress

Task 1: dispatched (sonnet, lead worktree, BASE 61d7b718, agent af6343cea5e7ff889) Task 5: dispatched (fable, isolated worktree, BASE 61d7b718, agent a0c36dc212c21b2b0) Task 4: dispatched (sonnet, isolated worktree, BASE 61d7b718, agent a8e717b52cbde098e)

  • Ruling: Task 4 also runs in its own isolated worktree in parallel — its files (wakeOnEntry.ts, TempleGrounds.ts/.vue, copy catalog, wakeOnEntry.spec) are disjoint from Task 1's — cost if wrong: a hand merge in TempleGrounds wiring when Task 3 lands.
  • Peer note 2026-10-19: another session relayed an owner rule (shared checkout = master only, chemx locks, path-scoped commits). This plan never touches the shared checkout; replied with our file list. Docs submodule commits ef50b59/25be956/aa350da still to push with the PR.
  • Peer note 2: the shared checkout's local docs master also holds another session's unpushed commits (b2e6967 spec, 5efcf5e plan). When pushing docs, push ONLY ef50b59, 25be956, aa350da (cherry-pick onto origin/master of docs in this worktree's own docs submodule), never the shared docs master as a whole. This session cannot run git against the shared checkout (worktree guard).
  • Peer note 3: the other session pushed docs master (origin 0d01a0b), carrying ef50b59/25be956/aa350da; verified ancestors of origin docs master from this worktree's docs submodule. No docs push left for this plan. Task 1: implementer DONE_WITH_CONCERNS (01da66ca); review dispatched (sonnet, agent ac7ecbd18c78eec65)
  • Ruling: Task 1 concern 2 (pre-existing: blowBombableSide records the side in openedDoors, so doorKind would let a Bomb skip the Boss Key on a cracked wall into a boss room) goes into Task 3's brief (it touches the play/doors path) — dress never draws a bombable side into a boss room, so converted temples are safe meanwhile — cost if wrong: a GM-built temple with a cracked boss wall can be skipped until Task 3 lands.
  • Handoff item: docs/Temple-Generation-Contract.md line 28 still says a cracked wall is a wall to the solver (Task 1 changed that); update in the docs submodule with the PR.
  • Gate item: run TempleDataModules.spec.ts and TempleGenerator.spec.ts (not run by the Task 1 implementer). Task 4: implementer DONE_WITH_CONCERNS (184ac299 on worktree-agent-a8e717b52cbde098e, worktree .claude/worktrees/agent-a8e717b52cbde098e); report copied to task-4-report.md; review dispatched (sonnet, agent a36ef4a1355cd9e83)
  • Gate item: run quickStartTemple.spec.ts, voices.spec.ts, TempleSystemCleared.spec.ts (not run by the Task 4 implementer) after merging Task 4. Task 1: complete (commits 61d7b718..01da66ca, review clean) Task 1: minor (deferred): roomGrants header says play hands out fight drops; true only after Task 3 Task 1: minor (deferred): solver stuckReason still says "no locked door in reach" when a cracked wall without a reachable Bomb blocks the hero Task 1: minor (deferred): a side drawn both bombable and small-locked becomes a pure bomb door (matches engine doors.ts:241-243) but no test pins it Task 1: minor (deferred): solver treats Bombs as unlimited once any source is reached (dress places one Bomb chest per blocking wall, per ruling) Task 1: minor (deferred): FightDrops.spec asserts FIGHT_ROOM_TYPES and BOMB_ITEM against themselves (tautological) Task 1: minor (deferred): quickStartTemple.walkingRank now walks through cracked walls (bomb doors), so rooms behind a crack rank by distance Task 4: complete (commits 61d7b718..184ac299, review clean; merged into feat/classic-temples as 07aad715)
  • Ruling: the first walk into a temple wakes the entrance floor silently (no reveal); only arriving on another floor shows "N beasts stir" — the spec says one-floor temples wake "exactly as today" on entry, and today is silent — cost if wrong: one call to showPrompt in the mount path. Task 4: minor (deferred): useTempleEntry's watch + prompt wiring has no composable spec Task 4: minor (deferred): a temple whose entrance is not on 1F can show the reveal on first entry (currentLevel starts "1F"); Task 5's converter names the entrance floor 1F, so classic temples are safe Task 4: minor (deferred): entranceFloorOf duplicates the engine's entrance-floor rule (heroRuns.startAt, templeGraph.resolveEntranceFloor) and ignores fallbackStart Task 4: minor (deferred): catalog/temple.ts header says voices equal to adventure are left out, but both entries repeat the adventure line as classic Task 4: minor (deferred): every floor change re-reads the layout before deciding "already woken" and re-awaits whenOpened/whenProgressReady Task 4: minor (deferred): the "Onward" choice label is hardcoded English (consistent with building prompts) Gate (after Tasks 1+4 merged, 07aad715): TempleDataModules|TempleGenerator|quickStartTemple|voices|wakeOnEntry|FightDrops|TempleSolver|WindTemple -> 253 passed, 1 skipped. Task 5: implementer run cut off by API ECONNRESET mid-task (worktree .claude/worktrees/agent-a0c36dc212c21b2b0, branch worktree-agent-a0c36dc212c21b2b0); resumed via SendMessage from its transcript. Task 5: implementer DONE_WITH_CONCERNS (2db3e819 on worktree-agent-a0c36dc212c21b2b0); 81 JSON checks green; overrides: PoD Compass Room SE -> 0x1a (0,1), Ice Spike Room Down Stairs -> 0x5f (1,1); extra pinned sources DoorShuffle.py, RoomData.py, PotShuffle.py; sporchia V30 8c043a40 (MIT) for vanilla items Task 5: review dispatched (opus, focused package review-task5-focused.diff without vendored sources, agent a749d1a3a3ced5302) Task 5: review Needs fixes (4 Important): edge overwrite drops PoD locks; locked stairways missing from JSON; mustClear defined wrong; shutter flag on wrong cell
  • Ruling: two different non-open kinds on one cell edge stop the converter with an error naming both pairs; overrides settle each — a silent overwrite hid two PoD locks — cost if wrong: a few more override entries.
  • Ruling: locked stairways become ClassicLink.lock?: "small-key" | "big-key" on the stairs link of the cell holding the locked door (additive contract change); spec asserts smallLocks = small-key side pairs + locked links; the engine learns locked climbs in a new task before Task 7 — keeps Zelda's structure (Hera's only lock gates the tower) without reshaping halls — cost if wrong: one engine task (RoomInteractions climb, solver stairs lock, unlock state).
  • Ruling: report.mustClear = distinct LTTP rooms holding a cell with enemies and (shutter or keyDrop); bosses/minibosses not counted — the design spec's definition, and the art task is sized from it — cost if wrong: art estimate off.
  • Ruling: shutter flag only on the cell whose own door has .trap()/Trap kind; the side stays shutter on both ends — cost if wrong: none.
  • Ruling: also in this round: side overrides applied before flags and counts; misspelt door/chest names in overrides are errors (rulings 1-2 depend on them). Task 5: minor (deferred): smallKeys counted from the same cells the spec counts (count from source locations instead) Task 5: minor (deferred): pot regex drops hex-coordinate pots (e.g. GT Hidden Spikes switch pot loses its puzzle flag); Tables has no count assertion Task 5: minor (deferred): "Floor conflict" and "no path places ... on 1F" are warnings, should stop the run Task 5: minor (deferred): undrawn pit/warps (1 Hera, 5 GT) and 17 merged "other" chests recorded only in console output, not in the JSON Task 5: minor (deferred): an unplaced main door crashes instead of a named error (convert.py:744-745) Task 5: minor (deferred): pinning a door mutates shared Tables dicts (harmless while dungeons are disjoint) Task 5: minor (deferred): spec lacks checks: stairs reciprocal and +-1 floor; hole drops exactly one floor Task 5: minor (deferred): SOURCES.md gives no hashes for the eight vanilla PHP files and the licence texts
  • Handoff item for Task 7 (dress): ~60 cells hold several contents (Skull entrance: big-chest + teleport; Hera boss cell: stairs + hole + teleport); dress needs a precedence rule (one room type per cell) and may move extras to a free neighbour cell; boss rooms reached only by stairs/falls (Hera, Skull, Ice) need the Boss Key gate on the link (lock: big-key) or the cell before.
  • Handoff item: sparse floor grids (Ice B6 17x3 with 5 cells, PoD B1 13x6 with 10) — dress should trim or accept. Task 5: fix round 1/5 dispatched (resumed implementer)
  • Board: new task #1484 (CT7a locked climbs, engine) added under #1453; #1457 (Task 7 dress) now depends on it. Task 5: fix round 1/5 (implementer DONE: 5491b30f; 89 checks green; PoD 6/6 locks, Swamp keeps bomb wall, 8 locked stairs as ClassicLink.lock; commits 2db3e819..5491b30f); scoped re-review dispatched (sonnet, agent a35f2331fde42e313) Task 5: fix round 1/5 (5 addressed, 0 open; commits 2db3e819..5491b30f) Task 5: complete (commits 61d7b718..5491b30f, review clean after 1 fix round) Task 5: minor (deferred): spec checks only lock totals; a stairway locked on both ends would pass Task 5: minor (deferred): spec never recomputes mustClear/side, and does not check that a shutter flag implies a shutter side
  • Handoff item for Task 7 (dress): GT Quad Pot (moon 3F 12,24) has enemies=3 that are all miniboss sprites; report.mustClear excludes it, so dress must not count it from enemies > 0 alone (or the converter should split enemies vs minibosses)
  • Handoff item: task-5-report.md's early sections are stale; only "Fix round 1" is current Merge origin/master into feat/classic-temples (clean); gate on merged branch: chemx typecheck clean, chemx lint passed (9 warnings), 522 touched specs green. Pushed c66598fc. PR #155 (opened earlier by the owner's account with auto-merge squash; title/body updated to cover Tasks 1, 4, 5). Bound to this session. CLOSE-OUT (owner option 2, 2026-10-21): handoff posted on #1453. Next session: fresh branch off master after #155 merges; resume at Task 2. Workspace kept in this worktree (do not delete); Tasks 1, 4, 5 complete. CI on #155 red on the audit ratchet ([email protected] audit --no-index): CRITICAL x2 (vendored DoorShuffle.py, EnemyList.py), LINE_BUDGET 39->47, TYPE_COLOCATION 0->1, INLINE_BOOLEAN 8->9. Fixed in a5f13ea1: tools/temples/classic/sources -> vendor/ (chemx skips vendor; JSON byte-identical), EntryWakeSkipInput + named isLastTurn in wakeOnEntry.ts, floor-wake prompt moved into useTempleEntry (TempleGrounds.ts 511 -> 498). convert.py (1214 lines) split dispatched (sonnet, agent adf1365a6efd12b0c). The local audit rewrites chemx-ratchet.json: always git checkout -- chemx-ratchet.json.
  • Before pushing: run the audit with BOTH [email protected] and [email protected] (PR #157 moves CI to 26.10.19-530). convert.py split into stage modules (0d037b73: convert.py 163, lttp_tables 254, lttp_layout 333, lttp_doors 262, lttp_contents 250; JSON byte-identical; 89 JSON checks green). SOURCES.md fixed (69b0b1ed). Audit vs chemx-ratchet.json: no rule worse under [email protected] (LINE_BUDGET 39, INLINE_BOOLEAN 8, TYPE_COLOCATION 0, 0 critical) nor under [email protected]. Pushed 69b0b1ed to #155. #155 MERGED (squash; Tests passing). Another session removed the feat+classic-temples worktree and both builder worktrees at the owner's request. Before removal: Task 2/3 briefs posted on #1455, Task 6 brief on #1456, ledger addendum on #1453. After removal: all 79 files touched by this work's commits verified identical on origin/master; builder reports for Tasks 1, 4, 5 rebuilt from the builders' transcripts (Task 5's fix section from the session scratchpad) and archived beside this ledger.
⚠️ **GitHub.com Fallback** ⚠️