task 11 context - xopherdeep/do-it-for-the-xp GitHub Wiki

Task 11 context from the lead (decisions the brief cannot know)

OWNER RULING 2026-10-27 (supersedes the brief where they differ): the credits roll DROPS THE AGES.

  • src/lib/services/copy/credits.ts holds the makers' roster as the ONE data file the owner trims later: interface Maker { name: string; role: string } and MAKERS: readonly Maker[], in the brief's order with the brief's names and roles exactly. NO birthYear, NO makerAge, no age or year field anywhere.
  • CreditsRoll shows each maker's role and name only. No spec, fixture or snapshot asserts or mentions an age or a birth year (drop the brief's "makerAge in 2027 gives 43, 20, ..." test; test the names and roles in order instead).
  • The "lead asks the owner before committing credits.ts" step is settled by this ruling: the lead commits it.

Earlier tasks you consume (on this branch; read with chemx read <file> --outline / --symbol=<name>):

  • T7 src/lib/services/projects/projectRecord.ts (ProjectRecord: reward { text, earnedAt?, givenAt?, seenBy }, creditsSeenBy, floors[] with multiplier, clearedAt), src/lib/databases/ProjectDb.ts (getAll, lastOfType).
  • T8 src/lib/services/projects/projectService.ts (markRewardGiven(), markSeen(heroId, "reward" | "credits")) and projectProgress.ts.
  • T9 src/app/SideMenu/XpSettings/components/XpProjectWizardModal.vue (the trophy's "Start again" opens it; choresFromLastRun is how it fills the re-run).
  • T10 src/app/Console/MyPortal/HomeTown/components/ProjectTowerSheet.vue: the Hometown tower spot; with no active project it hides today (ruling R5). Task 11 wires ProjectTrophySheet into that spot: no active project but a cleared one shows the trophy, and the test "no active but a cleared one shows the trophy" lives in this task.

Rulings (decided; follow them):

  1. heroCredits reads who did what from the quest log (paid entries of the project's quests), never from a second store (spec section 8). A team finale counts for every assignee who has a paid entry. A boss is a chore whose room is a boss room on its floor (the floor boss / the key guard / the finale): read it from the tower record the way T6 typed them, say in the report what you keyed on.
  2. "days early" = days between the project's clearedAt local day and its endOn (0 when on time or late; never negative).
  3. The credits are CSS-animated, StatusPlz font, cream text on the theme's window colour (--gs-* tokens only; no hex literals in .vue/.scss: a ratchet spec counts them), skippable, emitting done at the end or on skip. The tower's music keeps playing (do not change BGM).
  4. The reward reveal and the credits on portal open are reveal prompts (the in-world prompt the temple uses, useRevealPrompt), not Ionic alerts; each hero sees each once, then markSeen.
  5. All visible copy through the copy catalogue in three voices (copyFor(key, voice, vars)), except the makers' names and roles, which are data in credits.ts. No em dashes in new copy.
  6. Toasts, if any: cssClass: "rpg-toast", position middle.

From Task 10 (built; read before wiring the trophy):

  • src/app/Console/MyPortal/HomeTown/components/towerSpot.ts (towerSpotOf(project, voice)) and HomeTown.ts/.vue show the project-tower spot only while a project is active. Task 11 shows it also when there is no active project but a cleared one (the trophy: the newest cleared run's tower), and hides it when there is neither.
  • ProjectTowerSheet.vue shows the empty slot when no tower is standing: put ProjectTrophySheet there (or open it from the spot directly), with the test "no active but a cleared one shows the trophy" in this task.
  • "Floor cleared!" seen-ness is ProjectFloor.seenBy; the reveal prompts use useRevealPrompt (see src/lib/services/projects/towerPrompts.ts and src/app/Console/TempleGrounds/templeGrounds/useProjectTower.ts for how T10 drives them). The finish prompts follow the same pattern.
  • The trophy's "Start again" opens Task 9's XpProjectWizardModal on the run's type (the wizard already fills from choresFromLastRun when lastOfType has a run); the floors' multipliers come from ProjectFloor.multiplier (empty floors are x1).
  • The trophy is a sheet, not a walk: do not route heroes back into a cleared tower (its stairs read as locked, because T10's tower code answers only for the running project of that temple).
  • T10's onFloorReached(templeId, floorKey, ...) and settleReadyFloors() live in projectService.ts; the roof's finale settling is what sets status: "cleared", clearedAt and reward.earnedAt (T8).
⚠️ **GitHub.com Fallback** ⚠️