docs: engine spec + test cases documentation (#3)
This commit is contained in:
parent
be380a53ca
commit
208447d3e5
85
docs/engine-spec.md
Normal file
85
docs/engine-spec.md
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
# Pulse Engine 目录规范
|
||||||
|
|
||||||
|
> `~/.upulse/engine/` — Pulse 的"用户态"代码空间,独立 git 仓库。
|
||||||
|
|
||||||
|
## 架构
|
||||||
|
|
||||||
|
```
|
||||||
|
~/.upulse/engine/ # 独立 git repo
|
||||||
|
├── package.json # @upulse/engine, 依赖 @uncaged/pulse
|
||||||
|
├── tsconfig.json
|
||||||
|
├── templates/ # Scaffold 模板(meta coder 参考)
|
||||||
|
│ ├── workflow.ts.tmpl
|
||||||
|
│ └── workflow.test.ts.tmpl
|
||||||
|
├── src/
|
||||||
|
│ └── workflows/
|
||||||
|
│ ├── ping-pong.ts # 示例 workflow
|
||||||
|
│ ├── ping-pong.test.ts
|
||||||
|
│ ├── werewolf.ts # 业务 workflow
|
||||||
|
│ ├── werewolf.test.ts
|
||||||
|
│ └── roles/
|
||||||
|
│ ├── meta-gate.ts # Gate: 准入检查(无 LLM)
|
||||||
|
│ ├── meta-gate.test.ts
|
||||||
|
│ ├── meta-coder-cursor.ts # Coder: Cursor Agent 写代码
|
||||||
|
│ ├── meta-checker.ts # Checker: 验证 scope + build + unit test
|
||||||
|
│ ├── meta-tester.ts # Tester: E2E lifecycle 验证
|
||||||
|
│ └── meta-promoter.ts # Promoter: commit + push + code_rev
|
||||||
|
└── docs/
|
||||||
|
```
|
||||||
|
|
||||||
|
## 核心概念
|
||||||
|
|
||||||
|
### Engine vs 核心包
|
||||||
|
|
||||||
|
| | Engine (`~/.upulse/engine/`) | 核心包 (`packages/pulse/`) |
|
||||||
|
|---|---|---|
|
||||||
|
| 谁改 | Meta workflow(agent 自主改) | 人工 / subagent |
|
||||||
|
| 内容 | 业务 workflow + meta roles | 框架代码 |
|
||||||
|
| 版本控制 | engine repo git hash = `code_rev` | pulse repo |
|
||||||
|
| 部署 | promote event → daemon 热加载 | npm publish |
|
||||||
|
|
||||||
|
### code_rev
|
||||||
|
|
||||||
|
Engine repo 的 **git commit hash** 就是 `code_rev`。
|
||||||
|
|
||||||
|
- 每次 promoter commit 后,commit hash 成为新的 `code_rev`
|
||||||
|
- Guard state 按 `code_rev` 隔离(同一 guard + 同一 key,不同版本有独立 state)
|
||||||
|
- 回滚 = 切回旧 `code_rev`,旧 state 还在
|
||||||
|
|
||||||
|
### Meta Workflow 流程
|
||||||
|
|
||||||
|
```
|
||||||
|
START → gate → coder → checker → tester → promoter → END
|
||||||
|
↑ | |
|
||||||
|
└── fail ──┘── fail ──┘
|
||||||
|
```
|
||||||
|
|
||||||
|
| Role | 职责 | LLM |
|
||||||
|
|------|------|-----|
|
||||||
|
| **gate** | 准入检查:任务描述够不够详细、是否在 engine scope | ❌ |
|
||||||
|
| **coder** | 用 Cursor Agent 写代码,参考 templates/ | ✅ Agent |
|
||||||
|
| **checker** | 验证文件 scope + `bun run build` + `bun test` | ❌ |
|
||||||
|
| **tester** | E2E lifecycle 验证:import → temp store → tick → quiescence | ❌ |
|
||||||
|
| **promoter** | `git commit` + `git push` + 输出 `codeRev` | ❌ |
|
||||||
|
|
||||||
|
### Daemon 加载机制
|
||||||
|
|
||||||
|
1. Daemon 启动时 `tryLoadFromEngine`,优先加载 engine 目录下的 workflow/role
|
||||||
|
2. Engine 文件 import 用 `@uncaged/pulse`(npm link 到核心包)
|
||||||
|
3. Promote event 触发 daemon 重新加载
|
||||||
|
|
||||||
|
## 开发新 Workflow
|
||||||
|
|
||||||
|
1. 参考 `templates/workflow.ts.tmpl` 创建 `src/workflows/{name}.ts`
|
||||||
|
2. 参考 `templates/workflow.test.ts.tmpl` 创建配套测试
|
||||||
|
3. `bun test` 确认通过
|
||||||
|
4. Git commit + push
|
||||||
|
|
||||||
|
或者通过 meta workflow 自动生成:向 daemon 提交任务 → gate → coder → checker → tester → promoter → 自动完成。
|
||||||
|
|
||||||
|
## 约束
|
||||||
|
|
||||||
|
- Workflow 文件只放 `src/workflows/` 下
|
||||||
|
- Meta role 文件只放 `src/workflows/roles/` 下
|
||||||
|
- Import 用 `@uncaged/pulse`,不用相对路径到核心包
|
||||||
|
- Commit author: `小橘 <xiaoju@shazhou.work>`
|
||||||
154
docs/test-cases.md
Normal file
154
docs/test-cases.md
Normal file
@ -0,0 +1,154 @@
|
|||||||
|
# Pulse 测试用例文档
|
||||||
|
|
||||||
|
> 所有已验证的测试场景,含 unit test 和 e2e 场景描述。
|
||||||
|
|
||||||
|
## 测试统计
|
||||||
|
|
||||||
|
- **核心包** (`packages/pulse/src/`): 350 tests
|
||||||
|
- **Engine** (`~/.upulse/engine/`): 14 tests
|
||||||
|
- **总计**: 364 tests, 0 fail
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 一、Guard 系统
|
||||||
|
|
||||||
|
### 1.1 Guard 注册与 State 管理
|
||||||
|
|
||||||
|
| 场景 | 描述 | 文件 |
|
||||||
|
|------|------|------|
|
||||||
|
| 注册 guard 写入 guard_defs 表 | `registerGuard` 持久化定义到 SQLite | `guard-projection.test.ts` |
|
||||||
|
| 从表读 guard 定义 | `listGuardDefs` 纯从 `guard_defs` 表读,不依赖内存缓存 | `guard-projection.test.ts` |
|
||||||
|
| Guard state 初始值 | 首次 check 时 state 从 `initial_value` 开始 | `guard-projection.test.ts` |
|
||||||
|
| Guard state 转换 | check 通过后 transition 更新 state | `guard-projection.test.ts` |
|
||||||
|
| Guard 拒绝非法事件 | check 不通过时抛出 `GuardViolationError` | `guard-projection.test.ts` |
|
||||||
|
|
||||||
|
### 1.2 Guard 版本化(code_rev 维度)
|
||||||
|
|
||||||
|
| 场景 | 描述 | 文件 |
|
||||||
|
|------|------|------|
|
||||||
|
| 同 guard 不同 code_rev 独立 state | `(guard_name, key, code_rev)` 三元组主键,不同版本互不干扰 | `guard-projection.test.ts` |
|
||||||
|
| 新版本从 initial_value 开始 | code_rev 切换后,state 不存在 → 从 initial_value 重建 | `guard-projection.test.ts` |
|
||||||
|
| 回滚续写旧 state | 切回旧 code_rev 时,旧 state 还在,从 last_event_id 增量 | `guard-projection.test.ts` |
|
||||||
|
|
||||||
|
### 1.3 GuardProjection(pulse#9)
|
||||||
|
|
||||||
|
| 场景 | 描述 | 文件 |
|
||||||
|
|------|------|------|
|
||||||
|
| 子 Guard 过滤 | subagent 注册的 guard 只在该 subagent 上下文生效 | `guard-projection.test.ts` |
|
||||||
|
| Guard 表达式缓存 | JSONata 编译结果缓存,第二次 check 不重新编译 | `guard-projection.test.ts` |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 二、Workflow 核心(Adapter)
|
||||||
|
|
||||||
|
### 2.1 基本生命周期
|
||||||
|
|
||||||
|
| 场景 | 描述 | 文件 |
|
||||||
|
|------|------|------|
|
||||||
|
| START → roles → END | `__start__` event 触发 moderator 状态机,依次执行 role,写 `__end__` | `workflow-rule-adapter.test.ts` |
|
||||||
|
| Role 输出存 CAS | role 的 content 存入 objects/,event 只存 hash | `workflow-rule-adapter.test.ts` |
|
||||||
|
| Meta 存入 event | role 的 meta 作为 JSON 存入 event.meta 字段 | `workflow-rule-adapter.test.ts` |
|
||||||
|
| Moderator 路由 | moderator 根据 role + meta 决定下一步 | `workflow-rule-adapter.test.ts` |
|
||||||
|
| 多 topic 并行 | 不同 key 的 workflow 独立运行,互不干扰 | `workflow-rule-adapter.test.ts` |
|
||||||
|
|
||||||
|
### 2.2 Lifecycle Guard
|
||||||
|
|
||||||
|
| 场景 | 描述 | 文件 |
|
||||||
|
|------|------|------|
|
||||||
|
| 正常生命周期 | unknown → active(start)→ ended(end)| `workflow-rule-adapter.test.ts` |
|
||||||
|
| Abort 阻止重启 | aborted 状态的 topic 不能再 `__start__` | `workflow-rule-adapter.test.ts` |
|
||||||
|
| 双重保护 | event-based lastRole 检查(第一层)+ guard state(第二层)| `workflow-rule-adapter.test.ts` |
|
||||||
|
|
||||||
|
### 2.3 Abort(pulse#10)
|
||||||
|
|
||||||
|
| 场景 | 描述 | 文件 |
|
||||||
|
|------|------|------|
|
||||||
|
| Abort 写 `__abort__` event | abort 后 moderator 不再调度该 topic | `workflow-rule-adapter.test.ts` |
|
||||||
|
| Abort 后不能 end | `__abort__` 后写 `__end__` 被 guard 拒绝 | `workflow-rule-adapter.test.ts` |
|
||||||
|
| Abort 后不能重启 | 同一 key 再次 `__start__` 被 guard 拒绝 | `workflow-rule-adapter.test.ts` |
|
||||||
|
|
||||||
|
### 2.4 Chain 过滤(信息防护)
|
||||||
|
|
||||||
|
| 场景 | 描述 | 文件 |
|
||||||
|
|------|------|------|
|
||||||
|
| Role 只看同 topic 消息 | chain 按 key 过滤,不同 topic 的消息不可见 | `workflow-rule-adapter.test.ts` |
|
||||||
|
| Role 只看已完成消息 | 当前 role 不看自己的 event(防幻觉) | `workflow-rule-adapter.test.ts` |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 三、Gate Role(pulse#11)
|
||||||
|
|
||||||
|
| 场景 | 描述 | 文件 |
|
||||||
|
|------|------|------|
|
||||||
|
| 任务描述足够通过 | ≥20 字符、有明确动词 → pass | `meta-gate.test.ts` |
|
||||||
|
| 空/短描述拒绝 | 不足 20 字符 → reject | `meta-gate.test.ts` |
|
||||||
|
| 核心包任务拒绝 | 提到 `packages/pulse/src` 等核心路径 → reject | `meta-gate.test.ts` |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 四、Meta Workflow E2E
|
||||||
|
|
||||||
|
### 4.1 成功场景
|
||||||
|
|
||||||
|
| 场景 | 描述 | 事件链 |
|
||||||
|
|------|------|--------|
|
||||||
|
| 完整 happy path | gate pass → coder → checker pass → tester pass → promoter → END | Event #90→#98→#100→#101→#102→#103 |
|
||||||
|
|
||||||
|
### 4.2 失败场景
|
||||||
|
|
||||||
|
| 场景 | 描述 | 事件链 |
|
||||||
|
|------|------|--------|
|
||||||
|
| Checker 失败回退 coder | 文件 scope 违规或 build 失败 → 回退 coder 重试 | Event #88→#89 |
|
||||||
|
| Tester 失败回退 coder | E2E lifecycle 未到 END → 回退 coder 重试 | — |
|
||||||
|
|
||||||
|
### 4.3 Abort 场景
|
||||||
|
|
||||||
|
| 场景 | 描述 | 事件链 |
|
||||||
|
|------|------|--------|
|
||||||
|
| 手动 abort | 写 `meta.__abort__` 终止 workflow | Event #104→#105 |
|
||||||
|
|
||||||
|
### 4.4 Gate 拒绝场景
|
||||||
|
|
||||||
|
| 场景 | 描述 | 事件链 |
|
||||||
|
|------|------|--------|
|
||||||
|
| 不合格任务 | 描述过短或涉及核心包 → gate reject → END | — |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 五、Daemon 容错
|
||||||
|
|
||||||
|
| 场景 | 描述 | 文件 |
|
||||||
|
|------|------|------|
|
||||||
|
| GuardViolationError 不 crash | guard 拒绝时 warn 日志,daemon 继续运行 | `workflow-daemon.ts` |
|
||||||
|
| Tick 异常不 crash | 其他异常也 catch + 日志,不停 daemon | `workflow-daemon.ts` |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 六、Engine Workflow(`~/.upulse/engine/`)
|
||||||
|
|
||||||
|
### 6.1 ping-pong
|
||||||
|
|
||||||
|
| 场景 | 描述 | 文件 |
|
||||||
|
|------|------|------|
|
||||||
|
| START → pong → END | 最简 workflow,验证 engine 加载机制 | `ping-pong.test.ts` |
|
||||||
|
|
||||||
|
### 6.2 werewolf
|
||||||
|
|
||||||
|
| 场景 | 描述 | 文件 |
|
||||||
|
|------|------|------|
|
||||||
|
| 狼人杀多角色交互 | 多 role 状态机验证 | `werewolf.test.ts` |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 七、Checker 增强
|
||||||
|
|
||||||
|
| 场景 | 描述 | 文件 |
|
||||||
|
|------|------|------|
|
||||||
|
| 文件 scope 验证 | `git diff --name-only HEAD` 只允许 engine 目录改动 | `meta-checker.ts` |
|
||||||
|
| Build 验证 | `bun run build`(tsc --noEmit)通过 | `meta-checker.ts` |
|
||||||
|
| Unit test 验证 | `bun test` 通过 | `meta-checker.ts` |
|
||||||
|
| 实际改动 vs 声称改动 | 对比 coder meta.filesChanged 与 git diff | `meta-checker.ts` |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
_最后更新: 2026-04-19 — 小橘 🍊(NEKO Team)_
|
||||||
Loading…
x
Reference in New Issue
Block a user