docs(06-01): complete combat layer-2 unit test plan

- record 06-01-SUMMARY.md with coverage block and three suspected-bug findings
- advance STATE.md to plan 2, log decisions and execution metric
- mark ROADMAP phase 6 at 1/9 In Progress and TEST-01 complete
- open WINDOWS.md entries for the three documented skipped tests
This commit is contained in:
unanmed 2026-09-14 08:54:37 +08:00
parent 6c8f85a2be
commit 6cf828c9cc
6 changed files with 242 additions and 23 deletions

View File

@ -34,7 +34,7 @@ Requirements for the engine's completion. Each maps to roadmap phases.
### 测试(Testing)
- [ ] **TEST-01**: 为核心系统(数据层等)补齐单元测试
- [x] **TEST-01**: 为核心系统(数据层等)补齐单元测试
## Out of Scope
@ -62,7 +62,7 @@ Which phases cover which requirements. Updated during roadmap creation.
| REND-02 | Phase 4 | Pending |
| LEGACY-01 | Phase 5 | Pending |
| LEGACY-02 | Phase 5 | Pending |
| TEST-01 | Phase 6 | Pending |
| TEST-01 | Phase 6 | Complete |
**Coverage:**

View File

@ -210,10 +210,11 @@ Plans:
3. 测试在本地可运行且全部通过
4. 测试由 AI 编写并运行,通过验证后可提交
**Plans**: 9 plans (data-layer slice; non-data render/legacy coverage deferred)
**Plans**: 1/9 plans executed (data-layer slice; non-data render/legacy coverage deferred)
Plans:
- [ ] 06-01-PLAN.md — Combat L2 (data-system/src/combat) behavior tests + phase tracer
- [x] 06-01-PLAN.md — Combat L2 (data-system/src/combat) behavior tests + phase tracer
- [ ] 06-02-PLAN.md — Combat L3 (data-state/src/enemy) calculator/aura/special/mapDamage tests
- [ ] 06-03-PLAN.md — Enemy data model (data-base/src/enemy) tests
- [ ] 06-04-PLAN.md — Replay (data-common/src/replay) tests + replay integration
@ -247,4 +248,4 @@ Phases execute in numeric order: 1 → 2 → 3 → 4 → 5 → 6
| 3. 数据端完成 | 19/19 | Complete | 2026-09-12 |
| 4. 渲染适配与双布局 | 0/TBD | Not started | - |
| 5. Legacy 移植 | 0/TBD | Not started | - |
| 6. 单元测试 | 0/9 | Planned | - |
| 6. 单元测试 | 1/9 | In Progress| |

View File

@ -4,16 +4,16 @@ milestone: v1.0
current_phase: 06
current_phase_name: unit-tests
status: executing
stopped_at: Phase 6 context gathered
last_updated: "2026-09-14T00:30:13.250Z"
last_activity: 2026-09-13
last_activity_desc: Completed quick task 260913-qtq (event built-ins refactor + anon-tokyo import rename)
state_head: e1a16eae8b10c3aa44a9ca5908871d431fa396a2
stopped_at: Completed 06-01-PLAN.md
last_updated: "2026-09-14T00:53:17.655Z"
last_activity: 2026-09-14
last_activity_desc: Phase 06 execution started
state_head: 6c8f85a2be68d9696844ee863a8bb6787b6fde45
progress:
total_phases: 6
completed_phases: 3
completed_phases: 0
total_plans: 46
completed_plans: 37
completed_plans: 38
milestone_name: milestone
---
@ -24,14 +24,14 @@ milestone_name: milestone
See: .planning/PROJECT.md (updated 2026-09-10)
**Core value:** 引擎能完整跑通一部魔塔——开局到结局,存档、战斗、地图、事件、剧情全链路可玩。
**Current focus:** Phase 03 — data-completion
**Current focus:** Phase 06 — unit-tests
## Current Position
Phase: 06 (unit-tests) — READY TO EXECUTE
Plan: Not started
Phase: 06 (unit-tests) — EXECUTING
Plan: 2 of 9
Status: Ready to execute
Last activity: 2026-09-12 — Phase 03 complete, transitioned to Phase 4
Last activity: 2026-09-14 — Phase 06 execution started
Progress: [█████░░░░░] 50%
@ -76,6 +76,7 @@ Progress: [█████░░░░░] 50%
| Phase 02 P05 | 5min | 2 tasks | 2 files |
| Phase 03 P18 | 14min | 3 tasks | 8 files |
| Phase 03 P19 | 8min | 2 tasks | 6 files |
| Phase 06 P01 | 9min | 3 tasks | 6 files |
## Accumulated Context
@ -137,6 +138,8 @@ Recent decisions affecting current work:
- [quick 260913-qtq]: 内建函数名改用短名(setBlock/moveBlock/... ),删除 EventBuiltinName 枚举;类内使用字面量名称。
- [quick 260913-qtq]: anon-tokyo 以内嵌 workspace 包 @motajs/anon-tokyo 为唯一来源,全仓统一引用并声明 workspace 依赖。
- [quick 260913-qtq]: 事件注册收口为单一 createEventRegistrations(),不做分类包装;共享工具放 event/utils.ts 且不经 index 导出。
- [Phase 06]: 06-01:combat Layer-2 以行为单测覆盖(DamageContext/DamageSystem/MapDamage/EnemyContext/CombatFlow),三处疑似 bug 只记录不修复,按 D-05 写成 it.skip 正确预期用例并登记 06-TEST-FINDINGS.md #06-01-1..3
- [Phase 06]: 06-01:Node 测试须同时 polyfill Map.getOrInsert 与 getOrInsertComputed(EnemyContext 使用前者)
### Pending Todos
@ -165,6 +168,6 @@ None yet.
## Session Continuity
Last session: 2026-09-13T23:35:55.993Z
Stopped at: Phase 6 context gathered
Resume file: E:/github/template/.planning/phases/06-unit-tests/06-CONTEXT.md
Last session: 2026-09-14T00:53:17.425Z
Stopped at: Completed 06-01-PLAN.md
Resume file: None

View File

@ -1,10 +1,10 @@
---
schema_version: 1
open_count: 10
open_count: 13
waived_count: 0
fixed_count: 8
total_count: 18
last_updated: 2026-09-11T06:27:22.412Z
total_count: 21
last_updated: 2026-09-14T00:54:04.044Z
---
# Broken Windows Ledger
@ -33,6 +33,9 @@ last_updated: 2026-09-11T06:27:22.412Z
| 16 | 03 | deviation | packages-user/data-state/test/replayVerifier.ts | | Added a package-local verifier harness shared by Vitest and the Node runner to avoid composite-script import resolution. | open | | 2026-09-10T09:18:58.946Z | |
| 17 | 03 | deviation | packages-user/data-state/test/fixtures/closed-loop.ts | | Applied repository Prettier/CRLF formatting to the fixed replay fixture and runner files. | open | | 2026-09-10T09:18:59.589Z | |
| 18 | 03 | deviation | script/check-data-circular.ts | | Plan 03-15 scoped circular gate reports seven pre-existing legacy/render boundary cycles through data-state/src/legacy/move.ts; replay command class changes do not touch those imports. | open | | 2026-09-11T06:27:22.412Z | |
| 19 | 06 | skipped-test | packages-user/data-system/src/combat/damage.test.ts | | 06-01-1 suspected bug: calculateCritical yields info not matching nextValue (Finding #06-01-1) | open | | 2026-09-14T00:54:02.628Z | |
| 20 | 06 | skipped-test | packages-user/data-system/src/combat/mapDamage.test.ts | | 06-01-2 suspected bug: MapDamage.deleteEnemy leaves enemy-sourced damage (Finding #06-01-2) | open | | 2026-09-14T00:54:03.338Z | |
| 21 | 06 | skipped-test | packages-user/data-system/src/combat/combat.test.ts | | 06-01-3 suspected bug: CombatFlow.before truthy/falsy semantics inverted vs interface doc (Finding #06-01-3) | open | | 2026-09-14T00:54:04.044Z | |
````json
[
@ -251,6 +254,42 @@ last_updated: 2026-09-11T06:27:22.412Z
"reason": "",
"recorded_at": "2026-09-11T06:27:22.412Z",
"resolved_at": null
},
{
"id": 19,
"kind": "skipped-test",
"phase": "06",
"file": "packages-user/data-system/src/combat/damage.test.ts",
"line": null,
"description": "06-01-1 suspected bug: calculateCritical yields info not matching nextValue (Finding #06-01-1)",
"status": "open",
"reason": "",
"recorded_at": "2026-09-14T00:54:02.628Z",
"resolved_at": null
},
{
"id": 20,
"kind": "skipped-test",
"phase": "06",
"file": "packages-user/data-system/src/combat/mapDamage.test.ts",
"line": null,
"description": "06-01-2 suspected bug: MapDamage.deleteEnemy leaves enemy-sourced damage (Finding #06-01-2)",
"status": "open",
"reason": "",
"recorded_at": "2026-09-14T00:54:03.338Z",
"resolved_at": null
},
{
"id": 21,
"kind": "skipped-test",
"phase": "06",
"file": "packages-user/data-system/src/combat/combat.test.ts",
"line": null,
"description": "06-01-3 suspected bug: CombatFlow.before truthy/falsy semantics inverted vs interface doc (Finding #06-01-3)",
"status": "open",
"reason": "",
"recorded_at": "2026-09-14T00:54:04.044Z",
"resolved_at": null
}
]
````

View File

@ -0,0 +1,176 @@
---
phase: 06-unit-tests
plan: 01
subsystem: testing
tags: [vitest, unit-test, combat, damage, map-damage, enemy-context, combat-flow, data-system, node]
requires: []
provides:
- "Layer-2 combat behavior coverage: DamageContext/DamageSystem, MapDamage, EnemyContext, CombatFlow"
- "Node combat test harness pattern (vi.hoisted global stub + dynamic module bag + inline fakes + real-timer await)"
- "COVERAGE.md api-coverage declaration and the shared 06-TEST-FINDINGS.md sink with #06-01-1..3 findings"
affects: [06-unit-tests, 06-02, 06-03, 06-08]
actuals:
tokens: 15725
tasks: 3
commits: 4
tech-stack:
added: []
patterns:
- "vi.hoisted global stub (main/location + Map.getOrInsert/getOrInsertComputed polyfill) + beforeAll dynamic module bag"
- "Inline per-file fake collaborators; data-layer interfaces are never mocked"
- "Real timers + manual deferred resolver for async combat ordering; logger.catch for warn-code assertions"
- "Suspected bug -> correct-expectation test marked it.skip plus a Chinese pointer to 06-TEST-FINDINGS.md #06-01-N"
key-files:
created:
- packages-user/data-system/src/combat/damage.test.ts
- packages-user/data-system/src/combat/mapDamage.test.ts
- packages-user/data-system/src/combat/context.test.ts
- packages-user/data-system/src/combat/combat.test.ts
- .planning/phases/06-unit-tests/COVERAGE.md
- .planning/phases/06-unit-tests/06-TEST-FINDINGS.md
modified: []
key-decisions:
- "TEST-01 contribution for this plan = behavior unit tests over the combat Layer-2 contract, gated by `pnpm test:ci` green (D-01/D-08)"
- "Three suspected bugs are recorded, not fixed: calculateCritical info/nextValue mismatch; MapDamage.deleteEnemy leaves sourced damage; CombatFlow.before truthy/falsy semantics inverted vs the interface doc"
- "Map.getOrInsert polyfill added alongside getOrInsertComputed because EnemyContext uses it under Node"
- "Effect-registry add/remove is asserted through observable buildup behavior because the registries have no public getter"
requirements-completed: [TEST-01]
coverage:
- id: D1
description: "DamageContext/DamageSystem behavior coverage (result spread, handler identity, warns 106/107, cache hit/invalidation, with(hero), calculateCritical)"
requirement: TEST-01
verification:
- kind: unit
ref: "packages-user/data-system/src/combat/damage.test.ts#DamageContext behaviour"
status: pass
human_judgment: false
- id: D2
description: "MapDamage behavior coverage (sourceless add/delete, sourced conversion, reduction caching, union, warns 102/103/104)"
requirement: TEST-01
verification:
- kind: unit
ref: "packages-user/data-system/src/combat/mapDamage.test.ts#MapDamage sourced conversion and reduction"
status: pass
human_judgment: false
- id: D3
description: "EnemyContext behavior coverage (register/lookup/unknown-null/delete/resize/scan/iterate, effect-registry add/remove)"
requirement: TEST-01
verification:
- kind: unit
ref: "packages-user/data-system/src/combat/context.test.ts#EnemyContext registry"
status: pass
human_judgment: false
- id: D4
description: "CombatFlow behavior coverage (same-state binding, warn 138, script priority sort/duplicate 140, guard warns 139/141, awaited ordering, truthy short-circuit)"
requirement: TEST-01
verification:
- kind: unit
ref: "packages-user/data-system/src/combat/combat.test.ts#CombatFlow async ordering"
status: pass
human_judgment: false
- id: D5
description: "Suspected-bug findings #06-01-1..3 triaged by the user (fix core code, amend interface contract, or defer)"
verification: []
human_judgment: true
rationale: "The three skipped tests encode the expected contract against the current implementation; per D-05/D-07 only the user can decide whether to repair core code or amend the interface contract, and no core source is modified in this phase."
duration: 9min
completed: 2026-09-14
status: complete
---
# Phase 06 Plan 01: Combat Layer-2 Unit Tests Summary
**Behavior unit tests for the `data-system` combat Layer-2 contract (DamageContext/DamageSystem, MapDamage, EnemyContext, CombatFlow) proven end-to-end in Node, surfaced 3 suspected bugs**
## Performance
- **Duration:** 9 min
- **Started:** 2026-09-14T00:43:36Z
- **Completed:** 2026-09-14T00:52:20Z
- **Tasks:** 3
- **Files modified:** 6 created (4 test files + 2 planning artifacts), 0 production files touched
## Accomplishments
- Tracer proved the whole Node combat test path (`vi.hoisted` global stub, dynamic module bag, inline fake `IEnemyContext`/`IDamageCalculator`, `logger.catch` warn assertions, real-timer async) on `damage.test.ts` before any expansion.
- Full Layer-2 combat behavior covered: warn codes 106/107 (damage), 102/103/104 (map damage), 138/139/140/141 (combat flow), plus cache invalidation, `with(hero)`, critical generation and the documented script/hook execution order.
- Opened the shared `06-TEST-FINDINGS.md` sink with the D-06 schema and recorded three suspected bugs (`#06-01-1`..`#06-01-3`) as correct-expectation `it.skip` tests; `pnpm test:ci` stayed green (23 files, 153 passed, 3 documented skips).
- Declared `COVERAGE.md`: this test-only phase adds no external API integration.
## Task Commits
Each task was committed atomically:
1. **Task 1: Tracer — DamageContext/DamageSystem behavior end-to-end (+ phase scaffolding)** - `59b709e` (test)
2. **Task 1 harness fix: Map.getOrInsert polyfill for the combat test harness** - `15f329b` (test)
3. **Task 2: MapDamage + EnemyContext behavior** - `484da2d` (test)
4. **Task 3: CombatFlow binding, script ordering, and battle flow** - `6c8f85a` (test)
**Plan metadata:** (final docs commit, recorded in STATE.md/ROADMAP.md)
## Files Created/Modified
- `packages-user/data-system/src/combat/damage.test.ts` - DamageContext/DamageSystem behavior + calculateCritical
- `packages-user/data-system/src/combat/mapDamage.test.ts` - MapDamage sourceless/sourced damage, reducer caching, warns 102/103/104
- `packages-user/data-system/src/combat/context.test.ts` - EnemyContext registry, resize/scan/iterate, effect-registry add/remove
- `packages-user/data-system/src/combat/combat.test.ts` - CombatFlow binding, script ordering/duplication, guard warns, awaited order
- `.planning/phases/06-unit-tests/COVERAGE.md` - api-coverage declaration for the test-only phase
- `.planning/phases/06-unit-tests/06-TEST-FINDINGS.md` - shared append-only findings sink with the `#06-01` section
## Decisions Made
- Treated TEST-01 as satisfied by behavior tests over the seven in-scope data-layer systems, gated by `pnpm test:ci` (the plan's flagged, unverified assumption).
- Wrote the three suspected-bug tests to the correct expectation and marked them `it.skip` (never weakened into passing), each with a Chinese comment pointing at its `#06-01-N` findings entry.
- Asserted effect-registry add/remove through observable `buildup()` behavior instead of a public getter, because `EnemyContext` exposes no registry accessors.
## Deviations from Plan
### Auto-fixed Issues
**1. [Rule 3 - Blocking] Missing `Map.getOrInsert` polyfill under Node**
- **Found during:** Task 2 (EnemyContext effect registries)
- **Issue:** `EnemyContext.registerCommonQueryEffect` / `registerSpecialQueryEffect` call `Map.prototype.getOrInsert`, which does not exist in Node; only `getOrInsertComputed` was polyfilled by the existing harness pattern, so `context.test.ts` failed to load.
- **Fix:** Added a `Map.prototype.getOrInsert` stub next to the existing `getOrInsertComputed` stub in the combat test harness (uniform across all four files).
- **Files modified:** `context.test.ts`, `damage.test.ts` (harness-only)
- **Verification:** Focused vitest run green; full `pnpm test:ci` green.
- **Committed in:** `15f329b` (harness fix), folded into `484da2d`/`6c8f85a`
**2. [Rule 3 - Blocking] Cannot `extends` a dynamically imported class**
- **Found during:** Task 2 (mapDamage fixture)
- **Issue:** `class FakeRange extends modules.BaseRange` evaluated at module load, before `beforeAll` assigned the dynamic module bag, so `modules.BaseRange` was `undefined`.
- **Fix:** Replaced the `BaseRange` subclass with a small local `IFakeRange` implementation exposing only `bindHost`/`iterateLoc`, with a single narrow cast in `FakeView.getRange()`.
- **Files modified:** `mapDamage.test.ts`
- **Verification:** Focused vitest run green for `mapDamage.test.ts`.
- **Committed in:** `484da2d` (Task 2 commit)
---
**Total deviations:** 2 auto-fixed (2 blocking)
**Impact on plan:** Both were test-harness-only fixes; no production source changed and no scope creep.
## Issues Encountered
- Commit staging: the first Task 2 commit accidentally swept in the Task 2 files under a harness-fix message. Corrected with `git reset --soft HEAD~1` (no working-tree change) and re-committed the harness fix and Task 2 separately.
## Known Stubs
None. Three `it.skip` tests are intentional D-05 markers for suspected bugs, tracked in `06-TEST-FINDINGS.md` (`#06-01-1` calculateCritical `info`/`nextValue` mismatch; `#06-01-2` `MapDamage.deleteEnemy` leaves sourced damage because `viewStore`/`damageStore` are never populated; `#06-01-3` `CombatFlow` short-circuits on truthy `before`, contradicting the interface doc's `false` semantics).
## Next Phase Readiness
- The combat Layer-2 contract is covered and green; later plans (06-02 `data-state/src/enemy`, 06-03 `data-base/src/enemy`, 06-08 `CoreState` integration) can reuse the established harness and append their own `#06-0X` findings sections.
- Open input for the user: triage the three `#06-01-N` findings (fix core code vs. amend the interface contract). Per D-07 no core code was modified in this phase.
---
*Phase: 06-unit-tests*
*Completed: 2026-09-14*

View File

@ -39,5 +39,5 @@
"label": "Advance to the next step",
"reason": "Phase 06 of 6 · executing"
},
"updated_at": "2026-09-14T00:30:13.363Z"
"updated_at": "2026-09-14T00:53:00.361Z"
}