| phase |
plan |
type |
wave |
depends_on |
files_modified |
autonomous |
gap_closure |
requirements |
estimate |
must_haves |
| 02-pathfinding |
04 |
execute |
4 |
|
| packages-user/data-system/src/path/types.ts |
| packages-user/data-system/src/path/graph.ts |
| packages-user/data-system/src/path/finder.ts |
| packages-user/data-system/src/path/system.ts |
| packages-user/data-state/src/hero/moverImpl.ts |
| .planning/phases/02-pathfinding/deferred-items.md |
|
true |
true |
|
| tokens |
raw_tokens |
tasks |
confidence |
| 26000 |
26000 |
2 |
low |
|
| truths |
artifacts |
key_links |
The user-owned path contract matches commit 7a011b2 except for the two authorized nullable moveTo/teleportTo return corrections (D-07). |
| Existing pathfinding graph, search, and hero movement behavior remains reachable through the restored public contract. |
| The phase-owned moverImpl file has no nullable-static TypeScript diagnostic, while its static and dynamic event collection semantics remain intact. |
| D-01: Existing minimum-loss and custom-cost behavior remains unchanged. |
| D-02: Existing directed reachable-graph behavior remains unchanged. |
| D-03: Existing map-layer and movable binding behavior remains available. |
| D-04: Existing step, teleport, and fallback behavior remains unchanged. |
| D-05: Existing injectable event-aware fallback policy remains unchanged. |
| D-06: Existing path-only retrieval remains unchanged. |
| D-07: The user-authored contract remains the source of truth after review. |
| D-08: Existing approved no-pass OnTouch semantics remain unchanged. |
| D-09: Existing hero-mover hook reuse remains unchanged. |
| D-10: Existing stop-then-await interruption handoff remains unchanged. |
| D-11: This gap closure remains data-side and excludes the Phase 4 click adapter. |
|
| packages-user/data-system/src/path/types.ts |
| packages-user/data-system/src/path/graph.ts |
| packages-user/data-system/src/path/finder.ts |
| packages-user/data-system/src/path/system.ts |
| packages-user/data-state/src/hero/moverImpl.ts |
|
| The restored user contract is consumed by the L2 path implementation without exposing phase-added graph/helper types through types.ts. |
| The nullable static guard still allows dynamic tile events to be collected before the existing source-aware executor path runs. |
|
|
Close the unauthorized user-owned path/types.ts expansion and the TS18047 diagnostic in moverImpl.ts without changing the locked Phase 2 pathfinding behavior.
Purpose: The verification report found that the user-owned contract grew beyond the authorized nullable return edits and that a phase-modified event loop still fails the type gate. D-07 makes the user-authored contract authoritative; this plan restores that boundary while preserving the already-verified L2/L3 runtime path.
Output: A baseline-faithful types.ts, relocated implementation-only graph contracts, a nullable-safe event-source loop, and focused evidence that PATH-01 behavior still passes.
<execution_context>
@C:/Users/book/.config/opencode/gsd-core/workflows/execute-plan.md
@C:/Users/book/.config/opencode/gsd-core/templates/summary.md
</execution_context>
@.planning/PROJECT.md
@.planning/ROADMAP.md
@.planning/STATE.md
@.planning/phases/02-pathfinding/02-VERIFICATION.md
@.planning/phases/02-pathfinding/02-CONTEXT.md
@.planning/phases/02-pathfinding/02-RESEARCH.md
@.planning/phases/02-pathfinding/02-INTERFACE-DRAFT.md
@.planning/phases/02-pathfinding/02-02-SUMMARY.md
@.planning/phases/02-pathfinding/02-03-SUMMARY.md
@packages-user/data-system/src/path/types.ts
@packages-user/data-system/src/path/graph.ts
@packages-user/data-system/src/path/finder.ts
@packages-user/data-system/src/path/system.ts
@packages-user/data-state/src/hero/moverImpl.ts
@dev.md
Task 1: Restore the authorized path contract while preserving the end-to-end path stack
packages-user/data-system/src/path/types.ts, packages-user/data-system/src/path/graph.ts, packages-user/data-system/src/path/finder.ts, packages-user/data-system/src/path/system.ts
packages-user/data-system/src/path/types.ts, packages-user/data-system/src/path/graph.ts, packages-user/data-system/src/path/finder.ts, packages-user/data-system/src/path/system.ts, packages-user/data-state/src/path/heroPathfinding.ts, .planning/phases/02-pathfinding/02-INTERFACE-DRAFT.md, .planning/phases/02-pathfinding/02-02-SUMMARY.md, dev.md
Use commit
7a011b2 as the exact user-owned contract baseline for packages-user/data-system/src/path/types.ts and reapply only the two authorized IPathfindingSystem return-type corrections: moveTo and teleportTo return IPathfindingController | null (D-07: user-authored contract is authoritative after review). Remove the later useMover/IObjectMover contract substitution, regions, and graph-helper interfaces from that file. Relocate IPathGraphEdge, IPathGraphNode, IPathGraph, and IPathfindingGraphBuilder to the implementation-owned graph.ts export surface, then update graph.ts and finder.ts imports accordingly. Keep the public IPathfinder/IPathfindingSystem behavior from the baseline, including useMovable; retain a concrete implementation-only mover bridge in system.ts so HeroPathfinding can continue to bind the existing IObjectMover without adding that bridge to the user-owned interface. Preserve D-01: minimum-loss search with custom cost support; D-02: directed reachable graph construction; D-03: IMapLayer and IObjectMovable binding; D-04: step and teleport modes with fallback; D-05: injectable event-aware fallback policy; D-06: path-only retrieval; D-09: existing hero mover hooks; and D-10: stop-then-await interruption handoff. Preserve the existing controller return behavior and L2-to-L3 dependency direction. Do not modify any client input code: D-11: this phase remains data-side and the mobile click adapter belongs to Phase 4.
node -e "const fs=require('node:fs'),cp=require('node:child_process'); const b=cp.execFileSync('git',['show','7a011b2:packages-user/data-system/src/path/types.ts'],{encoding:'utf8'}).replace(/\r\n/g,'\n').replaceAll('IPathfindingController;','IPathfindingController | null;'); const c=fs.readFileSync('packages-user/data-system/src/path/types.ts','utf8').replace(/\r\n/g,'\n'); if (b!==c) process.exit(1)"; if ($?) { pnpm exec vitest run "packages-user/data-system/src/path" "packages-user/data-state/src/path/heroPathfinding.test.ts" }
Non-zero exit, the normalized baseline comparison differs, or any focused Vitest suite reports a failed test.
types.ts differs from
7a011b2 only at the two authorized nullable return declarations; graph/search/hero integration tests pass through the restored contract with no client-side click wiring added.
Task 2: Close the nullable static event-source type gap
packages-user/data-state/src/hero/moverImpl.ts, .planning/phases/02-pathfinding/deferred-items.md
packages-user/data-state/src/hero/moverImpl.ts, packages-user/data-state/src/path/heroPathfinding.test.ts, packages-user/data-state/src/coreEventLayer.test.ts, .planning/phases/02-pathfinding/02-VERIFICATION.md, dev.md
Guard the loc.static event-source iteration before calling tileEvent(), while continuing to collect every dynamic tile event from loc.dynamics and preserving the existing priority ordering, trigger value, source-aware environment, and executor call. Update deferred-items.md to record the previously reported moverImpl.ts TS18047 diagnostic as resolved and leave the unrelated Phase 1 TileStore/type and legacy lint baselines unchanged. Preserve D-08: a target reached through allowed movement can receive the approved OnTouch behavior, while mask-blocked movement does not trigger it. Do not alter any Phase 1 source-aware event behavior.
$output = pnpm check:type 2>&1; $output; if ($output -match 'packages-user[\\/]data-state[\\/]src[\\/]hero[\\/]moverImpl\.ts\(') { exit 1 }; if ($?) { pnpm exec vitest run "packages-user/data-state/src/coreEventLayer.test.ts"; if ($?) { pnpm exec vitest run "packages-user/data-state/src/path/heroPathfinding.test.ts" } }
Non-zero focused test exit, or the type-check output contains any diagnostic path for moverImpl.ts.
moverImpl.ts produces no type diagnostic, static-null locations remain safe, dynamic event collection and Phase 1 event regressions pass, and the phase ledger identifies only the unrelated existing baselines as open.
<threat_model>
Trust Boundaries
| Boundary |
Description |
| User-authored path contract → L2 implementation |
The implementation consumes a public interface whose shape is controlled by the user baseline and must not silently expand it. |
| Map location data → event-source collection |
A nullable static tile and dynamic tile collection enter the movement event path. |
STRIDE Threat Register
| Threat ID |
Category |
Component |
Severity |
Disposition |
Mitigation Plan |
| T-02-06 |
Tampering |
path/types.ts public contract |
medium |
mitigate |
Compare the final file to git baseline 7a011b2 after applying only the two authorized nullable return edits; keep graph helper contracts outside the user-owned file. |
| T-02-07 |
Tampering/DoS |
moverImpl.ts event-source loop |
medium |
mitigate |
Narrow the nullable static value before method access, retain dynamic iteration, and run core-event plus hero-path integration tests. |
| T-02-SC |
Tampering |
npm/pip/cargo installs |
low |
accept |
No package installation is part of this gap closure. |
| </threat_model> |
|
|
|
|
|
- `pnpm exec vitest run "packages-user/data-system/src/path" "packages-user/data-state/src/path/heroPathfinding.test.ts"` passes after the contract restoration.
- `pnpm check:type` contains no diagnostic for `packages-user/data-state/src/hero/moverImpl.ts`; unrelated baseline diagnostics remain explicitly scoped in the ledger.
- `pnpm exec vitest run "packages-user/data-state/src/coreEventLayer.test.ts"` and the hero path integration test pass.
- A normalized baseline comparison proves path/types.ts has no unauthorized additions beyond the two nullable return corrections.
<success_criteria>
The two verified gaps are closed: the user-owned contract is restored to its authorized scope, the phase-owned TS18047 error is absent, and the existing automatic pathfinding/event behavior remains green. Mobile click integration is not included because D-11 explicitly assigns that rendering concern to Phase 4.
</success_criteria>
Create `.planning/phases/02-pathfinding/02-04-SUMMARY.md` when done