ledger - xopherdeep/do-it-for-the-xp GitHub Wiki
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).
| 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 |
- 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
Iitems the one reached by the stairway (the bow basement) is thebig-chest, the other ischest: '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.
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 > 0alone (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.