Archived
- pnpm workspaces / tsconfig 双工程(node · web)/ 路径别名(§11.1) - eslint flat(§11.3 + §12.5 可机检项)/ dependency-cruiser 基线八条 + JCAI 增补(§11.4) - tools/module-tiers.json + gen-depcruise-tiers.ts 生成 tier-order 逐层规则 - tools/api-report.mjs 契约快照只留契约面(ADR-005) - docker-compose(PG16)+ db/init 四 schema;种子数据五岗位五员工冻结为常量 - docs/debt.md · docs/adr/ADR-005 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KeDBx2PHLavbURXB8LJJ7m
678 lines
42 KiB
Markdown
678 lines
42 KiB
Markdown
# JCAI 编码规范
|
||
|
||
> **版本 V0.1 · 结构契约 · 2026-07-26 · 读者:Coding Agent**
|
||
>
|
||
> 本文件是本仓库的**架构约束契约**:任何人或 AI 在本仓库写代码前必须先读完本文件。与本文件冲突的代码是 bug,不是风格问题。
|
||
>
|
||
> 语义权威是两卷规范:**《操作系统.html》(V2.15,系统侧)与《活动模型.html》(V2.0,活动侧)**——系统"做什么、什么语义"以两卷为准,本文件不复述也不改写;本文件只规定"代码长什么样、放在哪、谁能依赖谁"。语义冲突以两卷为准,结构冲突以本文件为准;发现两类权威打架,停下来报告,不得自行仲裁。
|
||
|
||
---
|
||
|
||
## 0. 一句话改动原则
|
||
|
||
任何一次改动都必须能被一句话精确描述:**"只改 `<模块路径>` 的 `<层>`,公开契约不变。"**
|
||
|
||
这句话成立的充要条件:
|
||
|
||
1. 每个模块有**唯一物理边界**(一个目录)
|
||
2. 每个模块有**唯一对外出口**(`index.ts`)
|
||
3. 依赖方向**单向无环**
|
||
4. 以上三条**由工具强制**(§11),不靠自觉
|
||
|
||
---
|
||
|
||
## 1. 技术选型(定案)
|
||
|
||
| 领域 | 选型 | 一句话理由 |
|
||
|---|---|---|
|
||
| 语言 | TypeScript(全栈,ESM only,`"type": "module"`) | 单语言全栈,契约可共享 |
|
||
| 运行时 | Node.js 22 LTS | — |
|
||
| 包管理 | pnpm workspaces | monorepo 原生,严格依赖隔离 |
|
||
| 前端 | React 19 + Vite + TanStack Router | SPA;类型安全路由(路由状态即应用状态,配零过程状态) |
|
||
| 前端样式 | 设计令牌 + 原生 CSS(飞书蓝体系,不引 Tailwind/CSS-in-JS) | 两台 PRD 原型的令牌与组件视觉直接平移,双主题(工作台浅色/治理台深轨浅面)已验证 |
|
||
| 前端服务端状态 | TanStack Query | 缓存/失效语义现成;SSE 事件按信封目标失效对应缓存(§9.2) |
|
||
| 编排画布 | diagram-js(PRD 画布件 1:1 平移) | 布局引擎与画笔(flow-layout/flow-node-paint)是框架无关纯 TS,治理台原型已验证「连线即映射、画图即校验」与蛇形正交布线;React Flow 的 DOM 节点模型需整套重写布局与视觉,弃 |
|
||
| 后端 HTTP | Hono(自建应用,**Mastra 以库形态嵌入**) | 鉴权、岗位权限、SSE 全归我们;不暴露 Mastra 默认端点(ADR-001) |
|
||
| Agent/编排框架 | **Mastra**(`@mastra/core` + `@mastra/memory` + `@mastra/pg`) | 图编排(挂起/恢复/快照持久)、Agent 回路、会话记忆、工具系统(§6) |
|
||
| 模型接入 | Vercel AI SDK provider 工厂(经 Mastra) | 四元绑定(Provider/URL/API-Key/Model)落 provider 工厂 |
|
||
| 数据库 | PostgreSQL 16(单库多 schema) | 事件存储、台账自生长、Mastra 存储、队列同库(§7) |
|
||
| 系统自持 ORM | Drizzle ORM(+ drizzle-kit 迁移) | 类型安全、迁移随系统版本 |
|
||
| 台账自生长 | node-postgres(`pg`)直写(ledger adapter 内) | 运行时 DDL/DML 由声明生成,ORM 静态 schema 不适用 |
|
||
| 队列/定时 | pg-boss | PG 原生,先持久后投递、至少一次天然契合 |
|
||
| 代码契约校验 | zod | 仓库内 API/DTO |
|
||
| 声明数据校验 | ajv(JSON Schema 2020-12 子集) | 活动声明是运行时数据,不是编译期代码(ADR-003) |
|
||
| 测试 | Vitest;集成测试用 Testcontainers(PG) | domain 层测试零 mock |
|
||
| 门禁 | tsc / ESLint(flat) / dependency-cruiser / 契约快照 | §11 |
|
||
|
||
版本号以实现时最新稳定版为准;**新增任何表外依赖 = 契约变更,走 §12 申请**。
|
||
|
||
---
|
||
|
||
## 2. 仓库形态(唯一合法形态)
|
||
|
||
```
|
||
repo/
|
||
├── docs/ 两卷规范 + 本文件 + debt.md + adr/
|
||
├── apps/
|
||
│ ├── web/ 前端:工作台 + 治理台
|
||
│ │ └── src/
|
||
│ │ ├── app/ 路由、Provider、鉴权壳、SSE 连接。唯一组装层
|
||
│ │ ├── features/ 前端业务模块(§9 清单)
|
||
│ │ │ └── desk-task/
|
||
│ │ │ ├── index.ts 唯一出口
|
||
│ │ │ ├── contract.ts 对外类型
|
||
│ │ │ ├── internal/
|
||
│ │ │ └── __tests__/
|
||
│ │ └── shared/ 无业务语义:typed-fetch、sse hook、format
|
||
│ └── api/ 后端:五层的系统侧全部
|
||
│ └── src/
|
||
│ ├── app/ 启动、Hono 路由注册、Mastra 实例、DI 装配、workers
|
||
│ ├── modules/ 后端业务模块(§4 清单)
|
||
│ │ └── ledger/
|
||
│ │ ├── index.ts 唯一出口(纯 re-export)
|
||
│ │ ├── contract.ts 对外类型
|
||
│ │ ├── port.ts 本模块需要外界提供的接口
|
||
│ │ ├── CONTRACT.md 给 AI 读的地址簿
|
||
│ │ ├── internal/
|
||
│ │ │ ├── domain/ 纯逻辑,零 IO,零框架
|
||
│ │ │ ├── usecase/ 编排 domain,依赖 port
|
||
│ │ │ └── adapter/ 实现 port(Drizzle/pg/pg-boss/Mastra 只准在这)
|
||
│ │ └── __tests__/
|
||
│ └── shared/
|
||
├── packages/
|
||
│ ├── contracts/ 前后端唯一共享点:zod schema + 推导类型(§8.1)
|
||
│ ├── activity-sdk/ 活动开发面:基座六件接口 + mock 宿主 + 回放夹具(§8.2)
|
||
│ ├── sfeel/ S-FEEL 子集解析与求值,纯函数(§8.3)
|
||
│ ├── ui-kit/ 无业务语义展示组件(卡片原语/时间线/净化视图容器)
|
||
│ └── utils/ 纯函数,零依赖
|
||
└── activities/ 第一方活动包(「系统外开发」的仓内形态,§8.2)
|
||
└── <activity-name>/ 只准依赖 @sdk 与 @contracts;禁止 import apps/**
|
||
```
|
||
|
||
### 2.1 结构规则
|
||
|
||
- 一个模块 = 一个目录 = 一个能用一句话说清职责的业务概念,通常 5–20 个文件
|
||
- 模块目录名**单数名词、kebab-case**;模块**不可嵌套**,子概念放 `internal/`,大到需要独立就升格为平级模块
|
||
- 文件名 kebab-case,类型名 PascalCase,函数名 camelCase
|
||
- 禁止按技术类型分目录(`controllers/`、`services/` 各一坨),按业务概念聚拢
|
||
- `activities/` 下的活动包**不是模块**:它们是活动库的安装物,编译为单文件 ESM 产物,经 `activity-registry` 安装进系统;api 侧任何文件**不得静态 import** `activities/**`
|
||
|
||
---
|
||
|
||
## 3. 架构五层 → 代码落点
|
||
|
||
| 架构层(《操作系统》01) | 代码落点 |
|
||
|---|---|
|
||
| 交互层(工作台 + 治理台) | `apps/web`(features)+ `apps/api` 的 `interaction` / `message` / `human-tool` 模块(协议侧) |
|
||
| 流程层(触发器 + 流程包/工作流) | `process`、`trigger` 模块 |
|
||
| 引擎层(流程引擎 + 活动基座) | 流程引擎在 `process` 内;活动基座六件 = `ledger` / `memory` / `toolbox` / `llm` / `interaction` + 契约类型(@contracts);范式运行器 = `loop-engine` / `flow-engine` / `skill-engine`;任务运行时 = `task` |
|
||
| 调用层(系统调用 · LLM 工具 · 人类工具 · 通道) | `toolbox`(功能工具/纯工具)、`llm`、`human-tool`、`channel` |
|
||
| 基座层(数据 · 台账 · 记忆 · 工具箱 · 活动库 · 流程包 · 事件存储) | PostgreSQL 四 schema(§7)+ `event` / `ledger` / `memory` / `toolbox` / `activity-registry` / `process` 各自的 adapter |
|
||
|
||
治理台九功能**不设**后端"governance 模块":每个功能是对应模块的管理用例 + `apps/api/src/app/routes/governance/*` 的路由组装;前端是 `gov-*` features。工作台五要素同理(`desk-*` features + 各模块用例)。
|
||
|
||
---
|
||
|
||
## 4. 后端模块清单
|
||
|
||
依赖层级 L1 最低;**import 只准指向更低层级模块的 `index.ts`;同层模块互不 import,协作走 port + app 装配**(§5)。
|
||
|
||
| 层 | 模块 | 职责(一句话) | 语义出处 |
|
||
|---|---|---|---|
|
||
| L1 | `event` | 统一事件标准:信封存储、归属解析、投递五诺(先持久后投递/同任务按序/至少一次+幂等/死信回执/无主兜底);监听注册表与出站关联记录存放于此——上层经出口写入,归属解析对表匹配,不反向依赖上层 | OS 06 |
|
||
| L1 | `org` | 员工与岗位:账号、岗位授权(客体三类×动作三种)、停用前置检查 | OS 02 |
|
||
| L1 | `llm` | LLM 实例:自定义模型名 → 四元绑定(Provider 枚举/URL/API-Key/Model),ModelGateway 含录制/回放缝 | OS 04/11 |
|
||
| L1 | `ledger` | 数据与台账:三级寻址、通用事务接口、schema 自生长(最大化合并/最宽类型/只增不破坏)、任务级草稿层与任务视图、写三分 | OS 04/09 |
|
||
| L2 | `memory` | 任务记忆(会话历史+窗口配置)、活动记忆四层存取、任务日志两级投影、蒸馏钩子执行 | OS 08 |
|
||
| L2 | `toolbox` | 功能工具注册与两审、调用契约、效应等级、连接配置声明与凭证绑定、调用留痕、纯工具作用域 | OS 07 |
|
||
| L2 | `channel` | 通道实例:入站归一(解析→系统写→数据事件)、出站发送 | OS 07 |
|
||
| L2 | `message` | 系统消息:通知、跨任务征答收件箱、死信与回执的人侧呈现 | OS 02/06 |
|
||
| L3 | `interaction` | 交互协议:对话流单入口、视图区推送、控制权按态转交、SSE 会话 | OS 02,AM 07 |
|
||
| L3 | `human-tool` | 人类工具:工单两模式(执行/验收)+ 对话卡族(决策/补全/评价)的卡协议与回传校验、到达面两路、跨人卡、驳回重答 | OS 05,AM 06 |
|
||
| L4 | `release` | 放行与落地:落地预检、放行写合并、幂等落地、落地失败卡、输出口发射 | OS 7.3/09,AM 06 |
|
||
| L4 | `activity-registry` | 活动库:包清单六区、安装两审(静态审+回放审)、包版本×资产版本、两维分类、.JS 装载、资产版本进化管线(候选增量状态机 → 回放重演 → 人放行生效 → 回退) | OS 11,AM 11 |
|
||
| L4 | `skill-engine` | skill 范式:技能脚本(结晶片段 = 确定性动作链)运行器——装配语义、三层软硬、**载方法不载权力**(脚本引用的工具仍过本活动白名单与调用契约);loop 临场装配 / flow 步引用 / 纯技能活动由 task 直跑 | AM 08 |
|
||
| L5 | `loop-engine` | loop 范式:CMMN+DMN 语义引擎(纯 domain)× Agent 回路(Mastra Agent 为 case worker)。**CMMN 子集封顶**:构件与生命周期以 AM 03 构件表 + AM 4.1 两副状态表为全集,不实现 CMMN 1.1 其余构件,扩构件 = 改本行 + ADR;**DMN 落点**:DRD 遍历、决策表求值与命中行留痕在本模块 domain,单元格谓词复用 `@sfeel` | AM 03/04 |
|
||
| L5 | `flow-engine` | flow 范式:步序声明运行器(四种步型、重试与兜底、事件即步条件) | AM 05 |
|
||
| L6 | `task` | 任务运行时:生命周期与终态五名裁定、Harness 预算执行器/停滞熔断、控制三语义、改派、断点续跑 | OS 04,AM 01/10 |
|
||
| L7 | `process` | 流程层:流程包定义与版本、边映射闭合校验、工作流实例(网关/审批点/失败走向/负责人四策略/聚合) | OS 03 |
|
||
| L7 | `trigger` | 触发器三类(周期两型/事件/登记),独立配置存放,判定与调用接口调起 | OS 03 |
|
||
| L8 | `minute` | 纪要:团队主动记录,可带触发器 | OS 02 |
|
||
| L8 | `report` | 汇报:日/周/月/年对任务日志的聚合投影 | OS 02/08 |
|
||
|
||
约束:
|
||
|
||
- 技能编排属于活动(AM:活动内容物含技能清单)——`skill-engine` 与 loop/flow 同列范式运行器;置于 L4 因两范式依赖它(临场装配/步引用),import 恒向下、免 port。
|
||
- 找不到归属的代码,先怀疑模块拆分错了,再考虑 `shared/`;`shared/` 只收无业务语义的纯工具
|
||
- 度量八指标(OS 8.3)是 `memory`(任务日志)与 `task`(终态/纠正信号)之上的**只读投影**,落 `report` 的用例,不设独立模块
|
||
- 鉴权定调:单组织 cookie session——登录、会话与岗位权限校验中间件在 apps/api 的 app 层实现,权限判定读 `org` 出口;不引 OAuth/OIDC 与多租户机制
|
||
|
||
---
|
||
|
||
## 5. 依赖方向(硬规则)
|
||
|
||
### 5.1 顶层
|
||
|
||
```
|
||
apps/web ──┐
|
||
├─→ packages/contracts ─→ (无依赖)
|
||
apps/api ──┘
|
||
├─→ packages/sfeel, packages/utils
|
||
apps/web ──→ packages/ui-kit
|
||
activities/* ──→ packages/activity-sdk ──→ packages/contracts
|
||
```
|
||
|
||
- `apps/web` 与 `apps/api` 互不 import;跨端唯一通道是 `packages/contracts`(路由契约 zod schema + 推导类型)。**禁止 Hono RPC 客户端**——它要求前端 import 后端类型,违反本条
|
||
- `packages/*` 不得反向 import `apps/*`;`packages/utils` 是叶子
|
||
- `activities/*` 只准 import `@sdk`、`@contracts` 与白名单纯库;`apps/**` 与 `activities/**` 互不静态 import(活动经安装装载,ADR-004)
|
||
|
||
### 5.2 应用内
|
||
|
||
```
|
||
app/ ─→ modules/<x>(只经 index.ts)─→ 更低层模块 index.ts ─→ shared/, packages/*
|
||
```
|
||
|
||
- `app/` 是唯一组装层:只有这里能同时认识多个模块,new 出 adapter、注入 port、注册路由/worker/Mastra 实例
|
||
- 模块 import 模块:**只准指向 §4 表中层级更低者的 `index.ts`**;同层互需(如 `release` 落地时要发落地失败卡 vs `human-tool`)一律由需要方声明 port、app 层把对方的用例注入
|
||
- 任何文件不得 import `modules/*/internal/**`(同模块自己除外)
|
||
|
||
### 5.3 模块内
|
||
|
||
```
|
||
adapter/ ──实现──→ port.ts ←──依赖── usecase/ ──→ domain/
|
||
```
|
||
|
||
- `domain/`:纯函数、值对象、领域错误。**零 IO、零框架、零 Date.now/Math.random**(时钟与随机走 port)。npm 白名单:`zod`、`decimal.js`、`date-fns` + 仓内纯包 `@contracts`、`@sfeel`、`@utils`
|
||
- `usecase/`:编排 domain,依赖 `port.ts` 声明的能力(`EventPublisher`、`ModelGateway`、`Clock`…),不 import 任何 adapter
|
||
- `adapter/`:实现 port。**Drizzle / pg / pg-boss / @mastra/\* / AI SDK 只准出现在 adapter 与 app**(§11 机器强制)
|
||
- 优先导出工厂函数而非 class
|
||
|
||
### 5.4 模块依赖图(权威在 §4 层级表,此图为速览)
|
||
|
||
```mermaid
|
||
graph BT
|
||
subgraph L1
|
||
event; org; llm; ledger
|
||
end
|
||
subgraph L2
|
||
memory; toolbox; channel; message
|
||
end
|
||
subgraph L3
|
||
interaction; human-tool
|
||
end
|
||
subgraph L4
|
||
release; activity-registry; skill-engine
|
||
end
|
||
subgraph L5
|
||
loop-engine; flow-engine
|
||
end
|
||
task --> loop-engine & flow-engine & activity-registry
|
||
loop-engine & flow-engine --> skill-engine
|
||
process --> task
|
||
trigger --> process
|
||
L5 --> L4 --> L3 --> L2 --> L1
|
||
```
|
||
|
||
---
|
||
|
||
## 6. Mastra 能力映射
|
||
|
||
Mastra 承担四件事:**图编排(含挂起/恢复与快照持久)、Agent 回路、会话记忆、工具定义**。它是实现件,不是架构件——**架构语义以两卷为准,Mastra 的概念不得泄漏进 domain/usecase**。
|
||
|
||
### 6.1 映射表
|
||
|
||
| 系统概念 | Mastra 机制 | 落点(adapter) |
|
||
|---|---|---|
|
||
| 流程包 → 工作流实例(图编排) | 流程包版本(DB 中的 DSL)动态编译为 `createWorkflow`/`createStep` 图;XOR 网关 = `.branch()`,AND 网关 = `.parallel()`,条件求值调 `@sfeel` | `process/internal/adapter/workflow-compiler.ts` |
|
||
| 审批点 / 活动节点等终态 | `suspend()` 挂起,快照持久于存储;审批卡回传、任务终态事件到达后按 runId `resume(payload)` | `process` adapter |
|
||
| 崩溃后续跑 | Mastra 快照 + 启动时恢复活跃 run(`restartAllActiveWorkflowRuns`) | `app/boot.ts` |
|
||
| flow 活动步序 | 每活动版本的步序声明编译为一条 Mastra workflow:步→step(重试参数随声明),人类工具步/监听步 = `suspend()`,人事件/数据事件消费者 `resume` | `flow-engine` adapter |
|
||
| loop 活动 Agent 回路 | Mastra `Agent`,`instructions/tools/model` 全部走 `({ requestContext }) =>` 动态形态:按任务注入案例模型装载、白名单工具、活动声明的模型;**回合由 usecase 驱动,不放开自由 maxSteps,预算在环外由 Harness 强制** | `loop-engine/internal/adapter/agent-runner.ts` |
|
||
| 任务记忆 = 会话历史 + 窗口配置 | `@mastra/memory` `Memory`,thread = 任务 ID、resource = 活动 ID;**窗口配置 ↔ `options.lastMessages`**(活动唯一记忆接口,AM 09) | `memory` adapter |
|
||
| LLM 工具 / 功能工具呈现给 Agent | `createTool`(zod 入参);功能工具由调用契约(JSON Schema)在注册时转换生成,execute 内走 `toolbox` 调用留痕 | `toolbox` adapter |
|
||
| 模型四元绑定 | Provider 枚举 → AI SDK provider 工厂(`baseURL`/`apiKey`)→ 模型实例;活动只见自定义模型名,解析在 `llm` | `llm/internal/adapter/model-gateway.ts` |
|
||
| 活动记忆四层 / 蒸馏 | **不用** Mastra working memory(语义不合:活动记忆是结构化四层、只经蒸馏写入)——自研 sys 表;装载选摘可选 PgVector 语义召回 | `memory` adapter |
|
||
|
||
### 6.2 边界三规则(机器强制,§11)
|
||
|
||
1. `@mastra/*` 与 AI SDK 只准出现在 `internal/adapter/**` 与 `app/**`
|
||
2. port 与 contract 一律用自定义类型,不得出现 Mastra 类型(`Agent`、`Workflow`、`Memory` 等不出 adapter)
|
||
3. Mastra 存储表(`mastra` schema)由 Mastra 单写;业务代码不得直读直写,投影一律经 `memory` 模块出口
|
||
|
||
### 6.3 骨架示例
|
||
|
||
流程包编译(process adapter,示意):
|
||
|
||
```ts
|
||
// process/internal/adapter/workflow-compiler.ts
|
||
import { createWorkflow, createStep } from '@mastra/core/workflows';
|
||
import { evaluate } from '@sfeel';
|
||
import type { ProcessPackage } from '@contracts';
|
||
|
||
export function compile(pkg: ProcessPackage, deps: CompilerDeps) {
|
||
const steps = pkg.nodes.map(node => createStep({
|
||
id: node.id,
|
||
execute: async ({ inputData, suspend, resumeData }) => {
|
||
if (resumeData) return deps.mapOutcome(node, resumeData); // 任务终态/审批回传到达
|
||
await deps.startNode(node, deps.assemble(node.inEdges, inputData)); // 起任务/发审批卡(边映射装配)
|
||
return suspend({}); // 等终态事件 resume
|
||
},
|
||
}));
|
||
// XOR → .branch([[d => evaluate(edge.cond, d), step]...]);AND → .parallel(...)
|
||
return createWorkflow({ id: pkg.id + '@' + pkg.version, /* zod io */ })
|
||
.then(/* 按 pkg.edges 组图 */).commit();
|
||
}
|
||
```
|
||
|
||
loop 回合驱动(loop-engine usecase,示意——三型行动与断点判定是 domain,Agent 是 port):
|
||
|
||
```ts
|
||
// loop-engine/internal/usecase/run-turn.ts
|
||
export function createTurnRunner(deps: { engine: CmmnEngine; agent: AgentPort; harness: HarnessPort }) {
|
||
return async function runTurn(taskId: TaskId) {
|
||
await deps.harness.assertBudget(taskId); // 预算环外强制
|
||
const enabled = await deps.engine.evaluate(taskId); // 语义引擎:Enabled 集与红绿灯(零 LLM)
|
||
const action = await deps.agent.decide(taskId, enabled); // Agent 决断(Mastra 在 adapter)
|
||
switch (action.kind) { // 三型行动,AM 04
|
||
case 'tool': return deps.engine.applyToolResult(taskId, await deps.agent.invoke(action));
|
||
case 'human': return deps.engine.suspendOnCard(taskId, action.card); // 调人 = 立监听听人
|
||
case 'listen': return deps.engine.registerListener(taskId, action.listener);
|
||
}
|
||
};
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 7. 持久层
|
||
|
||
单 PostgreSQL 实例,四个 schema,**各自单写者**——这是「资产与包分离,各自单写者」原则(OS 11.3)在存储上的同构:
|
||
|
||
| schema | 内容 | 写者 | 迁移方式 |
|
||
|---|---|---|---|
|
||
| `sys` | 系统自持:员工/岗位、LLM 实例、工具注册表、活动库(包×资产两序列)、流程包、触发器配置、事件存储、消息、任务与工作流台账、活动记忆四层、回放录制 | 各模块 adapter(经 Drizzle) | drizzle-kit,随系统版本 |
|
||
| `ledger` | 活动自生长台账:正式版、任务级草稿层、共享域 | 仅 `ledger` adapter(动态 DDL/DML,raw pg) | 声明合并自生长,无人工迁移 |
|
||
| `mastra` | Mastra 存储:线程/消息(任务记忆会话轴)、workflow 快照 | 仅 Mastra(`@mastra/pg` PostgresStore) | Mastra 自管 |
|
||
| `queue` | pg-boss 作业表 | 仅 pg-boss | pg-boss 自管 |
|
||
|
||
### 7.1 事件存储与投递五诺(实现要点)
|
||
|
||
| 承诺(OS 06) | 实现 |
|
||
|---|---|
|
||
| 先持久后投递 | 信封写 `sys.event` 与 pg-boss 入队在**同一事务** |
|
||
| 同任务按序 | 任务级串行消费:按目标 ID 取 advisory lock 的串行执行器 |
|
||
| 至少一次 + 幂等 | pg-boss 至少一次;消费侧幂等表(事件 ID × 消费者)唯一约束 |
|
||
| 回执与死信走系统通知 | 重试超限 → `message` 模块 port(app 装配) |
|
||
| 无主兜底 | 归属解析(`event` domain)无主 → `message` |
|
||
|
||
### 7.2 台账自生长与草稿层
|
||
|
||
- 声明合并(最大化合并/最宽兼容类型/只增不破坏)是**纯算法**,落 `ledger/internal/domain/schema-merge.ts`,零 mock 全覆盖测试;DDL 生成与执行在 adapter
|
||
- 草稿层:推荐形态为 `ledger.__draft`(task_id × 对象 × 主键 × patch jsonb),读时叠加出**任务视图**;物理形态可换,**功能约束不可变**:读己之写、不产生数据事件、放行合并原子且过数据冲突检查(与 `release` 协作经 port)
|
||
- 写三分(系统写/草稿写/放行写)是 `ledger` 出口上的**三个不同方法**,不是一个带 flag 的方法——调用方拿不到"绕门"的形态
|
||
|
||
### 7.3 录制与回放(回放审的底盘)
|
||
|
||
两条缝,一个开关:`llm` 的 `ModelGateway` 与 `toolbox` 的 `ToolInvoker` 都支持 `record | replay | live` 模式,录制落 `sys.replay_*`(按任务×步序号)。回放审(OS 11.2)= 用 replay 模式的 adapter 重跑引擎;样例集/契约测试集走同一夹具(@sdk 提供)。**新增任何外部 IO 必须过这两缝之一,否则回放审对它失明——这是新增 port 的验收条件。**
|
||
|
||
---
|
||
|
||
## 8. packages 清单
|
||
|
||
### 8.1 `@contracts`(前后端唯一共享点)
|
||
|
||
只有 zod schema、常量、品牌类型与推导类型,零实现。内容物按文件:
|
||
|
||
```
|
||
envelope.ts 信封六字段 + 四类事件(数据/时间/人/控制)
|
||
terminal.ts 终态五名:'released'|'blocked'|'stalled'|'exhausted'|'terminated' + 非终态注记
|
||
card.ts 人类工具 schema:工单两模式(执行 = 空表单/验收 = 可修订报告)+ 对话卡族(决策/补全/评价)+ 落地失败卡(执行工单预置形态)+ 回传协议
|
||
contract7.ts 契约七件(输入 data+message / 输出口 / 必交付物 / 验收判据 L1–L5 / 禁区 / 授权边界 / 资源声明)
|
||
process-package.ts 流程包 DSL:节点/边与载荷映射/审批点/两种网关/失败走向四选一/S-FEEL 表达式引用
|
||
manifest.ts 活动包清单六区(身份/契约/声明/资产初始版/样例集/代码入口)
|
||
ledger.ts 三级寻址(域.对象.字段)、事务接口 DTO、任务视图 DTO
|
||
api/ 路由契约(按面分文件:workbench.ts / governance.ts / ingest.ts)
|
||
id.ts 品牌 ID(TaskId/WorkflowId/ActivityId/EventId/StaffId…)
|
||
```
|
||
|
||
修改本包任何导出 = 契约变更(§12.4)。
|
||
|
||
### 8.2 `@activity-sdk` 与 `activities/`
|
||
|
||
- SDK = 活动开发者看到的世界:**基座六件接口**(`ContractSpec` / `InteractionHandle` / `MemoryHandle` / `LedgerHandle` / `ToolInvoker` / `LlmHandle`)+ `defineActivity()` 入口 + 本地开发宿主(mock 工具表、模拟人类工具(工单/卡)、回放夹具)+ 编译预设(tsup → 单文件 ESM)
|
||
- 活动包 ABI(ADR-004):默认导出 `defineActivity({...})` 的返回值;包内不得出现 SDK 与白名单纯库之外的 import,不得触任何环境能力(`process.env`/`fs`/`fetch`…)——**静态审扫描产物 import 与全局引用,不过不上架**
|
||
- `activities/` 是第一方活动的仓内工位,与 api 之间**只有安装通道**(registry 装载编译产物),没有代码通道
|
||
|
||
### 8.3 `@sfeel`
|
||
|
||
S-FEEL 子集(OS 03 定义域)的解析与求值,纯函数。被 `process`(边条件/失败走向)、`flow-engine`(条件谓词)、`trigger`(判定)、前端 `gov-process`(画布即时校验预览)共用——**求值语义一份代码,前后端同源**;后端裁决为权威。
|
||
|
||
---
|
||
|
||
## 9. 前端(apps/web)
|
||
|
||
> **范式 × 交互,双层边界(定调)**:**执行范式是后端实现逻辑的模型,交互模型是前端呈现协议——两层不冲突**(AM 本就规定两范式统一执行契约、对交互层不可区分)。范式 = loop / flow / skill,只存在于引擎层;前端**永远感知不到范式**,只感知统一交互模型——**任务面四区**(任务列表/标题区/工作区/对话区)、**工单两模式**(验收 = AI 拟好的报告可修改;执行 = 指导书 + 空表单)、**对话卡族**(决策/补全/任务评价,补全含「没法填」旁路,决策含自定义收尾项),以 2026-07-26 原型定稿为准。旧文「四卡」是交互层旧措辞,映射:执行卡→执行工单、放行卡→验收(工作区报告 + 对话区验收单)、决策/补全→对话卡;两卷交互章节措辞待同步,同步前**交互结构与视觉以原型为准**,语义打架的落点照前言规矩停下来报告。
|
||
|
||
### 9.1 features 清单
|
||
|
||
| 组 | feature | 职责 |
|
||
|---|---|---|
|
||
| 工作台 | `desk-task` | 任务要素四区:任务列表 / 标题区 / 工作区(工单两模式 + 驾驶舱)/ 对话区(卡族 + composer 锁);控制权按态转交的呈现 |
|
||
| | `desk-approval` | 审批点收件与裁决 |
|
||
| | `desk-message` | 消息:通知、跨任务征答就地作答、死信回执 |
|
||
| | `desk-minute` | 纪要(可带触发器) |
|
||
| | `desk-report` | 汇报:日/周/月/年聚合 |
|
||
| 治理台 | `gov-task` | 任务管理:监控、控制事件、改派、任务日志查看 |
|
||
| | `gov-staff` | 员工管理:账号、岗位授权、停用检查 |
|
||
| | `gov-process` | 流程包编排画布(diagram-js 画布件平移):**连线即映射、画图即校验、不闭合不得发布**;导出依赖文件 |
|
||
| | `gov-trigger` | 触发器配置(三类) |
|
||
| | `gov-activity` | 活动库:安装/两审结果/两维分类/包×资产版本 |
|
||
| | `gov-tool` | 工具管理:注册、白名单、凭证绑定 |
|
||
| | `gov-data` | 数据管理:域/对象目录、schema 视图、**记录浏览与管理**(检索/分页/记录详情;修订走草稿写、归档走确认带)、清理归档 |
|
||
| | `gov-memory` | 记忆管理:活动记忆四层、修剪 |
|
||
| | `gov-system` | 系统管理:LLM 实例四元绑定、通道实例、系统用途模型 |
|
||
|
||
### 9.2 前端硬规则
|
||
|
||
- 服务端交互只经 `shared/typed-fetch` + `@contracts/api` 的路由契约;组件内禁止裸 `fetch`
|
||
- 对话流与视图区推送经单一 SSE 连接(`app/` 建连,feature 订阅);**前端零过程状态**(OS 10):刷新即从服务端投影重建
|
||
- 视图区容器渲染活动推送的 HTML:**沙箱 iframe(`srcdoc` + `sandbox` 属性)或净化后注入,二选一由 `ui-kit` 的 `ViewContainer` 统一实现,feature 不得自行 `dangerouslySetInnerHTML`**;无脚本执行权(AM 07)
|
||
- 卡片表单由 `@contracts/card.ts` schema 驱动渲染与校验,与后端回传校验同 schema
|
||
- SSE 事件到达 → 按信封目标(任务/工作流/要素)**失效对应 TanStack Query 缓存**,由订阅层统一做;组件禁止自行轮询或手写缓存
|
||
- 路由状态即应用状态:当前区/页签/下钻栈可从 URL 完整还原(TanStack Router 类型化 search params);内存路由栈只是原型期形态,正式系统必须可深链
|
||
|
||
---
|
||
|
||
## 10. 模块骨架与命名
|
||
|
||
### 10.1 固定骨架
|
||
|
||
新建模块严格照抄,不许发明变体(以 `ledger` 为例):
|
||
|
||
```ts
|
||
// modules/ledger/contract.ts —— 对外类型,只有类型和常量,没有实现
|
||
export type LedgerAddress = { domain: string; object: string; field?: string };
|
||
export class DraftConflictError extends Error {}
|
||
```
|
||
|
||
```ts
|
||
// modules/ledger/port.ts —— 本模块要外界提供的能力
|
||
export interface EventPublisher { publish(e: EnvelopeDraft): Promise<void> }
|
||
export interface Clock { now(): Date }
|
||
```
|
||
|
||
```ts
|
||
// modules/ledger/index.ts —— 唯一出口。只做 re-export,不写逻辑
|
||
export type { LedgerAddress } from './contract';
|
||
export { DraftConflictError } from './contract';
|
||
export type { EventPublisher, Clock } from './port';
|
||
export { createLedgerService } from './internal/usecase/ledger-service';
|
||
```
|
||
|
||
规则:
|
||
|
||
- `index.ts` 只允许 `export` 语句,零逻辑零副作用
|
||
- `contract.ts` 不得 import `internal/`
|
||
- `internal/` 内禁止 barrel 文件,直接引用具体文件
|
||
- 每个模块根有 `CONTRACT.md`(模板见 §12.6)
|
||
|
||
### 10.2 术语表(中文概念 → 代码标识符)
|
||
|
||
命名以本表为准,禁止一概念多名:
|
||
|
||
| 中文 | 代码 | 中文 | 代码 |
|
||
|---|---|---|---|
|
||
| 活动 / 任务 | activity / task | 放行 / 落地 / 预检 | release / landing / precheck |
|
||
| 流程包 / 工作流 | process package / workflow | 驳回(重做/迭代) | reject (redo / revise) |
|
||
| 触发器(周期/事件/登记) | trigger (periodic / event / registration) | 终态五名 | released / blocked / stalled / exhausted / terminated |
|
||
| 审批点 / 网关(并行/异或) | approval point / gateway (parallel / exclusive) | 叫停 / 暂停 / 终止 | halt / pause / terminate |
|
||
| 边与载荷映射 | edge mapping | 台账 / 草稿层 / 任务视图 | ledger / draft layer / task view |
|
||
| 负责人 / 岗位 | owner / position | 信封 / 留痕 / 归侧 | envelope / trace / attribution |
|
||
| 工单两模式(执行/验收) | work order (execution / acceptance) | 归属解析 / 无主兜底 / 死信 | ownership resolution / unowned fallback / dead letter |
|
||
| 对话卡族:决策/补全/评价 | decision / elicitation / rating card | 技能范式 / 结晶片段 | skill paradigm / crystallized fragment |
|
||
| 输出口(必发/选择) | output port (mandatory / selective) | 催办 / 时限 / 监听 | nudge / deadline / listener |
|
||
| 契约七件 | seven-part contract | 蒸馏 / 装载 / 技能 | distill / load / skill |
|
||
| 验收判据 L1–L5 | acceptance criteria | 白名单 / 禁区 / 授权边界 | allowlist / prohibition / authorization boundary |
|
||
| 活动记忆四层:事实/模式/裁决/例外 | fact / pattern / verdict / exception layer | 停滞 / 熔断 / 预算 | stall / circuit-break / budget |
|
||
| 工作台 / 治理台 | workbench / governance console | 改派 / 起单 | reassign / initiate |
|
||
|
||
---
|
||
|
||
## 11. 机器强制配置
|
||
|
||
规范靠嘱咐是守不住的。以下配置必须存在且在 CI 执行;**约束报错时,改代码,不改约束**。
|
||
|
||
### 11.1 tsconfig(根)
|
||
|
||
```jsonc
|
||
{
|
||
"compilerOptions": {
|
||
"strict": true,
|
||
"noUncheckedIndexedAccess": true,
|
||
"exactOptionalPropertyTypes": true,
|
||
"noImplicitOverride": true,
|
||
"verbatimModuleSyntax": true,
|
||
"isolatedModules": true,
|
||
"moduleResolution": "bundler",
|
||
"paths": {
|
||
"@contracts": ["./packages/contracts/src/index.ts"],
|
||
"@sdk": ["./packages/activity-sdk/src/index.ts"],
|
||
"@sfeel": ["./packages/sfeel/src/index.ts"],
|
||
"@ui": ["./packages/ui-kit/src/index.ts"],
|
||
"@utils": ["./packages/utils/src/index.ts"],
|
||
"@modules/*": ["./apps/api/src/modules/*"],
|
||
"@features/*": ["./apps/web/src/features/*"]
|
||
}
|
||
}
|
||
}
|
||
```
|
||
|
||
### 11.2 更硬的封装(启用)
|
||
|
||
每个模块加 workspace 包 `package.json`,用 `exports` 做解析层封装(穿透 internal 直接解析失败):
|
||
|
||
```jsonc
|
||
{ "name": "@order", "private": true, "exports": { ".": "./index.ts" } }
|
||
```
|
||
|
||
### 11.3 ESLint(要点)
|
||
|
||
```js
|
||
'no-restricted-imports': ['error', { patterns: [
|
||
{ group: ['**/internal/**'], message: '禁止穿透模块出口' },
|
||
{ group: ['@modules/*/*', '@features/*/*'], message: '只能 import 到模块根' },
|
||
{ group: ['../../../*'], message: '跨模块请用路径别名' },
|
||
]}],
|
||
'@typescript-eslint/no-explicit-any': 'error',
|
||
'@typescript-eslint/consistent-type-imports': 'error',
|
||
'@typescript-eslint/ban-ts-comment': 'error',
|
||
```
|
||
|
||
### 11.4 dependency-cruiser(在基线规则之上,JCAI 增补)
|
||
|
||
基线八条(no-circular / no-cross-module-internal / app-not-into-internal / domain-is-pure / usecase-not-to-adapter / web-not-to-api / packages-are-leaves / no-orphans)由 M0 依名实现(见本节末注),之上增补:
|
||
|
||
```js
|
||
{ name: 'framework-only-in-adapter',
|
||
comment: 'Mastra/AI SDK/Drizzle/pg/pg-boss 只准在 adapter 与 app',
|
||
severity: 'error',
|
||
from: { path: 'src/modules/.+/internal/(domain|usecase)/' },
|
||
to: { path: 'node_modules/(@mastra|ai|@ai-sdk|drizzle-orm|pg|pg-boss)' } },
|
||
{ name: 'tier-order',
|
||
comment: '模块只准依赖 §4 表中更低层级;矩阵与本文件同步维护',
|
||
severity: 'error',
|
||
from: { path: '^apps/api/src/modules/(process|trigger|minute|report)/' },
|
||
to: { path: '^apps/api/src/modules/$1/' , pathNot: '…按 §4 层级表展开为逐层规则…' } },
|
||
{ name: 'activities-isolated',
|
||
severity: 'error',
|
||
from: { path: '^activities/' }, to: { path: '^apps/' } },
|
||
{ name: 'apps-not-into-activities',
|
||
severity: 'error',
|
||
from: { path: '^apps/' }, to: { path: '^activities/' } },
|
||
```
|
||
|
||
`tier-order` 的完整展开由 `tools/gen-depcruise-tiers.ts` 从 §4 层级表(以 JSON 形式维护在 `tools/module-tiers.json`)生成——**改层级 = 改 JSON + 改本文件 §4,一起提交**。
|
||
|
||
八条基线规则不随包携带定义——M0 依规则名实现(语义见其名与 §5 的依赖规则);**本文件自足,门禁配置不依赖任何外部基线文件**。
|
||
|
||
### 11.5 契约快照与 CI 门禁
|
||
|
||
```bash
|
||
pnpm tsc --noEmit
|
||
pnpm eslint .
|
||
pnpm depcruise apps packages activities
|
||
pnpm api:check # tsc --emitDeclarationOnly → api-report/ 与 git diff 比对
|
||
pnpm test
|
||
```
|
||
|
||
改 `internal/` 时 `api-report/` 纹丝不动;碰了公开契约,diff 立刻可见。
|
||
|
||
---
|
||
|
||
## 12. AI 协作协议(多 Agent 并行 · 主 Agent 编排制)
|
||
|
||
### 12.0 角色与授权矩阵
|
||
|
||
三层角色,授权自上而下收窄:
|
||
|
||
| 角色 | 职责 | 权限要点 |
|
||
|---|---|---|
|
||
| 用户(终审) | 只审三类保留项 | ①破坏性契约变更(12.4) ②新增 npm 依赖(§1 表外,12.5#3) ③修改门禁与规则(§11 配置、本文件、module-tiers.json,12.5#8) |
|
||
| 主 Agent(唯一集成人) | 拆承包工单派活、仲裁跨模块契约、把关合入主干(12.7)、维护 docs/debt.md 与 ADR | **契约单写者**:`@contracts` 与全部模块契约面(index.ts / contract.ts / port.ts / CONTRACT.md)只经它变更或合入 |
|
||
| 子 Agent(模块承包者) | 在承包工单允许范围内自主实现与测试 | 工单范围内 `internal/**` 与 `__tests__/**` 自由改动,不逐次申请;触碰契约面即停,向主 Agent 提变更申请 |
|
||
|
||
### 12.1 三段式工作流(承包工单级)
|
||
|
||
三段式以**承包工单**为单位,不以单次改动为单位:①侦察(子 Agent 领单后只读摸底:相关模块 CONTRACT.md 摘要、文件清单、当前公开契约签名、改动落点判断)→ ②计划(变更申请单,交主 Agent 批)→ ③执行(严格按单,不增单外文件)。工单范围内的 internal 改动不再逐次申请;越界即停(12.3)。
|
||
|
||
### 12.2 变更申请单模板
|
||
|
||
```
|
||
## 变更申请
|
||
申请人: <子 Agent · 工单号>
|
||
审批人: 主 Agent(涉 12.0 用户保留三类的,由主 Agent 上升)
|
||
模块: apps/api/src/modules/ledger
|
||
变更层: internal/domain
|
||
允许修改: internal/domain/schema-merge.ts;__tests__/schema-merge.test.ts(新增)
|
||
禁止修改: index.ts, contract.ts, port.ts, 其他任何模块
|
||
契约影响: 无——公开签名不变,api-report/ 预期无 diff
|
||
新增依赖: 无
|
||
新增测试: 同名异型取最宽类型;互斥类型拦下报错
|
||
风险: 安装静态审共用该函数,需回归 activity-registry 测试
|
||
```
|
||
|
||
### 12.3 越界条款
|
||
|
||
判断必须改申请范围外的文件才能完成任务时:**立即停止编码**,输出「需要越界:原因 / 最小方案 / 替代方案」,等主 Agent 确认(涉用户保留三类的由主 Agent 上升)。不得先改再说明。
|
||
|
||
### 12.4 契约变更的额外要求
|
||
|
||
修改 `index.ts` / `contract.ts` / `port.ts` / `@contracts` 任何导出,除三段式外还需:①depcruise 反查列出全部下游受影响模块;②同步更新该模块 CONTRACT.md;③更新 api-report/ 快照并单独说明;④破坏性变更走「先加新的、旧的标 `@deprecated`、下个迭代删除」三步。契约变更的执行与合入只归主 Agent(子 Agent 以提案交单);破坏性变更须用户终审(12.0)。
|
||
|
||
### 12.5 禁止清单(未经授权一律禁止;授权主体按 12.0 矩阵——契约面归主 Agent,#3 / #8 与破坏性契约归用户)
|
||
|
||
1. 修改任何 `index.ts` / `contract.ts` / `port.ts` / `@contracts`
|
||
2. 修改申请范围之外的任何文件;顺手重构、顺手改格式、顺手升级依赖
|
||
3. 新增 npm 依赖(§1 表外)
|
||
4. `any`、`as unknown as`、`@ts-ignore`、`@ts-expect-error`
|
||
5. 在 `domain/` 写 IO(fetch、fs、db、`Date.now`、`Math.random`)
|
||
6. 全局可变状态、单例缓存、模块级 `let`
|
||
7. 删除或跳过已有测试
|
||
8. 修改 `.dependency-cruiser.js` / `eslint.config.js` / `tsconfig.json` / `tools/module-tiers.json` 让报错消失
|
||
9. **绕过写三分**:任何台账写入不经 `ledger` 出口的三个方法之一
|
||
10. **绕过两缝**:任何模型调用不经 `ModelGateway`、任何工具执行不经 `ToolInvoker`(回放审会失明)
|
||
|
||
### 12.6 提交前自检 + CONTRACT.md
|
||
|
||
提交前自检清单,逐条打勾:diff 不超单 / tsc / eslint / depcruise / api-report / 有测试 / 无 any / 无单外重构 / 未动约束配置。每模块 CONTRACT.md 模板:
|
||
|
||
```markdown
|
||
# module: ledger
|
||
职责: 台账:三级寻址、事务接口、schema 自生长、草稿层与任务视图、写三分
|
||
不负责: 放行时机与预检(见 release)、数据事件投递(见 event)
|
||
公开出口: index.ts —— <逐项列出>
|
||
依赖: @contracts;port:EventPublisher(app 注入 event)、Clock
|
||
被依赖: channel, release, activity-registry, loop-engine, flow-engine, task, trigger
|
||
不变量: 正式版写入必产生数据事件;草稿写不产生事件;同名异型取最宽兼容类型;声明只增不破坏
|
||
影响半径: index/contract/port 未变 → 对外零影响
|
||
```
|
||
|
||
### 12.7 git 工作流(并行合入)
|
||
|
||
- 主干受保护:**只有主 Agent 合入**;合入前五门禁全绿(§11.5),且 api-report/ 的 diff 与申请单「契约影响」声明一致
|
||
- **分支即工单**:每张承包工单一条分支 `wo/<模块>-<短述>`;子 Agent 只在自己分支提交,不碰他人分支与主干
|
||
- 合入 rebase 后快进(或 squash),保持线性历史;冲突回子 Agent 分支解决,主干上不解决冲突
|
||
- 契约面变更单独成分支、单独合入,并**先于**依赖它的实现工单
|
||
- 提交信息 `<模块>: <一句话>`,正文引用工单号
|
||
|
||
---
|
||
|
||
## 13. 对基线工程规范的调整清单
|
||
|
||
依据「不合理可调整」授权,差异全部登记于此。基线工程规范不随包——本表仅记录本文件的出身差异,**本文件自足生效,无需回查基线**:
|
||
|
||
| # | 调整 | 理由 |
|
||
|---|---|---|
|
||
| 1 | `packages/` 增加 `activity-sdk`、`sfeel` 两个**带业务语义**的包(基线只允许 contracts/ui-kit/utils) | 活动 SDK 必须可独立发布给系统外开发者;S-FEEL 求值前后端同源。二者仍受「叶子不依赖 apps」约束 |
|
||
| 2 | 新增顶层 `activities/` 工作区 | 「系统外开发」的仓内形态;以 depcruise 双向隔离代偿物理分仓 |
|
||
| 3 | 模块互依从「可以互相依赖(经 index)」收紧为「**只准依赖更低层级;同层走 port + app 装配**」 | 20 个模块的自由互依无法靠"不得成环"事后拦截;分层表可生成 depcruise 规则,机器可证 |
|
||
| 4 | domain npm 白名单增补仓内纯包 `@contracts` / `@sfeel` / `@utils` | 纯类型与纯函数,不破坏零 IO |
|
||
| 5 | 禁止清单增补 #9 写三分、#10 两缝 | 本系统的安全根基在放行门与回放审,须与结构规则同级强制 |
|
||
|
||
---
|
||
|
||
## 14. 决策记录(ADR)
|
||
|
||
已决(全文为准,细节在 `docs/adr/` 逐条建档):
|
||
|
||
- **ADR-001** 自建 Hono 应用,Mastra 以库形态嵌入;不用 Mastra server 对外暴露(鉴权/岗位权限/SSE 全归 app 层;开发期可另起 entry 用 mastra playground)
|
||
- **ADR-002** 持久分工:Drizzle(sys)/ raw pg(ledger 动态 DDL)/ pg-boss(队列定时)/ @mastra/pg(mastra schema),四写者互不越界
|
||
- **ADR-003** schema 方言:**声明层 = JSON Schema 2020-12 子集**(活动声明是数据,可 diff 可版本),**代码层 = zod**;运行时校验用 ajv;声明→zod 仅在工具呈现给 LLM 时转换
|
||
- **ADR-004** 活动 .JS 装载 ABI:单文件 ESM,默认导出 `defineActivity()`;能力全部注入(基座六件句柄),零环境能力;静态审扫描产物 import 与全局引用
|
||
- **ADR-005** 工具 `validate` 能力位:调用契约 `capabilities.validate?: true`,预检存在即调(OS 7.3 落地预检第四项)
|
||
- **ADR-006** S-FEEL 自研于 `@sfeel`,子集文法冻结于 OS 03;不引第三方 FEEL 引擎
|
||
|
||
留白(实现期再定,各建 ADR 后方可动工):鉴权会话与凭证加密方案;JSON Schema→zod 转换库选型;活动装载的 worker 隔离硬化;活动记忆向量召回启停;e2e 框架。
|
||
|
||
---
|
||
|
||
## 15. 实施序(里程碑)
|
||
|
||
每个里程碑必须先立骨架(index/contract/port/CONTRACT.md + 空测试)再填实现;门禁从 M0 起全绿。
|
||
|
||
| 里程碑 | 内容 |
|
||
|---|---|
|
||
| M0 | 工作区骨架 + 全部门禁跑通(tsc/eslint/depcruise/api:check/test 空转绿)+ 环境自举:docker-compose.yml(PG16,四 schema 初始化)、种子脚本(五名员工与岗位)、tools/module-tiers.json(从 §4 表生成)与 gen-depcruise-tiers.ts |
|
||
| M1 | 底座:`@contracts` 首版、`event`、`ledger`、`org`、`llm`(含录制回放缝)|
|
||
| M2 | 基座能力:`memory`、`toolbox`、`channel`、`message` |
|
||
| M3 | 执行面:`interaction`、`human-tool`、`release`、`activity-registry`、`@sfeel` |
|
||
| M4 | 范式引擎与任务:`skill-engine`、`loop-engine`、`flow-engine`、`task`(断点续跑三份持久贯通)|
|
||
| M5 | 流程层:`process`(编排校验 + 工作流实例)、`trigger`;`@activity-sdk` + 首个样例活动(`activities/`)|
|
||
| M6 | 前端:工作台五要素 → 治理台九功能;`minute`、`report` |
|
||
|
||
并行纪律(主 Agent 编排,12.0):**里程碑内模块并行承包**——同层模块互不依赖,天然可并行;**跨里程碑骨架先行**——下一里程碑各模块的 contract.ts / port.ts 骨架由主 Agent 提前冻结,下游子 Agent 对 port 的 mock 开工,不等上游填完;合入顺序按层级自低向高(§4)。
|
||
|
||
---
|
||
|
||
## 16. 新建模块检查清单
|
||
|
||
```
|
||
[ ] 目录名单数名词、kebab-case,且已登记 §4 层级表与 tools/module-tiers.json
|
||
[ ] 有 index.ts(纯 re-export)、contract.ts(纯类型)、port.ts(后端)
|
||
[ ] usecase 不 import adapter;domain 零 IO;Mastra/DB 只在 adapter
|
||
[ ] internal/ 无 barrel 文件
|
||
[ ] 有 CONTRACT.md;有 __tests__/,domain 测试零 mock
|
||
[ ] depcruise 通过:无入边指向 internal,无同层依赖
|
||
[ ] 若声明新 port:确认外部 IO 已过录制回放两缝之一(§7.3)
|
||
```
|
||
|
||
---
|
||
|
||
## 17. 例外与演进
|
||
|
||
- 本文件的任何例外必须写进本文件并注明原因与预期清理时间;散落的 `eslint-disable` 不算例外,算违规
|
||
- 历史违规集中登记 `docs/debt.md`:旧路径 `warn`、新代码 `error`,清零后升级
|
||
- 规则要改就改本文件并同步改配置(含 `tools/module-tiers.json`),一起提交。只改配置不改文档 = 规则失效
|
||
|
||
|