Summary
Day 13 closed the generational loop opened by Day 10's ChildSystem and extended by Day 12's LifespanSystem. Adult children (age >= 14) are now promoted into the workforce: they leave the child roster, receive a randomly chosen profession from a weighted pool, join NPCManager as full Villagers, and register with LifespanSystem so they will age, eventually become elders, and die like any other townsperson. Alongside promotion, household surnames were introduced: when a couple marries, their household is assigned a fantasy surname (e.g. "Ashwood", "Embervale") which propagates to all children born into that family. Children carry their surname into adulthood and it appears in all chronicle messages. SAVE_VERSION was bumped to 6. The test suite grew by 25 to 692 passing across 67 files.
The disk-truncation issue struck again on PersistenceManager.js, SimEngine.js, ChildSystem.test.js, and Villager.test.js — all four recovered via bash heredoc or Python-driven rewrite.
Project Manager
Contribution: Led Day 13 scrum, selected features, set scope.
Key Decisions:
- Headlined adult children joining the workforce — the single most critical follow-on from Day 12. Elders are dying; nothing was replacing them. Today's change gives the town genuine generational continuity.
- Paired with surname inheritance as a zero-cost companion feature. Surnames require no new systems — they ride the existing household/child graph — but they make every chronicle message richer: "Pip Ashwood joins the town as a Merchant!" is far more evocative than just "Pip joins."
- Deferred Day 14 candidates: memorial panel + graveyard tiles, hero visits buildings, persist villager positions. All three remain healthy backlog items for tomorrow.
Reasoning: The simulation now has a complete life-cycle: born → child → adult with a profession → ages → elder → dies. Surnames make that history legible across generations.
World Designer
Contribution: Specified visual and narrative treatment for adult promotion and surnames.
Surname list: 25 fantasy surnames added to Villager.js as FAMILY_NAMES:
Ashwood, Bramble, Coldwater, Duskmantle, Embervale, Frostholm, Graystone,
Hearthwick, Ironbark, Jadehollow, Kettleford, Lyremore, Moonveil,
Nighthollow, Oakenshield, Pinecrest, Quickthorn, Ravenmoore, Silverbrook,
Thornwall, Underhill, Vexford, Whisperwind, Yelwick, Zinderfall. Each
household gets the name at index householdId % 25 so assignment is
deterministic but varied.
Chronicle messages:
- Marriage: "Alice and Bob are wed! — House of Ashwood" — surname revealed on the wedding day, the moment it is assigned.
- Birth: "Pip Ashwood is born to Alice & Bob!" — child already carries the name.
- Coming of age (adult): "Pip Ashwood, raised by Alice & Bob, comes of age and takes up a trade!" then "Pip Ashwood joins the town as a Merchant!"
Profession weighting: The promotion pool is weighted toward high-turnover roles (Farmer x2, Merchant x2) so the town gradually restores the economic backbone as elders die, while still occasionally producing Guards, Priests, Smiths, and others.
Backend Developer
Contribution: Implemented all backend changes across 5 files.
Files modified:
server/Villager.js- Added
FAMILY_NAMESarray (25 names). - Added optional
surnameparam to constructor (default''). - Added
fullNamegetter:"FirstName Surname"or just"FirstName". - Added
static pickSurname()utility. serialize()now includesfullNameandsurnamefields.
- Added
server/HouseholdSystem.js- Added
#surnames = new Map()(householdId -> surname). tick(): when a marriage fires, assignsFAMILY_NAMES[hhId % 25]to the household if none yet; includessurnamein the returned marriage object so SimEngine can log it.getSurname(householdId): new accessor for ChildSystem.restore(): now accepts optionalsurnamesarray.serialize(): includessurnamesarray.
- Added
server/ChildSystem.js#checkConceptions(): readshouseholdSystem.getSurname(householdId)and storessurnameon the pregnancy record.#advancePregnancies(): propagatessurnameto the child record; birth message includes the surname if present.#ageChildren(): at ADULT_AGE emits acomingofageevent withpromote: true, childId, childName, surname, householdId, homeTileso SimEngine can act on it. Also refreshesc.surnamefrom the household if the child was born before the parents married.promoteToAdult(childId): new public method — splices child out of#children, returns the record. Second call returnsnull(idempotent).
server/NPCManager.js- Added
PROMOTION_POOLconstant: weighted list of professions for child promotion. addVillager(id, name, profession, homeTile, surname): creates and appends a newVillager; updates internal#fieldIdx/#patrolIdxcounters so new Farmers/Guards get sensible work tiles.get nextVillagerId():max(villager ids) + 1.static pickPromotion(): random draw fromPROMOTION_POOL.
- Added
server/SimEngine.js- Child events loop now checks
e.promoteand calls#promoteChildToAdult(e). #promoteChildToAdult({ childId, childName, surname, homeTile }): callschildren.promoteToAdult(childId), thennpcs.addVillager(...), thenlifespan.register(newId, 14), and logs acomingofageevent with the full name and new profession.- Marriage log updated to show surname: "Alice and Bob are wed! — House of Embervale".
- Child events loop now checks
server/PersistenceManager.js(SAVE_VERSION 6)save(): addssocial.surnamesfromhouseholds.serialize().surnames.restoreSocial(): passessurnamestohouseholdSystem.restore().
Frontend Developer / Designer
Contribution: No frontend changes needed today. The fullName and
surname fields are now present in the villager SSE payload, ready for the
client to display when a tooltip or panel is built. The new comingofage
chronicle event type was already styled on Day 10 (gold-yellow, person icon)
and renders correctly for adult promotions.
Tester / QA
Contribution: Wrote 3 new test files (25 tests). Verified suite after each truncation repair.
New test files:
server/ChildSystem.promote.test.js(9 tests):promote:truefires at ADULT_AGE, carriessurname/homeTile/childId,promoteToAdultremoves child, double-call is null, unknown id is null.server/NPCManager.promote.test.js(8 tests):addVillagerincrements roster, sets id/name/profession/surname, serializesfullName,nextVillagerIdtracks correctly,removeVillagerstill works,pickPromotionalways returns a valid profession.server/HouseholdSystem.surname.test.js(7 tests): No surname before marriage, surname assigned on marriage, marriage event carries surname, surname persists, serialize includes surnames array, restore round-trips surnames.
Existing tests patched:
server/ChildSystem.test.js:makeHouseholdStubstub extended withgetSurname: () => surname(previously caused 12 test failures).server/Villager.test.js: serialize expectation updated to includefullNameandsurnamefields; added one new serialize test.
Truncation repairs (4 files): PersistenceManager.js, SimEngine.js,
ChildSystem.test.js, Villager.test.js — all repaired via bash heredoc or
Python-driven rewrite. Confirmed via tail and byte-level inspection
before proceeding.
Results: npm test -> 692 / 692 passing across 67 files (was 668/667;
+25 new tests, +1 Villager serialize test).
What Was Built
FAMILY_NAMESlist +surnamefield onVillager;fullNamegetter.HouseholdSystem: surname assignment at marriage;getSurname(); persist/restore.ChildSystem: surname propagation at birth; late surname refresh;promoteToAdult();promote:trueevent at ADULT_AGE.NPCManager:addVillager(),nextVillagerId,pickPromotion(),PROMOTION_POOL.SimEngine:#promoteChildToAdult()wired into child event loop; marriage log shows surname.PersistenceManager: SAVE_VERSION 6; surnames persisted and restored.- 3 new test files (25 tests); 2 existing test files patched.
Tomorrow (Day 14 Candidates)
- Memorial panel / graveyard tiles — surface
snapshot.deceasedin the UI as a "Town History" sidebar panel; optionally place a GRAVE tile cluster on the map once a few deaths accumulate. - Hero visits buildings — give
#restingstate real behaviour: Inn (heal more), Temple (stat buff), Smith (ATK bump), Merchant (sell loot). - Persist villager positions — small infra; persist
posper villager so the map picks up where it left off on reboot. - Second town — second settlement on the world map with its own population; hero can travel between them; trade caravans.