feat(rfc-001): Drizzle 作为 Sense schema 标准工具链

- schema.ts 为 single source of truth,migration 由 drizzle-kit 自动生成
- Sense 目录结构从单文件改为目录(schema.ts + index.ts + migrations/)
- 设计理由:开发者是 Coding Agent,确定性工具链优于概率模型自律
- 更新 §4.1 存储设计、§8 目录结构

小橘 <xiaoju@shazhou.work>
This commit is contained in:
2026-04-22 05:36:17 +00:00
parent 8379dae585
commit 8a3937f0e1
+64 -6
View File
@@ -84,6 +84,51 @@ export async function compute(): Promise<Task[] | null> {
这是合理的,因为 Signal 本质是 append-only 的时序数据,不会跨 Sense join。每个 Sense 最了解自己的查询模式。
#### Schema 管理:Drizzle 作为标准工具链
每个 Sense 用 Drizzle ORM 定义 schema,**`schema.ts` 是 single source of truth**:
```typescript
// senses/cpu-usage/schema.ts
import { sqliteTable, integer, real } from 'drizzle-orm/sqlite-core'
export const samples = sqliteTable('samples', {
ts: integer('ts').primaryKey(),
value: real('value').notNull(),
})
```
Migration 由 `drizzle-kit generate` 自动生成,提交进 git:
```
senses/
cpu-usage/
schema.ts ← 开发者(agent)写这个
index.ts ← compute,查询有类型推导
migrations/ ← drizzle-kit 自动生成
0001_init.sql
```
compute 拿到的 db 实例是 Drizzle 包装过的,查询全部 type-safe:
```typescript
// senses/cpu-usage/index.ts
import { db } from './schema'
import { samples } from './schema'
export async function compute(): Promise<number | null> {
const load = os.loadavg()[0]
await db.insert(samples).values({ ts: Date.now(), value: load })
return load
}
```
**为什么用 Drizzle 而不是手写 SQL migration:**
Nerve 的 Sense 开发者是机器上的 Coding Agent(通过 Nerve 自身的 Workflow 自举开发)。Agent 行为的正确性应靠确定性工具保证,不应依赖概率模型的"自律"。Drizzle 让 agent 只写一个东西(`schema.ts`),migration 和类型都是机械派生,消除了 TS 与 SQL 不一致的风险。
**引擎职责:** 运行时只执行 migration SQL(`drizzle migrate`),不依赖 drizzle-kit。生成 migration 是开发时(workflow role action)的事。
#### Sense 不知道 Workflow
Sense 只感知世界并产出 Signal,永远不关心"谁在听"或"听了之后要做什么"。Sense 不引用 Workflow、不返回 `ThreadStart`、不知道自己的 Signal 会触发什么动作。
@@ -511,12 +556,24 @@ Reflex ──→ Sense ──→ Sense (复合依赖)
```
~/.uncaged-nerve/
package.json # 依赖管理
package.json # 依赖管理(含 drizzle-orm)
nerve.yaml # 主配置(含 reflexes)
senses/
cpu-usage.ts
disk-usage.ts
active-tasks.ts
cpu-usage/
schema.ts # Drizzle schema(single source of truth)
index.ts # compute 逻辑
migrations/ # drizzle-kit 自动生成
0001_init.sql
disk-usage/
schema.ts
index.ts
migrations/
0001_init.sql
active-tasks/
schema.ts
index.ts
migrations/
0001_init.sql
workflows/ # post-MVP
cleanup.ts
data/ # ⛔ gitignored
@@ -535,9 +592,10 @@ Reflex ──→ Sense ──→ Sense (复合依赖)
### 设计要点
- **local git repo** — 配置和 sense 逻辑可回滚,data 不进 git
- **package.json** — 标准 npm 包,`npm install` 管理依赖
- **package.json** — 标准 npm 包,`npm install` 管理依赖(含 `drizzle-orm``drizzle-kit` 为 devDependency)
- **nerve.yaml** — 单一配置入口,含 senses(运行时属性如 throttle)和 reflexes(触发条件)两个字段
- **data/senses/** — 每个 sense 一个 sqlite 文件,存关系型数据
- **senses/{name}/** — 每个 sense 一个目录,含 `schema.ts`(Drizzle schema)、`index.ts`(compute)、`migrations/`(自动生成)
- **data/senses/** — 每个 sense 一个 sqlite 文件,引擎启动时自动执行 migration
- **data/blobs/** — CAS(Content-Addressable Storage),sha256 前两位分片目录,sense 存大对象时写 blob 拿 hash,db 里只存 hash 引用
- **data/ 和 node_modules/ gitignored** — 只有逻辑和配置进版本控制