template/.planning/phases/02-pathfinding/02-04-PLAN.md

11 KiB

phase plan type wave depends_on files_modified autonomous gap_closure requirements estimate must_haves
02-pathfinding 04 execute 4
02-03
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
PATH-01
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