# IMPRINT First Contact Refined Build

## 第一性原则

首局优化只解决三个问题：

1. 玩家知道自己被允许怎样行动，但不知道哪条路线“正确”。
2. 第一次有效输入后，玩家能确认自己的话改变了某些东西，但系统不替变化定性。
3. 网络、刷新、重复操作或窄屏布局不能让玩家怀疑自己的选择是否被记录。

以下内容被视为不可稀释的核心：自由对话、基质的不可逆生长、隐藏的 MI、审查压力、
7706 回声、七日结构、八个结局、跨周目残留与印记卡。正典、规则与结局代码均未修改。

## 优化内容

- 首轮显示一次性的行动许可说明，不展示隐藏数值或推荐路线。
- 提供三个不同语气的可选起手句；它们只负责降低空白输入框压力，不会自动发送。
- 第一次有效回合后提示“基质结构已发生变化”，不评价变化的好坏。
- 增加可随时关闭的操作说明，明确最低回合数、监测并非好感度。
- 模型请求期间同时锁定输入与发送按钮，并显示“接收中…”。
- 请求失败时保留原输入，撤回未计入的玩家消息，避免重试后重复入档。
- 限制输入为 600 字，并在客户端与服务端保持一致。
- 修复移动端侧栏返回、首次自动聚焦导致页面上移、基质 resize 报错。
- 侧栏和移动导航改为真实按钮，补充对话日志与弹窗的可访问语义。
- 跨日与最终报告请求失败后可恢复，不会永久卡在忙碌状态。

## 对抗性审核

| 场景 | 预期 | 结果 |
|---|---|---|
| 390×844 全新首局 | 页面不跳动，输入、提示和导航都可见 | 通过 |
| 1280×720 桌面首局 | Ada、对话、监测三栏完整 | 通过 |
| 空输入点击发送 | 不写入记录，不消耗回合 | 通过 |
| 连续提交 | 请求开始后立即锁定输入与按钮 | 通过 |
| 输入超过 600 字 | 客户端截断至与服务端相同长度 | 通过 |
| 模型等待 | 有明确但不破坏沉浸的状态反馈 | 通过 |
| 服务突然停止 | 按钮恢复、输入保留、回合不计入 | 通过 |
| 失败后重试 | 失败的玩家消息不残留，不会重复入档 | 通过 |
| 首轮后查看基质 | 导航出现未读信号，查看后清除 | 通过 |
| 移动端对话→监测→基质→档案→对话 | 始终可以返回对话 | 通过 |
| 刷新续玩 | 从服务器存档恢复历史、监测与基质 | 通过 |
| 窗口 resize | 未进入游戏时不访问空画布 | 通过 |
| 启动页与首轮控制台 | 无 error / warning | 通过 |

## 审核中发现并二次修正

1. 移动端自动聚焦会让虚拟键盘推走 Ada 画面：改为只在桌面自动聚焦。
2. 自动化粘贴可绕过 HTML `maxlength`：增加输入事件与发送前双重截断。
3. 断服后重试会留下两条相同玩家消息：未计入的消息现在会从记录中撤回。
4. 隐藏提示仍可能进入辅助技术阅读树：改为未触发前 `display:none` 与
   `aria-hidden` 双重隐藏。

## 运行

```bash
cd imprint_refined
./run.sh
```

默认地址：`http://localhost:8791`
