id: 616d235868f14945a78d400ea12fe361
parent_id: 61812f5cc5d54be0af15567677e1c1c3
item_type: 1
item_id: 088737f31c514f1da21cc42c0ab6acc1
item_updated_time: 1785752426101
title_diff: "[]"
body_diff: "[{\"diffs\":[[0,\"te. \"],[-1,\"Quality-checked with 0 clippy warnings\"],[1,\"Three quality audits passed\"],[0,\".\\\n\\\n-\"]],\"start1\":285,\"start2\":285,\"length1\":46,\"length2\":35},{\"diffs\":[[0,\" fight. \"],[-1,\"**\"],[0,\"Mage↔Mag\"]],\"start1\":1335,\"start2\":1335,\"length1\":18,\"length2\":16},{\"diffs\":[[0,\"ping\"],[-1,\"** resolved\"],[0,\" via\"]],\"start1\":1360,\"start2\":1360,\"length1\":19,\"length2\":8},{\"diffs\":[[0,\"s()`\"],[-1,\"\\\n- **Spell combat integration**: damage/heal spells applied during adventure rounds\"],[1,\" / `is_caster_class()`\"],[0,\"\\\n- *\"]],\"start1\":1385,\"start2\":1385,\"length1\":91,\"length2\":30},{\"diffs\":[[0,\"uffs\"],[-1,\" applied in combat\"],[0,\"\\\n- *\"]],\"start1\":1462,\"start2\":1462,\"length1\":26,\"length2\":8},{\"diffs\":[[0,\"via \"],[-1,\"polling (\"],[0,\"15s \"]],\"start1\":1636,\"start2\":1636,\"length1\":17,\"length2\":8},{\"diffs\":[[0,\"ent \"],[-1,\"interval)\"],[1,\"polling\"],[0,\"\\\n- *\"]],\"start1\":1647,\"start2\":1647,\"length1\":17,\"length2\":15},{\"diffs\":[[0,\"s.rs` — \"],[-1,\"`\"],[0,\"pick_ene\"]],\"start1\":1937,\"start2\":1937,\"length1\":17,\"length2\":16},{\"diffs\":[[0,\"_enemy()\"],[-1,\"`\"],[0,\", \"],[-1,\"`\"],[0,\"equipped\"]],\"start1\":1949,\"start2\":1949,\"length1\":20,\"length2\":18},{\"diffs\":[[0,\"damage()\"],[-1,\"`\"],[0,\", \"],[-1,\"`\"],[0,\"total_de\"]],\"start1\":1980,\"start2\":1980,\"length1\":20,\"length2\":18},{\"diffs\":[[0,\"efense()\"],[-1,\"`\"],[0,\", \"],[-1,\"`\"],[0,\"equip/un\"]],\"start1\":1997,\"start2\":1997,\"length1\":20,\"length2\":18},{\"diffs\":[[0,\"em()\"],[-1,\"`\"],[0,\", \"],[-1,\"`\"],[0,\"trai\"]],\"start1\":2023,\"start2\":2023,\"length1\":12,\"length2\":10},{\"diffs\":[[0,\"n_stat()\"],[-1,\"`\"],[0,\" with in\"]],\"start1\":2033,\"start2\":2033,\"length1\":17,\"length2\":16},{\"diffs\":[[0,\"- **\"],[-1,\"Seeded users**: admin (id=1) + player (id=2)\\\n- **0 clippy warnings** — all collapsible_if, useless_vec, comparison_to_empty, manual_range_contains fixed\"],[1,\"Review Board level-up**: POST `/api/characters/{id}/level-up`, manual level-up at guild, XP + gold cost, fully restores HP/energy/nerve/SP. MAX_LEVEL = 100. XP curve: `18 * 100 * (level-1)^2` (Lv2=1,800, Lv10=513K, Lv50=72.8M, Lv100=591M total)\\\n- **44 unit tests**: character (19), combat (8), services (17) — all passing\\\n- **Seeded users**: admin (id=1) + player (id=2)\\\n- **0 clippy warnings** with `-W clippy::all`\"],[0,\"\\\n\\\n##\"]],\"start1\":2062,\"start2\":2062,\"length1\":160,\"length2\":424},{\"diffs\":[[0,\"n-only)\\\n\"],[1,\"- **Review Board**: Level-up panel on Home dashboard when XP threshold met, shows progress bar + gold cost\\\n\"],[0,\"- **Spel\"]],\"start1\":2768,\"start2\":2768,\"length1\":16,\"length2\":123},{\"diffs\":[[0,\"cter\"],[-1,\", triggers server-side `apply_regen()`\\\n- **Custom favicon**: SVG shield with sword\\\n- **Dynamic browser title**: `Skara Brae - {page label}`\\\n\\\n### Quality (2026-08-03)\\\n- **3 critical bugs fixed**:\\\n  1. Mage class couldn't cast spells (magician/mage mismatch) — `class_for_spells()` + `is_caster_class()` in spells.rs, client casterClasses updated\\\n  2. R\"],[1,\"\\\n- **MAX_LEVEL = 100** in client (matches server)\\\n\\\n### Quality (3 audits passed)\\\n- **Audit 1**: Fixed 3 critical bugs (mage spell mismatch, r\"],[0,\"ace \"]],\"start1\":3212,\"start2\":3212,\"length1\":359,\"length2\":149},{\"diffs\":[[0,\"tion in \"],[-1,\"`\"],[0,\"run_adve\"]],\"start1\":3366,\"start2\":3366,\"length1\":17,\"length2\":16},{\"diffs\":[[0,\"ture\"],[-1,\"()` — all post-combat mutations now inside write lock\\\n  3. `buy_item()` decremented stock before gold check — reordered to check gold first\\\n- **18 clippy warnings resolved** (collapsible_if, useless_vec, unused_mut, filter_next, comparison_to_empty, manual_range_contains)\\\n- **Remaining known warnings** (deferred — architecture-level, not bugs):\\\n  - 14 route handlers contain inline business logic (should be extracted to domain)\\\n  - 16 handlers return untyped `Json<serde_json::Value>` instead of typed structs\\\n  - 25+ magic numbers in comb\"],[1,\", buy_item stock ordering) + 18 clippy warnings\\\n- **Audit 2**: Fixed 3 critical bugs (xp_for_level overflow, crit_damage_cap dead branch, default zone_id mism\"],[0,\"at\"],[-1,\"/\"],[0,\"ch\"],[-1,\"aracter code\\\n  - 4 non-injective RNG calls (create_character, resolve_combat_full, 2 in run_adventure)\\\n  - 11 unwrap() calls in route handlers\\\n- **0 tests** — no test infrastructure yet\"],[1,\")\\\n- **Audit 3**: Fixed MAX_LEVEL 50→100, crit_damage_cap param rename. Zero new criticals.\"],[0,\"\\\n\\\n--\"]],\"start1\":3383,\"start2\":3383,\"length1\":740,\"length2\":260},{\"diffs\":[[0,\"\\\n## \"],[-1,\"Next Steps (priority order)\\\n\\\n1. **Leveling system** — XP accumulates but level never increases\\\n2. **Test infrastructure** — at least unit tests for combat, stat_bonus, services\\\n3\"],[1,\"Remaining Known Warnings (deferred)\\\n- `create_character()` and `resolve_combat_full()` use `rand::rng()` directly (should accept injectable RNG)\\\n- ~140 lines of business logic in `run_adventure` route handler\\\n- 25+ magic numbers across combat/character code\\\n- 16 handlers return untyped `Json<serde_json::Value>` instead of typed structs\\\n- 11 low-risk `unwrap()` calls in route handlers\\\n- SP deducted on combat loss (may be intentional — you cast, you pay)\\\n- `caster_classes()` returns \\\"magician\\\" alongside `is_caster_class()` (latent naming)\\\n\\\n---\\\n\\\n## Next Steps (priority order)\\\n\\\n1\"],[0,\". **\"]],\"start1\":4526,\"start2\":4526,\"length1\":186,\"length2\":590},{\"diffs\":[[0,\"exists)\\\n\"],[-1,\"4\"],[1,\"2\"],[0,\". **PvP \"]],\"start1\":5188,\"start2\":5188,\"length1\":17,\"length2\":17},{\"diffs\":[[0,\" screen\\\n\"],[-1,\"5\"],[1,\"3\"],[0,\". **Idle\"]],\"start1\":5241,\"start2\":5241,\"length1\":17,\"length2\":17},{\"diffs\":[[0,\"rogress\\\n\"],[-1,\"6\"],[1,\"4\"],[0,\". **Dung\"]],\"start1\":5284,\"start2\":5284,\"length1\":17,\"length2\":17},{\"diffs\":[[0,\"ap data\\\n\"],[-1,\"7\"],[1,\"5\"],[0,\". **Meda\"]],\"start1\":5333,\"start2\":5333,\"length1\":17,\"length2\":17},{\"diffs\":[[0,\" system\\\n\"],[-1,\"8\"],[1,\"6\"],[0,\". **Auth\"]],\"start1\":5378,\"start2\":5378,\"length1\":17,\"length2\":17},{\"diffs\":[[0,\"n-based\\\n\"],[-1,\"9\"],[1,\"7\"],[0,\". **Arch\"]],\"start1\":5413,\"start2\":5413,\"length1\":17,\"length2\":17},{\"diffs\":[[0,\"response\"],[-1,\" struct\"],[0,\"s, extra\"]],\"start1\":5457,\"start2\":5457,\"length1\":23,\"length2\":16},{\"diffs\":[[0,\"act \"],[-1,\"remaining \"],[0,\"busi\"]],\"start1\":5472,\"start2\":5472,\"length1\":18,\"length2\":8},{\"diffs\":[[0,\"ants\"],[-1,\" for magic numbers\"],[1,\"\\\n8. **Injectable RNG** — for create_character and resolve_combat_full\"]],\"start1\":5515,\"start2\":5515,\"length1\":22,\"length2\":73}]"
metadata_diff: {"new":{},"deleted":[]}
encryption_cipher_text: 
encryption_applied: 0
updated_time: 2026-08-03T10:29:25.004Z
created_time: 2026-08-03T10:29:25.004Z
is_locked: 0
type_: 13