|
1 | 1 | # Neural Engine |
2 | 2 |
|
3 | | -> 中文文字游戏引擎 v0 baseline |
| 3 | +> 中文文字游戏引擎 · v0 baseline 已完工 |
4 | 4 |
|
5 | 5 | ## 状态 |
6 | 6 |
|
7 | | -**v0-issue-1 骨架已就位,引擎未实现。** |
| 7 | +| 维度 | 状态 | 证据 | |
| 8 | +|---|---|---| |
| 9 | +| v0 基础版引擎 | ✅ **已闭环** | v0-issue-1 ~ 19 全部落地(19 feat commit) | |
| 10 | +| pytest | ✅ **182/182 PASSED** | `python3 -m pytest tests/ -q` | |
| 11 | +| §8 MVP 表 | ✅ **18/18** | `tests/test_mvp_table.py` | |
| 12 | +| §11 关键不变量 | ✅ **10/10** | `tests/test_invariants.py` | |
| 13 | +| 端到端跑通路径 | ✅ **in → echo → end** | `tests/integration/test_echo_path.py` | |
| 14 | +| GitHub Issues | ✅ **22/22 closed** | 含 19 AFK + 2 HITL + 1 父 issue | |
| 15 | +| 实现偏差登记 | 4 条(owner 已接受) | [ADR-0002 §5](docs/adr/0002-v0-engine-implementation.md) | |
8 | 16 |
|
9 | | -## 安装 |
| 17 | +> v0 阶段边界:引擎解析 + 核心调度 + CLI 占位 GUI 跑通;真跨进程 PyQt6 窗口(v0-issue-18 路径 A)**推迟到 v1**。 |
| 18 | +
|
| 19 | +## 这是什么 |
| 20 | + |
| 21 | +一个面向中文创作者的文字游戏引擎。剧情写作者用 Markdown + 内嵌的 ` ```neon ` DSL 描述剧情节点,引擎进程解析并执行节点、广播事件给 GUI 进程,GUI 渲染文本 / 接收玩家输入。 |
| 22 | + |
| 23 | +**v0 设计核心**: |
| 24 | +- 剧情格式 = Markdown + `neon` 代码块 |
| 25 | +- 节点 = `node start` ~ `node end` 的连续语句 |
| 26 | +- 控制流 = 隐藏变量 `NEXT` 引用 `next` 声明表项 |
| 27 | +- 跨块路由 = `id:endX:chapterYY` 块执行到 `node end` 时广播 `RouteEvt` |
| 28 | +- 进程模型 = Engine(core 进程) + GUI(runtime 进程)双向 `multiprocessing.Queue` |
| 29 | +- 修饰器 = `@style key:val, ...` 块内作用域、last-wins |
| 30 | + |
| 31 | +## 快速跑通 |
| 32 | + |
| 33 | +### 安装 |
10 | 34 |
|
11 | 35 | ```bash |
12 | | -# 开发依赖(pytest 等) |
13 | 36 | python3 -m pip install -r requirements-dev.txt |
| 37 | +# 可选(v1 用):python3 -m pip install -r requirements-gui.txt |
| 38 | +``` |
| 39 | + |
| 40 | +### 跑测 |
| 41 | + |
| 42 | +```bash |
| 43 | +python3 -m pytest tests/ -q |
| 44 | +# 期望:182 passed in ~9s |
| 45 | +``` |
14 | 46 |
|
15 | | -# 可选:PyQt6 GUI(v0 占位) |
16 | | -python3 -m pip install -r requirements-gui.txt |
| 47 | +### 跑引擎(v0 CLI 占位 GUI) |
| 48 | + |
| 49 | +```bash |
| 50 | +# v0 入口:解析 + 调度 + CLI 占位渲染(不用 PyQt6) |
| 51 | +python3 -m core.engine.main chapters/chapter01.md |
17 | 52 | ``` |
18 | 53 |
|
19 | | -## 跑测 |
| 54 | +GUI 进程是 `python3 -m runtime.gui.main`,由 `core.engine.main` 自动 spawn 启动;GUI 不可用时降级为 headless 模式(事件走 `EngineBus` 但无人渲染),日志里会写 `GUI not available, running headless`。 |
| 55 | + |
| 56 | +### 跑 v0 唯一端到端路径 |
20 | 57 |
|
21 | 58 | ```bash |
22 | | -python3 -m pytest tests/ |
| 59 | +python3 -m pytest tests/integration/test_echo_path.py -v |
| 60 | +# 走 fixture tests/test_echo.md:in → echo → end |
| 61 | +``` |
| 62 | + |
| 63 | +## 架构 |
| 64 | + |
| 65 | +### 双进程 |
| 66 | + |
| 67 | +```text |
| 68 | +┌────────────────────┐ EngineBus ┌────────────────────┐ |
| 69 | +│ core/engine/main │ ◀──JSON dict──▶ │ runtime/gui/main │ |
| 70 | +│ - interpreter.py │ cmd_q / evt_q │ (v0: CLI 占位) │ |
| 71 | +│ - executor.py │ multiprocessing │ (v1: PyQt6 路径 A)│ |
| 72 | +│ - bus.py │ .Queue │ │ |
| 73 | +└────────────────────┘ └────────────────────┘ |
| 74 | + │ │ |
| 75 | + ▼ ▼ |
| 76 | + chapters/*.md 章节 文本 / 输入框 / 富文本渲染 |
23 | 77 | ``` |
24 | 78 |
|
| 79 | +- 消息 schema:[`src/core/engine/protocol.py`](src/core/engine/protocol.py) — 3 条 `Cmd` + 6 条 `Evt`,全部 `@dataclass` + `to_dict` / `from_dict` JSON |
| 80 | +- 传输层:[`src/core/engine/bus.py`](src/core/engine/bus.py) — `EngineBus` 封装 `multiprocessing.Queue`(真进程)/ `queue.Queue`(测试注入) |
| 81 | + |
| 82 | +### 核心模块 |
| 83 | + |
| 84 | +| 模块 | 行数(实) | 职责 | 入口符号 | |
| 85 | +|---|---|---|---| |
| 86 | +| `src/core/engine/ast_nodes.py` | AST dataclass | 17 AST 节点 + 3 sentinels + `ParserError` | `Story`, `Block`, `Text`, `In`, `Echo`, `NextId`, `If`, `Branch`, `NextDecl`, `CallExpression` | |
| 87 | +| `src/core/engine/protocol.py` | 进程协议 | 3 Cmd + 6 Evt 消息 dataclass | `LoadChapterCmd`, `UserInputCmd`, `TextEvt`, `PromptInputEvt`, `RouteEvt`, `ChapterEndEvt`... | |
| 88 | +| `src/core/engine/bus.py` | 数据总线 | 双向 Queue + JSON 序列化 | `EngineBus` | |
| 89 | +| `src/core/engine/interpreter.py` | 解析器 | 6 段流水线:fence → skeleton → meta → next → body → if | `extract_neon_blocks`, `parse_block_skeleton`, `parse_block_meta`, `parse_next_decls`, `parse_block_body`, `parse_if_stmt`, `parse_decorator` | |
| 90 | +| `src/core/engine/executor.py` | 调度器 | 节点循环 + 修饰器 + 分支桩 + 跨块 ID 校验 | `Executor`, `GameState`, `EventSink`, `MemoryEventSink`, `MemoryInputSink` | |
| 91 | +| `src/core/engine/main.py` | 进程入口 | 装配 + 加载 + GUI spawn + 降级 | `main()` | |
| 92 | +| `src/runtime/gui/main.py` | GUI 入口 | v0 CLI 占位(v1 切 PyQt6) | `main()` | |
| 93 | + |
| 94 | +> 行数 / 符号数来源:[`codegraph files`](.codegraph/) 索引(37 文件 / 470 nodes / 1566 edges)。 |
| 95 | +
|
25 | 96 | ## 项目结构 |
26 | 97 |
|
27 | 98 | ``` |
28 | | -src/ |
29 | | -├── core/ # 核心引擎(v0-issue-2 起实现) |
30 | | -│ ├── engine/ # 引擎进程(main / bus / protocol / interpreter / executor) |
31 | | -│ └── decorators/ # 修饰器实现(@style 等) |
32 | | -├── runtime/ # 运行时(v0-issue-18 起实现) |
33 | | -│ └── gui/ # PyQt6 GUI 占位 |
34 | | -└── editor/ # 剧情编辑器(v0 不实现) |
| 99 | +. |
| 100 | +├── src/ |
| 101 | +│ ├── core/ |
| 102 | +│ │ ├── decorators/ # 修饰器实现(@style 等,v0 解析 + 占位调度) |
| 103 | +│ │ └── engine/ # 核心引擎 7 文件 |
| 104 | +│ │ ├── ast_nodes.py # AST dataclass |
| 105 | +│ │ ├── bus.py # EngineBus |
| 106 | +│ │ ├── executor.py # Executor + GameState + Sinks |
| 107 | +│ │ ├── interpreter.py # 6 段解析流水线 |
| 108 | +│ │ ├── main.py # core 进程入口 |
| 109 | +│ │ └── protocol.py # Cmd / Evt schema |
| 110 | +│ ├── editor/ # 剧情编辑器(v0 不实现) |
| 111 | +│ └── runtime/ |
| 112 | +│ └── gui/ # GUI 进程(v0 CLI 占位 / v1 PyQt6) |
| 113 | +├── tests/ |
| 114 | +│ ├── core/ # 单元测试(16 文件) |
| 115 | +│ ├── integration/ # 端到端测试(2 文件) |
| 116 | +│ ├── runtime/ # GUI 协议测试(1 文件) |
| 117 | +│ ├── test_invariants.py # §11 10 条不变量守护(11 用例) |
| 118 | +│ ├── test_mvp_table.py # §8 18 条 MVP 表逐条勾(19 用例) |
| 119 | +│ └── test_skeleton_smoke.py # 包导入冒烟 |
| 120 | +├── chapters/ |
| 121 | +│ └── chapter01.md # v0 官方 fixture(ADR-0001 附录 A) |
| 122 | +├── docs/ |
| 123 | +│ ├── adr/ # 架构决策记录 |
| 124 | +│ │ ├── 0001-v0-baseline-script-spec.md # v0 规范 |
| 125 | +│ │ └── 0002-v0-engine-implementation.md # v0 完工 + 4 条偏差登记 |
| 126 | +│ ├── prds/ |
| 127 | +│ │ └── 0001-v0-engine-implementation.md # v0 PRD(22 user stories) |
| 128 | +│ ├── audit/ |
| 129 | +│ │ └── v0-invariant-audit.md # §11 + §8 验收报告 |
| 130 | +│ └── agents/ # Agent 协作说明 |
| 131 | +├── 工作Wiki/ # 项目 wiki(Obsidian vault) |
| 132 | +│ ├── 00-index/ |
| 133 | +│ ├── 10-design/ |
| 134 | +│ ├── 20-architecture/ |
| 135 | +│ ├── 30-protocol/ # 含 implementation-deviations.md |
| 136 | +│ └── 90-meta/ |
| 137 | +├── pyproject.toml |
| 138 | +├── pytest.ini |
| 139 | +├── requirements.txt |
| 140 | +├── requirements-dev.txt |
| 141 | +├── requirements-gui.txt |
| 142 | +└── README.md |
| 143 | +``` |
| 144 | + |
| 145 | +## 文档与设计 |
| 146 | + |
| 147 | +| 主题 | 路径 | |
| 148 | +|---|---| |
| 149 | +| v0 脚本规范 | [docs/adr/0001-v0-baseline-script-spec.md](docs/adr/0001-v0-baseline-script-spec.md) | |
| 150 | +| v0 完工记录 + 4 条实现偏差 | [docs/adr/0002-v0-engine-implementation.md](docs/adr/0002-v0-engine-implementation.md) | |
| 151 | +| v0 PRD(22 user stories) | [docs/prds/0001-v0-engine-implementation.md](docs/prds/0001-v0-engine-implementation.md) | |
| 152 | +| §11 不变量审计 | [docs/audit/v0-invariant-audit.md](docs/audit/v0-invariant-audit.md) | |
| 153 | +| 实现偏差详细分析 | [工作Wiki/30-protocol/implementation-deviations.md](工作Wiki/30-protocol/implementation-deviations.md) | |
| 154 | +| Agent 协作约定 | [CLAUDE.md](CLAUDE.md) | |
| 155 | +| 多上下文域文档 | [CONTEXT-MAP.md](CONTEXT-MAP.md) | |
| 156 | + |
| 157 | +### v0 实现偏差摘要(4 条,owner 已接受) |
| 158 | + |
| 159 | +完整登记见 ADR-0002 §5。 |
| 160 | + |
| 161 | +1. **D1-confirmed** · `decorator_state` 在 `run_block` **入口**清(不是 `End` 时清)—— owner 接受,理由是更稳妥 |
| 162 | +2. **D-NEW-1** · 分支项用 `CallExpression(kind, var)` 包装 echo/in —— owner 接受,理由是和块内 `In`/`Echo` 节点语义解耦 |
| 163 | +3. **D-NEW-2** · `ParserError.loc` 变可选 —— owner 接受 |
| 164 | +4. **D-main** · `core.engine.main` 在 GUI 不可用时降级为 headless 日志 —— owner 接受 |
| 165 | + |
| 166 | +### v0 已知未实现(推到 v1+) |
| 167 | + |
| 168 | +- **PyQt6 GUI 窗口**(v0-issue-18 路径 A) |
| 169 | +- **CodeGraph 4 个 internal helper 单测**(`EngineBus._drain/_close_queue`、`Executor._emit_decorator/_validate_target_ids`、`main._try_spawn_gui`)—— 当前 152 测试已间接覆盖,缺边界单测 |
| 170 | +- **GUI 跨进程联调**(v0 阶段 CLI 占位即满足 AC) |
| 171 | +- **v0-issue-22** 待 owner 开启 v1 |
| 172 | + |
| 173 | +## 开发 |
| 174 | + |
| 175 | +### 跑单测 |
| 176 | + |
| 177 | +```bash |
| 178 | +# 全部 |
| 179 | +python3 -m pytest tests/ -q |
| 180 | + |
| 181 | +# 单文件 |
| 182 | +python3 -m pytest tests/core/test_executor_nodes.py -v |
| 183 | + |
| 184 | +# 单用例 |
| 185 | +python3 -m pytest tests/test_mvp_table.py::test_mvp_18 -v |
| 186 | + |
| 187 | +# 不变量守护(含 3 条 grep) |
| 188 | +python3 -m pytest tests/test_invariants.py -v |
| 189 | +``` |
| 190 | + |
| 191 | +### CodeGraph(推荐代码探索工具) |
35 | 192 |
|
36 | | -tests/ # pytest 测试 |
37 | | -├── parser/ # 解析器测试 + inputs/ fixture |
38 | | -└── executor/ # 执行器测试 + inputs/ fixture |
| 193 | +仓库已初始化 CodeGraph 索引(37 文件 / 470 nodes / 1566 edges,1.38 MB SQLite): |
39 | 194 |
|
40 | | -chapters/ # 端到端 fixture(v0-issue-19 落地) |
41 | | -docs/ |
42 | | -├── adr/ # 架构决策记录 |
43 | | -├── prds/ # 产品需求文档 |
44 | | -└── agents/ # Agent 协作说明 |
| 195 | +```bash |
| 196 | +# 列出文件结构 |
| 197 | +codegraph files |
| 198 | + |
| 199 | +# 看某符号的源码 + 调用者 + 被调用者 |
| 200 | +codegraph explore Executor |
| 201 | +codegraph node EngineBus |
| 202 | +codegraph callers run |
| 203 | +codegraph callees parse_block_body |
45 | 204 | ``` |
46 | 205 |
|
47 | | -## 规范与设计 |
| 206 | +详见 [CLAUDE.md](CLAUDE.md) "Agent 工具链"节。 |
| 207 | + |
| 208 | +### 分支与 commit |
48 | 209 |
|
49 | | -- 规范:[`docs/adr/0001-v0-baseline-script-spec.md`](docs/adr/0001-v0-baseline-script-spec.md)(ADR-0001) |
50 | | -- 需求:[`docs/prds/0001-v0-engine-implementation.md`](docs/prds/0001-v0-engine-implementation.md)(PRD-0001) |
| 210 | +- 分支:`feature/功能描述`、`fix/问题描述`、`chore/任务描述` |
| 211 | +- Commit:中文简述,例 `feat: 添加存档系统`、`fix: 修复选项无法跳转的bug` |
| 212 | +- 当前活跃分支:`cursor/setup-issues-v0-vertical-slices`(领先 remote 22+ commits) |
51 | 213 |
|
52 | | -## 进程模型 |
| 214 | +## 许可 |
53 | 215 |
|
54 | | -v0 采用双进程模型:core 进程负责解析+执行,runtime/gui 进程负责渲染。两进程通过 `multiprocessing.Queue` 数据总线通信。 |
| 216 | +MIT(见 [pyproject.toml](pyproject.toml)) |
0 commit comments