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:
@@ -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** — 只有逻辑和配置进版本控制
|
||||
|
||||
|
||||
Reference in New Issue
Block a user