From 123493ccb42678f6d1dbf806aba331f750fb553f Mon Sep 17 00:00:00 2001 From: unanmed <1319491857@qq.com> Date: Tue, 15 Sep 2026 21:43:18 +0800 Subject: [PATCH] docs(07-08): amend plan for test-side layer binding and rename --- .planning/phases/07-data-fixes/07-08-PLAN.md | 173 +++++++++++-------- 1 file changed, 97 insertions(+), 76 deletions(-) diff --git a/.planning/phases/07-data-fixes/07-08-PLAN.md b/.planning/phases/07-data-fixes/07-08-PLAN.md index 246128f..e1dbce1 100644 --- a/.planning/phases/07-data-fixes/07-08-PLAN.md +++ b/.planning/phases/07-data-fixes/07-08-PLAN.md @@ -10,49 +10,48 @@ files_modified: autonomous: false requirements: - FIX-01 -user_setup: - - service: "本地开发环境(无外部服务)" - why: "D-07 规定 #06-07-1 的接线由用户亲自完成:CoreState 必须向 pathfinding.finder 注入 useMapState/useMapLayer/usePassPredicate" - env_vars: [] - dashboard_config: - - task: "在 packages-user/data-state/src/core.ts 中、地图可用之后(initMapState 之后或 loading.once('loaded') 钩子内)调用 state.pathfinding.finder.useMapState(this.maps)、useMapLayer(<当前 eventLayer>)、usePassPredicate(new DefaultPassPredicateImpl(this.maps))" - location: "packages-user/data-state/src/core.ts(装配点参考 core.ts:248-264;等价注入逐字见 data-state/test/replayPlayback.test.ts:108-114);AI 不实现该接线" estimate: - tokens: 16000 - raw_tokens: 16000 + tokens: 18000 + raw_tokens: 18000 tasks: 3 confidence: low must_haves: truths: - - "用户完成 CoreState → finder 注入后,取消 skip 的顶层录像瞬移用例转绿" - - "顶层录像瞬移不再因 maps/layer 未注入而告警 173 并返回空路径(不再下发错误码 2005)" + - "core.ts 已提供 useMapState(this.maps) 与 usePassPredicate(new DefaultPassPredicateImpl(this.maps)),且 useMapLayer(null) 为有意设计(勇士初始不在任何楼层,待切层时再设置)" + - "测试在楼层激活后把 map.eventLayer 绑定到 finder,顶层录像瞬移可解析出路径并到达 (1,0)(不再告警 173、不再下发 2005)" + - "重命名后的用例不再以 it.skip 存在;wireFinder=true 的既有兄弟用例一字未改" - "pnpm test:ci 全绿,且本计划不新增任何 it.skip" - - "AI 未修改任何生产源码(D-07)" + - "AI 未修改任何生产源码;楼层切换重注入缺口作为用户负责项在 SUMMARY 登记,本阶段不修复" artifacts: - path: packages-user/data-state/test/replayPlayback.test.ts - provides: "顶层录像瞬移回归见证(取消 skip 后覆盖真实 finder 装配)" + provides: "顶层录像瞬移回归见证(createSmallMapScene 返回 map、测试侧绑定 eventLayer、原 skip 用例重命名并转绿)" + - path: packages-user/data-state/src/core.ts + provides: "用户已产出的三处 finder 注入(:236 maps、:238 layer=null、:239-240 predicate)——本计划只读,不修改" key_links: + - "测试侧 state.pathfinding.finder.useMapLayer(map.eventLayer) ↔ finder.find 的 layer 非空判定(finder.ts:210-215),使告警 173 早退分支不再命中" - "data-state/src/core.ts 的 finder 注入点 ↔ data-system/src/path/finder.ts:117-131 的注入 API ↔ data-state/src/hero/predicate.ts 的 DefaultPassPredicateImpl" - - "finder.find 在 maps/layer 为 null 时的告警 173 ↔ replayPlayback.test.ts:362-375 的期望行为" + - "createSmallMapScene 的返回值 ↔ 顶层录像瞬移用例的层绑定(对既有忽略返回值的调用方为加法式变更)" assumptions: - - "FIX-01 探针未分类:本计划以显式假设承接,即 FIX-01 = 「登记缺陷的正确预期 skip 用例转绿且不新增跳过」;#06-07-1 属 D-07 的用户负责项,AI 只在其后验证" - - "用户接线属一次性注入;楼层切换时事件层会变化(gameMap.ts:146/152),是否需在切层时重新注入由用户设计决定,AI 不预设、不评价" + - "FIX-01 探针未分类:本计划以显式假设承接,即 FIX-01 = 「登记缺陷的正确预期 skip 用例转绿且不新增跳过」" + - "core.ts:238 useMapLayer(null) 属有意设计(源码注释:初始状态下勇士不在任何楼层,切换楼层后再具体设置);本计划保持 core.ts 原样,由测试侧显式绑定事件层来验证真实装配" + - "楼层切换时事件层会变化(gameMap.ts:43 的 eventLayer);仓库内除测试外没有任何生产调用点重新调用 useMapLayer。该重注入缺口是已登记的用户负责后续项,不在本阶段(AI 不实现、不评价其设计)" prohibitions: - - "AI 不修改 packages-user/data-state/src/core.ts 或任何生产源码(D-07);失败时退出并汇报,不得自行另辟他法" - - "不新增测试用例(D-10);只取消 it.skip" - - "不弱化断言,不改写为可跑绿假象" + - "AI 不修改 packages-user/data-state/src/core.ts 或任何生产源码;接线已是用户产出(提交 1ff22dd),本计划不追加、不调整、不重注入" + - "不新增测试用例(D-10):本次只取消一条既有 skip 并重命名,且只允许对 createSmallMapScene 做「返回 map」的加法式变更" + - "不弱化断言,不改写为可跑绿假象;不删除或跳过任何其它用例" - "不修改渲染端 @user/client-* 与 legacy 渲染接线" + - "不为 #06-07-1 新建 WINDOWS.md 账本条目" - "不引入新依赖、不新建文件" --- -处置 path 系统的 `#06-07-1`(D-07 用户负责):`CoreState` 未向 `pathfinding.finder` 注入 `useMapState`/`useMapLayer`/`usePassPredicate`,导致顶层录像瞬移恒因 `maps`/`layer` 为 `null` 告警 173 并返回空路径,进而下发错误码 2005。用户完成接线后,由 AI 取消 `replayPlayback.test.ts:362-375` 的 skip 并验证转绿;AI **不实现**该接线。 +处置 path 系统的 `#06-07-1`(D-07 用户负责):接线已由用户落地——`core.ts:236` `pathfinding.finder.useMapState(this.maps)`、`core.ts:238` `pathfinding.finder.useMapLayer(null)`、`core.ts:239-240` `usePassPredicate(new DefaultPassPredicateImpl(this.maps))`,其中 `useMapLayer(null)` 是**有意设计**(勇士初始不在任何楼层,切层后再具体设置),不是遗漏。因此仅取消 skip 仍会命中 `finder.ts:212-215` 的告警 173 → 空路径 → 2005。本计划据此改为:**由测试侧在楼层激活后显式绑定 `map.eventLayer`**,并把用例**重命名**为反映该事实的名字,取消 skip 后验证转绿;AI **不修改** `core.ts`。 -Purpose: 这是 20 条中唯一的装配缺口(L3 顶层接线),属用户设计的接口装配范畴;完成它才能让顶层录像瞬移链路真实可用。 +Purpose: 这是 20 条中唯一的装配缺口(L3 顶层接线),其接线已由用户完成;测试侧的层绑定与重命名完成后,顶层录像瞬移链路才有一份真实、可跑的回归见证。 -Output: 用户接线完成的事实确认 + 顶层录像瞬移用例取消 skip 并转绿 + 未新建账本条目的处置记录。 +Output: 接线事实与「layer 有意为 null」的确认 + 测试侧绑定 `map.eventLayer` 并重命名用例后转绿 + 未新建账本条目的处置记录 + 楼层切换重注入缺口在 SUMMARY 登记为**用户负责后续项**(本阶段不修复)。 -执行序:本计划在 07-07(save)之后串行执行。`depends_on: 07-07` 是**真实**依赖——`core.ts` 同时是本计划的前置修改目标(07-07 改其 `loadState` 的 178 判定)与用户接线文件,两者必须串行以避免对同一文件并发编辑。 +执行序:本计划在 07-07(save)之后串行执行。`depends_on: 07-07` 是**真实**依赖——`core.ts` 同时是 07-07 的修改目标(`loadState` 的 178 判定)与用户接线文件,两者必须串行以避免对同一文件并发编辑。 @@ -72,95 +71,110 @@ Output: 用户接线完成的事实确认 + 顶层录像瞬移用例取消 skip @.planning/WINDOWS.md @dev.md @packages-user/data-system/src/path/finder.ts +@packages-user/data-base/src/map/gameMap.ts @packages-user/data-state/src/hero/predicate.ts - Task 0: D-07/D-09 确认 —— 用户已完成后端接线,并确认取消 skip + Task 0: D-07/D-09 确认 —— 接线已落地且 layer 有意为 null,用户授权测试侧绑定 + 重命名 (只读确认,不修改任何文件) - - packages-user/data-state/src/core.ts(:240-270 装配区域;核对是否已出现 useMapState/useMapLayer/usePassPredicate) - - packages-user/data-state/test/replayPlayback.test.ts(:100-120 等价注入逐字、:355-380 目标 skip) - - packages-user/data-system/src/path/finder.ts(:98-131 注入 API、:205-233 maps/layer 为 null 时的告警 173) + - packages-user/data-state/src/core.ts(:232-241 装配区域::236 useMapState(this.maps)、:237-238 useMapLayer(null) 及其中文注释、:239-240 usePassPredicate(new DefaultPassPredicateImpl(this.maps))) + - packages-user/data-state/test/replayPlayback.test.ts(:80-116 createSmallMapScene 与 wireFinder 注入、:66-78 withReplayDisabled 返回值、:287/:302/:320 忽略返回值的既有调用方、:360-373 目标 skip 用例) + - packages-user/data-system/src/path/finder.ts(:117-131 注入 API、:205-233 maps/layer 为 null 时告警 173 并返回空数组) + - packages-user/data-base/src/map/gameMap.ts(:43 eventLayer 字段,楼层切换时会变化) - .planning/phases/07-data-fixes/07-RESEARCH.md(§Per-Finding #06-07-1、§WINDOWS.md 收口映射) -执行前置:先用只读方式核对用户是否已在 `core.ts` 的装配区域调用 `state.pathfinding.finder.useMapState(...)`、`useMapLayer(...)`、`usePassPredicate(...)`。若未出现,**必须停止本计划**并把缺失项与接线依据(`replayPlayback.test.ts:108-114` 的等价注入)汇报给用户,等待用户完成后再重新执行本计划;不得由 AI 代改 `core.ts`(D-07)。 +执行前置(只读核对,勿写):确认用户接线已在源码中落地——`core.ts:236` `pathfinding.finder.useMapState(this.maps)`、`core.ts:238` `pathfinding.finder.useMapLayer(null)`(其上中文注释:初始状态下勇士不在任何楼层,切换楼层后再具体设置)、`core.ts:239-240` `usePassPredicate(new DefaultPassPredicateImpl(this.maps))`。若三处中任一缺失,**必须停止本计划**并把缺失项与接线依据(`replayPlayback.test.ts:108-114` 的等价注入)汇报给用户;不得由 AI 代改 `core.ts`(D-07)。 -若已接线,向用户汇报以下内容并等待确认: -① 接线事实:`core.ts` 中三处注入的调用位置与实参(`this.maps` / 具体 `eventLayer` / `new DefaultPassPredicateImpl(this.maps)`);注入时机是否在地图可用之后(`initMapState` 之后或 `loaded` 钩子内)。 -② 预期效果:`finder.find` 在 `maps`/`layer` 均可用时不再进入告警 173 早退分支,顶层录像瞬移可解析出路径,不再下发 2005。 -③ 验证方式:取消 `replayPlayback.test.ts:362-375`(`plays a teleport step without manual finder wiring`)的 skip,断言一字不改,运行该文件确认转绿。 -④ 已知设计边界(不作评价,仅陈述):`useMapLayer` 传入的是某个 `IGameMap.eventLayer`,而楼层切换时事件层会变化(`gameMap.ts:146/152`);若注入是一次性的,是否在切层时重新注入由用户决定(属用户设计范畴)。 -⑤ 失败纪律:若取消 skip 后用例仍红,AI 必须**退出本计划**、如实汇报观测到的告警码与路径结果,并等待用户修订接线或修订本计划;**不得**自行修改 `core.ts`、不得改断言(D-07/D-09)。 -⑥ 账本事实:`#06-07-1` 在 WINDOWS.md 中无对应条目,D-14 的 waive 没有可 waive 的对象;研究建议不新建条目(避免抬高 `open_count` 门禁),改为在本计划 SUMMARY 记录用户负责项与验证结果。请用户确认。 +核对通过后,向用户汇报以下内容并等待确认: +① 已确认的接线事实:三处注入的调用位置与实参如上;`useMapLayer` 传入 `null` 是**有意设计**(勇士初始不在任何楼层),不是遗漏。 +② 由此的必然结果:`finder.find` 在 `layer` 为 `null` 时进入 `finder.ts:212-215` 的告警 173 早退分支并返回空数组,顶层录像瞬移随之下发 2005——仅取消 skip、不绑定事件层仍会红。 +③ 用户已确认的处置方式(本计划据此执行):**保持 `core.ts` 原样**;在**测试侧**于楼层激活后调用 `state.pathfinding.finder.useMapLayer(map.eventLayer)`,并把用例从 `plays a teleport step without manual finder wiring` **重命名为** `plays a teleport step after the event layer is bound on floor activation`(名字须反映其不再宣称「无需手动接线」)。 +④ 需要登记的用户负责项(本阶段**不修复**):`core.ts:238` 的 `useMapLayer(null)` 是一次性注入,楼层切换时事件层会变化(`gameMap.ts:43`),仓库内除测试外没有任何生产调用点在切层时重新注入;该缺口归用户所有,在 SUMMARY 登记为后续项,且不新建账本条目。 +⑤ 验证方式:取消 skip 后运行该文件确认转绿;断言一字不改(`x` 为 1、`y` 为 0)。 +⑥ 失败纪律:若绑定事件层后用例仍红,AI 必须**退出本计划**、如实汇报观测到的告警码与路径结果,并等待用户修订接线或修订本计划;**不得**自行修改 `core.ts`、不得改断言(D-07/D-09)。 +⑦ 账本事实:`#06-07-1` 在 WINDOWS.md 中无对应条目,D-14 的 waive 没有可 waive 的对象;按用户确认不新建条目(避免抬高 `open_count` 门禁),改为在本计划 SUMMARY 记录用户负责项与验证结果。请用户确认。 - 用户是否已完成 `CoreState` → `pathfinding.finder` 的三处注入(D-07),以及是否确认取消 `replayPlayback.test.ts:362-375` 的 skip 验证 + 用户是否确认「保持 core.ts 原样(layer 有意为 null)、由测试侧绑定 map.eventLayer 并重命名用例、取消 skip 验证、不新建账本条目」 - `#06-07-1` 是唯一的顶层装配缺口,D-07 明确规定接线由用户完成、AI 只做接线后的验证。若接线尚未完成,本计划无法执行也必须停止——AI 不得代改 core.ts。接线采用一次性注入还是切层重注入,由用户设计决定。 + `#06-07-1` 是唯一的顶层装配缺口,D-07 规定接线由用户完成。用户已完成接线并把事件层**有意**留为 `null`(勇士初始不在任何楼层),故「取消 skip」不再等价于「无需接线即可通过」:测试必须自己绑定事件层。楼层切换时的重注入是用户负责的后续缺口,本计划只登记、不实现、不评价。 - + - 回复 wired-approve / not-wired(并说明后重新执行)/ new-window-entry,或给出修订意见 + 默认按已确认的 test-binds-layer 继续;如需改为 core-reinject-first / not-wired / new-window-entry,或给出修订意见,请直接回复 - 用户明确回复 wired-approve、not-wired 或 new-window-entry - 用户回复 not-wired 或 revise;或未回复即继续 —— 必须停止执行 + 用户确认按 test-binds-layer 执行(或给出其它明确指示) + 用户回复 not-wired / core-reinject-first / revise;或未回复即继续 —— 必须停止执行 - - `core.ts` 的装配区域存在 `useMapState`、`useMapLayer`、`usePassPredicate` 三处调用(源码断言) - - 用户明确确认取消 skip 与账本条目处置 + - `core.ts` 的装配区域存在 `useMapState`、`useMapLayer(null)`、`usePassPredicate` 三处调用(源码断言) + - `useMapLayer(null)` 被记录为有意设计,且用户确认测试侧绑定事件层 + 重命名用例 + - 楼层切换重注入缺口被登记为用户负责后续项,且不新建账本条目 - 用户确认为 wired-approve 或 new-window-entry,且 `core.ts` 三处注入在源码中可见 + 用户确认为 test-binds-layer,且 `core.ts` 三处注入在源码中可见(`:236`/`:238`/`:239-240`) - Task 1: 取消 #06-07-1 的 skip 并验证顶层录像瞬移转绿 + Task 1: 测试侧绑定事件层、重命名用例并验证顶层录像瞬移转绿 packages-user/data-state/test/replayPlayback.test.ts - - packages-user/data-state/test/replayPlayback.test.ts(:100-120 等价注入、:355-380 目标 skip、文件内其余既有绿用例) - - packages-user/data-state/src/core.ts(:240-270 用户接线后的装配) + - packages-user/data-state/test/replayPlayback.test.ts(:80-116 createSmallMapScene/wireFinder 注入、:66-78 withReplayDisabled 返回 action() 的返回值、:287/:302/:320 忽略返回值的既有调用方、:360-373 目标 skip 用例) + - packages-user/data-state/src/core.ts(:232-241 用户接线后的装配) + - packages-user/data-system/src/path/finder.ts(:121-123 useMapLayer 接受 IMapLayer | null、:209-215 layer 为 null 时告警 173 并返回空数组) -把 `replayPlayback.test.ts:362-375`(`plays a teleport step without manual finder wiring`)的 `it.skip` 改为 `it`,断言一字不改,同步 it 前的中文注释(去掉「疑似 bug/待修复」措辞,改为中性描述该用例覆盖真实 finder 装配)。 +仅改 `replayPlayback.test.ts` 一个文件,做三处加法式/最小变更,不动生产源码(`core.ts` 为用户产出,保持原样): +(a) 让 `createSmallMapScene`(:85)**返回 `map`**:在函数体末尾(`resetHero(state)` 之后,且仍在 `if (!map || !map.eventLayer) throw` 造成的非空收窄范围内)加 `return map;`。既有调用方 :287/:302/:320 忽略返回值,不受影响;`withReplayDisabled`(:71-78)返回 `action()` 的返回值,故返回值可穿透该包装器。 +(b) 在目标用例中捕获该 map 并在**楼层激活后**显式绑定事件层:把 `withReplayDisabled(state, () => createSmallMapScene(state, false));` 改为捕获返回值的形式(`const map = withReplayDisabled(state, () => createSmallMapScene(state, false));`),随后在 `runHeroStep`/`replay.record`/`playRoute` **之前**调用 `state.pathfinding.finder.useMapLayer(map.eventLayer);`。`wireFinder = false` 保持不变——该用例刻意不依赖 createSmallMapScene 内部的手动注入,只补上事件层。 +(c) 取消 skip 并重命名:`it.skip('plays a teleport step without manual finder wiring', ...)` 改为 `it('plays a teleport step after the event layer is bound on floor activation', ...)`;同步把 :360-361 的中文注释从「疑似缺陷 #06-07-1 …… 修复后取消 skip」改为中性描述(说明本用例在楼层激活后由测试侧绑定事件层、验证顶层录像瞬移仍可解析并到达目标),不得再出现「疑似 bug / 待修复」措辞。 -不改 `:108-114` 的 `wireFinder` 等价注入逻辑(该用例正是以 `wireFinder = false` 区分真实装配与测试注入);不改该文件任何其它用例;不新增用例;不改任何生产源码。 +断言保持一字不改(`expect(state.hero.location.x).toBe(1)` 与 `expect(state.hero.location.y).toBe(0)`);不改 :108-114 的 `wireFinder` 分支;不改该文件任何其它用例;不新增用例;不改任何生产源码;不引入新依赖、不新建文件。 -若用例仍红:立即停止并按 Task 0 的第 ⑤ 条退出汇报(记录实际告警码、找到的路径与首个分歧),不得改断言、不得改 `core.ts`。 +若用例仍红:立即停止并按 Task 0 的第 ⑥ 条退出汇报(记录实际告警码、找到的路径与首个分歧),不得改断言、不得改 `core.ts`。 -验证:`pnpm exec vitest run packages-user/data-state/test/replayPlayback.test.ts` 全绿 → D-44 门禁三步(本计划仅一个测试文件)。提交信息:`test(07-08): #06-07-1 verify the top-level teleport with the wired finder`。 +验证:`pnpm exec vitest run packages-user/data-state/test/replayPlayback.test.ts` 全绿 → D-44 门禁三步(本计划仅一个测试文件)。提交信息:`test(07-08): #06-07-1 bind the event layer in the teleport playback test`。 pnpm exec vitest run packages-user/data-state/test/replayPlayback.test.ts 非零退出,或摘要行出现 "1 failed" / "failed"(仍告警 173 / 路径为空 / 下发 2005),或输出出现 "no tests found" - - `replayPlayback.test.ts` 的 `plays a teleport step without manual finder wiring` 不再以 `it.skip` 存在(源码断言:该行不含 `.skip`) - - `pnpm exec vitest run packages-user/data-state/test/replayPlayback.test.ts` 全绿 + - `replayPlayback.test.ts` 中 `plays a teleport step without manual finder wiring` 已不存在;`it('plays a teleport step after the event layer is bound on floor activation', ...)` 不以 `.skip` 存在(源码断言:该行不含 `.skip`) + - `createSmallMapScene` 返回 `map`,且目标用例在 `playRoute` 之前调用 `state.pathfinding.finder.useMapLayer(map.eventLayer)` + - `core.ts` 保持原样(`:236` 提供 `useMapState`、`:239-240` 提供 `usePassPredicate`、`:238` 的 `useMapLayer(null)` 不变) + - `pnpm exec vitest run packages-user/data-state/test/replayPlayback.test.ts` 全绿,且断言未被改写 - 本计划未修改任何生产源码(以本计划提交 sha 核验:`git show --name-only <本计划提交 sha>` 仅含该测试文件与 .planning 文档) - 用例取消 skip 并转绿,且未触碰任何生产源码;已一个原子提交入库 + 用例已重命名并在测试侧绑定事件层后转绿,三个 `wireFinder=true` 兄弟用例未改动,且未触碰任何生产源码;已一个原子提交入库 @@ -169,13 +183,18 @@ Output: 用户接线完成的事实确认 + 顶层录像瞬移用例取消 skip - .planning/phases/07-data-fixes/07-VALIDATION.md(§Manual-Only Verifications 的 #06-07-1 行) - .planning/phases/07-data-fixes/07-RESEARCH.md(§WINDOWS.md 收口映射「需澄清」、§Open Questions) + - packages-user/data-state/src/core.ts(:232-241,供 SUMMARY 逐字记录接线实参) 对唯一改动文件串行执行 D-12(沿用 D-44 的文件级判定)三步门禁:`pnpm exec eslint --fix` 后 `pnpm exec eslint` 0 错误;`pnpm exec vue-tsc --noEmit` 后按该文件相对路径过滤输出 0 类型错误(不以整仓退出码判定);`pnpm test:ci` 全绿。 -账本:`#06-07-1` 无对应条目,按 Task 0 的用户确认处置(默认不新建);若用户选择 `new-window-entry`,按用户指示执行 `windows` 的 append/waive 流程并在 SUMMARY 记录 `open_count` 变化。 +账本:`#06-07-1` 在 WINDOWS.md 中无对应条目,**不新建条目**(Task 0 已确认 test-binds-layer);若用户在 Task 0 改选 `new-window-entry`,则按用户指示执行 `windows` 的 append/waive 流程并在 SUMMARY 记录 `open_count` 变化。 -在 SUMMARY 中记录:用户接线的事实(三处注入的调用位置与实参)、验证命令与结果、用户负责项的边界说明(一次性注入 vs 切层重注入由用户决定)、以及 D-14 的账本处置结论。 +在 SUMMARY 中记录以下四类内容: +① 已确认的接线事实(源码逐字):`core.ts:236 pathfinding.finder.useMapState(this.maps)`、`:238 pathfinding.finder.useMapLayer(null)`(含中文注释原意:初始状态下勇士不在任何楼层,切换楼层后再具体设置)、`:239-240 usePassPredicate(new DefaultPassPredicateImpl(this.maps))`;用户接线提交 `1ff22dd`。 +② `core.ts` 的 `layer` 为 `null` 是**有意设计**(非遗漏),因此单纯取消 skip 仍会命中 `finder.ts:212-215` 的告警 173 → 空路径 → 2005。 +③ 本计划的测试侧处置:`createSmallMapScene` 返回 `map`(加法式);目标用例在楼层激活后调用 `state.pathfinding.finder.useMapLayer(map.eventLayer)`;用例由 `plays a teleport step without manual finder wiring` 重命名为 `plays a teleport step after the event layer is bound on floor activation`;断言未改。 +④ 剩余的用户负责缺口(本阶段**不修复**):`core.ts:238` 的一次性 `useMapLayer(null)` 在楼层切换(`gameMap.ts:43` 的 `eventLayer` 变化)时不会被重新注入,仓库内无对应生产调用点;登记为用户负责后续项,D-14 账本无 `#06-07-1` 条目、不新建。 pnpm test:ci @@ -185,9 +204,9 @@ Output: 用户接线完成的事实确认 + 顶层录像瞬移用例取消 skip - `pnpm exec eslint` 对该文件 0 错误 - `pnpm exec vue-tsc --noEmit` 按该文件路径过滤后无命中 - `pnpm test:ci` 全绿,且本计划未新增 `it.skip` - - SUMMARY 含用户接线事实、验证结果与账本处置结论 + - SUMMARY 含①接线事实(`1ff22dd` 与三处实参)、②layer 有意为 null、③测试侧绑定与重命名、④楼层切换重注入的用户负责缺口登记 - D-44 三步全过、全量套件绿、用户负责项处置已登记于 SUMMARY(提交粒度按 D-13 一个缺陷一个原子提交) + D-44 三步全过、全量套件绿、四类登记内容均写入 SUMMARY(提交粒度按 D-13 一个缺陷一个原子提交) @@ -197,39 +216,41 @@ Output: 用户接线完成的事实确认 + 顶层录像瞬移用例取消 skip | Boundary | Description | |----------|-------------| -| 顶层装配 → finder | `maps`/`layer`/谓词未注入时 finder 返回空路径并依赖诊断码上报,属装配缺陷而非安全边界 | -| 用户代码 → AI 范围 | D-07 明确接线属用户,AI 越界即违反协作边界 | +| 顶层装配 → finder | `core.ts` 已注入 `maps` 与谓词,但 `layer` 有意为 `null`;测试必须自行绑定事件层,属装配边界而非安全边界 | +| 用户代码 → AI 范围 | 接线已由用户落地(D-07);AI 只改测试侧,越界修改 `core.ts` 即违反协作边界 | | 包管理器 → 仓库 | 本阶段无安装动作 | ## STRIDE Threat Register | Threat ID | Category | Component | Severity | Disposition | Mitigation Plan | |-----------|----------|-----------|----------|-------------|-----------------| -| T-7-14 | DoS(功能性) | `path/finder.ts` 未注入时的早退路径(告警 173) | low | accept | 接线由用户完成(D-07);AI 只在接线后取消 skip 验证,失败即退出汇报,不修改生产代码 | +| T-7-14 | DoS(功能性) | `path/finder.ts` 的 `layer = null` 早退路径(告警 173)与楼层切换重注入缺口 | low | accept | 接线由用户完成(D-07);`layer = null` 为有意设计,由测试侧显式绑定 `map.eventLayer` 规避;切层重注入属用户负责后续项,本阶段登记于 SUMMARY 而不修改生产代码 | | T-7-SC | Tampering | npm/pip/cargo 安装 | high | accept | 本阶段不安装任何包(`package.json`/`pnpm-lock.yaml` 不变);若执行中出现安装需求,立即停止并汇报 | -- `core.ts` 中存在 `useMapState`/`useMapLayer`/`usePassPredicate` 三处注入(用户产出,源码断言) +- `core.ts` 中存在 `useMapState`(`:236`)/`useMapLayer(null)`(`:238`)/`usePassPredicate`(`:239-240`)三处注入(用户产出,本计划只读) +- `replayPlayback.test.ts` 的目标用例已重命名为 `plays a teleport step after the event layer is bound on floor activation` 且不以 `it.skip` 存在 +- `createSmallMapScene` 返回 `map`;该用例在 `playRoute` 之前调用 `state.pathfinding.finder.useMapLayer(map.eventLayer)` +- 改动文件仅 `replayPlayback.test.ts`(AI 未触碰生产源码;`git show --name-only <本计划提交 sha>` 可核验) - `pnpm exec vitest run packages-user/data-state/test/replayPlayback.test.ts` 全绿 - `pnpm test:ci` 全绿且本计划不新增 `it.skip` -- 改动文件仅 `replayPlayback.test.ts`(AI 未触碰生产源码) -1. 用户完成 `CoreState` → `finder` 注入(D-07) -2. `#06-07-1` 正确预期用例取消 skip 并转绿 +1. 确认 `core.ts` 的三处 finder 注入已由用户落地(D-07),且 `useMapLayer(null)` 为有意设计 +2. 测试侧在楼层激活后绑定 `map.eventLayer`,`#06-07-1` 用例重命名、取消 skip 后转绿 3. AI 未修改任何生产源码;失败时按 D-09 退出并汇报 -4. 用户负责项与账本处置在 SUMMARY 登记 +4. 用户负责的楼层切换重注入缺口与账本处置(不新建条目)在 SUMMARY 登记 ## Artifacts this phase produces | 类型 | 路径 | 内容 | |------|------|------| -| 用户产出(AI 不改) | `packages-user/data-state/src/core.ts` | `pathfinding.finder` 的三处注入 | -| 测试(修改) | `packages-user/data-state/test/replayPlayback.test.ts` | 1 条 skip 取消 | -| 摘要 | `.planning/phases/07-data-fixes/07-08-SUMMARY.md` | 用户接线事实、验证结果、账本处置 | +| 用户产出(AI 只读) | `packages-user/data-state/src/core.ts` | `pathfinding.finder` 的三处注入(`:236`/`:238`/`:239-240`);`useMapLayer(null)` 有意为 null | +| 测试(修改) | `packages-user/data-state/test/replayPlayback.test.ts` | `createSmallMapScene` 返回 `map`;目标用例测试侧绑定 `map.eventLayer`、重命名并取消 skip | +| 摘要 | `.planning/phases/07-data-fixes/07-08-SUMMARY.md` | 接线事实、layer 有意为 null、测试侧绑定与重命名、切层重注入用户负责缺口登记、账本处置 | Create `.planning/phases/07-data-fixes/07-08-SUMMARY.md` when done