mirror of
https://github.com/motajs/template.git
synced 2026-09-13 02:08:50 +08:00
docs(03-01): complete Node data tracer plan
This commit is contained in:
parent
4eec08638e
commit
710c67ab60
@ -1,10 +1,10 @@
|
||||
---
|
||||
schema_version: 1
|
||||
open_count: 4
|
||||
open_count: 9
|
||||
waived_count: 0
|
||||
fixed_count: 2
|
||||
total_count: 6
|
||||
last_updated: 2026-09-10T01:38:48.570Z
|
||||
total_count: 11
|
||||
last_updated: 2026-09-10T07:45:45.249Z
|
||||
---
|
||||
|
||||
# Broken Windows Ledger
|
||||
@ -21,6 +21,11 @@ last_updated: 2026-09-10T01:38:48.570Z
|
||||
| 4 | 02 | skipped-test | packages-user/data-common/src/common/mover.test.ts | | 4 个 it.skip 坐标回写回归用例(x/y 正交、斜向、传送),待 02-02 修复 mover.ts:651 后翻绿 | fixed | | 2026-09-09T07:51:25.555Z | 2026-09-09T09:34:39.843Z |
|
||||
| 5 | 02 | stub | packages-user/data-system/src/path/system.ts | 254 | interrupt() is an intentional placeholder that only stops the in-flight move; takeover sequencing (stop-then-await per approved option 1) is implemented by 02-03 Task 4 | fixed | | 2026-09-09T09:34:59.707Z | 2026-09-09T13:24:24.755Z |
|
||||
| 6 | 02 | stub | packages-user/data-state/src/hero/moverImpl.ts | 284 | Existing cannotEnter() is intentionally empty because no event trigger corresponds to movement blocked by an impassable mask; D-08 direct OnTouch dispatch handles allowed adjacent no-pass targets. | open | | 2026-09-10T01:38:48.570Z | |
|
||||
| 7 | 03 | stub | packages-user/data-common/src/save/memory.ts | 90 | MemorySaveSystem.saveAutosaveToDB is an intentional no-op because Node never persists to IndexedDB. | open | | 2026-09-10T07:45:16.944Z | |
|
||||
| 8 | 03 | stub | packages-user/data-common/src/save/memory.ts | 90 | MemorySaveSystem.saveAutosaveToDB is an intentional no-op because Node never persists to IndexedDB. | open | | 2026-09-10T07:45:32.524Z | |
|
||||
| 9 | 03 | stub | packages-user/data-state/src/legacy/dependencies.ts | 53 | Node legacy dependency boundary intentionally registers no browser loading callbacks. | open | | 2026-09-10T07:45:33.228Z | |
|
||||
| 10 | 03 | deviation | packages-user/data-base/src/map/mapLayer.ts | 216 | Replaced Map.getOrInsertComputed with explicit Map lookup so the replay event path is Node-safe without a global prototype shim. | open | | 2026-09-10T07:45:33.930Z | |
|
||||
| 11 | 03 | unrun-verify | .planning/phases/03-data-completion/deferred-items.md | | Repository type gate remains non-zero on pre-existing render/legacy and Tile contract diagnostics; owned Node tracer and data tests pass. | open | | 2026-09-10T07:45:45.249Z | |
|
||||
|
||||
````json
|
||||
[
|
||||
@ -95,6 +100,66 @@ last_updated: 2026-09-10T01:38:48.570Z
|
||||
"reason": "",
|
||||
"recorded_at": "2026-09-10T01:38:48.570Z",
|
||||
"resolved_at": null
|
||||
},
|
||||
{
|
||||
"id": 7,
|
||||
"kind": "stub",
|
||||
"phase": "03",
|
||||
"file": "packages-user/data-common/src/save/memory.ts",
|
||||
"line": 90,
|
||||
"description": "MemorySaveSystem.saveAutosaveToDB is an intentional no-op because Node never persists to IndexedDB.",
|
||||
"status": "open",
|
||||
"reason": "",
|
||||
"recorded_at": "2026-09-10T07:45:16.944Z",
|
||||
"resolved_at": null
|
||||
},
|
||||
{
|
||||
"id": 8,
|
||||
"kind": "stub",
|
||||
"phase": "03",
|
||||
"file": "packages-user/data-common/src/save/memory.ts",
|
||||
"line": 90,
|
||||
"description": "MemorySaveSystem.saveAutosaveToDB is an intentional no-op because Node never persists to IndexedDB.",
|
||||
"status": "open",
|
||||
"reason": "",
|
||||
"recorded_at": "2026-09-10T07:45:32.524Z",
|
||||
"resolved_at": null
|
||||
},
|
||||
{
|
||||
"id": 9,
|
||||
"kind": "stub",
|
||||
"phase": "03",
|
||||
"file": "packages-user/data-state/src/legacy/dependencies.ts",
|
||||
"line": 53,
|
||||
"description": "Node legacy dependency boundary intentionally registers no browser loading callbacks.",
|
||||
"status": "open",
|
||||
"reason": "",
|
||||
"recorded_at": "2026-09-10T07:45:33.228Z",
|
||||
"resolved_at": null
|
||||
},
|
||||
{
|
||||
"id": 10,
|
||||
"kind": "deviation",
|
||||
"phase": "03",
|
||||
"file": "packages-user/data-base/src/map/mapLayer.ts",
|
||||
"line": 216,
|
||||
"description": "Replaced Map.getOrInsertComputed with explicit Map lookup so the replay event path is Node-safe without a global prototype shim.",
|
||||
"status": "open",
|
||||
"reason": "",
|
||||
"recorded_at": "2026-09-10T07:45:33.930Z",
|
||||
"resolved_at": null
|
||||
},
|
||||
{
|
||||
"id": 11,
|
||||
"kind": "unrun-verify",
|
||||
"phase": "03",
|
||||
"file": ".planning/phases/03-data-completion/deferred-items.md",
|
||||
"line": null,
|
||||
"description": "Repository type gate remains non-zero on pre-existing render/legacy and Tile contract diagnostics; owned Node tracer and data tests pass.",
|
||||
"status": "open",
|
||||
"reason": "",
|
||||
"recorded_at": "2026-09-10T07:45:45.249Z",
|
||||
"resolved_at": null
|
||||
}
|
||||
]
|
||||
````
|
||||
|
||||
198
.planning/phases/03-data-completion/03-01-SUMMARY.md
Normal file
198
.planning/phases/03-data-completion/03-01-SUMMARY.md
Normal file
@ -0,0 +1,198 @@
|
||||
---
|
||||
phase: 03-data-completion
|
||||
plan: 01
|
||||
subsystem: data-state
|
||||
tags: [node, replay, core-state, memory-save, legacy-boundary, vitest]
|
||||
|
||||
requires:
|
||||
- phase: 02-pathfinding
|
||||
provides: awaited hero mover and source-aware movement integration path
|
||||
provides:
|
||||
- Node-safe no-argument CoreState factory with independent memory-backed instances
|
||||
- Internal legacy converter/data-source boundary with browser compatibility loading
|
||||
- Fixed closed-loop replay fixture covering movement, event execution, map mutation, and normal replay end
|
||||
affects: [03-02, 03-03, 03-04, 03-05, 03-06]
|
||||
|
||||
actuals:
|
||||
tokens: 7872
|
||||
tasks: 2
|
||||
commits: 3
|
||||
|
||||
tech-stack:
|
||||
added: []
|
||||
patterns:
|
||||
- Internal host-detection boundary selects MemorySaveSystem for Node and preserves SaveSystem for browser/legacy hosts
|
||||
- Focused replay tests use a private direct ReplaySystem harness and explicit state/map/event fixtures
|
||||
|
||||
key-files:
|
||||
created:
|
||||
- packages-user/data-common/src/save/memory.ts
|
||||
- packages-user/data-state/src/legacy/dependencies.ts
|
||||
- packages-user/data-state/test/fixtures/closed-loop.ts
|
||||
- packages-user/data-state/test/nodeTracer.test.ts
|
||||
- .planning/phases/03-data-completion/deferred-items.md
|
||||
modified:
|
||||
- packages/common/src/logger.ts
|
||||
- packages-user/data-base/src/game.ts
|
||||
- packages-user/data-base/src/hero/mover.ts
|
||||
- packages-user/data-base/src/map/mapLayer.ts
|
||||
- packages-user/data-common/src/replay/sandbox.ts
|
||||
- packages-user/data-common/src/save/index.ts
|
||||
- packages-user/data-state/src/core.ts
|
||||
- packages-user/data-state/src/enemy/calculator.ts
|
||||
- packages-user/data-state/src/legacy/move.ts
|
||||
|
||||
key-decisions:
|
||||
- "createCoreState() remains parameterless and directly returns new CoreState(); Node composition is selected internally rather than through factory options."
|
||||
- "CoreState consumes the internal legacy dependency boundary only; the Node branch skips legacy loading and IndexedDB initialization."
|
||||
- "The tracer owns a private direct ReplaySystem harness until later top-level replay registration plans assemble the public compatibility path."
|
||||
|
||||
requirements-completed: []
|
||||
|
||||
coverage:
|
||||
- id: D1
|
||||
description: "Node imports CoreState without browser globals and creates two independent MemorySaveSystem-backed instances."
|
||||
verification:
|
||||
- kind: other
|
||||
ref: "pnpm exec tsx -e import createCoreState; create two instances and assert identity/save backend"
|
||||
status: pass
|
||||
human_judgment: false
|
||||
- id: D2
|
||||
description: "The fixed replay fixture performs a real rightward hero move, awaits the event, mutates the event-layer matrix, and reaches ended state."
|
||||
requirement: DATA-01
|
||||
verification:
|
||||
- kind: integration
|
||||
ref: "packages-user/data-state/test/nodeTracer.test.ts#replays movement, awaits event mutation, and ends normally"
|
||||
status: pass
|
||||
- kind: unit
|
||||
ref: "pnpm exec vitest run packages-user/data-state/test/nodeTracer.test.ts"
|
||||
status: pass
|
||||
human_judgment: false
|
||||
- id: D3
|
||||
description: "The existing four-package data test suite remains green after the Node-safe composition and replay fixes."
|
||||
verification:
|
||||
- kind: integration
|
||||
ref: "pnpm test:ci packages-user/data-common packages-user/data-base packages-user/data-system packages-user/data-state"
|
||||
status: pass
|
||||
human_judgment: false
|
||||
|
||||
duration: 19 min
|
||||
completed: 2026-09-10
|
||||
status: complete
|
||||
---
|
||||
|
||||
# Phase 3 Plan 1 Summary
|
||||
|
||||
**Node-safe four-layer state construction with injected legacy boundaries and an awaited replay movement/event/map tracer**
|
||||
|
||||
## Performance
|
||||
|
||||
- **Duration:** 19 min
|
||||
- **Started:** 2026-09-10T15:27:00+08:00
|
||||
- **Completed:** 2026-09-10T15:46:21+08:00
|
||||
- **Tasks:** 2
|
||||
- **Files modified:** 13 implementation/test files, plus planning ledgers
|
||||
|
||||
## Accomplishments
|
||||
|
||||
- Guarded logger and game-loading module evaluation against missing `main`, `window`, `document`, and `location` globals
|
||||
- Added `MemorySaveSystem`, parameterless `createCoreState()`, independent Node-safe construction, and centralized legacy dependency injection
|
||||
- Removed the enemy calculator singleton edge and legacy movement barrel edge without reintroducing a data-state singleton into the Node path
|
||||
- Added a fixed three-cell map tracer that awaits hero movement and source-aware enter-event mutation before replay completion
|
||||
- Removed two Node blockers: nonstandard `Map.getOrInsertComputed` use in the event path and the replay sandbox play-loop state guard
|
||||
|
||||
## Task Commits
|
||||
|
||||
Each task was committed atomically:
|
||||
|
||||
1. **Task 1: singleton back-edge 修复与 Node-safe CoreState construction tracer** - `a707be4` (feat)
|
||||
2. **Task 2: Node-safe CoreState 与最小 replay→move→event→map tracer** - `4eec086` (feat)
|
||||
|
||||
**Plan metadata:** pending final metadata commit
|
||||
|
||||
## Files Created/Modified
|
||||
|
||||
- `packages-user/data-common/src/save/memory.ts` - in-memory save/global storage adapter that does not instantiate Dexie
|
||||
- `packages-user/data-state/src/legacy/dependencies.ts` - internal host-aware legacy converter and loading boundary
|
||||
- `packages-user/data-state/src/core.ts` - no-options factory and dependency-driven four-layer constructor
|
||||
- `packages-user/data-state/test/fixtures/closed-loop.ts` - fixed map, event, and direct replay fixture
|
||||
- `packages-user/data-state/test/nodeTracer.test.ts` - focused Node construction and replay closure tests with Chinese `it` comments
|
||||
- `packages/common/src/logger.ts`, `packages-user/data-base/src/game.ts` - Node-safe global guards
|
||||
- `packages-user/data-base/src/map/mapLayer.ts`, `packages-user/data-common/src/replay/sandbox.ts` - runtime fixes required by the tracer
|
||||
|
||||
## Decisions Made
|
||||
|
||||
- Kept the public factory contract parameterless; host selection and legacy injection remain internal to the constructor boundary
|
||||
- Kept the compatibility singleton available through the existing barrel while direct Node tests import `src/core.ts`
|
||||
- Used the existing `DefaultHeroMoveTopImpl`, `EventExecutor`, and `ReplaySandbox` instead of creating a parallel movement or event engine
|
||||
|
||||
## Deviations from Plan
|
||||
|
||||
### Auto-fixed Issues
|
||||
|
||||
**1. [Rule 1 - Bug] Avoided reading an uninitialized hero mover during construction**
|
||||
- **Found during:** Task 1
|
||||
- **Issue:** `HeroLocation` constructs `HeroMover` before assigning `location.mover`, while the mover constructor read `tile.getCurrentFaceDirection()` and crashed in Node
|
||||
- **Fix:** Initialize the base mover with `FaceDirection.Unknown`; the location constructor applies the requested initial direction immediately afterward
|
||||
- **Files modified:** `packages-user/data-base/src/hero/mover.ts`
|
||||
- **Verification:** Node factory probe and focused tracer pass
|
||||
- **Committed in:** `a707be4`
|
||||
|
||||
**2. [Rule 3 - Blocking] Removed the event-layer dependency on a nonstandard Map prototype extension**
|
||||
- **Found during:** Task 2 tracer execution
|
||||
- **Issue:** The real movement path called `Map.getOrInsertComputed`, which is absent in a clean Node process and stalled the movement Promise
|
||||
- **Fix:** Replaced it with explicit `Map.get`/`Map.set` construction
|
||||
- **Files modified:** `packages-user/data-base/src/map/mapLayer.ts`
|
||||
- **Verification:** Focused tracer and full four-package data suite pass without a global Map shim
|
||||
- **Committed in:** `4eec086`
|
||||
|
||||
**3. [Rule 1 - Bug] Allowed ReplaySandbox.play() to execute its command loop**
|
||||
- **Found during:** Task 2 tracer execution
|
||||
- **Issue:** `ReplaySandbox.play()` sets `pausing` false, but `step()` rejected every step while not paused, so replay never reached `ended`
|
||||
- **Fix:** `step()` now rejects only inactive or already-ended sandboxes, preserving paused single-step behavior while allowing the play loop
|
||||
- **Files modified:** `packages-user/data-common/src/replay/sandbox.ts`
|
||||
- **Verification:** Replay tracer reaches normal end after the awaited movement/event Promise; full data suite passes
|
||||
- **Committed in:** `4eec086`
|
||||
|
||||
---
|
||||
|
||||
**Total deviations:** 3 auto-fixed (1 Rule 1 bug, 1 Rule 3 blocking issue, 1 Rule 1 replay bug)
|
||||
**Impact on plan:** All fixes were direct blockers for the requested Node/replay vertical tracer; no new public interface or package dependency was introduced.
|
||||
|
||||
## Known Stubs
|
||||
|
||||
- `packages-user/data-common/src/save/memory.ts:90` — `saveAutosaveToDB()` is intentionally a no-op in the Node adapter because the Node path must not persist to IndexedDB; recorded in `.planning/WINDOWS.md`.
|
||||
- `packages-user/data-state/src/legacy/dependencies.ts:51` — the Node boundary intentionally registers no browser loading callback; recorded in `.planning/WINDOWS.md`.
|
||||
- `packages-user/data-state/src/core.ts:156` — serialized external event registration remains the existing deferred TODO for later Phase 3 assembly; recorded in `.planning/WINDOWS.md`.
|
||||
|
||||
## Issues Encountered
|
||||
|
||||
- `pnpm check:type` remains non-zero on pre-existing render/legacy diagnostics and the user-owned Tile events contract mismatch (`TileStore`/`TileLegacyBridge` still use the old `trigger` shape). No new diagnostics were reported in the new fixture/test files or the memory/dependency boundary files. The issue is logged in `deferred-items.md` and `.planning/WINDOWS.md` for the later tile-events/type closure plan.
|
||||
|
||||
## Verification
|
||||
|
||||
- PASS: `pnpm exec vitest run packages-user/data-state/test/nodeTracer.test.ts` — 2 tests
|
||||
- PASS: `pnpm test:ci packages-user/data-common packages-user/data-base packages-user/data-system packages-user/data-state` — 11 files, 60 tests
|
||||
- PASS: exact canonical madge back-edge check for `enemy/calculator.ts -> ins.ts` and `legacy/move.ts -> index.ts`
|
||||
- PASS: direct Node factory probe creates two distinct `MemorySaveSystem`-backed states
|
||||
- DEFERRED: repository-wide `pnpm check:type`, due only to pre-existing render/legacy and Tile contract diagnostics
|
||||
|
||||
## User Setup Required
|
||||
|
||||
None - no external service configuration required.
|
||||
|
||||
## Next Phase Readiness
|
||||
|
||||
- The next replay/event plans can consume a direct Node-safe `CoreState` and fixed fixture without browser globals or IndexedDB.
|
||||
- Top-level replay enum/registration and event built-ins remain intentionally delegated to the subsequent Phase 3 plans.
|
||||
- The repository-wide type gate remains deferred as documented; the focused Node tracer and all current data-package tests are green.
|
||||
|
||||
---
|
||||
*Phase: 03-data-completion*
|
||||
*Completed: 2026-09-10*
|
||||
|
||||
## Self-Check: PASSED
|
||||
|
||||
- Summary and all declared created artifacts exist on disk
|
||||
- Task commits `a707be4` and `4eec086` are present in git history
|
||||
- Focused tracer and full data-package test suite passed
|
||||
3
.planning/phases/03-data-completion/deferred-items.md
Normal file
3
.planning/phases/03-data-completion/deferred-items.md
Normal file
@ -0,0 +1,3 @@
|
||||
# Deferred Items — Phase 03
|
||||
|
||||
- `pnpm check:type` remains blocked by pre-existing render/legacy diagnostics and the user-owned Tile events contract migration (`TileStore.getEvent` and `TileLegacyBridge` still use the old `trigger` shape). The migration is outside Plan 03-01 and remains assigned to the later Phase 3 tile-events plan.
|
||||
Loading…
Reference in New Issue
Block a user