chore(spec): 综合清理 + legacy-layer 迁移 spec/plan/data

主要改动:
- 切到 funplay-cocos-mcp v0.5.1 (用户级配置, 项目级 .mcp.json 删除)
- 仓库文档/CLAUDE.md/.gitignore 等清理过时 cocos-mcp-server 引用
- memory 文件同步: cocos-mcp-setup/path/blocker/spriteframe-uuid/prefab-persist 等加 funplay 实测警告
- memory 新建 funplay-cocos-mcp-pending-verification.md (后已被实测覆盖)
- spec/plan/data:
  - docs/superpowers/specs/2026-09-02-legacy-layer-migration-design.md
  - docs/superpowers/plans/2026-09-02-legacy-layer-migration.md
  - docs/superpowers/data/layer-spirit-summary.json
- YouleNexus: profiles.ts / defaults.ts / PlayerInfoView.prefab / scene 改动

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-09-02 07:36:54 +08:00
co-authored by Claude Opus 5
parent fea85c6644
commit 02dc5d51ca
100 changed files with 3480 additions and 6961 deletions
@@ -29,7 +29,7 @@ function makePlayer() {
test('self_join_room: 已在房应被覆盖(再次入房罕见但支持)', () => {
const room = makeRoom();
// 假设自己是 seat=2 加入
roomHandlers.self_join_room({ room }, { seat: 2, playerid: 200 } as any);
roomHandlers.self_join_room({ room, player: makePlayer() }, { seat: 2, playerid: 200 } as any);
assert.equal(room.state.value.seat, 2);
});
@@ -39,7 +39,7 @@ test('other_join_room: 第三方加入,players 数组对应座位填入', () =>
roomcode: 'R1', seat: 1, isowner: 0,
players: [null, { playerid: 100 } as any, null, null],
} as RoomRecoveryData);
roomHandlers.other_join_room({ room }, { seat: 3, playerid: 300, nickname: '丙' } as any);
roomHandlers.other_join_room({ room, player: makePlayer() }, { seat: 3, playerid: 300, nickname: '丙' } as any);
const v = room.state.value;
assert.equal(v.players[2]?.playerid, 300, 'seat=3 应填到 players[2]');
assert.equal(v.players[2]?.nickname, '丙');
@@ -55,33 +55,33 @@ test('self_exit_room: 自己座位清空', () => {
test('other_exit_room: 第三方座位清空', () => {
const room = makeRoom();
roomHandlers.other_exit_room({ room }, { seat: 2 } as any);
roomHandlers.other_exit_room({ room, player: makePlayer() }, { seat: 2 } as any);
assert.equal(room.state.value.players[1], null);
});
test('other_exit_room: 未知座位 → 显式抛错(第二准则)', () => {
const room = makeRoom();
assert.throws(
() => roomHandlers.other_exit_room({ room }, { seat: 99 } as any),
() => roomHandlers.other_exit_room({ room, player: makePlayer() }, { seat: 99 } as any),
/seat=99/,
);
});
test('self_apply_free_room: state 进入解散投票中', () => {
const room = makeRoom();
roomHandlers.self_apply_free_room({ room }, { applyer: 1 } as any);
roomHandlers.self_apply_free_room({ room, player: makePlayer() }, { applyer: 1 } as any);
assert.equal(room.state.value.state, 1);
});
test('other_apply_free_room: state 进入解散投票中', () => {
const room = makeRoom();
roomHandlers.other_apply_free_room({ room }, { applyer: 2 } as any);
roomHandlers.other_apply_free_room({ room, player: makePlayer() }, { applyer: 2 } as any);
assert.equal(room.state.value.state, 1);
});
test('self/other_agree_free_room: 不改变 state,仅标记同意', () => {
const room = makeRoom();
roomHandlers.self_apply_free_room({ room }, {} as any);
roomHandlers.self_apply_free_room({ room, player: makePlayer() }, {} as any);
roomHandlers.self_agree_free_room({ room, player: makePlayer() }, {} as any);
// 协议无 agreeList 字段(state 保持 1=投票中),由其他机制累计
assert.equal(room.state.value.state, 1);
@@ -89,7 +89,7 @@ test('self/other_agree_free_room: 不改变 state,仅标记同意', () => {
test('self/other_refuse_free_room: 不改变 state', () => {
const room = makeRoom();
roomHandlers.self_apply_free_room({ room }, {} as any);
roomHandlers.self_apply_free_room({ room, player: makePlayer() }, {} as any);
roomHandlers.self_refuse_free_room({ room, player: makePlayer() }, {} as any);
assert.equal(room.state.value.state, 1);
});
@@ -97,14 +97,14 @@ test('self/other_refuse_free_room: 不改变 state', () => {
test('other_offline: 触发但不破坏 RoomStore(offline 状态由子游戏持有)', () => {
const room = makeRoom();
// RoomStore 不持有 offline 字段(handler 应是 no-op 或仅校验入参)
roomHandlers.other_offline({ room }, { seat: 1 } as any);
roomHandlers.other_offline({ room, player: makePlayer() }, { seat: 1 } as any);
// state 不变
assert.equal(room.state.value.state, 0);
});
test('other_online: 触发但不破坏 RoomStore', () => {
const room = makeRoom();
roomHandlers.other_online({ room }, { seat: 1 } as any);
roomHandlers.other_online({ room, player: makePlayer() }, { seat: 1 } as any);
assert.equal(room.state.value.state, 0);
});
@@ -113,7 +113,7 @@ test('change_seat: 交换两个座位(seat=1 ↔ seat=3)', () => {
// 初始: players = [null, 100, 200, null]
// change_seat(from=1, to=3) → i_from=0, i_to=2
// swap: [null, 100, 200, null] ↔ [200, 100, null, null]
roomHandlers.change_seat({ room }, { from: 1, to: 3 } as any);
roomHandlers.change_seat({ room, player: makePlayer() }, { from: 1, to: 3 } as any);
const v = room.state.value;
// swap 结果:players[0]=200, players[1]=100, players[2]=null, players[3]=null
assert.equal(v.players[0]?.playerid, 200, '原 seat=3 的 200 现在在 seat=1(0基=0)');
@@ -123,8 +123,8 @@ test('change_seat: 交换两个座位(seat=1 ↔ seat=3)', () => {
test('free_room: 解散投票结束 → state=2(已解散,业务侧清场)', () => {
const room = makeRoom();
roomHandlers.self_apply_free_room({ room }, {} as any);
roomHandlers.free_room({ room }, { result: 1 } as any);
roomHandlers.self_apply_free_room({ room, player: makePlayer() }, {} as any);
roomHandlers.free_room({ room, player: makePlayer() }, { result: 1 } as any);
// state 字段语义: 0=正常 1=投票中 2=已解散
assert.equal(room.state.value.state, 2);
});