Repository navigation
task 4 report
Branch: worktree-agent-a8e717b52cbde098e (worktree .claude/worktrees/agent-a8e717b52cbde098e, off origin/master 61d7b718)
Head: 184ac299 feat(temples): beasts wake floor by floor: the entrance floor on entry, each other floor on first arrival
(Note: the harness refused a write to the feat+classic-temples worktree path from this isolated agent, so this report is at
<my worktree>/.superpowers/sdd/2026-10-19-classic-dungeon-temples/task-4-report.md.)
src/lib/services/temples/wakeOnEntry.ts (still pure; writes only through the writers it is handed; doc comments rewritten for the floor rule):
-
wakeKey(templeId, floor)->${templeId}@${floor}. -
floorsOfLayout(layout)(new, exported): a one-grid maze is["1F"], a record maze is its keys in drawn order, no maze is[]. -
entranceFloorOf(layout): mirrors the engine'sstartAt(heroRuns.ts): an entrance of[floorIndex, row, col]indexesObject.keys(maze), a[row, col]entrance is the first floor; falls back to the first floor, then "1F". It accepts null/undefined (returns "1F"). -
wasWokenFor(effects, templeId, floor, entranceFloor): true forwakeKey, and for the legacy baretempleIdonly whenfloor === entranceFloor. -
rememberWake(effects, templeId, floor, now): writes thetempleId@floorkey, keeps every other key (legacy keys included). -
EntryWakeInput.floor(required);EntryWakeInput.layoutis nowPlayedLayout;EntryWakePlan.floor. The plan readsmonsterTemplateCells(layout).filter(cell => cell.floor === floor). - New skip reason
"noFloor": a floor the layout does not draw wakes nothing and writes no key (guards junk keys such aswind-temple@9F). -
entryWakeSkiptakes optionalfloor+entranceFloor; "alreadyWoken" is decided only when both are known (the entrance floor lives in the layout, sorunEntryWakefirst does the who/where check with no reads, then reads the layout, then decides alreadyWoken). -
EntryWakeDonegainsfloorandstirred(woken + joined);changedisstirred > 0. -
wakeTempleOnEntry(templeId, heroId, deps?, now = new Date(), floor?):floordefaults to the entrance floor. A hero's wakes now take turns (a per-hero promise chain), because the floor watch makes two wakes for one hero possible at once and both write the onequestEffects(a lost-update race: the later write would drop the earlier floor's key). Two asks for the same hero+temple+floor still share one promise. -
PlayedLayouttype moved above first use (new "Floors" section).
src/app/Console/TempleGrounds/templeGrounds/useTempleEntry.ts (this is where the mount-time wake lives; TempleGrounds.ts just calls it): mount-time wake kept (entrance floor, silent). New watch(currentLevel): whenOpened -> whenProgressReady -> wakeFloor(floor); when changed: refreshQuestRooms, then showPrompt with one Onward choice (icon arrow-right, primary, Escape = Onward), no building accent.
src/app/Console/TempleGrounds/TempleGrounds.ts / .vue: useRevealPrompt() created in setup, currentLevel and showPrompt handed to useTempleEntry, XpRevealPrompt registered and mounted once at the end of the page (it teleports to ion-app, like the buildings).
src/lib/services/copy/catalog/temple.ts (new, registered in catalog/index.ts parts and CATALOG): temple.floorWake {count, floor} ("3 beasts stir on 2F.") in simple/adventure/classic, plus temple.floorWakeOne ("A beast stirs on 2F.") so a single beast never reads "1 beasts" (same one/many pattern as beastCard.tamed.*).
src/lib/services/temples/quickStartTemple.ts: required by the new rememberWake signature. Quick Start wakes every monster room of every floor, so it now remembers every floor of the layout it used (falls back to the entrance floor if the layout draws none).
src/lib/engine/quests/QuestSchedule.ts: doc comment of templesWokenAt only.
RED (spec rewritten first for the new API; ts-jest fails to compile because the new exports do not exist):
$ chemx test tests/unit/wakeOnEntry.spec.ts
✖ Test Failures (1 failed out of 1)
✖ Test suite failed to run
tests/unit/wakeOnEntry.spec.ts:24:3 - error TS2305: Module '"@/lib/services/temples/wakeOnEntry"' has no exported member 'wakeKey'.
GREEN (after the implementation; run again after the UI/copy work, same result):
$ chemx test tests/unit/wakeOnEntry.spec.ts
✔ All tests passed (54 passed in 34169ms)
New copy spec (written after the catalogue file, so it has no RED run of its own):
$ chemx test tests/unit/templeCopy.spec.ts
✔ All tests passed (3 passed in 16910ms)
Brief's seven cases are all in wakeOnEntry.spec.ts under "waking floor by floor" (fixture tower() = Spire + a 2F with three monster rooms + a 3F with none), plus: legacy memory with an entrance on 2F, noFloor, a beast already theirs from another floor, joining a quest woken for another hero on the arrival floor, entranceFloorOf cases, wakeKey, stirred counts, a concurrent entry + 2F wake that keeps both keys (slow saveEffects makes the race real), shared promise for the same floor, and layout-only reads for an already-woken hero.
- src/lib/services/temples/wakeOnEntry.ts
- src/lib/services/temples/quickStartTemple.ts
- src/lib/engine/quests/QuestSchedule.ts (comment)
- src/app/Console/TempleGrounds/TempleGrounds.ts, TempleGrounds.vue
- src/app/Console/TempleGrounds/templeGrounds/useTempleEntry.ts
- src/lib/services/copy/catalog/temple.ts (new), catalog/index.ts
- tests/unit/wakeOnEntry.spec.ts, tests/unit/quickStartTemple.spec.ts (the three
wasWokenFor/key assertions), tests/unit/templeCopy.spec.ts (new)
- Brief says
useRevealPrompt().ask; the composable has noask: it returnsshowPrompt(resolves with the choice id). UsedshowPrompt. - Brief says the watch lives in
TempleGrounds.ts~line 375; the mount-time wake actually lives inuseTempleEntry.ts(called from TempleGrounds.ts), so the watch went there next to it. - "Already woken" now costs one layout read instead of zero (the entrance floor needed for the legacy rule is in the layout). Quests and bestiary are still not read for an already-woken floor. Test updated to say so.
- Mount-time wake stays silent (no reveal); only the floor-arrival watch tells the hero. The brief's "When stirred > 0 ... reveal" sits under the watch bullet; if the owner wants a reveal on first entry too, it is one line in
useTempleEntry.ts. - Portal Home: re-entry starts at the entrance floor, which is already remembered, so
wakeTempleOnEntryreturns null and no reveal shows. -
HeroQuestEffects.templesWokenAtvalues/shape unchanged; keys nowtemple@floor. Old bare keys keep working as the entrance floor's.
- I did not run (per the rules)
chemx typecheck,lint, or any spec but the two above. Specs that may be affected and were not run:tests/unit/quickStartTemple.spec.ts(edited: 3 assertions now expectwind-temple@1F),tests/unit/voices.spec.ts(catalogue shape: unique keys, adventure present, simple lines <= 10 words: my lines are 6 words each), andtests/unit/TempleSystemCleared.spec.ts(mounts TempleGrounds with a mocked user store and no pinia; the new setup code callsuseCopy(), which tolerates no active pinia, and importsuseRevealPrompt/XpRevealPrompt; its temples are not shipped, so the watch's wake returns null immediately). - Type-level review done by reading only for
useTempleEntry.ts,TempleGrounds.ts,quickStartTemple.ts(ts-jest type-checkedwakeOnEntry.tsand the catalogue through the two specs that passed). - Edge: a shipped temple whose entrance floor is not the first level the screen shows (useTemple's
currentLevelstarts at "1F") could fire the watch for the entrance floor before the mount wake and show the reveal at first entry. All nine shipped temples enter on 1F, so this is theoretical; CT3's temples should keep 1F as the entrance floor or accept the reveal. -
chemx team task show 1468carried the same brief text as the file; no extra instructions in the comments.
- Architecture
- Component-Library
- Hooks-Reference
- Temple-System
- Battle-Field-Architecture
- current_context - For AI/Human Handoff
- User Menu
- General Settings
- Family Settings
- Sound Settings
- Notification Settings
- Reward Settings
- Party Settings
- Theme Settings
- Chore Settings