Files
gogobee/gogobee_dnd_session_summary.md
prosolis 9e1a1f606c Adv 2.0 D&D layer: Phases 1-8 + Phase 9 SP1+SP2
Combines all uncommitted D&D work into one checkpoint:

Phases 1-8 (per gogobee_dnd_session_summary.md):
- Race/class/stats system, !setup flow, !sheet, !respec
- d20-vs-AC combat with race/class passives, auto-migration
- XP/level-up, skill checks, NPC refund hooks
- Equipment slot mapping, rarity, !rest short/long
- Pre-arm active abilities, resource pools
- Bestiary, !roll/!stats/!level, onboarding DM
- Audit fixes A-I, flavor wiring under internal/flavor/
- Phase 8 weapon dice + armor AC tables (gogobee_equipment_appendix)

Phase 9 SP1 — spell system foundations:
- 79 SpellDefinitions (76 in-scope + 3 reaction-deferred)
- dnd_known_spells, dnd_spell_slots tables
- pending_cast / concentration_* columns on dnd_character
- Slot tables for Mage/Cleric/Ranger, DC + attack-bonus math
- Long-rest refreshes slots; respec wipes spell state
- Auto-grant default known list on !setup confirm and auto-migration

Phase 9 SP2 — !cast / !spells / !prepare commands:
- Out-of-combat HEAL and UTILITY resolve immediately
- Damage/control/buff queue as pending_cast for next combat
- Audit-style save-then-debit, slot refund on save failure
- !cast --drop, concentration supersession, prep-cap enforcement
- Reaction spells refused with Phase 11 note

SP3 (combat-time resolution of pending_cast) and SP4 (full prep/learn
tests) are next. Build clean, full test suite green.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-09 14:25:21 -07:00

387 lines
27 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# GogoBee D&D Integration — Session Summary
> **Scope:** End-to-end build of the D&D layer from design through audit cleanup, audit fixes, flavor wiring, branding rebrand to "Adv 2.0", and Phase 8 (equipment & damage math).
> **Status:** Deploy-ready. **122 D&D tests** passing, full suite + vet clean, prod-DB integration verified, root build with `-tags goolm` clean.
> **Source design:** Eleven design docs at the repo root — see `gogobee_design_index.md` for the canonical list and dependency graph. Phases 1-7 + audit fixes were built from `gogobee_dnd_design_doc.md` v1.0 / `gogobee_dnd_design_doc_v1.1.md` (implementation revision); Phase 8 from `gogobee_equipment_appendix.md`.
> **What's next:** Phase 9 — spell system (`gogobee_spell_system.md`). See the auto-loaded memory entry `project_dnd_phase_plan.md` for the full Phase 8-16 roadmap.
---
## 1. Design documents produced
| Document | Purpose |
|---|---|
| `gogobee_dnd_design_doc.md` (existing v1.0) | Vision document. Untouched. |
| `gogobee_dnd_design_doc_v1.1.md` (new) | Implementation revision. Reconciles v1.0 against the actual codebase: real schema, real archetype names, real combat engine. Replaces v1.0's Phase 14 with a smaller-scoped phase plan. Annotated with `[REVISED]` tags everywhere it diverges from v1.0. |
| `gogobee_dnd_session_summary.md` (this file) | Session-wide change log. |
| `gogobee_design_index.md` | **Canonical map of all 11 design docs** + their dependency graph + reading order by intent. New sessions should read this first. |
The original design doc treated combat as greenfield. An audit revealed `combat_engine.go`, `combat_bridge.go`, `combat_stats.go`, and `combat_narrative.go` (~3,500 LOC) already existed in production. v1.1 was rewritten around that constraint: the D&D layer would be additive, not a replacement.
---
## 2. Phase-by-phase delivery
### Phase 1 — Layering proof
- Schema: `dnd_character`, `dnd_abilities`, `dnd_resources`, `dnd_combat_state`, plus a one-shot `adventure_characters_pre_dnd` snapshot table populated at deploy as a rollback safety net.
- Nullable D&D columns added to `adventure_equipment` / `adventure_inventory` (rarity, stat_bonus_json, attuned).
- Race/class types and tables (7 races, 5 classes), repository functions, stat math (`abilityModifier`, `computeMaxHP`, `computeAC`).
- `!setup` flow with persistent draft state (`pending_setup=1`) — survives bot restarts.
- `!sheet` read-only renderer with archetype-driven inference.
### Phase 2 — d20-vs-AC combat
- `CombatStats` extended with `AC` and `AttackBonus`; `CombatEvent` with `Roll` and `RollAgainst`.
- `resolvePlayerAttack` and `resolveEnemyAttack` rewritten as d20-vs-AC. Nat 20 = auto-hit + crit, nat 1 = auto-miss tagged "fumble".
- `applyDnDPlayerLayer` / `applyDnDArenaMonsterLayer` / `applyDnDDungeonMonsterLayer` populate AC and attack bonuses based on class/level and threat/tier.
- `persistDnDHPAfterCombat` writes proportional damage back to the sheet.
- **Auto-migration** on first combat: legacy players with no `dnd_character` row get one built from archetype inference + class-tuned standard array. `auto_migrated=1` flag enables free `!setup` rebuild without consuming `!respec` cooldown.
- **Legacy combat ripped out**: dual-path branching deleted, `DnDMode` field removed. Single d20 path for all combat.
### Phase 3 — XP, level-up, class passives
- `dndXPTable` cumulative table anchored to v1.0's design values; `dndXPToNextLevel` returns segment cost.
- `grantDnDXP` handles cascading level-ups, recomputes HP max, increments current HP by the gain, sends a level-up DM. Caps cleanly at L20.
- XP grants on every arena and dungeon combat, with near-death win bonuses.
- One class passive per class via `applyClassPassives`: Fighter +5% damage, Rogue auto-crit-first, Mage +1 attack bonus, Cleric +5 HP heal at low HP, Ranger +5% damage and +1 attack bonus.
- `!abilities` lists class + race passives. `!sheet` shows XP progress.
### Round 1 — race passives, freeze, respec, subclass stub
- Race passives via `applyRacePassives` and three new `CombatModifiers` fields: Halfling Lucky (reroll first nat 1), Orc Rage (+50% damage on first attack after dropping below 50% HP), Dwarf poison resistance (poison ticks halved).
- `combat_level` freeze: once a player has confirmed a D&D character, `checkAdvLevelUp("combat", ...)` becomes a no-op. Skill levels (mining/foraging/fishing) keep advancing independently.
- `!respec` command: 5000 euros, 7-day cooldown via `last_respec_at`. Auto-migrated chars use the existing free `!setup` path.
- Subclass-L5 placeholder line added to level-up DM when crossing L5.
### Round 2 — Phase 5 (skill checks + NPC wiring)
- 10 skills (Athletics, Acrobatics, Stealth, Arcana, Investigation, Perception, Insight, Persuasion, Intimidation, Deception) with correct stat mapping.
- DC table constants matching D&D 5e (Trivial 5 → Impossible 30).
- `performSkillCheck`: d20 + ability modifier + race bonus, with nat 20/1 auto-results.
- Race skill bonuses: Half-Elf +1 to all skills, Tiefling +2 on CHA-based.
- `!check <skill> [dc]` command.
- NPC wiring: passing Insight DC 12 refunds Misty donation; passing Arcana DC 14 refunds Arina investment; passing Persuasion DC 15 grants 10% session shop discount. Silent upside for opted-in players, no UX change for legacy.
### Round 3 — Phase 4 (equipment slot mapping + rarity)
- Read-time slot mapping: legacy 5 slots → D&D 10 slots (`mapLegacySlot`).
- Rarity inference from tier + masterwork + arena tier (`inferRarity`): Common → Legendary.
- `!sheet` renders equipment with rarity icons in D&D slot order.
- Full `!equip`/`!unequip`/`!attune` deferred — nothing to populate the new slots yet (legs, hands, rings, amulet) until a future loot pass.
### Round 4 — Phase 6 (rest system)
- `!rest short`: 1h cooldown, 1d6+CON HP recovery (doubled at L5+ per design doc), no daily-action cost.
- `!rest long`: 24h cooldown, full HP, requires housing (any tier) or pays Thom Krooke inn (200 euros).
- New columns `last_short_rest_at`, `last_long_rest_at` on `dnd_character`.
- Long rest also refreshes all class resources via `refreshAllResources`.
### Round 5 — Phase 7 partial (bestiary)
- Starter bestiary in `dnd_bestiary.go`: Goblin, Skeleton, Orc Grunt, Troll, Wyvern, Ancient Dragon. Each with HP, AC, attack stats, optional ability, XP value.
- `toCombatStats()` helper converts a template to the engine's stat shape.
- `dndBestiaryByCR(maxCR)` for procedural CR-appropriate selection.
- **Rival RPS conversion deliberately deferred** — the existing rival mini-game is narratively rich and works; the user confirmed leaving it alone.
### Round 6 — active abilities + resources
- Pre-arm model (combat is one-shot, so `!use mid-fight` doesn't fit): `!arm <ability>` consumes a resource immediately and primes the ability for the next combat. `applyArmedAbility` fires it via existing `CombatModifiers` fields and clears the flag.
- Three starter active abilities: Fighter Second Wind, Mage Magic Missile, Cleric Healing Word. Rogue Sneak Attack and Ranger Hunter's Mark stay passive.
- Resource pools per class (`stamina`, `focus`, `spell_slot`, `favor`) initialized at setup confirm and on auto-migration. Refreshed on long rest.
### "Plug the holes" — quality-of-life additions
- **`!roll <dice>`** with full NdN+M notation (`2d6+3`, `d20`, `4d6-1`). Caps at 100 dice × 1000 sides. Single-d20 highlights nat 20 / nat 1.
- **`!stats`** — quick ability scores + modifiers + proficiency + AC view.
- **`!level`** — level + XP progress with percent-to-next.
- **Combat HP scaling**: wounded D&D players (sheet HP < max) fight with proportionally reduced legacy combat MaxHP, floor 25%. The rest system finally has gameplay teeth.
- **Roll summary line**: every fight ends with `🎲 d20 — N/M hit (X crits, Y fumbles). Best: nat 20!` injected into arena and dungeon outcome messages without touching protected flavor files.
### Onboarding DM
- One-shot welcome DM for legacy players (`combat_level >= 2`) on first auto-migration. Includes their actual level mapping (`Your previous level X is now D&D level Y`).
- Triggered via `freshMigrate` bool returned from `ensureDnDCharacterForCombat`; only fires the very first time a row is created.
- The full text the user wrote is in `dndOnboardingText` — TwinBee, Pinkerton agent, divide-by-five, the works.
---
## 3. Audit + remediation
After all features shipped, four parallel agents audited the D&D layer:
1. **Security & player-exploitability**
2. **Concurrency & data integrity**
3. **Code quality & correctness**
4. **Test coverage gaps**
Findings consolidated and de-duplicated into 9 actionable items (A through I). All 9 fixed.
| ID | Issue | Fix |
|---|---|---|
| **A** | No per-user lock around D&D handlers. Read-modify-write on `dnd_character` could race. | Acquired existing `advUserLock` at entry of every top-level D&D mutating command. Internal helpers (called from already-locked combat paths) intentionally stay lock-free. |
| **B** | `!respec` debited euros before saving the wipe. Save failure → euros lost, character intact. | Reordered: balance pre-check → save → resource wipe → debit. Save failure leaves all state intact; debit failure (rare race) grants a free respec rather than a destructive debit. |
| **C** | `!arm` spent resource before saving the armed flag. Save failure → resource wasted. | Reordered: save first → spend. On spend failure, revert armed flag and surface error. |
| **D** | Orc Rage threshold used `HP < MaxHP/2` integer division — drifted on odd MaxHP. | Replaced with `HP*2 < MaxHP`. Exact 50% threshold regardless of parity. |
| **E** | Respec didn't wipe old class's resource pool (Fighter→Mage left stale `stamina` rows). | `DELETE FROM dnd_resources WHERE user_id = ?` in the respec wipe path before the new class initializes via `initResources`. |
| **F** | Onboarding DM re-fired if a player canceled `!setup` mid-draft and then ran combat. | New `onboarding_sent` column on `dnd_character`, set on first successful send, never reset (survives respec, draft cancel, anything). |
| **G** | Persuasion shop discount session had no expiry. Player could chain across all purchases. | 30-minute TTL from session start (`dndPersuasionDiscountTTL`). Both pricing and announcement honor the expiry. |
| **H** | NPC refund hooks (Misty Insight / Arina Arcana) did separate Load + skill check + Credit. Architecturally fragile. | Covered by Fix A — encounter handlers already hold `advUserLock`, so the refund's `LoadDnDCharacter` is safe inside that lock. No code change needed. |
| **I** | `applyDnDHPScaling` lacked a post-scale `min(scaled, MaxHP)` clamp. Currently safe but fragile. | Added the bounds check defensively. |
10 new audit-fix tests added; all pass.
---
## 4. New files (production)
```
internal/plugin/dnd.go — types, repository, stat math
internal/plugin/dnd_setup.go — !setup flow, !respec
internal/plugin/dnd_sheet.go — !sheet, !abilities renderer
internal/plugin/dnd_combat.go — auto-migration, HP persistence, HP scaling, roll summary
internal/plugin/dnd_passives.go — class + race passives
internal/plugin/dnd_xp.go — XP curve, grant, level-up DM
internal/plugin/dnd_skills.go — skill checks, !check, NPC refund hooks
internal/plugin/dnd_equipment.go — slot mapping, rarity inference
internal/plugin/dnd_rest.go — !rest short / long
internal/plugin/dnd_abilities.go — pre-arm model, resources
internal/plugin/dnd_bestiary.go — starter monster templates
internal/plugin/dnd_misc_cmds.go — !roll, !stats, !level
internal/plugin/dnd_onboarding.go — legacy-player welcome DM
```
13 new production files, all additive.
## 5. Modified files
```
internal/db/db.go — schema additions, snapshot logic
internal/plugin/combat_engine.go — d20 hit resolution (legacy path replaced),
race-passive fields and triggers
internal/plugin/combat_bridge.go — auto-migrate hook, D&D layer wiring,
class+race passive application,
armed-ability firing, HP persistence,
XP grant, roll summary
internal/plugin/adventure.go — D&D command routing in OnMessage,
registry entries in Commands(),
roll summary appended to dungeon output
internal/plugin/adventure_arena.go — roll summary appended to win/death output
internal/plugin/adventure_character.go — combat_level freeze for D&D players
internal/plugin/adventure_npcs.go — Misty/Arina skill-check refund hooks
internal/plugin/adventure_shop.go — Persuasion discount session,
price-factor applied at every Debit site,
30-minute TTL
internal/plugin/plugin.go — Base.SendDM made nil-Client-safe (test support)
```
## 6. Test files
```
internal/db/proddb_integration_test.go — full migration on real prod DB copy
internal/plugin/dnd_test.go — types, math, parsing
internal/plugin/dnd_combat_test.go — d20 path, monster layers, hit-rate stats
internal/plugin/dnd_round1_test.go — race passives, combat_level freeze, respec format
internal/plugin/dnd_skills_test.go — DC table, skill check math
internal/plugin/dnd_equipment_test.go — slot mapping, rarity inference
internal/plugin/dnd_rest_test.go — short/long rest mechanics, housing gating
internal/plugin/dnd_abilities_test.go — resource pool, arm/spend, applyArmed
internal/plugin/dnd_bestiary_test.go — starter monsters well-formed
internal/plugin/dnd_xp_test.go — curve, grant, level-up cascade, L20 cap
internal/plugin/dnd_onboarding_test.go — message format, threshold, no-panic
internal/plugin/dnd_proddb_integration_test.go — real prod players auto-migrate cleanly
internal/plugin/dnd_plugs_test.go — HP scaling, roll summary, dice parser
internal/plugin/dnd_audit_fixes_test.go — all 9 audit findings covered
```
**Total: 90 D&D-layer tests** + 1 prod-DB-migration integration test in `internal/db`.
## 7. Schema changes
All additive. No drops, no renames.
### New tables
```sql
dnd_character -- per-player D&D state (race, class, stats, HP, XP, flags)
dnd_abilities -- per-ability uses-remaining (reserved for Phase 7+)
dnd_resources -- per-class resource pools (stamina/focus/mana/favor)
dnd_combat_state -- active encounter state (reserved)
adventure_characters_pre_dnd -- one-shot rollback snapshot
```
### New columns on `adventure_equipment` / `adventure_inventory`
- `dnd_rarity TEXT NOT NULL DEFAULT ''`
- `dnd_stat_bonus_json TEXT NOT NULL DEFAULT ''`
- `dnd_attuned INTEGER NOT NULL DEFAULT 0` (equipment only)
### New columns on `dnd_character`
Added incrementally across phases:
- `auto_migrated`, `armed_ability`, `onboarding_sent`
- `last_short_rest_at`, `last_long_rest_at`
---
## 8. New player-facing commands
| Command | What it does |
|---|---|
| `!setup` | Begin or continue D&D character creation (race / class / stats / confirm) |
| `!setup race <name>` | Pick race |
| `!setup class <name>` | Pick class |
| `!setup stats <STR> <DEX> <CON> <INT> <WIS> <CHA>` | Assign standard array {15,14,13,12,10,8} |
| `!setup confirm` | Finalize |
| `!setup cancel` | Scrap draft |
| `!sheet` | Full character sheet with equipment, treasures, legacy progress |
| `!stats` | Ability scores + modifiers + proficiency + AC |
| `!level` | Current level + XP progress |
| `!abilities` | Class + race passives + active abilities + resource pool |
| `!arm <ability>` | Pre-arm an active ability for next combat |
| `!check <skill> [dc]` | Roll a skill check |
| `!rest short` | Short rest (1h cooldown, partial heal) |
| `!rest long` | Long rest (24h cooldown, full heal, requires housing or inn) |
| `!respec` | Wipe and rebuild character (5000 euros, 7-day cooldown) |
| `!roll <dice>` | Roll arbitrary dice (NdN+M notation) |
## 9. Player-visible behavior changes
- Existing players auto-migrate to a sensible inferred sheet on their next combat — no setup required, no progress lost. They get a one-shot welcome DM with their actual level mapping.
- Combat resolves with d20 + attack bonus vs AC. Every fight ends with a roll summary line.
- Class identity comes through every fight via passives (Fighter +damage, Rogue first-hit auto-crit, Mage attack bonus, Cleric low-HP heal, Ranger +damage and attack).
- Race traits matter: Halfling rerolls one nat 1 per fight, Orc rages at <50% HP, Dwarf takes half poison damage, Half-Elf and Tiefling get skill check bonuses.
- HP carries between fights. A wounded player who skips rest fights at reduced max HP.
- Levels advance based on combat XP. Skill XP (mining/foraging/fishing) advances independently and unaffected.
- Skill checks unlock NPC bonuses: Insight at Misty refunds, Arcana at Arina refunds, Persuasion at the shop grants 10% off for 30 minutes.
## 10. Level mapping (existing prod players)
Legacy `combat_level` mapped to D&D level via `dndLevelFromCombatLevel = clamp(1, combat_level/5, 20)`:
| Player | Legacy | D&D | Auto-built |
|---|---|---|---|
| holymachina | L49 | L9 | Dwarf Fighter |
| prosolis | L28 | L5 | Human Rogue |
| quack | L24 | L4 | Dwarf Fighter |
| nonk | L20 | L4 | Human Rogue |
Verified end-to-end against a copy of the prod database in `data/gogobee.db`.
## 11. What was deliberately deferred or pushed back on
- **Rival RPS → D&D combat**: confirmed by user to leave alone. The existing mini-game is narratively rich and works.
- **Equipment expansion (`!equip`/`!unequip` for new D&D slots)**: nothing to fill rings/amulet/legs/hands until shop or loot expansion. Rendering in `!sheet` works fine via the read-time mapping.
- **Active abilities for Rogue and Ranger**: their passives are strong; no actives needed yet.
- **Subclass mechanics at L5**: placeholder DM only; full content design pending.
- **D&D-specific death mechanic**: legacy `Alive`/`DeadUntil` retained. Sheet HP at 0 means "fight at 25% on next combat, rest to recover" — graceful via Fix #2.
- **Closer 5e fidelity (weapon damage dice, saving throws, full spell lists, action economy)**: per user direction, the d20-flavored adventure feel is the intended ceiling. Approachable beats faithful for a chat bot.
- **Dead `DodgeRate`/`CritRate` field-population code**: cosmetic; not worth regression risk.
- **Per-class short-vs-long rest split for resources**: all resources currently refresh on long rest only. Cheap follow-up if desired.
## 11.5 Audit fixes (post-Phase-7)
After all features shipped, four parallel audit agents reviewed the D&D layer. Findings consolidated and de-duplicated into 9 actionable items (A-I), all addressed:
- **A** — Per-user lock on D&D handlers (reuses existing `advUserLock`). Prevents double-arm, double-respec, level-up clobbers.
- **B** — `!respec` save-then-debit ordering. Save failure no longer destroys euros.
- **C** — `!arm` save-then-spend ordering with revert on failure.
- **D** — Orc Rage threshold off-by-one (`HP*2 < MaxHP` instead of `HP < MaxHP/2`).
- **E** — Resource pool wiped on respec (Fighter→Mage no longer leaves stale `stamina` rows).
- **F** — `onboarding_sent` column for one-shot welcome DM dedup across draft cancel/respec/etc.
- **G** — Persuasion shop discount expires after 30 minutes.
- **H** — NPC refund atomicity (covered by Fix A).
- **I** — `applyDnDHPScaling` post-clamp.
10 audit-fix tests added.
## 11.6 Flavor wiring (post-audit)
Five `twinbee_*_flavor.go` files were sitting in the repo root with conflicting `package flavor` declarations — never compiled, never wired. Moved to `internal/flavor/`, fixed one missing-comma syntax error, and wired the player-visible pools that mapped to existing D&D-layer features:
| Trigger | Pool | Where it surfaces |
|---|---|---|
| Combat starts (arena/dungeon) | `flavor.CombatStart` | Prepended to first phase message |
| Player wins (T1-T4 round, dungeon) | `flavor.CombatVictory` | Italicized in finalMessage |
| Player wins arena T5 round | `flavor.BossDeath` | Same slot, boss-specific |
| Player dies | `flavor.PlayerDeath` | Appended to death-output |
| Any nat 20 | `flavor.Nat20` | Roll summary, once per fight |
| Any nat 1 (no nat 20) | `flavor.Nat1` | Same slot |
| Level-up DM | `flavor.LevelUp` | Italicized prelude after banner |
| `!rest short` | `flavor.RestShort` | Appended |
| `!rest long` (housing) | `flavor.HomeLongRest` | Appended; falls back to `RestLong` |
| Misty encounter open | `MistyGreeting` legacy | ~2× variety |
| Arina encounter open | `ArinaGreeting` legacy | Same |
| Misty refund pass/fail | `MistyInsightSuccess` / `MistySkillFail` | Italicized |
| Arina refund pass/fail | `ArinaArcanaSuccess` / `ArinaSkillFail` | Italicized |
| Onboarding DM | `flavor.ExpeditionStart` | Random prelude |
Pools deferred to legacy-system migration (harvest events, housing announcements, scheduler tickers, Pete bot) and pools without features (quests, expedition system, traps, save throws, idle/lore chatback) remain unwired pending later phases.
## 11.7 Branding rebrand: D&D → Adv 2.0 (player-facing only)
Player-visible strings rebranded from "D&D" to "Adv 2.0":
- Command descriptions in `Commands()` registry (10 commands)
- `!setup` flow headers
- `!sheet` and `!rest` error messages
- Onboarding DM literal level-mapping line
- The deliberate "Dungeons & Drag-" / "d20 System" gag preserved verbatim (it's the joke about being legally distinct)
Internal type names, function names, file names, schema, and code comments still say "D&D" — accurate technical description, no risk to durable state. Full rationale in conversation history.
## 11.8 Phase 8 — Equipment & damage math
Built per `gogobee_equipment_appendix.md` (354 lines).
**`dnd_equipment_profiles.go` (new):**
- 36 weapons from appendix §2-§3 (10 simple melee, 4 simple ranged, 18 martial melee, 4 martial ranged) with damage dice, types, properties, versatile alt-dies
- 13 armors from appendix §5 (3 light, 5 medium, 4 heavy, 1 shield) with base AC, DEX caps, STR requirements, stealth flags
- `dndClassWeaponProficiency` and `dndClassArmorProficiency` per appendix §9 affinity matrix (Rogue's restricted martial list hardcoded)
- `rollWeaponDamage(weapon, abilityMod, twoHanded)` — real dice roll honoring versatile mode and magic bonus
- `computeArmorAC(armor, shield, dexMod)` — exact appendix `ComputeAC` semantics
- Legacy gear synthesis: `synthesizeWeaponProfile` / `synthesizeArmorProfile` / `synthesizeShield` map existing `AdvEquipment` rows to D&D profiles by tier+name keyword. Masterwork promotes; tier 6+ adds magic bonus up to +3.
**`combat_engine.go`:**
- `CombatStats` extended with `Weapon`, `AbilityModForDamage`, `WeaponProficient`, `TwoHandedMode` fields. Zero values = backward-compatible.
- `resolvePlayerAttack` branches: when `Stats.Weapon != nil`, rolls weapon dice; when nil, legacy `calcDamage`. Class proficiency penalty (-4 attack) at hit-check time.
**`dnd_combat.go`:**
- New `applyDnDEquipmentLayer(stats, c, equip)` — synthesizes profiles, populates the new fields, recomputes AC. Two-handed weapons forbid shields.
- `pickWeaponAbilityMod(weapon, c)` — STR for melee non-finesse, DEX for ranged, finesse picks the higher.
**`combat_bridge.go`:**
- Both arena and dungeon paths call `applyDnDEquipmentLayer` after `applyDnDPlayerLayer`. Equipment-derived AC overrides the placeholder class-armor-floor.
**24 new tests** covering weapon registry coverage, armor appendix values, ComputeAC math (unarmored, light, medium-capped, heavy, magic bonus), weapon damage roll bounds, versatile two-handed mode, damage floor, class proficiency matrices, legacy gear synthesis (tier mapping, masterwork promotion, high-tier magic), shield name matching, ability mod selection (STR/DEX/finesse), end-to-end equipment layer.
**Player-visible balance change for prod players:**
| User | Class | Synthesized weapon | Damage roll |
|---|---|---|---|
| holymachina | Dwarf Fighter L9 | T6+ Greatsword w/ +1 magic | 2d6 + STR mod + 1 |
| prosolis | Human Rogue L5 | T3-5 Longsword or Shortbow | 1d8 + best mod |
| quack | Dwarf Fighter L4 | T3-5 weapon | dice + STR mod |
| nonk | Human Rogue L4 | T3-5 weapon | dice + best mod |
Plus AC recomputed from real armor profiles.
**Deferred to Phase 8b:** magic item slots (rings/amulet), named magic weapons with special properties (Flame Tongue's +2d6 fire, etc.), `!equip`/`!unequip`/`!attune` commands, loot rarity flavor wiring, ammunition tracking, heavy armor STR-requirement penalty.
## 12. Final state (post-Phase 8)
- Build clean across `internal/...`
- Root build clean with `-tags goolm`
- `go vet` clean across `internal/...`
- **122 D&D-layer tests + 1 prod-DB migration integration test passing**
- All 9 audit findings closed
- Zero modifications to protected `internal/flavor/twinbee_*_flavor.go` content
- Snapshot rollback table populated; rollback path documented in v1.1 §11.4
- Onboarding flow handles all four prod players cleanly with verified output (now firing on `!setup`, `!check`, `!stats`, `!level`, `!rest`, `!arm` first-touch in addition to combat auto-migration)
- Phase 8 weapon dice + armor AC active for all four prod players on their next combat
## 13. Next phase: Phase 9 — Spell System
Per the auto-loaded memory entry `project_dnd_phase_plan.md` and `gogobee_design_index.md`, Phase 9 implements `gogobee_spell_system.md`: 79 spells, slots, concentration, `!cast` command, spell save DCs. Mage/Cleric/Ranger become genuinely playable distinctly.
Architecture commitment from earlier this session: **Path C hybrid combat** — one-shot for arena/random encounters, turn-based for boss fights only. Phase 9 should preserve approachability outside boss fights; spell mechanics in non-boss combat must fit the pre-arm pattern (consistent with current `!arm` for active abilities).
### Kickoff for next session
```
Read gogobee_design_index.md and gogobee_spell_system.md cold. Then open
gogobee_dnd_session_summary.md to see what's already shipped. Plan Phase 9
(spell system) per the recommended order in the auto-loaded memory entry.
Show me a tight phase plan before writing any code — what spells, what slots,
what the !cast command flow looks like, how concentration interacts with the
existing one-shot combat (Path C hybrid is locked in). Then once I confirm
scope, build it.
```
The codebase is deploy-ready. Existing players will see the new system on their next interaction — auto-migrated, onboarded, and never blocked from gameplay regardless of setup state. Phase 9-16 each add depth in a focused session.