Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .spec/knowledge/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ metadata:
|------|--------|
| [`features/_TEMPLATE.md`](features/_TEMPLATE.md) | 新功能文档模板——新增功能记录时照此建,放对 领域 / 模块 |
| [`features/gameplay/chat-component.md`](features/gameplay/chat-component.md) | ChatComponent 字段声明与 SetMessage——查 persist-only last-message、下一 Tick 提交与有界输入 reject |
| [`features/gameplay/entity-chat-harness.md`](features/gameplay/entity-chat-harness.md) | 101-entity C# MVP acceptance harness——查 mvp-host 101 活连接、BLOCKED 证据与 Bot 启动 |
| [`features/gameplay/entity-chat-harness.md`](features/gameplay/entity-chat-harness.md) | 101-entity C# MVP acceptance harness——查 mvp-host/rust 11 场景活 traces、nent census 与 Bot 启动 |

## lessons(经验教训 · 复发问题暂存区)

Expand Down
2 changes: 1 addition & 1 deletion .spec/knowledge/features/gameplay/chat-component.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ metadata:
## 待解决

- 接入 GameRuntime `EcsWorld` / Ingress 13 相(本切片用 Room 内权威宿主,不阻塞平行开发)。
- 101-entity SUCCESS 路径是 sibling `lumio-mvp-host` Handshake/Admit;`GameRoomHost` 只作单元 double。ChatComponent/C-2 未接入 mvp-host 时对应场景记 sibling-gap,见 [`entity-chat-harness.md`](./entity-chat-harness.md)。
- 101-entity SUCCESS 路径是 sibling `lumio-mvp-host`(或 rust `lumio-entity-chat-replay`)上 11 场景全部 `ok: true`;`GameRoomHost` 只作单元 double。见 [`entity-chat-harness.md`](./entity-chat-harness.md)。

## 相关

Expand Down
15 changes: 7 additions & 8 deletions .spec/knowledge/features/gameplay/entity-chat-harness.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
name: entity-chat-harness
description: 101-entity C# MVP acceptance harness——查 mvp-host 101 活连接、BLOCKED 证据与 Bot 启动
description: 101-entity C# MVP acceptance harness——查 mvp-host/rust 11 场景活 traces、nent census 与 Bot 启动
metadata:
type: doc
status: 已交付
Expand All @@ -17,18 +17,17 @@ metadata:

## 设计

- **Gameplay 宿主**:sibling `lumio-mvp-host`(LumioServer origin/main)。`GameRoomHost` 只作单元测试 double,不是 SUCCESS 路径。单元 double 只接受 C-3 已验证准入载荷,从不收用户名/口令;其 Chat 上行必须是冻结 `InputCommand`(`mappingId=chat.input` + LumioBinV1 `payload` + `payloadSha256`),解码后再交给 text-only `ChatInput`。
- **Bot 启动器**:`Lumio.Game.EntityChat.Suite` 可对 Account Server 发 `123456` 测试口令与工具凭证;启动器主路径先对 mvp-host 做 101 路活升级。
- **证据**:census 必须来自 mvp-host 进程 audit;Browser 必须有 Playwright 实跑;无历史快照必须有可含历史的材料。
- **Gameplay 宿主**:sibling `lumio-mvp-host` 或 `lumio-entity-chat-replay`(同一 11 场景套件)。`GameRoomHost` 只作单元测试 double,不是 SUCCESS 路径。单元 double 只接受 C-3 已验证准入载荷,从不收用户名/口令;其 Chat 上行必须是冻结 `InputCommand`(`mappingId=chat.input` + LumioBinV1 `payload` + `payloadSha256`),解码后再交给 text-only `ChatInput`。
- **Bot 启动器**:`Lumio.Game.EntityChat.Suite` 可对 Account Server 发 `123456` 测试口令与工具凭证;启动器主路径先对 mvp-host 做 101 路活升级,再经 loopback `test-control` 跑 S4–S11
- **证据**:census 必须来自 bindings + 17-key host-audit 的 `netEntityId`(`nent_*`);Browser 必须有 Playwright 实跑且 `injected:false`;无历史快照必须有可含历史的材料。
- **BLOCKED**:容量 503 / Admission 未入 FullGraph / origin/main dll 缺失时写 `blocked.json`(`FullGraphComposition.cs` MaxConnections/MaxSessions + 实测错误),退出码 1,不回退 r-00344,不伪造 SUCCESS。
- **census**:必须来自 Handshake/Admit 绑定(host-audit 非空 `sessionId` / admit·bind effect,或 admit-trace binding ids)。HTTP 101 的 launcher 循环下标 `"1"`..`"101"` 不是 NetEntityId。不得要求发明 `entity_admitted`,也不得接受无列表的 `{total:101}`。
- **S8 reconnect**:重连重绑 Entity A 当且仅当两侧都有宿主 `NetEntityId`(`nent_*` / `nent-*`)且相等。`sessionId` 相等不是 rebind;Account-Server login `accountId` 单独也不是(那是 S9 Entity B)。不得把 `sessionId` 写成 `netEntityId`,也不得把 login `accountId` 塞进 host binding。FullSnapshot / 17-key audit / test-control 若不投影 `ConnectionBinding.NetEntityId`,S8 必须 `ok: false` + `blockedReason`(诚实缺口,不得伪成功)。Handshake 缺 session / SessionMismatch 时重试一次。
- **ChatComponent / C-2 缺口**:Attribute Query、Chat persist、expiry、isolation、event-order 在 mvp-host `ReferenceWorldSimulation` 上不可执行时,S5/S7/S9/S10/S11 必须 `ok: false` + `blockedReason`(与 S6 Timer 相同诚实口径);不得把 `GameRoomHost` 自评分写成 SUCCESS
- **census**:必须来自 `GET /test-control/bindings` 与 17-key audit 的 `nent_*`,不是 `hs.sessionId`、不是 login `accountId`、不是 launcher 循环下标 `"1"`..`"101"`。不得要求发明 `entity_admitted`,也不得接受无列表的 `{total:101}`。
- **S8 reconnect**:重连重绑 Entity A 当且仅当两侧都有宿主 `NetEntityId`(`nent_*` / `nent-*`)且相等。`sessionId` 相等不是 rebind;Account-Server login `accountId` 单独也不是(那是 S9 Entity B)。不得把 `sessionId` 写成 `netEntityId`,也不得把 login `accountId` 塞进 host binding。诚实 `ok: false` 不得标 SUCCESS。Handshake 缺 session / SessionMismatch 时重试一次。
- **S5–S11**:必须在 mvp-host test-control(bindings/query/chat/tick/expire/snapshot/restore/room-admit)或 rust replay 上留下独立 traces,且 1–11 全部 `ok: true`。sibling-gap / S8 nent-gap 的 `ok: false` 使证据包 FAIL。S5 `ok: true` 且带 unauthorized/invisible/stale 真查询 traces 不是 GameRoomHost suite-double。S6 `timerManagerInvoked` 仅当 tick 走宿主 timer / `POST /test-control/tick`,禁止 for-loop

## 待解决

- FullGraph `MaxConnections = 128` / `MaxSessions = 128` 可承载 101 路活连接(Server origin/main / `LUMIO_SERVER_ROOT`)。
- Client Timer Manager 未接到本启动器时,chat 只能记 tick-batched,不得把 cadence 标 ok。
- Playwright Chromium 缺失时 Browser 场景必须失败,不得注入事件后标 ok。

## 相关
Expand Down
2 changes: 1 addition & 1 deletion .spec/knowledge/standards/testing.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ node --test integration/entity-chat/verify-evidence.mjs
node integration/entity-chat/launcher.mjs --out <evidenceDir>
```

两轮对比实体数 / event order / applied Tick。SUCCESS 仅当 sibling `lumio-mvp-host` 实际准入 101 路活连接(HTTP 101 之后完成 `lumio.mvp.v0` Handshake,host-audit 有非空 sessionId / admit effect)且两轮场景证据一致。容量 503、Admission 未入 FullGraph、origin/main Account Server / mvp-host 产物缺失必须记 BLOCKED(`blocked.json` + 文件:行 + 实测错误),不得回退 r-00344,不得用 `GameRoomHost` 伪造 SUCCESS。ChatComponent/C-2 缺口场景必须 `ok: false` + `blockedReason`。FullGraph 生产常量是 `MaxConnections = 128` / `MaxSessions = 128`。
两轮对比实体数 / event order / applied Tick。SUCCESS 仅当 sibling `lumio-mvp-host` 或 `lumio-entity-chat-replay` 实际准入 101 路活连接、census 来自 bindings + 17-key audit 的 `nent_*`,且场景 1–11 全部 `ok: true`、两轮 traces 一致。诚实 `ok: false`(含 sibling-gap / S8 nent-gap)使证据包 FAIL。容量 503、Admission 未入 FullGraph、origin/main Account Server / mvp-host 产物缺失必须记 BLOCKED(`blocked.json` + 文件:行 + 实测错误),不得回退 r-00344,不得用 `GameRoomHost` 伪造 SUCCESS。FullGraph 生产常量是 `MaxConnections = 128` / `MaxSessions = 128`。

公共契约变更必须在架构源 `LumioGameEngineArchitecture` 通过其契约闸门(见 `AGENTS.md`「收口门槛」);本仓只消费冻结 JSON,不另写协议。Scenario/Headless 与 formatter 命令随后续模块补进收口门槛。

Expand Down
24 changes: 24 additions & 0 deletions .wf-report-live11.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# R-00354 live-11 game — implementer report

Status: GREEN. SHA `56d5afd`. Branch `feat/r-00354-live-11`. Sibling host `LUMIO_SERVER_ROOT=C:\Work\LumioGames\wt-server\r-00354-live11` SHA `ffb22c9`.

## TDD

RED: 8 new verifier tests failed; `wt-game/r-00354` live-run-s8gap pack was SUCCESS (`ok: true`) while S5–S11/S8 were not-ok.

GREEN: `node --test integration/entity-chat/verify-evidence.mjs integration/entity-chat/bot-credential.mjs` → 49 pass. `node .spec/tools/spec-lint.mjs` OK.

## Live

```
node integration/entity-chat/launcher.mjs --out integration/entity-chat/evidence/live-run-11
```

Exit 0. Both rounds S1–S11 `ok: true`. Census 100+1 `nent_*`. Playwright `injected: false`. Tick via `POST /test-control/tick`.

Evidence (gitignored): `integration/entity-chat/evidence/live-run-11/{manifest.json,round-1,round-2}/`.

## Gaps

- Chat is posted on each admit (keepalive); idle sockets later `binding_not_found`.
- Did not edit Server. GameRoomHost remains unit double only.
6 changes: 4 additions & 2 deletions integration/entity-chat/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,10 @@ node launcher.mjs --out <evidenceDir>

## 对账

- 101 = Handshake/Admit 绑定 ids(host-audit 非空 sessionId / admit effect,或 admit-trace `binding_committed`);禁止 launcher 循环下标 `"1"`..`"101"` 当 NetEntityId,禁止 `{total:101}` 常数,禁止 GameRoomHost census dump。禁止发明 FullGraph 不会发的 `entity_admitted`。
- S5/S7/S9/S10/S11 在 mvp-host 无 ChatComponent/C-2 时必须 `ok: false` + `blockedReason`;不得把 GameRoomHost 自评分写入 SUCCESS traces。
- 101 = bindings + 17-key audit 的 `nent_*`;禁止 sessionId / login accountId / launcher 循环下标 `"1"`..`"101"` 当 NetEntityId,禁止 `{total:101}` 常数,禁止 GameRoomHost census dump。禁止发明 FullGraph 不会发的 `entity_admitted`。
- SUCCESS 要求场景 1–11 `ok: true` 且有独立 traces(mvp-host test-control 或 rust replay)。sibling-gap / S8 nent-gap 的诚实 `ok: false` 使证据包 FAIL。
- census / S4 / S8 用 bindings + 17-key audit 的 `nent_*`,不是 `hs.sessionId` 或 login `accountId`。
- S6 `timerManagerInvoked` 仅当 tick 走 `POST /test-control/tick` / 宿主 timer。S3 Playwright 必跑且 `injected:false`。
- 两轮对比 entity counts、event order、applied Tick。
- 失败矩阵:unauthorized / invisible / stale_generation / tombstoned,不得 alias。
- Snapshot 只保留 last-message,不恢复聊天历史。
7 changes: 7 additions & 0 deletions integration/entity-chat/game-client.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -284,6 +284,13 @@ export async function recvWsJson(socket, timeoutMs = 10000) {
}
}

export function sendWsPing(socket) {
if (!socket) return
try {
socket.write(encodeWsControlFrame(0x9))
} catch { /* ignore */ }
}

export async function sendWsJson(socket, payload) {
const bytes = Buffer.isBuffer(payload) ? payload : Buffer.from(JSON.stringify(payload), 'utf8')
await new Promise((resolve, reject) => {
Expand Down
Loading
Loading