This repository has been archived on 2026-06-01. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
pulse/CONTRIBUTING.md
T
xingyue 10a601c28b 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
2026-04-15 19:44:11 +08:00

9.8 KiB

Contributing to Pulse

开发指南。

前置要求

  • Bun >= 1.0(运行时 + 包管理 + 测试)
  • Git
  • Cursor Agent CLI (可选,用于 AI 辅助编码)
git clone https://github.com/oc-xiaoju/pulse.git
cd pulse
bun install   # also installs pre-push hook

Git Hooks

bun install 自动安装 pre-push hook(via scripts/install-hooks.mjs),push 前自动跑 lint + tests。

手动跑检查:bun run precheck 删除 .git/hooks/pre-push 可禁用。

代码结构

pulse/
├── packages/
│   ├── pulse/src/                 ← 核心引擎(@uncaged/pulse)
│   │   ├── index.ts               ← Rule 类型、composeRules、runPulse、executorLoop、rebuildSnapshot
│   │   ├── store.ts               ← 存储层:events.db + vitals.db + objects/ CAS
│   │   ├── 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 不可改)
│   │   │   ├── system-resource.ts   CPU/内存/磁盘/swap
│   │   │   ├── process-alive.ts     关键进程存活检测
│   │   │   ├── network.ts           DNS + HTTP 连通性
│   │   │   ├── error-log.ts         日志关键词匹配
│   │   │   ├── pending-tasks-projection.ts  任务事件 fold → PendingTasksData + AgentCapabilityStats
│   │   │   └── index.ts
│   │   ├── rules/                 ← P0 保命层(植物神经,agent 不可改)
│   │   │   ├── constants.ts         ESSENTIAL_PROCESSES 白名单、阈值常量
│   │   │   ├── health.ts           HealthSnapshot 类型 + rebuildHealth
│   │   │   ├── survival.ts         保命 rules(洋葱最外层)
│   │   │   ├── builtin.ts          内置 rules:clampTick、dedup 等
│   │   │   └── index.ts
│   │   └── executors/             ← 保命 executors(确定性本地命令)
│   │       ├── survival.ts
│   │       └── index.ts
│   │
│   ├── pulse-cursor/src/          ← Cursor Agent 适配器(@uncaged/pulse-cursor)
│   │   ├── index.ts                re-export
│   │   └── cursor-agent.ts         Cursor Agent Executor
│   │
│   ├── pulse-hermes/src/          ← Hermes Agent 适配器(@uncaged/pulse-hermes)
│   │   └── index.ts
│   │
│   ├── pulse-openclaw/src/         ← OpenClaw 适配器(@uncaged/pulse-openclaw)
│   │   ├── index.ts                re-export
│   │   ├── watchers/               OC Gateway + LLM 健康探针
│   │   ├── rules/                  OC 专属保命 rules
│   │   └── executors/              OC 专属 executors
│   │
│   └── upulse/src/                ← CLI 工具(@uncaged/upulse)
│       ├── cli.ts                  命令路由
│       ├── daemon.ts               daemon 进程管理
│       ├── init.ts                 upulse init
│       ├── git.ts                  git 操作封装
│       ├── store.ts                CLI 层存储辅助
│       ├── config.ts               配置管理
│       ├── migrate.ts              scoped store 迁移
│       ├── ui/                    ← 内嵌 WebUI
│       │   ├── server.ts            Bun HTTP server(API + 前端)
│       │   └── dashboard.ts         单文件 HTML dashboard
│       └── commands/
│           ├── daemon.ts            upulse daemon start/stop
│           ├── deploy.ts            upulse deploy(staging → promote)
│           ├── dev.ts               upulse dev(热重载)
│           ├── gc.ts                upulse gc(vitals 清理)
│           ├── init.ts              upulse init
│           ├── inspect.ts           upulse inspect(查看 events/vitals)
│           ├── list.ts              upulse list(列出实例)
│           └── tick.ts              upulse tick(手动触发一次 tick)
│
├── biome.json                     ← Biome linter 配置
├── package.json                   ← monorepo root
└── bun.lock

架构

核心三原语:Percept → Understand → Execute

Percept(感知)→ Understand(认知)→ Execute(行动)
英文 组件 输出 佛教映射
感知 Percept Watchers(六处) Events(六入,按 sense 分类) 六处触尘
认知 Understand Rules Effects(序列化的行动参数) 受想行
行动 Execute Executors Events(执行结果) 身口意业

一切皆业:Percept / Tick / Execute 都写 events。Events 是不可变的业的记录。

Effects 不是行动本身,是行动的描述——序列化的参数,由 Executor 解释执行。

三层解耦驱动

Percept 层(vitals.db)
  Watchers 每 5s 感知 → 写 vitals → 唤醒判定 → wakeTick()
                                                    ↓
Understand 层(events.db)                          中断 sleep
  rebuildSnapshot → Rule Chain(洋葱)→ write effect events
  └── 被 timer 或 wakeTick 唤醒                 │
                                              ↓
Execute 层(executorLoop,独立循环)
  scan pending effect events → execute → effect-acked/effect-failed
  • Tick 串行不并发(加锁)
  • wakeTick 可中断 sleep,tick 执行中的 wake 设 pendingWake flag
  • executorLoop 与 tick 解耦:tick 只写 effect events,executorLoop 后台异步执行(fire-and-forget)

洋葱 Rule 模型

[panicRollback, processWatchdog, resourceGuard, ...survivalRules, ...agentRules]
 └────────── 核心包硬编码,最外层 ──────────┘  └── agent engine/ ──┘

最外层的保命 rules 由核心包注入,agent 看不到也改不了。

存储模型

一切皆事件。三个存储:

存储 内容 生命周期
events.db promote/rollback/effect/effect-acked/effect-failed/error/collect/tick/task-* 永不压缩
vitals.db 高频采样数据(系统资源/进程/网络/LLM) 可 gc(archive + downsample)
objects/ CAS 内容寻址存储 自动去重,不可变

开发工作流

跑测试

# 核心引擎测试
cd packages/pulse && bun test

# 全部测试(含 E2E)
bun test

Lint & 格式化

# 检查
bun run lint

# 自动修复
bun run lint:fix

项目使用 Biome 做 lint 和格式化。CI 会检查。

分支约定

git checkout -b feat/descriptive-name    # 新功能
git checkout -b fix/descriptive-name     # 修复
git checkout -b chore/descriptive-name   # 工具链/配置

Commit 格式

type: short description (closes #N)

Types: feat: fix: docs: refactor: chore:

Issue 驱动

每个改动都有 GitHub Issue。先开 issue,再写代码,commit 带 closes #N

关键设计原则

  1. Moore 机 — 不逐事件响应,只看两次快照间的 diff。Effects 由新状态决定。
  2. 保命零依赖 — 保命层不依赖 LLM、不依赖外部网络。全部确定性本地命令。
  3. Agent 不可改植物神经 — watchers/保命 rules/executors 硬编码在核心包。
  4. 幂等性靠 snapshot — Rule 只看 (prev, curr),不查 events 历史。rebuildSnapshot 预重建所有需要的状态。
  5. Bypass = 短路 — 保命 rule 不调 inner() 时,内层业务 rules 全部跳过。
  6. Tick 与 Execute 解耦 — tick 只产生 effect events,executorLoop 独立异步执行,互不阻塞。
  7. Task 状态由事件 fold — 任务状态从 task-* 事件序列重建,不单独存储,保证一致性。

测试约定

  • 单测文件和源码同目录:foo.tsfoo.test.ts
  • E2E 在 packages/upulse/src/e2e/
  • Mock 使用 bun:testjest.fn() / jest.spyOn()
  • 网络/进程相关测试用依赖注入(如 fetchFn 参数),不做真实 IO
  • Watcher 测试构造 mock store + mock wakeTick
  • Rule 测试构造 mock snapshot + mock inner

使用 Cursor Agent 编码

项目使用 Cursor Agent CLI 作为主要编码工具:

# 分析(只读,不改文件)
agent -p "分析 watchers/ 目录的结构和数据流" \
  --model claude-4.6-sonnet-medium --mode=ask --output-format text --trust

# 执行(改文件)
agent -p "实现 xxx 功能" \
  --model claude-4.6-sonnet-medium --force --output-format text --trust

模型选择

难度 模型 场景
🟢 简单 gpt-5.4-mini-medium 单文件小改、格式化
🟡 标准 claude-4.6-sonnet-medium bug fix、新功能、重构
🔴 复杂 claude-4.6-opus-high-thinking 架构改动、多文件重构

相关资源