diff --git a/docs/plan-refactor-inventory-core-v1.md b/docs/plan-refactor-inventory-core-v1.md index d261a58d8..0f51be968 100644 --- a/docs/plan-refactor-inventory-core-v1.md +++ b/docs/plan-refactor-inventory-core-v1.md @@ -6,7 +6,7 @@ - ✅ 2026-08-03 P0 完整契约面重写 + absorption audit - ⬜ P1:inventory 拆分 + txn/capacity 骨架 + inventory-layout/dropped-loot 纯 migration helpers(依赖 R3 P1 seam) -- ⬜ P2:production writer 迁移分为 P2a metadata/provider + Public writer path 与 P2b OwnerOnly private-writer activation;P2a 依赖 R3 P2 atomic commit seam 与旧 dropped-loot compatibility,P2b 必须等 R3 P4 dropped-loot migration/hydration、R6 P1 recipient projection/page、R5 P3 + R6 P4、R10 P3 pickup txn 及 R4 pickup consumer 全部完成后才可启用。 +- ⬜ P2:production writer 迁移分为 P2a metadata/provider + Public writer path 与 P2b OwnerOnly private-writer activation;P2a 依赖 R3 P2 atomic commit seam 与旧 dropped-loot compatibility,P2b 必须等 R3 P4 dropped-loot migration/hydration、R6 P3 recipient projection/page production activation、R5 P3 + R6 P4、R10 P3 pickup txn 及 R4 pickup consumer 全部完成后才可启用。 - ⬜ P3:pickup/merge txn(依赖 R5 P3 attrition API、R6 P4 receipt API) - ⬜ P4:联合 bot/e2e + plan 收口(依赖 R4 handler 与 R3 P4 legacy inventory-layout consumer) @@ -87,15 +87,15 @@ R10 的 inventory-layout 与 dropped-loot migration 函数均纯且幂等,保 ## 6. 所有权与顺序 -- **R10**:`server/src/inventory/**` model/grid/txn/capacity、writer enumeration、typed outcome、纯 migration。P1 仅在 **R3 P1** 的 inventory/overflow seam 冻结后实现 txn/capacity 骨架;P2a 负责 metadata/provider 与 `Public` writer path,依赖 **R3 P2** durable spill/pickup recoverable-commit seam、旧 dropped-loot migration compatibility 与 crash/retry pins;P2b 才能启用 `OwnerOnly` private writers,且必须等 **R3 P4 dropped-loot migration/hydration、R6 P1 recipient projection/page、R5 P3 + R6 P4、R10 P3 pickup txn、R4 pickup consumer** 全部完成;P3 pickup/attrition consumer 只有在 **R5 P3** incoming-only attrition/ledger API 与 **R6 P4** receipt wire/client API 已合入后才可接通。 +- **R10**:`server/src/inventory/**` model/grid/txn/capacity、writer enumeration、typed outcome、纯 migration。P1 仅在 **R3 P1** 的 inventory/overflow seam 冻结后实现 txn/capacity 骨架;P2a 负责 metadata/provider 与 `Public` writer path,依赖 **R3 P2** durable spill/pickup recoverable-commit seam、旧 dropped-loot migration compatibility 与 crash/retry pins;P2b 才能启用 `OwnerOnly` private writers,且必须等 **R3 P4 dropped-loot migration/hydration、R6 P3 recipient projection/page production activation、R5 P3 + R6 P4、R10 P3 pickup txn、R4 pickup consumer** 全部完成;P3 pickup/attrition consumer 只有在 **R5 P3** incoming-only attrition/ledger API 与 **R6 P4** receipt wire/client API 已合入后才可接通。 - **R3**:SQL/outbox、spill/pickup recoverable commit、hydration guard、migration consumer;R10 只消费 R3 P1/P2/P4 已冻结并实现的接口。P4 必须拆成 dropped-loot hydration 子批次与 inventory-layout overflow 子批次,前者不等待 R10 P3,后者才等待其实际 durable/capacity 前置。 -- **R4**:C2S gate/handler、authoritative pickup context、调用 R10 并转交 R6 outcome;R4 handler/consumer phase 必须等待 **R10 P3 pickup txn、R6 P4** receipt API 与 **R5 P3** attrition API,不得以 R10 mock 或仅 R6 P1 schema 代替。 +- **R4**:C2S gate/handler、authoritative pickup context、调用 R10 并转交 R6 outcome;R4 handler/consumer phase 必须等待 **R10 P3 pickup txn、R6 P4** receipt API 与 **R5 P3** attrition API,不得以 R10 mock 或仅 R6 P1 contract-only schema 代替。 - **R5**:incoming-only qi attrition/ledger;provider phase 为 R5 P3。 -- **R6**:receipt wire/client、recipient projection/page、decoder;canonical plan 登记 rotate、pack feedback、dropped sync;dropped-loot projection/page consumer 为 R6 P1,必须在 **R10 P2a owner/visibility metadata provider** 与 **R3 P4 dropped-loot migration/hydration consumer** 完成后才可消费;receipt provider phase 为 R6 P4。 +- **R6**:receipt wire/client、recipient projection/page、decoder;canonical plan 登记 rotate、pack feedback、dropped sync;dropped-loot projection/page production consumer 为 R6 P3,其 activation gate 仅引用总纲 §3 Wave 表;receipt provider phase 为 R6 P4。 - **R1**:txn stored/spilled 成功后才 teardown,失败保留 session。 - **R7**:UI 消费,不拥有事务。 -顺序:**R3 P1 → R10 P1(含纯 inventory-layout/dropped-loot migration helpers)→ R3 P2 atomic seam 实现 + legacy dropped-loot migration/hydration compatibility pins → R10 P2a metadata/provider + Public writer path → R3 P4 dropped-loot migration/hydration consumer → R6 P1 dropped-loot projection/page consumer → R5 P3 + R6 P4 → R10 P3 pickup/merge txn → R4 handler/pickup consumer → R10 P2b OwnerOnly private-writer activation → R3 P4 inventory-layout overflow consumer → R10 P4 联合 e2e**。R10 P2a 在 R3 P2 atomic seam 与旧 dropped-loot migration compatibility 未合入前不得开始;R3 P4 dropped-loot migration/hydration consumer 必须先于 R6 P1 dropped-loot projection/page consumer,确保旧 `entry_json` 已先升级为带 `owner`/`visibility` 的 canonical entry;R10 P2b 只有在 R3 P4 dropped-loot hydration、R6 P1 projection/page、R5 P3 + R6 P4、R10 P3 pickup txn 与 R4 pickup consumer 全部完成后才可启用,避免 OwnerOnly writer 在授权消费链闭合前广播或转移私有掉落;R10 P3 在 R5 P3/R6 P4 provider 未合入前不得开始 pickup consumer;R4/R3 的外轨交付物只作 R10 P4 验收前置、不计入 R10 自身 phase;R10 不越权改 persistence、wire、handler 或 client。 +顺序:**R3 P1 → R10 P1(含纯 inventory-layout/dropped-loot migration helpers)→ R3 P2 atomic seam 实现 + legacy dropped-loot migration/hydration compatibility pins → R10 P2a metadata/provider + Public writer path → R3 P4 dropped-loot migration/hydration consumer → R6 P3 dropped-loot projection/page production activation → R5 P3 + R6 P4 → R10 P3 pickup/merge txn → R4 handler/pickup consumer → R10 P2b OwnerOnly private-writer activation → R3 P4 inventory-layout overflow consumer → R10 P4 联合 e2e**。R10 P2a 在 R3 P2 atomic seam 与旧 dropped-loot migration compatibility 未合入前不得开始;R3 P4 dropped-loot migration/hydration consumer 必须先于 R6 P3 dropped-loot projection/page production activation,确保旧 `entry_json` 已先升级为带 `owner`/`visibility` 的 canonical entry;R10 P2b 只有在 R3 P4 dropped-loot hydration、R6 P3 production activation、R5 P3 + R6 P4、R10 P3 pickup txn 与 R4 pickup consumer 全部完成后才可启用,避免 OwnerOnly writer 在授权消费链闭合前广播或转移私有掉落;R10 P3 在 R5 P3/R6 P4 provider 未合入前不得开始 pickup consumer;R4/R3 的外轨交付物只作 R10 P4 验收前置、不计入 R10 自身 phase;R10 不越权改 persistence、wire、handler 或 client。 ## 7. 审核要求的 contract pins diff --git a/docs/plans-skeleton/plan-refactor-c2s-gate-v1.md b/docs/plans-skeleton/plan-refactor-c2s-gate-v1.md index bb02a4f60..64fd315f7 100644 --- a/docs/plans-skeleton/plan-refactor-c2s-gate-v1.md +++ b/docs/plans-skeleton/plan-refactor-c2s-gate-v1.md @@ -20,7 +20,7 @@ - ⬜ P0 设计收口 + 吸收清单验真:113 个变体普查(每个标注应有的门禁四元组现状);冻结 `GateSpec` 与拒绝回执语义;等 #1287(冷却重构,同文件大改)merge 定基线。 - ⬜ P1 门禁中间件落地:gate 层上线,先给"已知漏洞簇"的 ~20 个请求类型挂 spec(吸收清单全命中),旧内联校验保留并行断言一个版本期。 -- ⬜ P2 巨石拆分批次 A:巨型 match 拆为按域 handler 注册表(combat/production/world/social/npc 五组),行为不变,bot 场景锁住;inventory pickup handler 必须从 ECS `CurrentDimension`、authoritative position/observation range 与 owner/private permission 构造 R10 `PickupAuthorization`,禁止仅凭 client XYZ/instance id 调用 txn,且把 R10 accepted/rejected outcome 交给 R6 emit API。**本批次的 inventory pickup consumer 仅在 R10 P3 pickup/merge txn、R5 P3 attrition API 与 R6 P4 receipt API 均已合入后实施;此前不得以 mock 或旧 R6 P1 schema 接线。** +- ⬜ P2 巨石拆分批次 A:巨型 match 拆为按域 handler 注册表(combat/production/world/social/npc 五组),行为不变,bot 场景锁住;inventory pickup handler 必须从 ECS `CurrentDimension`、authoritative position/observation range 与 owner/private permission 构造 R10 `PickupAuthorization`,禁止仅凭 client XYZ/instance id 调用 txn,且把 R10 accepted/rejected outcome 交给 R6 emit API。**本批次的 inventory pickup consumer 仅在 R10 P3 pickup/merge txn、R5 P3 attrition API 与 R6 P4 receipt API 均已合入后实施;此前不得以 mock 或 R6 P1 contract-only schema 接线。** - ⬜ P3 巨石拆分批次 B + 全量挂 spec + 删旧:113 变体全部声明门禁(含显式 `no_gate` 声明,杜绝静默无门禁);删除各域内联距离常量与重复维度判断。 - ⬜ P4 bot 验收 + 吸收 plan 批量归档。 diff --git a/docs/plans-skeleton/plan-refactor-cast-av-contract-v1.md b/docs/plans-skeleton/plan-refactor-cast-av-contract-v1.md index fb6f07ef1..abe247925 100644 --- a/docs/plans-skeleton/plan-refactor-cast-av-contract-v1.md +++ b/docs/plans-skeleton/plan-refactor-cast-av-contract-v1.md @@ -12,7 +12,7 @@ ## 接入面 -- **进料**:`SkillRegistry`/`SkillDef`(既有)、R5 后的 qi 访问器(施法扣费)、R6 emit builder(cast_sync 走它)、R2 的 store 生命周期(client cast 状态店)。 +- **进料**:`SkillRegistry`/`SkillDef`(既有);R5 qi 访问器、R6 emit builder、R2 store 生命周期是 production activation 的接缝输入,不是 contract-first 的启动门。 - **出料**:cast_sync/S2C AV 事件 → client `VfxBootstrap`/`BongAnimationRegistry`/audio recipe/HUD/SkillIcon 单点绑定。 - **共享类型**:`SkillAvBinding { anim, vfx_event, audio_recipe, hud_hint, icon }` 每招一条,注册即校验(缺任何一项 = 启动 fail-fast,对齐「招式 A/V 差异化」红线);cast 生命周期枚举补 STOP/INTERRUPT 权威事件。 - **worldview/AV 锚点**:每招独立可辨五件套是 CLAUDE.md 红线;audio 沿用 Pattern A(cast_center 施法快照,不读实时 Position)。 @@ -20,7 +20,7 @@ ## 阶段 - ⬜ P0 设计收口 + 吸收清单验真:全部已注册招式普查(server 权威可达性 × client AV 五件套齐备度矩阵,#1249 已给出方法先例);冻结 `SkillAvBinding` 与 cast_sync 契约增量。 -- ⬜ P1 契约落地:cast_sync 补 source/target/phase 字段(走 R6 契约流程)+ STOP 权威事件;`SkillAvBinding` 注册表 + fail-fast 校验上线(死注册项即启动报错)。 +- ⬜ P1 契约落地:contract-first 先补 cast_sync 的 source/target/phase 字段与 STOP/INTERRUPT 权威事件、`SkillAvBinding` 注册表及 fail-fast 校验;**这些 artifacts 的首次提交必须同时携 pin suite**:TypeBox 正例覆盖每个 phase/discriminant,反例覆盖 source/target/phase 任一缺失与 invalid/unknown phase;client reducer/state-machine 覆盖每条合法转换、非法转换拒绝及 STOP/INTERRUPT 终止路径;registry 覆盖五件套齐备成功与任一缺项 fail-fast。不得把这些 pins 延后到 P4 bot/e2e。production activation 仅按总纲 §3/§4.1 的跨轨顺序、ownership 与 atomicity invariants 放行,具体接缝与验收由 owner track plans 定义。 - ⬜ P2 修复批次 A:双源去重(baomai-v3/tuike-v2)、错接纠正(dugu penetrate)、停止语义接线(tribulation brace/打坐腿 pitch 红线修正)。 - ⬜ P3 修复批次 B:skillbar 定义源统一(丹道三招接入)、HUD 提示/图标补齐(dugu-v2、zhenmai sever 标记语义修正)、缺失动画 JSON 补齐(woliu voidpath 五招,遵守 PlayerAnimator 四大坑)。 - ⬜ P4 bot 验收 + 吸收 plan 批量归档。 @@ -35,7 +35,7 @@ skeleton:dandao-basic-skillbar-bridge、dugu-v2-hud-skill-hint、skillbar-cast - 独占:server `combat/` 的 cast/AV emit 点、`skill/` 注册表、`network/cast_emit.rs`;client `combat/` handler/store 的 cast 部分、`VfxBootstrap`/动画注册的绑定结构。 - 不碰:qi 扣费语义(R5 访问器,本轨消费);emit 传输层(R6 builder,本轨消费);FPV 手臂动画(fpv-cast-av plan 域)。 -- 依赖:基线等 #1287、#1249 merge;R5 P1、R6 P1、R2 P1 之后开工(Wave 2)。P0 普查可先行。 +- **依赖**:#1287、#1249 是基线;P0 与 P1 contract-first 可独立开工,不等待其他 track 的 production artifacts。production activation/cutover 只按总纲 §3 Wave 与 §4.1 的 ownership/atomicity invariants 放行;具体接缝、artifact 和验收由各 owner track plan 定义。P0 普查可先行。 ## bot 验收场景 diff --git a/docs/plans-skeleton/plan-refactor-master-v1.md b/docs/plans-skeleton/plan-refactor-master-v1.md index 28e25c1ce..371d4a9c5 100644 --- a/docs/plans-skeleton/plan-refactor-master-v1.md +++ b/docs/plans-skeleton/plan-refactor-master-v1.md @@ -6,8 +6,8 @@ ## 0. 范围与铁律 -- **只重构 `server/` + `client/`**。`agent/`、`worldgen/`、`library-web/` 不动,相关 plan 独立保留(§6.11-6.12)。 -- 对外契约(Redis IPC、proto schema)原则上不动形状;确需变更走 buf breaking + samples 同步,agent 侧只做被动 regenerate。**不写兼容层**——切换一次到位,删旧路径。 +- **玩法/运行时重构只动 `server/` + `client/`**。`worldgen/`、`library-web/` 不动,agent runtime/prompt/arbiter 等行为域独立保留(§6.11-6.12);跨端 wire 的 TypeBox schema source 是本范围的唯一基础设施例外,按 §4.1 分 owner。 +- **TypeBox source 是 repo-wide schema source of truth**。对外契约(Redis IPC、proto schema)原则上不动形状;确需变更时先改 TypeBox canonical content,再由 R6-owned generation/transport machinery 按 R6 plan 同步其 mirrors,并走必要的 breaking checks。**不写兼容层**——production activation 服从 §4.1 不变量。 - 真元守恒律、worldview 正典、招式 A/V 差异化红线全部继续生效。 - **测试方针(用户 2026-07-27 指示,仅限重构轨道,覆盖根 CLAUDE.md「饱和化测试」节)**: 1. **bot e2e 场景是主验收门**——每条轨道自带 3-8 个 `scripts/bot/scenarios/` 场景,先于/伴随重构落地; @@ -41,26 +41,43 @@ | R3 | `plan-refactor-persistence-slices-v1` | 持久化 Slice 框架 + persistence 巨石拆分 | `server/src/persistence/**` + autosave | ~25 | | R4 | `plan-refactor-c2s-gate-v1` | C2S 声明式门禁 + handler 巨石拆分 | `client_request_handler.rs` + `network/gate/` | ~24 | | R5 | `plan-refactor-qi-ledger-v1` | qi 账本架构强制化(字段收私有) | `qi_physics/**` + 全仓直写点 | ~20 | -| R6 | `plan-refactor-wire-s2c-v1` | emit builder + client 双轨归一 + 作用域广播 | `network/*_emit.rs`、`proto_convert.rs`、client `network/` | ~12 | +| R6 | `plan-refactor-wire-s2c-v1` | S2C schema generation/transport machinery、emit builder、client 双轨归一与作用域广播 | TypeBox generation machinery、generated mirrors、`proto_convert.rs`、client bridge/router plumbing | ~12 | | R7 | `plan-refactor-client-ui-base-v1` | Screen 基类 + InspectScreen 拆解 + 输入/线程纪律 | client Screen/hud/keybind | ~17 | -| R9 | `plan-refactor-cast-av-contract-v1` | cast_sync 契约 + SkillAvBinding 单一事实源 | server cast/AV emit + client cast store | ~13 | +| R9 | `plan-refactor-cast-av-contract-v1` | cast TypeBox 内容语义 + reducer/state machine + SkillAvBinding 单一事实源 | TypeBox cast declarations、server cast/AV semantics、client cast store | ~13 | | R10 | `plan-refactor-inventory-core-v1` | inventory 巨石拆分 + InventoryTxn 事务 | `server/src/inventory/**` | ~7 | | V | `plan-bot-e2e-coverage-v1`(既有 skeleton 直接促升,不另立) | bot 场景 P1-P6 扩容 + CI 假绿修复 + build token 脚本 | `scripts/bot/**`、CI | ~9 | | 基建 | `plan-registry-datafication-v1`(既有 skeleton 直接促升) | 硬编码配方/功法/方块表迁数据 + fail-fast | 三张表 | 自身 | ## 3. 波次与依赖 -- **Wave 0(立即并行)**:V(bot 骨干 + build token 最先)、R3、R5、R2、registry-datafication;同时全部轨道的 P0(设计收口 + 吸收清单验真)都可开工。 -- **Wave 1**:R6(R2 合入后)、R7(R2 合入后)、R1(R3 P1 合入后)。 -- **Wave 2**:R4(#1287 + R6 P1 后)、R9(R5/R6/R2 P1 后)、R10(R3 P1 后)。 +**本节 Wave 表是全部轨道 inter-track ordering/start/cutover claims 的唯一权威(SOLE authority)**;各轨 plan 只能引用本节已有顺序,不得自行新增跨轨前置。需新增或改变顺序时先 amendment 本节,再同步子 plan。 + +- **Wave 0(立即并行)**:V(bot 骨干 + build token 最先)、R3、R5、R2、registry-datafication;同时全部轨道的 P0(设计收口 + 吸收清单验真)都可开工;R6 的 contract-first 工作与 R9 的 cast domain contract-first 工作均可在本波次按各自 plan 开工,不等待 production activation 条件。 +- **Wave 1**:R6、R7(R2 合入后)、R1(R3 P1 合入后)按各自 plan 推进;涉及 R2-owned production 接缝的工作须等待 R2 P1。 +- **Wave 2**:R4、R9 production activation(R5、R6、R2 的所属责任按各自 plan 就绪后,服从 §4.1 的 ownership 与 atomicity invariants)、R10(R3 P1 后)。**R6 dropped-loot P3 production activation merge unit 仅在 R10 P2a `DroppedLootEntry.owner/visibility` metadata provider 与 R3 P4 dropped-loot migration/hydration consumer 均合入后放行;此前只允许 declared/unwired/test-only 的 contract 与 pin artifacts。R10 P2b `OwnerOnly` private-writer activation 必须在该 R6 P3 merge unit 合入后放行,不得把 R6 P1/P2 的 unwired artifacts 当作 production consumer。**本表只裁决跨轨顺序与 activation 边界;各轨具体 deliverable inventory、phase mapping 与验收证据由各自 plan 定义,不在总纲重述。 - 近完成独立 plan(§6.9)在 Wave 0 窗口内优先收尾清场。 - R5 P1(字段收私有的全仓编译大爆破)挑在飞 PR 队列清空的窗口单独合入。 ## 4. 文件所有权矩阵(防并行打架,冲突时以本表为准) -- `persistence/**`+autosave=R3;`session/`+7 域 session.rs=R1;`client_request_handler.rs`+`gate/`=R4;`*_emit.rs` 公共层+`proto_convert.rs`=R6;`qi_physics/**`+qi 字段直写行=R5;`inventory/**`=R10;cast/AV emit+skill 注册=R9。 -- client:Store 生命周期+`clearClientStateOnDisconnect` 区段=R2;channel 注册区段+桥+router=R6(与 R2 同文件不同区段,merge 前互 fetch);Screen/hud/keybind/InspectScreen=R7;combat cast store=R9。 -- 任何轨道碰他轨文件:只允许"消费对方冻结后的 API",不允许改对方独占文件;接缝 API 归被依赖方定义。 +- `persistence/**`+autosave=R3;`session/`+7 域 session.rs=R1;`client_request_handler.rs`+`gate/`=R4;`*_emit.rs` 公共层+schema generation/transport machinery+`proto_convert.rs`=R6;`qi_physics/**`+qi 字段直写行=R5;`inventory/**`=R10;cast domain semantics/AV emit+skill 注册=R9。 +- client:Store 生命周期+`clearClientStateOnDisconnect` 区段=R2;generated bridge+channel/`ServerDataRouter` registration plumbing=R6(与 R2 同文件不同区段,merge 前互 fetch);Screen/hud/keybind/InspectScreen=R7;cast reducer/store 与具体 domain consumers=R9。 +- 任何轨道碰他轨文件:只允许“消费对方冻结后的 API”,不允许改对方独占文件;接缝 API 归被依赖方定义。跨轨 wire 共同交付按 §4.1,不得用此通则拆开 activation merge unit。 + +### 4.1 R9 ↔ R6 schema 与 production cutover 裁决(2026-08-04) + +本节是本计划族对 cast wire 的唯一上位裁决;R6/R9 子 plan 若冲突必须先同步到本节,禁止各自声明第二套 authority 或交付顺序。 + +1. **Schema authority**:TypeBox source 是 repo-wide schema source of truth;它拥有 shape、discriminant 与 validation semantics。所有生成或受约束 mirror 均不得反向定义 TypeBox 为“被动镜像”。每个 generated/constrained artifact(含 protobuf/Rust conversion、Java bridge 与 samples)必须携可核验的 TypeBox source hash 或 version reference;CI 必须 fail-closed 检查该 pin 与当前 TypeBox source 一致,禁止 stale mirror 通过。 +2. **Domain content vs machinery**:R9 负责 author/review cast domain 的 TypeBox content、domain semantics/reducer 与 `SkillAvBinding`;R6 负责 repo-wide schema generation/transport machinery 及其生成或受约束 artifacts。R9 定义“cast 消息/状态是什么意思”,R6 定义“canonical schema 如何生成、转换和运输”;双方不得复制或重新拥有对方 artifact。具体 deliverable inventory、phase mapping 与 acceptance evidence 仅由 owner track plan 定义。R6 plan 的 P1 必须交付 declared/unwired/test-only 的 schema generation chain contract 与 CI freshness/pin gate,P3 必须在单一 production activation merge unit 内生成 mirrors 并接入 transport/router;在 P1 contract 完成前,不得排期依赖该 generation chain 的 production cutover。 +3. **Contract-first 可早合**:R9 contract-first 工作不等待 R6 production machinery;R6 的 contract-first 工作也不因 production 接缝尚未完成而停止。contract-first artifacts 必须保持 declared/unwired/test-only,不得切换 production traffic 或宣称 live reachable。 +4. **Atomic production activation**:迁移某 channel 时,其 producer、transport plumbing、全部 consumers 与旧路径移除必须在**同一 merge unit**激活。若无法做到单一 merge unit,则旧 producer/receiver 必须原样保留,直到最终原子 activation;禁止 receiver-removed-before-consumer-installed,也禁止长期 dual emit。R6 dropped-loot 必须把 paginated producer、generated mirror/conversion、`ServerDataRouter` transport registration、完整 revision page assembler 的 atomic store replace 与旧路径移除绑定为一个 P3 merge unit;该 merge unit 的跨轨放行只取 §3 Wave 表。 +5. **Contract pin-test invariant**:任何 contract-first schema 或 reducer/state-machine artifact 在首次提交时即必须携 pin tests;不得以后续 production/e2e 阶段补测。TypeBox pin 至少覆盖必填字段、每个 enum/discriminant 变体、invalid/unknown 变体与缺字段拒绝;reducer pin 至少覆盖每条合法转换、非法转换拒绝,以及 STOP/INTERRUPT 等终止路径。cast schema 与 cast reducer 是本不变量的强制命中项。 +6. **Generalized cross-track dependency rule**: + - §3 Wave 表是 inter-track ordering claim 的**唯一权威**;track plan 不得引入本表没有的 start/order dependency。 + - master 只裁决 owner、跨轨顺序与 invariants;只有在 owner plan 已定义 phase/artifact/consumer 后才可引用其名称,不得替 owner plan 首次定义交付细节或验收步骤。 + - 若所需 upstream artifact 尚不存在,consumer track 只能先落 contract-first stub(declared、unwired、test-only,不接 production);真实 artifact 的名称、phase 与验收由 owner track plan 定义,且 production dependency **不得反写成 start gate**。 + - 两份 track plan 出现 sequencing conflict 时,先 amendment §3 Wave 表并形成唯一裁决,再同步双方;禁止靠任一子 plan prose 抢占 authority。R9 contract-first start 以 Wave 0 为准,production activation 以 Wave 2 与本节 atomicity invariant 为准。 ## 5. 工作流(GPT tmux 多会话) diff --git a/docs/plans-skeleton/plan-refactor-persistence-slices-v1.md b/docs/plans-skeleton/plan-refactor-persistence-slices-v1.md index c582a0f86..e2a328f9d 100644 --- a/docs/plans-skeleton/plan-refactor-persistence-slices-v1.md +++ b/docs/plans-skeleton/plan-refactor-persistence-slices-v1.md @@ -25,7 +25,7 @@ - ⬜ P2 载入守护推广:全部玩家 slice(SkillSet/Wounds/状态 buff/身份键……)收编,#1290 模式全量落地;dropped-loot slice 的有界 hydration guard 依赖 R10 P1 已 merge 的容量契约:仅在该前置成立后引用 `MAX_DURABLE_DROPPED_LOOT_ENTRIES` 与 `DroppedLootRegistry::try_insert/try_insert_batch`;超限进入统一 load-failure guard/只读降级并告警,禁止 `take(limit)` 截断、驱逐旧条目或以空 registry 覆盖数据库。在 R10 P1 未 merge 时,R3 P2 不得编译或复制临时常量。同步冻结并实现 spill/pickup persistence transaction/outbox seam:source mutation、attrited item、zone balance/qi ledger、drop insert/delete 与幂等 transaction id 构成一个 recoverable commit,且 crash/retry pins 常绿后才允许 R10 P2a 迁移 Public writer path;R10 P2b OwnerOnly private writers 另受 R10 P3、R4、R6 与 R3 P4 consumer gates 约束。 - ⬜ P3 关服 flush + tick rebase 批次:shutdown flush registry 收编全部"节流落盘"域;绝对 tick 全部改相对基准;autosave/事件写入竞态互斥(coffin-autosave-inflight-race 模式)。 - ⬜ P4 遗漏运行态补持久化批次:ActiveEvents、TiandaoAttention、状态效果、化虚冷却、灵眼、地表遗缴、散灵珠、可放置实体、dormant 往返身份完整性(heiwushi)等——逐个按 Slice 框架补表;P4 拆为两个独立 consumer 子批次: - - **dropped-loot hydration 子批次**:在 R10 P1 merge、R3 P2 persistence seam 与旧行 compatibility pins 就绪后,调用 `inventory::migration::migrate_legacy_dropped_loot_entry`,把旧 `dropped_loot.entry_json` 缺失字段补成 `owner = None`、`visibility = Public`,再反序列化为 `DroppedLootEntry`;此子批次先于 R6 P1 projection/page,且不等待 R10 P3/R5/R6 P4/R4。 + - **dropped-loot hydration 子批次**:在 R10 P1 merge、R3 P2 persistence seam 与旧行 compatibility pins 就绪后,调用 `inventory::migration::migrate_legacy_dropped_loot_entry`,把旧 `dropped_loot.entry_json` 缺失字段补成 `owner = None`、`visibility = Public`,再反序列化为 `DroppedLootEntry`;此子批次先于 R6 P3 projection/page production activation,且不等待 R10 P3/R5/R6 P4/R4。 - **inventory-layout overflow 子批次**:仅在 R10 P3 merge 后,调用 `inventory::migration::migrate_legacy_inventory_layout`,用玩家 identity、真实机制结算点/世界 position、dimension 组装 `SpillContext`,把 `MigrationOutcome::overflow` 通过 R10 capacity API 持久化到 durable registry。 两类 consumer 仅在新 schema 与各自全部输出成功持久化后提交新行,缺上下文/容量/持久化或 JSON migration 失败则保留旧行并进入可重试 load guard;dropped-loot 子批次依赖 R10 P1,inventory-layout 子批次依赖 R10 P3,不得合并为一个跨越两者的门禁或另造容量常量。 - ⬜ P5 bot 验收 + 吸收 plan 批量归档。 @@ -56,7 +56,7 @@ skeleton:coffin-autosave-inflight-race、identity-persist-key-mismatch、miner ## § P0 决议锚点(待 R3 P0 开工时补齐) - `MAX_DURABLE_DROPPED_LOOT_ENTRIES` 的引用门:R3 P2/P4 依赖 R10 P1 merge,R3 不复制常量或在此前编译引用。 -- dropped-loot hydration consumer:R3 P4 在 R10 P1 migration helper、R3 P2 persistence seam 与旧行 compatibility pins 就绪后执行,且必须先于 R6 P1 projection/page;失败保留旧行并可重试。 +- dropped-loot hydration consumer:R3 P4 在 R10 P1 migration helper、R3 P2 persistence seam 与旧行 compatibility pins 就绪后执行,且必须先于 R6 P3 projection/page production activation;失败保留旧行并可重试。 - inventory-layout migration consumer:R3 P4 的独立 overflow 子批次在 R10 P3 merge 后,使用真实 `SpillContext` 完成 overflow 持久化;失败保留旧行并可重试。 ## 验收测试声明 diff --git a/docs/plans-skeleton/plan-refactor-wire-s2c-v1.md b/docs/plans-skeleton/plan-refactor-wire-s2c-v1.md index 02af8d5f7..cfabfc272 100644 --- a/docs/plans-skeleton/plan-refactor-wire-s2c-v1.md +++ b/docs/plans-skeleton/plan-refactor-wire-s2c-v1.md @@ -14,15 +14,15 @@ - **进料**:各域游戏事件(emit 调用点)、`world` 维度/zone 信息(作用域过滤)。 - **出料**:`bong:server_data` 单通道(目标态:28 旁路全部收编或显式豁免登记);join/重连首包快照集契约(R2 清干净后靠它灌满)。 - **共享类型**:新 server `network/emit/` builder(`scope: Global | Dimension | Zone | Player`);client 桥接层唯一的枚举前缀剥离函数。 -- **跨仓库契约**:proto 形状原则上不动(收编旁路时如需并入 envelope 属破坏性变更,走 buf breaking + samples 同步;agent 侧 TS 只做被动 regenerate,不重构 agent 逻辑)。**不做双轨兼容层**——旁路收编是一次性切换。 +- **跨仓库契约**:proto 形状原则上不动(收编旁路时如需并入 envelope 属破坏性变更,走 buf breaking + samples 同步);TypeBox canonical content 是 repo-wide schema source of truth,R6 负责据此运行 generation pipeline 并同步 protobuf/generated Rust、Rust conversion、Java bridge、router plumbing 与 dist/JSON Schema/samples,agent 侧只消费生成结果,不反向定义 schema,也不重构 agent 逻辑。每个 generated/constrained artifact 必须携可核验的 TypeBox source hash 或 version reference,CI 对当前 source 与 pin 的不一致 fail-closed。**不做双轨兼容层**——旁路收编是一次性切换。 ## 阶段 - ⬜ P0 设计收口 + 吸收清单验真:28 旁路逐个普查(收编 vs 豁免理由);100 emit 文件的重复模式取样归纳 builder API;枚举前缀剥离点全量清点;冻结 scope 语义与 join 首包快照集清单;正式登记 `rotate-footprint-sync`、`bot-inventory-pack-feedback` 的 inventory wire/feedback 工作,并冻结 `dropped_loot_sync` 分片 envelope(`snapshot_revision/page_index/page_count`、每页上限常量 `DROPPED_LOOT_SYNC_PAGE_SIZE = 256`)。 -- ⬜ P1 emit builder + scope 落地:builder 上线,vfx/audio/env 三类先挂 scope(跨维 bleed 立灭);跨位面切换时 env/season 全量重发;**仅在 R10 P2a 的 `DroppedLootEntry.owner/visibility` metadata provider 与 R3 P4 dropped-loot migration/hydration consumer 均合入后**,dropped-loot 内容变化与 join sync 才通过共享 builder 按固定页大小发送,同一 visibility key 的 snapshot 只排序/编码一次后复用于目标 clients,禁止 per-client 重建无界全量 payload;在上述两个前置完成前不得启用该 private projection path。 -- ⬜ P2 client 桥接层收敛:枚举前缀剥离收敛到单点(含 forge-session 修复);`ServerDataRouter` 注册表整备(分域注册文件,不再单个 1547 行 switch 追加);dropped-loot client store 仅在同 revision 全部分片收齐后原子替换,缺页/混 revision 保留旧视图并请求/等待重发。 -- ⬜ P3 旁路归一批次:28 channel 逐批收编入 server_data envelope 或登记豁免(资源包/握手类可豁免);删除散装 receiver。 -- ⬜ P4 契约 pin 全量化:双向 sample 对拍测试补齐(113 C2S + 144 S2C 每变体至少一条正反 sample,schema 改动连 sample 一起改);emit 迁移到 builder 的长尾批次;完成 inventory receipt contract 子批次:`InventoryEventV1::Moved`(或等价 accepted receipt)必须携带 request identity、结果 revision、权威 item view,覆盖 schema/sample/convert/emit API、Fabric `InventoryEventHandler` 与 Python decoder,供 R4 handler 消费 R10 typed outcome。分片 dropped-loot 正反样本必须覆盖空/单页/恰好 256/257/末页缺失/混 revision。 +- ⬜ P1 schema generation chain contract + emit builder/scope:以 `agent/packages/schema/src/` 的分域 TypeBox declarations 与 `schema-registry.ts` 为 canonical source layout,交付 source→committed JSON Schema/dist→protobuf/generated Rust→Rust conversion→Java bridge/`ServerDataRouter` registration 的 generation manifest、单入口 tooling 与 artifact/source-pin inventory;CI 运行 freshness、missing/unexpected artifact、source hash/version pin 与 deterministic regeneration checks,任一 drift fail-closed。上述 generation artifacts 在本阶段必须 declared/unwired/test-only,不接 production traffic。同步上线与 schema chain 无关的共享 emit builder,并先让 vfx/audio/env 三类挂 scope(跨维 bleed 立灭);跨位面切换时 env/season 全量重发。dropped-loot 只提交分页 envelope、producer/consumer API stub 和空/单页/恰好 256/257/末页缺失/混 revision 的正反 pin,不启用发送。 +- ⬜ P2 client bridge/consumer contract:枚举前缀剥离收敛到单点(含 forge-session 修复);`ServerDataRouter` 分域注册接口整备;以 declared/unwired/test-only 形式交付 dropped-loot revision page assembler/store reducer,pin 同 revision 全部分片收齐后原子替换,以及缺页/混 revision 保留旧视图并请求/等待重发;旧 receiver 与旧 producer 原样保留。 +- ⬜ P3 schema mirrors + atomic production activation:运行 P1 generation chain 产出/刷新 protobuf/generated Rust、Rust conversion、Java bridge、dist/JSON Schema/samples,并接入 `ServerDataRouter`;28 channel 按 merge unit 逐批收编入 server_data envelope或登记豁免(资源包/握手类可豁免)。**dropped-loot 是一个不可拆 merge unit**:同一 merge unit 内同时启用共享 builder 的 paginated producer、generated mirror/conversion/router transport、P2 完整 revision page assembler 的 atomic store replace,并删除对应旧 producer/receiver;在总纲 §3 Wave 表放行前保持 P1/P2 artifacts unwired 且旧路径原样可用,禁止 P1 单独启用 producer、长期 dual emit 或 child-only 前置。 +- ⬜ P4 契约 pin 全量化:双向 sample 对拍测试补齐(113 C2S + 144 S2C 每变体至少一条正反 sample,schema 改动连 sample 一起改);emit 迁移到 builder 的长尾批次;完成 inventory receipt contract 子批次:`InventoryEventV1::Moved`(或等价 accepted receipt)必须携带 request identity、结果 revision、权威 item view,覆盖 schema/sample/convert/emit API、Fabric `InventoryEventHandler` 与 Python decoder,供 R4 handler 消费 R10 typed outcome。P1/P2 contract-first artifacts 的 pin tests 不得延期至本阶段。 - ⬜ P5 bot 验收 + 吸收 plan 批量归档。 R10 dropped-loot 契约优先:编码前按 recipient dimension/range/owner 投影,仅同 visibility key 复用;rejected receipt 含 reason/instance/from/to,并测两 recipient 正反可见性。 @@ -35,9 +35,9 @@ skeleton:vfx-audio-dimension-bleed、q-world-season-dimension-env-resync、for ## 文件所有权与边界 -- 独占:server `network/*_emit.rs` 公共模式与新 `network/emit/`、`schema/proto_convert.rs`;client `network/`(ProtoServerDataBridge、ServerDataRouter、BongNetworkHandler 的 channel 注册区段)。 +- 独占:`agent/packages/schema/src/{schema-registry,generated-artifacts,generate}.ts` generation machinery、`agent/packages/schema/generated/` 与 `proto/bong/` generated/constrained mirrors、`server/build.rs`/`server/src/schema/proto_gen.rs` generation 接缝、server `network/*_emit.rs` 公共模式与新 `network/emit/`、`schema/proto_convert.rs`;client `network/`(generated ProtoServerDataBridge、ServerDataRouter、BongNetworkHandler 的 channel 注册区段)。各 domain TypeBox declaration 内容仍归对应 domain owner,R6 只消费 canonical content。 - 不碰:`BongNetworkHandler.clearClientStateOnDisconnect` 区段(R2 域,同文件分区段,merge 前互相 fetch);`client_request_handler.rs`(R4);各 emit 的业务语义。 -- 依赖:无通用硬前置;R2 先合(同文件低冲突区段);R4 P2 建议在本轨 P1 后开。**P1 的 dropped-loot projection/page 子项例外:硬依赖 R10 P2a owner/visibility metadata provider 与 R3 P4 dropped-loot migration/hydration consumer,不能随其他 scope 子项提前实施。** +- 依赖:跨轨 start/order/cutover 以总纲 §3 Wave 表为唯一 authority;contract-first 工作可在 Wave 0 开始,涉及其他 track 所属 production 接缝时只引用总纲 Wave 放行,不在本 plan 重述或新增前置。dropped-loot 在放行前仅保留 P1/P2 contract/test-only artifacts 与完整旧路径;放行后由 P3 单一 merge unit 原子切换,不阻塞其他 scope 子项。 ## bot 验收场景