Commit Graph

535 Commits

Author SHA1 Message Date
d8fb6f088c fix(07-12): loadState 用 disable/revert 包裹重新装备(WR-06)
- HeroEquipment.loadState 在重新装备循环外包一层录像禁用窗口,try/finally 保证恢复
- 录像桩补禁用计数语义,读档期间写入的指令被丢弃
- 回归覆盖:读档不产生录像指令、禁用与恢复配对平衡、读档后 equip/unequip 记录仍保留
2026-09-17 16:01:32 +08:00
ab18aa3ec7 fix(07-12): deleteModifierByIndex 委托 deleteModifier(WR-05)
- 按索引取出修饰器后委托 deleteModifier,删除簿记收敛为一份实现
- 返回被删修饰器;索引越界或为负返回 null 且不删除任何修饰器
- 回归覆盖:迭代器产出、索引解析、final 重算、重新挂载、存盘开关清理、越界
2026-09-17 15:56:50 +08:00
762bf2e95c docs(07-12): 记录装备加成事实源契约(WR-04 设计如此,零行为变更)
- types.ts 的 IEquipmentStateSave / IEquipmentState 补充契约注释
- 装备自身数值与百分比加成是事实源,存档持久化这两个表并由其重建装备修饰器
- 跨读档不保留旧修饰器引用属预期;运行时改加成须经装备自身而非改其修饰器
2026-09-17 15:56:26 +08:00
b99d040b11 test(07-12): 对齐空存档 nextUid 重置契约(IN-02,测试专用)
- saveLoad.test.ts 的码 58 用例改写为「空存档 → 随后 add 发号 0 且不产生码 58」
- 用例内注释登记码 58 分支只剩非空畸形数组可达,生产实现保持原样
- equipStore.ts 零改动(生产修复基线 ba60ef9)
2026-09-17 15:54:02 +08:00
7c04ed4a58 docs(07-12): lock user adjudications for WR-04/05/06 + compareEquip 2026-09-17 15:48:53 +08:00
fe63494b12 docs(07-12): fold IN-02 test-only contract alignment into plan 07-12 2026-09-17 15:11:03 +08:00
ba60ef99eb fix: equipStore 的 nextUid 在空存档下报错 2026-09-17 14:56:56 +08:00
b6d1976fc7 docs(phase-07): update tracking after plan 07-11 2026-09-17 14:07:00 +08:00
4481ee91f8 docs(07-11): complete container same-reference save/load plan 2026-09-17 14:05:27 +08:00
e4d392330c fix(07-11): #06-17-4/5/6 add top-level same-reference integration assertions
- CoreState 三档往返中断言装备实例、flag 字段与 follower 实例跨读档为同一实例
- 同时断言其数值/位置仍等于存档点(同引用不改变恢复结果)
- 新增 registerIdentityEquipment 夹具,既有夹具与断言未改动
2026-09-17 13:57:46 +08:00
78f6796915 fix(07-11): #06-17-6 preserve follower instances across loadState
- HeroFollowersController 新增 restoreFollowers 保留式恢复入口
- 同索引同图块数字原地 loadState 并保留实例;否则替换槽位并按既有语义触发增删钩子
- 存档中不存在的末尾跟随者按存档为准删除
- HeroState.loadState 改用 restoreFollowers,不再 removeAllFollowers 全量重建(保持同步)
- IHeroFollowersController 补声明与 jsDoc;新增同实例/替换/删除/补齐回归用例
2026-09-17 13:53:46 +08:00
9964326210 fix(07-11): #06-17-5 preserve flag field instances across loadState
- FlagSystem.loadState 按 key 复用现有 FlagCommonField 并用 fromStructured 原地写值
- 存档中不存在的字段一律删除(以存档为准)
- IFlagSystem.loadState jsDoc 补写同引用与删除语义
- 新增同实例保真、getOrInsert 复用、结构化值恢复、删除多余字段回归用例
- flag/saveLoad.test.ts 的「重建字段对象」断言按 Q1=A 裁决改为同实例保真
2026-09-17 13:50:09 +08:00
153f4a490a fix(07-11): #06-17-4 preserve equipment instances across loadState
- HeroEquipsStore.loadState 按 uid 复用现有 EquipmentState 原地读档
- 同 uid 但装备图块数字不同时才替换该实例
- 存档中不存在的装备实例一律删除(以存档为准)
- IHeroEquipsStore.loadState jsDoc 补写同引用与删除语义
- 新增同实例保真、删除多余实例、num 不同替换三条回归用例
2026-09-17 13:47:20 +08:00
94ceb50cfe refactor: 存档系统挪至渲染端 2026-09-17 13:29:34 +08:00
89434537c8 docs(07-11): record contract decisions Q1=A Q2=A Q3=A Q4=C 2026-09-17 13:23:38 +08:00
7121c93914 test: update replay command assertions after ReplayCode rename
49aacb0 renamed ReplayMoveCommand -> ReplayMove (and siblings); sync the two stale expectations in data-state/src/replay/commands.test.ts (constructor names + core.ts source assertions).
2026-09-17 13:15:30 +08:00
0551738708 docs(phase-07): update tracking after plan 07-10 2026-09-17 13:03:51 +08:00
95e424fff8 docs(07-10): complete ReplayArray index/stream/codec fixes plan 2026-09-17 13:03:15 +08:00
0c6812fcda test(07-10): 末步 set 用例改为断言 paramUsed 的外部可观测偏移
- paramUsed 为私有成员,其正确性只能通过下一条命令参数的写入偏移观测
- 增长与缩短两条末步用例补充参数缓冲区原始字节断言,使「末步起点回退」子缺陷在未修复时可直接失败
2026-09-17 12:59:24 +08:00
5b26539b00 docs(07-10): WR-03 录像参数格式改为类型码只增不改的追加式约定
- 按 Q6=B 不加格式版本字段:array.ts 的类型码表注释写明只增不改约定(新语义必须分配新码,禁止复用),并记录 5/6/7/8 与短字符串基址的一次性重新分配
- types.ts 的 IReplaySystemSave.paramArray 与 IReplayArray.getParamArray jsDoc 同步该约定,并写明不承诺读回旧格式录像
- array.test.ts 新增类型码映射锚定用例(5/6/7/8/9/短字符串基址 9)
- system.ts 无改动(未引入版本字段)
2026-09-17 12:55:50 +08:00
35d4ad6f1c fix(07-10): 编解码自洽 —— bigint 长度字节守卫与参数计数取截断后长度
- WR-01:normalizeParam 的 bigint 分支按长度字节的真实容量(255 字节 = 2^2040)判定,|值| >= 2^2040 触发告警 152 并丢弃该参数;normalizeParamList 过滤被丢弃项,不保留占位
- WR-02:add/insert/set 写入的命令参数计数一律取标准化后的 normalizeParam.length,与 normalizeParamList 的 255 截断一致
- logger.json 的 warn 152 文案改为与真实可表示范围(2^2040 - 1)一致,并写明溢出参数会被忽略
- array.test.ts 新增 bigint 长度字节边界往返、超界丢弃后命令计数/读流对齐、256/300 参数截断计数回归
2026-09-17 12:53:27 +08:00
1f9fb18cf5 fix(07-10): 写入路径越界校验与读流跨读档过期
- insert/delete/set 在 disabled 早退后、任何缓冲读写前校验 index,越界不修改任何缓冲区并告警新码 179(携带操作名/索引/当前长度)
- insert(index === length) 判为合法追加,按 add 语义写入(paramUsed 起、indexArray[length] = paramUsed),insert 合法区间变为 [0, length]
- setReplayArray 在 rebuildIndexArray 后补 expireStreams(),活跃读流跨 ReplaySystem.loadState 标记过期(#06-17-3 / 审计 H)
- types.ts 的 insert/delete/set jsDoc 写明合法区间与越界契约
- logger.json 新增 warn 179(当前最大 warn 码 178 之后)
- array.test.ts 新增 5 条边界回归(含越界前后逐字节不变量);saveLoad.test.ts 新增活跃读流跨读档告警 156 回归
2026-09-17 12:50:45 +08:00
9ae28c68cc fix(07-10): CR-01 ReplayArray.set 索引回退起点与末步终点对齐
- set() 改用 getParamRange(index) 取 [start, end),末步终点取 paramUsed,不再直读未初始化的 indexArray[index + 1]
- 索引回退循环起点由参数字节偏移 paramStart + 1 改为命令索引 index + 1,与 delete() 同口径
- types.ts 的 IReplayArray.set jsDoc 写明允许参数编码长度变化及其后步骤索引平移
- array.test.ts 新增 6 条 CR-01 回归:中间步增长/缩短、末步增长/缩短、读流遍历(IN-03 场景)
2026-09-17 12:42:48 +08:00
b299d348a7 docs(07-10): record contract decisions Q1=A..Q6=B 2026-09-17 12:34:41 +08:00
fe595b7983 refactor: 存档系统应处于渲染层 2026-09-16 21:54:12 +08:00
49aacb087a refactor: 调整录像命名 2026-09-16 21:51:19 +08:00
513a9c354c fix: 读档的 executor 未执行 2026-09-16 21:44:52 +08:00
d856e06b7d docs(phase-07): pin file-level vue-tsc gate command per RESEARCH Pitfall 4 2026-09-16 21:30:12 +08:00
a81e445497 docs(07-10): correct expireStreams call-site count to 5 2026-09-16 21:28:29 +08:00
10f88628cd docs(phase-07): plan plan set 07-10..07-14 for registered-not-fixed data defects 2026-09-16 21:27:10 +08:00
f97c76966b docs(phase-06): update tracking after plan 06-18 2026-09-16 20:43:16 +08:00
83ba914b4c docs(06-18): complete merged real-map scenario perf plan 2026-09-16 20:42:20 +08:00
5317b2f1e3 test(06-18): add whole-map critical timing and total/avg summary table
Adds a third metric that calls the real calculateCritical for every monster on
the merged map and fully consumes the generator, plus a second console.table
with monsters / total ms (sampled median of one full-map sweep) / avg ms.
avg ms equals total ms divided by the monster count.
2026-09-16 20:39:45 +08:00
c193c4e9a9 test(06-18): add merged real-map scenario perf for buildup and map damage
Merges the first 1/5/13 real 13x13 maps into one grid-tiled map
(13x13, 39x26, 52x52 with 11/79/204 monsters), builds the scene from a real
CoreState (real converters/reducer/calculator/final effect), assigns 12 real
Enemy prefabs (3 CommonAura ranges + GuardAura) via a seeded mulberry32, and
records buildup + map damage build timings with performance.mark/measure.
Zero assertions.
2026-09-16 20:33:18 +08:00
6c4d3709d3 test(06-18): migrate 5 existing perf files to performance.mark/measure
- measureCase sampling loop now pairs mark(startTag)/mark(endTag) with
  measure(measureName, startTag, endTag) and clears marks/measures per sample
- tag names derive from caseName+scale so they never collide across cases
- WARMUP_RUNS/SAMPLE_RUNS/median/min/p95/toFixed(3)/columns unchanged
2026-09-16 20:26:42 +08:00
0da0117cd4 docs(06-18): flag MainEnemyComparer as intentionally uncovered 2026-09-16 20:17:45 +08:00
7ad903f156 docs(06-18): create phase plan 2026-09-16 20:15:19 +08:00
b2626bd438 fix(07-09): keep hero attribute instance stable and clear generic variance
- HeroAttribute.loadState replaces its private base object; the HeroAttribute wrapper identity is preserved so equipment/combat references stay valid across load (#06-17-1/#06-17-2).

- Clone the incoming base attribute in the constructor so the shared HERO_DEFAULT_ATTRIBUTE is no longer mutated across CoreState instances.

- Use any for the hero position in combat handler/aura/enemy-view generics to clear the 45 new type errors introduced by HeroAttribute implementing ISaveableContent.
2026-09-16 19:35:54 +08:00
9a2f581c80 docs(phase-07): update tracking after plan 07-09 2026-09-16 18:50:23 +08:00
c5eb1bcdad docs(07-09): complete hero attribute same-reference save/load plan
- record #06-17-1/#06-17-2 closure, option A registry, attachAttribute removal and readonly binding
- record A2 save-shape change, no-ledger-entry cross-reference and the C-H unfixed list
- record Phase 7 reopen / 07-VERIFICATION.md invalidation and measured gate results
2026-09-16 18:49:43 +08:00
940e31f293 test(07-09): #06-17-2 combat-side same-reference hero attribute regression
- migrate the top-level snapshot assertion to heroSave.attribute.values.hp
- add CoreState enemyContext.getBindedHero() regressions: same live attribute before/after load, no rebinding, across all compressions
2026-09-16 18:47:39 +08:00
1f0af69004 fix(07-09): #06-17-1 load hero attribute in place and keep equipment bonuses
- IHeroStateSave.attribute becomes IHeroAttributeSave<THero>; top-level modifiers removed
- HeroState.attribute is readonly and loadState delegates to attribute.loadState (never reassigns)
- delete attachAttribute from IHeroState and HeroState, and its only test case
- thin-delegate registerModifier/createModifier/createAndInsertModifier to the attribute registry
- loadEquipEffect mounts equipment modifiers with save=false so equipment bonuses only return via re-equip
- add #06-17-1 regressions: same attribute instance, bonuses kept, no double-count when type is registered
2026-09-16 18:43:33 +08:00
6a60476531 feat(07-09): make HeroAttribute own its save state in place
- add IHeroAttributeSave<THero> and have IHeroAttribute extend ISaveableContent
- move the modifier factory registry into HeroAttribute with registerModifier/createModifier/createAndInsertModifier
- implement in-place saveState/loadState (values deep copy, save-enabled modifier enumeration, registry-driven rebuild)
- carry registry entries into clone() output
- introduce IHeroModifierOwner so modifier owner typing stays assignable for generic attributes
- add attribute.test.ts same-reference save/load regressions across all compressions
2026-09-16 18:37:54 +08:00
94f6a70e38 docs(phase-07): lock 07-09 decisions - option A registry, delete attachAttribute, readonly attribute
Task 0 becomes a resolved decision record (options marked historical, locked results in <record>): registry moves into HeroAttribute with HeroState thin delegation and clone() carrying it; attachAttribute deleted from IHeroState/HeroState plus its sole test, attribute made readonly so loadState never rebinds; equipment modifiers excluded from the attribute save via addModifier(name, modifier, false); IHeroStateSave.attribute becomes IHeroAttributeSave<THero> with top-level modifiers removed (no compat branch); #06-17-1/#06-17-2 regressions authorized; #06-17-3..8 registered only.
2026-09-16 18:04:54 +08:00
c39f43c6da docs(phase-07): add plan 07-09 for hero attribute same-reference save/load 2026-09-16 17:16:44 +08:00
83853ea5b0 docs(phase-06): update tracking after plan 06-17 2026-09-16 16:25:09 +08:00
7a056bb970 docs(06-17): complete real-map save/load perf plan
- add 06-17-SUMMARY.md with the 27-row measured table, measurement parameters, fixed side load breakdown, truthful Low-vs-High branch note and D-44 gate results
- register 06-TEST-FINDINGS.md #06-17-1 (HeroEquipment keeps the replaced attribute reference, so equipment bonuses are lost after hero.loadState; confirmed by a throwaway probe: atk 5 -> 0 at all three compressions)
- register WINDOWS.md entry #28 for the stage-1 minimum equipment seed deviation
2026-09-16 16:23:04 +08:00
a44c5d8918 test(06-17): stage 3 complete Low/High compression and reach 27 rows
- expand COMPRESSIONS to NoCompression / LowCompression / HighCompression so the matrix is 3 map counts x 3 compressions x 3 timing items = 27 rows
- keep measureCase, fixture build order, side load and 06-16 files untouched; still zero assertions
- one full run: 5 perf files / 45 tests passed, 0 WARNING/ERROR codes, saveablesReal.perf.ts (27 tests) in 379ms -- no case approaches the 30000ms testTimeout
2026-09-16 16:21:26 +08:00
4476e19805 test(06-17): stage 2 add fixed real side load and map scales 1/5/13
- seed 50 flags, 20 item kinds (3 equipment + 17 consumables), 4 equipped instances on slots 0..3, 20 modifiers (4 from equipped items + 16 manual), 1000 mixed replay steps and an unmodified enemy baseline
- keep addTile -> itemStore.addItem -> equipment.add ordering and a single one-shot compareWith after all maps exist
- 9 rows (1/5/13 x NoCompression x save|load|round trip), zero assertions, zero warn/error codes
2026-09-16 16:10:10 +08:00
63485e93ca test(06-17): stage 1 real 13x13 map fixture and map-only save/load perf rows
- move root floors.json into packages-user/data-state/test/fixtures/ (byte-identical) and delete the root copy
- add saveablesReal.perf.ts: toFlat/clearCodes/registerTiles/createRealMapFixture with a one-shot compareWith baseline
- seed the minimum 1 equipment instance so HeroEquipsStore.loadState does not raise error 58
- 3 rows: save / load / round trip for 1 map x NoCompression, zero assertions
2026-09-16 16:02:58 +08:00