docs: update for executor loop, task events, pending-tasks projection

Reflect recent changes across all docs:
- README: add executor loop (fire-and-forget), task events lifecycle,
  pending-tasks projection, update architecture diagram, add pulse-hermes
  package, add RFC #58 reference
- CONTRIBUTING: add task-events.ts, defs.ts, projection-engine.ts,
  pending-tasks-projection.ts to code structure, update architecture
  diagram to three-layer decoupled model, add design principles 6-7,
  add ui/ directory, add migrate.ts, add RFC #58 reference
- DESIGN: update packages table with all current packages
This commit is contained in:
2026-04-15 19:43:53 +08:00
parent 234ca41c46
commit 10a601c28b
3 changed files with 72 additions and 16 deletions
+24 -6
View File
@@ -27,14 +27,18 @@ bun install # also installs pre-push hook
pulse/ pulse/
├── packages/ ├── packages/
│ ├── pulse/src/ ← 核心引擎(@uncaged/pulse) │ ├── pulse/src/ ← 核心引擎(@uncaged/pulse)
│ │ ├── index.ts ← Rule 类型、composeRules、runPulse、rebuildSnapshot │ │ ├── index.ts ← Rule 类型、composeRules、runPulse、executorLoop、rebuildSnapshot
│ │ ├── store.ts ← 存储层:events.db + vitals.db + objects/ CAS │ │ ├── store.ts ← 存储层:events.db + vitals.db + objects/ CAS
│ │ ├── watcher.ts ← Watcher 框架:startWatcher、wakeTick、WatcherDef │ │ ├── watcher.ts ← Watcher 框架:startWatcher、wakeTick、WatcherDef
│ │ ├── task-events.ts ← 任务生命周期类型(TaskState、PendingTasksData、AgentCapabilityStats)
│ │ ├── defs.ts ← Definition Layer(rule/watcher/executor 声明式定义)
│ │ ├── projection-engine.ts ← Projection Engine(基于声明式定义的 snapshot 构建)
│ │ ├── watchers/ ← P0 内置 watchers(植物神经,agent 不可改) │ │ ├── watchers/ ← P0 内置 watchers(植物神经,agent 不可改)
│ │ │ ├── system-resource.ts CPU/内存/磁盘/swap │ │ │ ├── system-resource.ts CPU/内存/磁盘/swap
│ │ │ ├── process-alive.ts 关键进程存活检测 │ │ │ ├── process-alive.ts 关键进程存活检测
│ │ │ ├── network.ts DNS + HTTP 连通性 │ │ │ ├── network.ts DNS + HTTP 连通性
│ │ │ ├── error-log.ts 日志关键词匹配 │ │ │ ├── error-log.ts 日志关键词匹配
│ │ │ ├── pending-tasks-projection.ts 任务事件 fold → PendingTasksData + AgentCapabilityStats
│ │ │ └── index.ts │ │ │ └── index.ts
│ │ ├── rules/ ← P0 保命层(植物神经,agent 不可改) │ │ ├── rules/ ← P0 保命层(植物神经,agent 不可改)
│ │ │ ├── constants.ts ESSENTIAL_PROCESSES 白名单、阈值常量 │ │ │ ├── constants.ts ESSENTIAL_PROCESSES 白名单、阈值常量
@@ -50,6 +54,9 @@ pulse/
│ │ ├── index.ts re-export │ │ ├── index.ts re-export
│ │ └── cursor-agent.ts Cursor Agent Executor │ │ └── cursor-agent.ts Cursor Agent Executor
│ │ │ │
│ ├── pulse-hermes/src/ ← Hermes Agent 适配器(@uncaged/pulse-hermes)
│ │ └── index.ts
│ │
│ ├── pulse-openclaw/src/ ← OpenClaw 适配器(@uncaged/pulse-openclaw) │ ├── pulse-openclaw/src/ ← OpenClaw 适配器(@uncaged/pulse-openclaw)
│ │ ├── index.ts re-export │ │ ├── index.ts re-export
│ │ ├── watchers/ OC Gateway + LLM 健康探针 │ │ ├── watchers/ OC Gateway + LLM 健康探针
@@ -63,6 +70,10 @@ pulse/
│ ├── git.ts git 操作封装 │ ├── git.ts git 操作封装
│ ├── store.ts CLI 层存储辅助 │ ├── store.ts CLI 层存储辅助
│ ├── config.ts 配置管理 │ ├── config.ts 配置管理
│ ├── migrate.ts scoped store 迁移
│ ├── ui/ ← 内嵌 WebUI
│ │ ├── server.ts Bun HTTP server(API + 前端)
│ │ └── dashboard.ts 单文件 HTML dashboard
│ └── commands/ │ └── commands/
│ ├── daemon.ts upulse daemon start/stop │ ├── daemon.ts upulse daemon start/stop
│ ├── deploy.ts upulse deploy(staging → promote) │ ├── deploy.ts upulse deploy(staging → promote)
@@ -96,19 +107,23 @@ Percept(感知)→ Understand(认知)→ Execute(行动)
> Effects 不是行动本身,是行动的描述——序列化的参数,由 Executor 解释执行。 > Effects 不是行动本身,是行动的描述——序列化的参数,由 Executor 解释执行。
### 双层驱动 ### 三层解耦驱动
``` ```
Percept 层(vitals.db) Percept 层(vitals.db)
Watchers 每 5s 感知 → 写 vitals → 唤醒判定 → wakeTick() Watchers 每 5s 感知 → 写 vitals → 唤醒判定 → wakeTick()
Understand + Execute 层(events.db) 中断 sleep Understand 层(events.db) 中断 sleep
rebuildSnapshot → Rule Chain(洋葱)→ Executors rebuildSnapshot → Rule Chain(洋葱)→ write effect events
└── 被 timer 或 wakeTick 唤醒 └── 被 timer 或 wakeTick 唤醒
Execute 层(executorLoop,独立循环)
scan pending effect events → execute → effect-acked/effect-failed
``` ```
- Tick 串行不并发(加锁) - Tick 串行不并发(加锁)
- wakeTick 可中断 sleep,tick 执行中的 wake 设 pendingWake flag - wakeTick 可中断 sleep,tick 执行中的 wake 设 pendingWake flag
- **executorLoop 与 tick 解耦**:tick 只写 effect events,executorLoop 后台异步执行(fire-and-forget)
### 洋葱 Rule 模型 ### 洋葱 Rule 模型
@@ -125,7 +140,7 @@ Understand + Execute 层(events.db) 中断 sleep
| 存储 | 内容 | 生命周期 | | 存储 | 内容 | 生命周期 |
|---|---|---| |---|---|---|
| `events.db` | promote/rollback/effect/error/collect/tick | 永不压缩 | | `events.db` | promote/rollback/effect/effect-acked/effect-failed/error/collect/tick/task-* | 永不压缩 |
| `vitals.db` | 高频采样数据(系统资源/进程/网络/LLM) | 可 gc(archive + downsample) | | `vitals.db` | 高频采样数据(系统资源/进程/网络/LLM) | 可 gc(archive + downsample) |
| `objects/` | CAS 内容寻址存储 | 自动去重,不可变 | | `objects/` | CAS 内容寻址存储 | 自动去重,不可变 |
@@ -180,6 +195,8 @@ Types: `feat:` `fix:` `docs:` `refactor:` `chore:`
3. **Agent 不可改植物神经** — watchers/保命 rules/executors 硬编码在核心包。 3. **Agent 不可改植物神经** — watchers/保命 rules/executors 硬编码在核心包。
4. **幂等性靠 snapshot** — Rule 只看 `(prev, curr)`,不查 events 历史。rebuildSnapshot 预重建所有需要的状态。 4. **幂等性靠 snapshot** — Rule 只看 `(prev, curr)`,不查 events 历史。rebuildSnapshot 预重建所有需要的状态。
5. **Bypass = 短路** — 保命 rule 不调 `inner()` 时,内层业务 rules 全部跳过。 5. **Bypass = 短路** — 保命 rule 不调 `inner()` 时,内层业务 rules 全部跳过。
6. **Tick 与 Execute 解耦** — tick 只产生 effect events,executorLoop 独立异步执行,互不阻塞。
7. **Task 状态由事件 fold** — 任务状态从 task-* 事件序列重建,不单独存储,保证一致性。
## 测试约定 ## 测试约定
@@ -217,4 +234,5 @@ agent -p "实现 xxx 功能" \
- [RFC #1: Pulse — Agent 的自主神经系统](https://github.com/oc-xiaoju/pulse/issues/1) - [RFC #1: Pulse — Agent 的自主神经系统](https://github.com/oc-xiaoju/pulse/issues/1)
- [RFC #23: Autonomic Layer + Rule Middleware](https://github.com/oc-xiaoju/pulse/issues/23) - [RFC #23: Autonomic Layer + Rule Middleware](https://github.com/oc-xiaoju/pulse/issues/23)
- [Design #27: P0 保命层](https://github.com/oc-xiaoju/pulse/issues/27) - [Design #27: P0 保命层](https://github.com/oc-xiaoju/pulse/issues/27)
- [RFC #58: Definition Layer + Projection Engine + Rule Projections](https://github.com/oc-xiaoju/pulse/issues/58)
- [Wiki: Pulse 架构](https://shazhou-ww.github.io/oc-wiki/shared/pulse-agent-architecture/) - [Wiki: Pulse 架构](https://shazhou-ww.github.io/oc-wiki/shared/pulse-agent-architecture/)
+43 -7
View File
@@ -23,12 +23,13 @@ Rule = (prev, curr, inner) => Promise<[Effect[], tickMs]>
## 架构 ## 架构
``` ```
Percept 层(vitals.db) Understand + Execute 层(events.db) Percept 层(vitals.db) Understand 层(events.db) Execute 层
Watchers → 写 vitals → 唤醒判定 rebuildSnapshot → Rule Chain → Executors Watchers → 写 vitals → 唤醒判定 rebuildSnapshot → Rule Chain executorLoop
└── wakeTick() ──────────────→ 提前唤醒 tick └── wakeTick() ──────────────→ 提前唤醒 → write effect events ───→ scan & execute
→ effect-acked/failed
``` ```
**双层驱动**:Watchers 每 5s 感知写 vitals,关键事件提前唤醒 tick。Tick 层重建 snapshot,Rules 认知产生 effects,Executors 执行 **三层解耦**:Watchers 每 5s 感知写 vitals,关键事件提前唤醒 tick。Tick 层重建 snapshot,Rules 认知产生 effects 写入 events.db。独立的 executorLoop 后台扫描 effect events 并异步执行(fire-and-forget)
**洋葱 Rule 模型**:每个 Rule 接收 `inner`(剩余 rule chain),可以放行、bypass(跳过内层)、修饰结果、变换 snapshot。保命 rules 硬编码在最外层,agent 的业务 rules 在内层。 **洋葱 Rule 模型**:每个 Rule 接收 `inner`(剩余 rule chain),可以放行、bypass(跳过内层)、修饰结果、变换 snapshot。保命 rules 硬编码在最外层,agent 的业务 rules 在内层。
@@ -46,10 +47,11 @@ Percept 层(vitals.db) Understand + Execute 层(events.db)
| 包 | 说明 | npm | | 包 | 说明 | npm |
|---|---|---| |---|---|---|
| `@uncaged/pulse` | 核心引擎 + 保命层 + watchers | [![npm](https://img.shields.io/npm/v/@uncaged/pulse)](https://www.npmjs.com/package/@uncaged/pulse) | | `@uncaged/pulse` | 核心引擎 + 保命层 + watchers + task projections + executor loop | [![npm](https://img.shields.io/npm/v/@uncaged/pulse)](https://www.npmjs.com/package/@uncaged/pulse) |
| `@uncaged/pulse-openclaw` | OpenClaw 适配器(Gateway/LLM watchers + rules + executors) | [![npm](https://img.shields.io/npm/v/@uncaged/pulse-openclaw)](https://www.npmjs.com/package/@uncaged/pulse-openclaw) | | `@uncaged/pulse-openclaw` | OpenClaw 适配器(Gateway/LLM watchers + rules + executors) | [![npm](https://img.shields.io/npm/v/@uncaged/pulse-openclaw)](https://www.npmjs.com/package/@uncaged/pulse-openclaw) |
| `@uncaged/pulse-cursor` | Cursor Agent CLI executor 适配器 | [![npm](https://img.shields.io/npm/v/@uncaged/pulse-cursor)](https://www.npmjs.com/package/@uncaged/pulse-cursor) | | `@uncaged/pulse-cursor` | Cursor Agent CLI executor 适配器 | [![npm](https://img.shields.io/npm/v/@uncaged/pulse-cursor)](https://www.npmjs.com/package/@uncaged/pulse-cursor) |
| `@uncaged/upulse` | CLI:daemon 管理、staging/promote/rollback | [![npm](https://img.shields.io/npm/v/@uncaged/upulse)](https://www.npmjs.com/package/@uncaged/upulse) | | `@uncaged/pulse-hermes` | Hermes Agent 适配器 | [![npm](https://img.shields.io/npm/v/@uncaged/pulse-hermes)](https://www.npmjs.com/package/@uncaged/pulse-hermes) |
| `@uncaged/upulse` | CLI:daemon 管理、staging/promote/rollback、WebUI | [![npm](https://img.shields.io/npm/v/@uncaged/upulse)](https://www.npmjs.com/package/@uncaged/upulse) |
## 快速开始 ## 快速开始
@@ -115,11 +117,44 @@ interface WatcherDef {
Watcher 持续采集写 vitals,唤醒判定看最近 1 分钟窗口(~12 条),关键事件 `wakeTick()` 提前唤醒 tick。 Watcher 持续采集写 vitals,唤醒判定看最近 1 分钟窗口(~12 条),关键事件 `wakeTick()` 提前唤醒 tick。
### 异步 Executor Loop
tick 循环与 effect 执行彻底解耦。tick 产生 effects 写入 events.db,独立的 `executorLoop` 后台扫描 pending effect events 并异步执行:
```
Tick Loop (sense·think) Executor Loop (act)
rebuildSnapshot → Rules scan effect events
→ write effect events ─────→ → effect-executing
→ sleep(tickMs) → execute(effect)
→ effect-acked / effect-failed
```
- **Fire-and-forget**:tick 不等待 effect 执行完成
- **去重**:inflight set + effect-acked/effect-failed 事件防止重复执行
- **可配置**:`executorScanIntervalMs`(默认 1000ms)
### Task Events & Projections
Pulse 内置任务生命周期管理。任务通过事件驱动状态机流转:
```
task-created → task-assigned → task-executing → task-acked → task-closed
→ task-given-up
```
| 类型 | 说明 |
|---|---|
| `TaskState` | 任务完整状态(id、project、title、prompt、priority、status、agent、result) |
| `PendingTasksData` | 待处理任务汇总(pendingCount、tasks、byProject) |
| `AgentCapabilityStats` | 每个 agent 的能力统计(assigned/closed/givenUp/consecutiveFailures/avgDurationMs) |
`rebuildSnapshot` 自动注入:当 `senseKeys` 包含 `'pending-tasks'` 时,snapshot 中自动包含 `pending-tasks``agent-capability-stats` 两个 projection,供 Rules 做任务分配决策。
### 存储 ### 存储
| 库 | 内容 | 策略 | | 库 | 内容 | 策略 |
|---|---|---| |---|---|---|
| `events.db` | promote/rollback/effect/error/collect | 永不压缩 | | `events.db` | promote/rollback/effect/effect-acked/effect-failed/error/collect/task-* | 永不压缩 |
| `vitals.db` | 系统资源/进程/网络/LLM 健康 | 可 gc | | `vitals.db` | 系统资源/进程/网络/LLM 健康 | 可 gc |
| `objects/` | CAS(内容寻址,不可变) | 自动去重 | | `objects/` | CAS(内容寻址,不可变) | 自动去重 |
@@ -170,6 +205,7 @@ Watcher 持续采集写 vitals,唤醒判定看最近 1 分钟窗口(~12 条
- [RFC #22: 多实例管理](https://github.com/oc-xiaoju/pulse/issues/22) - [RFC #22: 多实例管理](https://github.com/oc-xiaoju/pulse/issues/22)
- [RFC #23: Autonomic Layer + Rule Middleware Refactor](https://github.com/oc-xiaoju/pulse/issues/23) - [RFC #23: Autonomic Layer + Rule Middleware Refactor](https://github.com/oc-xiaoju/pulse/issues/23)
- [Design #27: P0 保命层完整设计](https://github.com/oc-xiaoju/pulse/issues/27) - [Design #27: P0 保命层完整设计](https://github.com/oc-xiaoju/pulse/issues/27)
- [RFC #58: Definition Layer + Projection Engine + Rule Projections](https://github.com/oc-xiaoju/pulse/issues/58)
## License ## License
+5 -3
View File
@@ -23,6 +23,8 @@ f(prevSnapshot, currSnapshot) → (Effect[], tickMs)
| Package | Purpose | | Package | Purpose |
|---------|---------| |---------|---------|
| `@uncaged/pulse` | Core engine: `runPulse()` + `Rule` type. Generic, zero deps. | | `@uncaged/pulse` | Core engine: `runPulse()` + `Rule` type + `executorLoop` + task projections. Generic, zero deps. |
| `@uncaged/upulse` | CLI: daemon lifecycle + test/staging/promote | | `@uncaged/pulse-openclaw` | OpenClaw adapter: Gateway/LLM watchers + OC-specific rules + executors. |
| `@uncaged/pulse-rules` | Shared rule library (future) | | `@uncaged/pulse-cursor` | Cursor Agent CLI executor adapter. |
| `@uncaged/pulse-hermes` | Hermes Agent adapter. |
| `@uncaged/upulse` | CLI: daemon lifecycle + test/staging/promote + embedded WebUI |