M0: 工作区骨架 + 五道门禁 + 环境自举
- 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
This commit is contained in:
@@ -0,0 +1,196 @@
|
||||
/* eslint-disable */
|
||||
/**
|
||||
* JCAI 依赖门禁 —— 编码规范 §11.4。
|
||||
*
|
||||
* 结构:基线八条(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)+ JCAI 增补四条(framework-only-in-adapter / tier-order /
|
||||
* activities-isolated / apps-not-into-activities)。
|
||||
*
|
||||
* tier-order 的逐层展开由 tools/gen-depcruise-tiers.ts 从 tools/module-tiers.json 生成。
|
||||
* **约束报错时,改代码,不改约束(§11)。**
|
||||
*/
|
||||
const tierRules = require('./tools/depcruise-tiers.generated.cjs');
|
||||
|
||||
const MODULES = '^apps/api/src/modules';
|
||||
|
||||
/** domain 层的 npm 白名单(§5.3):zod / decimal.js / date-fns + 仓内纯包 */
|
||||
const DOMAIN_NPM_ALLOWLIST = 'node_modules/(zod|decimal\\.js|date-fns)(/|$)';
|
||||
|
||||
module.exports = {
|
||||
forbidden: [
|
||||
// ── 基线八条 ────────────────────────────────────────────────────────────
|
||||
{
|
||||
name: 'no-circular',
|
||||
comment: '依赖方向单向无环(§0.1 第 3 条)',
|
||||
severity: 'error',
|
||||
from: {},
|
||||
to: { circular: true },
|
||||
},
|
||||
{
|
||||
name: 'no-cross-module-internal',
|
||||
comment: '任何文件不得 import modules/*/internal/**(同模块自己除外,§5.2)',
|
||||
severity: 'error',
|
||||
from: { pathNot: `${MODULES}/([^/]+)/` },
|
||||
to: { path: `${MODULES}/([^/]+)/internal/` },
|
||||
},
|
||||
{
|
||||
name: 'no-cross-module-internal-peer',
|
||||
comment: '模块之间只准 import 到对方的 index.ts,不得穿透 internal(§5.2)',
|
||||
severity: 'error',
|
||||
from: { path: `${MODULES}/([^/]+)/` },
|
||||
to: {
|
||||
path: `${MODULES}/([^/]+)/internal/`,
|
||||
pathNot: `${MODULES}/$1/internal/`,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'app-not-into-internal',
|
||||
comment: 'app/ 是组装层,只经模块出口认识模块(§5.2)',
|
||||
severity: 'error',
|
||||
from: { path: '^apps/(api|web)/src/app/' },
|
||||
to: { path: `${MODULES}/([^/]+)/internal/` },
|
||||
},
|
||||
{
|
||||
name: 'domain-is-pure',
|
||||
comment:
|
||||
'domain/ 零 IO、零框架:npm 只准 zod / decimal.js / date-fns,仓内只准 @contracts / @sfeel / @utils(§5.3)',
|
||||
severity: 'error',
|
||||
from: { path: `${MODULES}/([^/]+)/internal/domain/` },
|
||||
to: {
|
||||
path: 'node_modules',
|
||||
pathNot: DOMAIN_NPM_ALLOWLIST,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'domain-is-pure-core',
|
||||
comment: 'domain/ 不得触 Node 核心能力(fs / http / crypto / child_process …,§5.3)',
|
||||
severity: 'error',
|
||||
from: { path: `${MODULES}/([^/]+)/internal/domain/` },
|
||||
to: { dependencyTypes: ['core'] },
|
||||
},
|
||||
{
|
||||
name: 'usecase-not-to-adapter',
|
||||
comment: 'usecase/ 依赖 port.ts 声明的能力,不 import 任何 adapter(§5.3)',
|
||||
severity: 'error',
|
||||
from: { path: `${MODULES}/([^/]+)/internal/usecase/` },
|
||||
to: { path: `${MODULES}/([^/]+)/internal/adapter/` },
|
||||
},
|
||||
{
|
||||
name: 'web-not-to-api',
|
||||
comment: '前后端互不 import,跨端唯一通道是 @contracts(§5.1)',
|
||||
severity: 'error',
|
||||
from: { path: '^apps/web/' },
|
||||
to: { path: '^apps/api/' },
|
||||
},
|
||||
{
|
||||
name: 'api-not-to-web',
|
||||
comment: '前后端互不 import(§5.1)',
|
||||
severity: 'error',
|
||||
from: { path: '^apps/api/' },
|
||||
to: { path: '^apps/web/' },
|
||||
},
|
||||
{
|
||||
name: 'packages-are-leaves',
|
||||
comment: 'packages/* 不得反向 import apps/*(§5.1)',
|
||||
severity: 'error',
|
||||
from: { path: '^packages/' },
|
||||
to: { path: '^apps/' },
|
||||
},
|
||||
{
|
||||
name: 'utils-is-leaf',
|
||||
comment: 'packages/utils 是叶子,不依赖任何仓内包(§5.1)',
|
||||
severity: 'error',
|
||||
from: { path: '^packages/utils/' },
|
||||
to: { path: '^(apps|activities|packages/(?!utils))' },
|
||||
},
|
||||
{
|
||||
name: 'no-orphans',
|
||||
comment:
|
||||
'无孤儿模块;契约面(index/contract/port)、入口与配置是合法的无入边文件,不计孤儿',
|
||||
severity: 'error',
|
||||
from: {
|
||||
orphan: true,
|
||||
pathNot: [
|
||||
'(^|/)(index|contract|port)\\.ts$',
|
||||
'^apps/(api|web)/src/app/',
|
||||
'^activities/',
|
||||
'^tools/',
|
||||
'\\.d\\.ts$',
|
||||
'\\.(config|setup)\\.(js|cjs|mjs|ts)$',
|
||||
'(^|/)__tests__/',
|
||||
'\\.test\\.ts$',
|
||||
],
|
||||
},
|
||||
to: {},
|
||||
},
|
||||
|
||||
// ── JCAI 增补 ──────────────────────────────────────────────────────────
|
||||
{
|
||||
name: 'framework-only-in-adapter',
|
||||
comment: 'Mastra / AI SDK / Drizzle / pg / pg-boss / Hono 只准在 adapter 与 app(§6.2)',
|
||||
severity: 'error',
|
||||
from: { path: `${MODULES}/([^/]+)/internal/(domain|usecase)/` },
|
||||
to: {
|
||||
path: 'node_modules/(@mastra|ai|@ai-sdk|drizzle-orm|drizzle-kit|pg|pg-boss|hono|@hono)(/|$)',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'contracts-is-pure',
|
||||
comment: '@contracts 只有 zod schema / 常量 / 类型,零实现、零框架(§8.1)',
|
||||
severity: 'error',
|
||||
from: { path: '^packages/contracts/' },
|
||||
to: {
|
||||
path: 'node_modules',
|
||||
pathNot: 'node_modules/zod(/|$)',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'sfeel-is-pure',
|
||||
comment: '@sfeel 是纯函数包,零 IO 零框架(§8.3)',
|
||||
severity: 'error',
|
||||
from: { path: '^packages/sfeel/' },
|
||||
to: { dependencyTypes: ['core'] },
|
||||
},
|
||||
{
|
||||
name: 'activities-isolated',
|
||||
comment: 'activities/* 只准 import @sdk / @contracts 与白名单纯库,不得 import apps/**(ADR-004)',
|
||||
severity: 'error',
|
||||
from: { path: '^activities/' },
|
||||
to: { path: '^apps/' },
|
||||
},
|
||||
{
|
||||
name: 'apps-not-into-activities',
|
||||
comment: '活动经安装装载,api 侧任何文件不得静态 import activities/**(§2.1 / ADR-004)',
|
||||
severity: 'error',
|
||||
from: { path: '^apps/' },
|
||||
to: { path: '^activities/' },
|
||||
},
|
||||
{
|
||||
name: 'activity-no-environment-capability',
|
||||
comment: '活动包零环境能力:不得触 node 核心模块(AM 12.1 无越权代码)',
|
||||
severity: 'error',
|
||||
from: { path: '^activities/' },
|
||||
to: { dependencyTypes: ['core'] },
|
||||
},
|
||||
...tierRules,
|
||||
],
|
||||
|
||||
options: {
|
||||
doNotFollow: { path: 'node_modules' },
|
||||
exclude: {
|
||||
path: ['(^|/)dist/', '(^|/)node_modules/', '(^|/)api-report/', '\\.d\\.ts$'],
|
||||
},
|
||||
tsPreCompilationDeps: true,
|
||||
tsConfig: { fileName: 'tsconfig.base.json' },
|
||||
enhancedResolveOptions: {
|
||||
exportsFields: ['exports'],
|
||||
conditionNames: ['import', 'require', 'node', 'default', 'types'],
|
||||
extensions: ['.ts', '.tsx', '.js', '.jsx', '.json'],
|
||||
mainFields: ['module', 'main', 'types'],
|
||||
},
|
||||
reporterOptions: {
|
||||
text: { highlightFocused: true },
|
||||
},
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,9 @@
|
||||
node_modules/
|
||||
dist/
|
||||
.api-tmp/
|
||||
*.tsbuildinfo
|
||||
.DS_Store
|
||||
.env
|
||||
.env.local
|
||||
coverage/
|
||||
.vite/
|
||||
@@ -0,0 +1,5 @@
|
||||
/**
|
||||
* @sdk —— 活动开发面(编码规范 §8.2):基座六件接口 + defineActivity() + 本地开发宿主 + 回放夹具。
|
||||
* 活动包 ABI 见 ADR-004。
|
||||
*/
|
||||
export declare const SDK_VERSION = "0.0.0-m0";
|
||||
@@ -0,0 +1,6 @@
|
||||
/**
|
||||
* @contracts —— 前后端唯一共享点(编码规范 §8.1)。
|
||||
* 只有 zod schema、常量、品牌类型与推导类型,零实现。
|
||||
* 修改本包任何导出 = 契约变更(§12.4)。
|
||||
*/
|
||||
export declare const CONTRACTS_VERSION = "0.0.0-m0";
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
/**
|
||||
* @sfeel —— S-FEEL 子集(OS 03 定义域)的解析与求值,纯函数(编码规范 §8.3)。
|
||||
* 被 process / flow-engine / trigger 与前端 gov-process 共用:求值语义一份代码,前后端同源。
|
||||
*/
|
||||
export declare const SFEEL_VERSION = "0.0.0-m0";
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
/**
|
||||
* @utils —— 纯函数,零依赖(编码规范 §2 / §5.1:叶子包)。
|
||||
* 无业务语义;有业务语义的东西不属于这里。
|
||||
*/
|
||||
/** 穷尽性检查:switch 漏分支时编译期报错 */
|
||||
export declare function assertNever(value: never, message?: string): never;
|
||||
/** 类型守卫:滤掉 null / undefined */
|
||||
export declare function isDefined<T>(value: T | null | undefined): value is T;
|
||||
/** 按键分组 */
|
||||
export declare function groupBy<T, K extends string>(items: readonly T[], key: (item: T) => K): Record<K, T[]>;
|
||||
/** 稳定排序的键值对遍历(避免 Object.keys 顺序依赖) */
|
||||
export declare function sortedEntries<V>(record: Readonly<Record<string, V>>): Array<[string, V]>;
|
||||
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"name": "@app/api",
|
||||
"version": "0.0.0",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"exports": { ".": "./src/app/main.ts" },
|
||||
"scripts": {
|
||||
"dev": "tsup --watch --onSuccess \"node dist/main.js\"",
|
||||
"build": "tsup",
|
||||
"seed": "node dist/seed.js"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
/**
|
||||
* 环境配置 —— 只在 app/ 层读环境变量;模块内一律经 port 注入(§5.3)。
|
||||
*/
|
||||
export type AppConfig = {
|
||||
readonly nodeEnv: 'development' | 'test' | 'production';
|
||||
readonly port: number;
|
||||
readonly databaseUrl: string;
|
||||
};
|
||||
|
||||
const DEFAULT_DATABASE_URL = 'postgres://jcai:jcai@localhost:54329/jcai';
|
||||
|
||||
export function loadConfig(env: NodeJS.ProcessEnv = process.env): AppConfig {
|
||||
const nodeEnv = env['NODE_ENV'];
|
||||
return {
|
||||
nodeEnv: nodeEnv === 'production' || nodeEnv === 'test' ? nodeEnv : 'development',
|
||||
port: Number(env['PORT'] ?? 8787),
|
||||
databaseUrl: env['DATABASE_URL'] ?? DEFAULT_DATABASE_URL,
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
/**
|
||||
* apps/api 唯一组装层入口(编码规范 §5.2)。
|
||||
* 只有 app/ 能同时认识多个模块:new adapter、注入 port、注册路由 / worker / Mastra 实例。
|
||||
*
|
||||
* M0:骨架 —— 门禁跑通即可,业务装配自 M1 起逐层填入。
|
||||
*/
|
||||
import { loadConfig } from './config.ts';
|
||||
|
||||
export async function boot(): Promise<void> {
|
||||
const config = loadConfig();
|
||||
process.stdout.write(
|
||||
`JCAI api · M0 骨架 · env=${config.nodeEnv} · port=${config.port} · db=${config.databaseUrl.replace(/:[^:@]*@/, ':***@')}\n`,
|
||||
);
|
||||
}
|
||||
|
||||
if (import.meta.url === `file://${process.argv[1]}`) {
|
||||
await boot();
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
/**
|
||||
* 种子数据与播种入口(编码规范 §15 · M0)。
|
||||
*
|
||||
* 数据是常量、写入是端口 —— M0 立骨架:数据在此冻结,写入实现随 M1 的 `org` 模块落地。
|
||||
* 部署边界:单次部署 ≤50 人、单组织、不做多租户(OS 0.3)。
|
||||
*/
|
||||
|
||||
/** 岗位:编排层声明岗位,起单时按四策略解析出人(OS 03) */
|
||||
export const POSITION_SEED = [
|
||||
{ code: 'PM', name: '项目经理', note: '定价审批、策略拍板' },
|
||||
{ code: 'BD', name: '商务', note: 'RFQ 受理、成本定价、报价议价、情报归档' },
|
||||
{ code: 'FAE', name: '现场应用', note: '替代选型' },
|
||||
{ code: 'PRM', name: '采购/寻源', note: '渠道寻源' },
|
||||
{ code: 'OP', name: '运营', note: '运营支持' },
|
||||
] as const;
|
||||
|
||||
/** 员工五人;登录者 = 冯兵(BD) */
|
||||
export const STAFF_SEED = [
|
||||
{ account: 'dingziqiao', name: '丁子乔', position: 'PM' },
|
||||
{ account: 'fengbing', name: '冯兵', position: 'BD' },
|
||||
{ account: 'wangziming', name: '王梓名', position: 'FAE' },
|
||||
{ account: 'linpeixuan', name: '林佩萱', position: 'PRM' },
|
||||
{ account: 'liyuanchu', name: '李元初', position: 'OP' },
|
||||
] as const;
|
||||
|
||||
/** 默认登录者(MVP 单组织 cookie session,§4 鉴权定调) */
|
||||
export const DEFAULT_LOGIN_ACCOUNT = 'fengbing';
|
||||
|
||||
export type PositionSeed = (typeof POSITION_SEED)[number];
|
||||
export type StaffSeed = (typeof STAFF_SEED)[number];
|
||||
|
||||
/** 播种端口 —— 实现由 app/ 在 M1 注入(org 模块出口) */
|
||||
export type OrgSeeder = {
|
||||
upsertPosition(position: PositionSeed): Promise<void>;
|
||||
upsertStaff(staff: StaffSeed): Promise<void>;
|
||||
};
|
||||
|
||||
export async function runSeed(seeder: OrgSeeder): Promise<void> {
|
||||
for (const position of POSITION_SEED) await seeder.upsertPosition(position);
|
||||
for (const staff of STAFF_SEED) await seeder.upsertStaff(staff);
|
||||
}
|
||||
|
||||
if (import.meta.url === `file://${process.argv[1]}`) {
|
||||
process.stdout.write(
|
||||
`种子数据:${POSITION_SEED.length} 个岗位 / ${STAFF_SEED.length} 名员工;` +
|
||||
`登录者=${DEFAULT_LOGIN_ACCOUNT}\n` +
|
||||
'写入实现随 M1 `org` 模块落地(docs/debt.md · M0-1)。\n',
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
import { defineConfig } from 'tsup';
|
||||
|
||||
export default defineConfig({
|
||||
entry: { main: 'src/app/main.ts', seed: 'src/app/seed.ts' },
|
||||
format: ['esm'],
|
||||
target: 'node22',
|
||||
platform: 'node',
|
||||
outDir: 'dist',
|
||||
clean: true,
|
||||
sourcemap: true,
|
||||
skipNodeModulesBundle: true,
|
||||
tsconfig: '../../tsconfig.node.json',
|
||||
});
|
||||
@@ -0,0 +1,12 @@
|
||||
<!doctype html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>JCAI · 任务操作系统</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
<script type="module" src="/src/app/main.tsx"></script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,21 @@
|
||||
{
|
||||
"name": "@app/web",
|
||||
"version": "0.0.0",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
"build": "vite build",
|
||||
"preview": "vite preview"
|
||||
},
|
||||
"dependencies": {
|
||||
"react": "^19.2.0",
|
||||
"react-dom": "^19.2.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/react": "^19.2.2",
|
||||
"@types/react-dom": "^19.2.1",
|
||||
"@vitejs/plugin-react": "^5.0.4",
|
||||
"vite": "^7.1.12"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
/**
|
||||
* 应用壳 —— M0 骨架。工作台五要素 / 治理台九功能的 features 自 M6 起挂入。
|
||||
*/
|
||||
export function AppShell() {
|
||||
return (
|
||||
<div className="proto-root">
|
||||
<main className="app-shell">JCAI · 任务操作系统 —— M0 骨架</main>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
/**
|
||||
* apps/web 唯一组装层(编码规范 §9):路由、Provider、鉴权壳、SSE 连接。
|
||||
* M0:骨架 —— 两台原型的 1:1 平移自 M6 起(README《前端 UI · 原型 1:1 平移》)。
|
||||
*/
|
||||
import { StrictMode } from 'react';
|
||||
import { createRoot } from 'react-dom/client';
|
||||
import { AppShell } from './app-shell.tsx';
|
||||
|
||||
const container = document.getElementById('root');
|
||||
if (!container) throw new Error('#root 缺失');
|
||||
|
||||
createRoot(container).render(
|
||||
<StrictMode>
|
||||
<AppShell />
|
||||
</StrictMode>,
|
||||
);
|
||||
Vendored
+1
@@ -0,0 +1 @@
|
||||
/// <reference types="vite/client" />
|
||||
@@ -0,0 +1,26 @@
|
||||
import { defineConfig } from 'vite';
|
||||
import react from '@vitejs/plugin-react';
|
||||
import { fileURLToPath } from 'node:url';
|
||||
|
||||
const root = fileURLToPath(new URL('../..', import.meta.url));
|
||||
const p = (rel: string) => fileURLToPath(new URL(rel, import.meta.url));
|
||||
|
||||
export default defineConfig({
|
||||
plugins: [react()],
|
||||
resolve: {
|
||||
alias: {
|
||||
'@contracts': `${root}packages/contracts/src/index.ts`,
|
||||
'@sfeel': `${root}packages/sfeel/src/index.ts`,
|
||||
'@ui': `${root}packages/ui-kit/src/index.ts`,
|
||||
'@utils': `${root}packages/utils/src/index.ts`,
|
||||
'@features': p('./src/features'),
|
||||
'@web-shared': p('./src/shared'),
|
||||
},
|
||||
},
|
||||
server: {
|
||||
port: 5173,
|
||||
proxy: {
|
||||
'/api': { target: 'http://localhost:8787', changeOrigin: true },
|
||||
},
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,17 @@
|
||||
-- 编码规范 §7:单 PostgreSQL 实例,四个 schema,各自单写者。
|
||||
-- sys 系统自持 —— 各模块 adapter 经 Drizzle 写,drizzle-kit 迁移
|
||||
-- ledger 活动自生长 —— 仅 ledger adapter 写(动态 DDL/DML,raw pg)
|
||||
-- mastra Mastra 存储 —— 仅 Mastra(@mastra/pg)写,自管迁移
|
||||
-- queue pg-boss —— 仅 pg-boss 写,自管迁移
|
||||
|
||||
CREATE SCHEMA IF NOT EXISTS sys;
|
||||
CREATE SCHEMA IF NOT EXISTS ledger;
|
||||
CREATE SCHEMA IF NOT EXISTS mastra;
|
||||
CREATE SCHEMA IF NOT EXISTS queue;
|
||||
|
||||
CREATE EXTENSION IF NOT EXISTS pgcrypto;
|
||||
|
||||
COMMENT ON SCHEMA sys IS 'JCAI 系统自持:主数据/事件存储/记忆/活动库/流程包/触发器/运行时实例';
|
||||
COMMENT ON SCHEMA ledger IS 'JCAI 台账自生长:正式版 + 任务级草稿层 + 共享域';
|
||||
COMMENT ON SCHEMA mastra IS 'Mastra 单写:线程/消息/workflow 快照';
|
||||
COMMENT ON SCHEMA queue IS 'pg-boss 单写:作业与定时';
|
||||
@@ -0,0 +1,24 @@
|
||||
services:
|
||||
db:
|
||||
image: postgres:16-alpine
|
||||
container_name: jcai-pg
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
POSTGRES_USER: jcai
|
||||
POSTGRES_PASSWORD: jcai
|
||||
POSTGRES_DB: jcai
|
||||
# pgcrypto / uuid 由 init 脚本按需启用
|
||||
TZ: Asia/Shanghai
|
||||
ports:
|
||||
- '54329:5432'
|
||||
volumes:
|
||||
- jcai-pgdata:/var/lib/postgresql/data
|
||||
- ./db/init:/docker-entrypoint-initdb.d:ro
|
||||
healthcheck:
|
||||
test: ['CMD-SHELL', 'pg_isready -U jcai -d jcai']
|
||||
interval: 5s
|
||||
timeout: 3s
|
||||
retries: 20
|
||||
|
||||
volumes:
|
||||
jcai-pgdata:
|
||||
+1157
File diff suppressed because one or more lines are too long
+177
@@ -0,0 +1,177 @@
|
||||
# JCAI 任务操作系统 · MVP 规格包
|
||||
|
||||
这个目录是「企业级 AI Native 任务操作系统」的**完整规格包**:两卷语义规范 + 一份工程结构契约 +
|
||||
一份业务验收样例。交给编码 Agent,即可从零实现 MVP。
|
||||
|
||||
> 一句话系统:组织的工作被定义为可编排的工作流,工作流由活动编排而成;一个活动是一个完成一项
|
||||
> 任务的 Agent 机制,像小程序一样在系统外开发、安装即用;人只在责任点与放行点上出现——
|
||||
> 确定交系统,临场交 AI,落地交人。
|
||||
|
||||
---
|
||||
|
||||
## 启动提示词(编码仓库的 Agent 从这里启动)
|
||||
|
||||
```text
|
||||
你是本仓库的开发 Agent,任务:从零实现「JCAI 任务操作系统」的 MVP。
|
||||
|
||||
【第 0 步 · 建立权威——写任何代码之前必须完成】
|
||||
1. 读 docs/编码规范.md 的前言与 §0–§5 —— 先知道代码长什么样、放在哪、谁能依赖谁;
|
||||
2. 通读 docs/操作系统.html(V2.15,系统侧)—— 五层总图 / 工作台五要素与治理台九功能 /
|
||||
流程层(流程包·工作流·触发器·审批点·网关·边映射)/ 引擎(流程引擎 + 活动基座六件)/
|
||||
人类工具 / 统一事件标准 / 调用层与工具箱 / 记忆与度量 / 运行拓扑与写三分 / 基座与治理 /
|
||||
系统不变量——最后的不变量清单要能默写要点;
|
||||
3. 通读 docs/活动模型.html(V2.0,活动侧)—— 契约七件 / loop(CMMN+DMN·语义引擎×Agent 回路·
|
||||
双向驱动)/ flow(步序声明·四种步型)/ 人类工具的调用 / 交互内容 / 技能 / 记忆与迭代 /
|
||||
Harness 与验收分级 L1–L5 / 活动包与开发 / 合规判据(通用 17 + loop 8 + flow 6);
|
||||
4. 回头读完 docs/编码规范.md 全文(§6–§17);
|
||||
5. 读 docs/MVP示例工作流.html —— MVP 要跑通的那单生意(统一报价),
|
||||
按本 README 的《归一化对照表》把业务素材映射成系统概念。
|
||||
|
||||
【权威分工——冲突时的裁决顺序】
|
||||
- 语义(系统做什么、什么语义):以两卷规范为准;
|
||||
- 结构(代码长什么样、模块边界、依赖方向):以 编码规范.md 为准;
|
||||
- 业务内容(MVP 做哪单生意、字段与规则):以 MVP示例工作流.html 为准;
|
||||
- 前端 UI:**不是参照,是 1:1 平移**。两台高保真原型的前端代码就是 UI 的实现规格,
|
||||
原型仓库在本机(用户已授予读取权限):`~/coding/JCAI_PRD/workbench`(员工面工作台)与
|
||||
`~/coding/JCAI_PRD/governance`(管理面治理台)。按本 README《前端 UI · 原型 1:1 平移》
|
||||
一节的清单与规则执行——CSS 与 DOM 结构原样搬、组件按编码规范 §9 重排、mock 数据层换成
|
||||
真实 API;**只平移不 import**,编码仓与原型仓零依赖;
|
||||
- 发现两类权威打架:停下来报告,不得自行仲裁(编码规范·前言)。
|
||||
- 谨记双层边界:范式(loop / flow / skill)是后端实现逻辑的模型,只存在于引擎层;
|
||||
交互模型(工单两模式 + 对话卡族)是前端呈现协议——两层不冲突,前端永远感知不到范式
|
||||
(编码规范 §9 注记)。UI 文案用两卷术语(标准活动 / 案例活动 / 审批点),
|
||||
SOP / CMMN / BPMN 等字样只出现在代码与内部文档,不出现在界面上。
|
||||
|
||||
【实施纪律】
|
||||
- 严格按 编码规范.md §15 的里程碑序 M0→M6 推进;每个里程碑先立骨架
|
||||
(index / contract / port / CONTRACT.md + 空测试)再填实现;
|
||||
- 机器门禁(tsc / eslint / depcruise / 契约快照 / test)从 M0 起全绿,红了先修门禁再前进;
|
||||
- 遵守 §12 AI 协作协议(多 Agent 并行 · 主 Agent 编排制):**你即主 Agent(唯一集成人)**,
|
||||
按 §12.0 授权矩阵组织子 Agent 并行承包——分支即工单、合入唯经你(§12.7)、契约面由你单写;
|
||||
§12.5 禁止清单按矩阵授权,三类保留项(破坏性契约 / 新依赖 / 改门禁规则)永远上升用户;
|
||||
- 本 docs/ 即规格包原件,整包置于仓库 docs/ 下;另建 docs/debt.md 与 docs/adr/
|
||||
(ADR 编号从 005 续,001–004 已在编码规范 §14);
|
||||
- 四个落地裁量点已由用户裁定(见本 README《已裁定的落地决策》),照此实现、不必再问;
|
||||
实现中出现**新的**裁量点仍照前言规矩停下报告。
|
||||
|
||||
【MVP 完成判据——统一报价全链路验收场景】
|
||||
以下场景在真实运行的系统上从头到尾走通(mock 只允许出现在外界:邮件通道与外部系统可用
|
||||
模拟通道 / 录制回放替身,系统内部机制不得 mock):
|
||||
1. 治理台:录入五名员工与岗位、绑定 LLM 实例(任一 OpenAI 兼容端点)、
|
||||
编排「统一报价」流程包 v1 并发布(边映射闭合校验通过)、
|
||||
配置「客户RFQ询价」事件触发器与邮件通道实例;
|
||||
2. 一封样例 RFQ 邮件入站 → 归属解析 → 触发器命中起单:生成一条工作流,
|
||||
A1 任务落到 BD 冯兵的工作台任务清单;
|
||||
3. A1 受理归一(flow):步序推进,LLM 步抽取归一 → 台账「统一受理记录」(任务级草稿层),
|
||||
缺关键字段走补全卡,逐条打标走 DMN(三分类规则 P-03),放行通过 → 草稿合并正式版、
|
||||
数据事件发射,G2 网关按 Type 分流;
|
||||
4. B 类条目 → A3 渠道寻源(loop,林佩萱):CMMN 装载、Agent 回路推进、发询后登记
|
||||
数据监听 + 时限;供应商回价(模拟入站)→ 数据事件续跑;寻源比价表交付放行;
|
||||
5. C 类条目 → A2 替代选型(loop,王梓名):含一次跨人卡(向 BD 补全),
|
||||
替代对标表放行交回;
|
||||
6. A4 成本定价(flow):取价基准 → DMN 定价(利润模型 P-01)→ 底价自检(底价门禁 P-02)
|
||||
→ 报价草案;
|
||||
7. AP 定价审批(审批点):审批单卡到 PM 丁子乔工位——通过放行进 A6;
|
||||
驳回按声明走向回 A4 重开新实例;
|
||||
8. A6 报价议价(flow):生成正式报价单(写类动作登记为动作意向)→ 落地预检 →
|
||||
放行通过即落地(台账回写 + 出站发送)→ 输出口发射;建 D+3 跟进监听;
|
||||
9. 客户拒绝(模拟)→ A7 情报归档:历史价格情报回写、落地率统计落账,工作流「已完成」;
|
||||
10. 全程可审计:任务记忆只追加、信封盖戳、归侧标注;工作台五要素齐活
|
||||
(任务 / 审批 / 消息 / 纪要 / 汇报聚合自任务日志);治理台·任务管理可在途监控、
|
||||
叫停并恢复一单任务;终态封卷触发蒸馏钩子产出活动记忆候选条目(可为最小实现)。
|
||||
|
||||
【种子数据】
|
||||
- 员工五人:丁子乔(PM·项目经理)· 冯兵(BD·商务)· 王梓名(FAE·现场应用)·
|
||||
林佩萱(采购/寻源)· 李元初(OP·运营);登录者 = 冯兵;
|
||||
- 单次部署 ≤50 人、单组织、不做多租户——一切机制复杂度以此为预算。
|
||||
|
||||
现在从【第 0 步】开始。读完四份文档后,先提交 M0 的变更申请,不要直接写代码。
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 文件清单与权威分工
|
||||
|
||||
| 文件 | 版本 | 权威范围 |
|
||||
| --- | --- | --- |
|
||||
| `操作系统.html` | V2.15 · 2026-07-24 | **系统侧语义权威**:五层、交互两面、流程层、引擎与活动基座六件、人类工具、统一事件标准、调用层、记忆与度量、运行拓扑、边界四象限、基座与治理、系统不变量 |
|
||||
| `活动模型.html` | V2.0 · 2026-07-25 | **活动侧语义权威**:契约七件、loop(CMMN+DMN)、flow(步序声明)、人类工具的调用、交互内容、技能、记忆与迭代、Harness 与 L1–L5、活动包与开发、合规判据 17+8+6 |
|
||||
| `编码规范.md` | V0.1 · 2026-07-26 | **工程结构权威**:技术选型定案、monorepo 唯一形态、模块层级 L1–L8 与依赖门禁、Mastra 映射、持久层、前端 features、AI 协作协议、里程碑 M0–M6。服从两卷,只管「代码长什么样」 |
|
||||
| `MVP示例工作流.html` | 2026-07-26 导出 | **业务验收样例**:统一报价流程全套素材——7 节点(SOP×5 + Case×2)、3 网关、13 张流转单据、16 张静态库表、5 条规则判定表 + 经验。是原始业务素材,需按下表归一化 |
|
||||
|
||||
两卷互为关联卷(系统供给 vs 活动定义是镜像同表);编码规范前言载有仲裁规则:
|
||||
**语义冲突以两卷为准,结构冲突以编码规范为准,两类权威打架停下来报告**。
|
||||
|
||||
## 归一化对照表(MVP 素材 → 系统概念)
|
||||
|
||||
样例是业务分析会话的原始导出,术语与两卷未对齐;实现时按此表映射:
|
||||
|
||||
| 样例里的物件 | 归一化为 |
|
||||
| --- | --- |
|
||||
| 流程「统一报价」 | **流程包** v1:治理台编排五要素、边映射闭合、发布;运行即工作流 |
|
||||
| 触发器「客户RFQ询价」 | **事件触发器**:通道入站命中规则 → 字段映射 → 经调用接口起单 |
|
||||
| SOP 节点(A1/A4/A6/A7) | **标准活动(flow)**:任务定义卡→契约七件;作业指导书 S1…Sn→步序声明(四种步型);步内判断(如 A1 的 D1 完整度)→条件谓词或人类工具步;SLA→Harness 时限与预算 |
|
||||
| Case 节点(A2/A3) | **案例活动(loop)**:案例图→CMMN XML;案例说明书→同版本叙事面;`!必做`→entryCriterion 常项、`看情况`→discretionary、`#可反复`→repetitionRule、`▶需拍板`→manualActivation + 放行;`⏱时限/回价到期/✋客户改需求`→时间/数据/人监听(时限必配) |
|
||||
| A5 定价审批 | **审批点**(流程层内置人裁节点,功能属性四件);G3「审批结果」网关并入审批点的驳回走向(回 A4 重开新实例)。见裁量点 ① |
|
||||
| 规则五件(P-01 利润模型 / P-02 底价门禁 / P-03 三分类 / P-04 有效期 / 受理规范) | 判定表部分→ **DMN 决策表**(确定性求值、命中行留痕);「经验」段落→**技能 / 活动记忆种子**(载方法不载权力) |
|
||||
| 动态数据(流转单据 13 张) | **台账对象**(活动自持域,schema 声明自生长)+ **输出口载荷 schema**(流转的事实经边映射拼接) |
|
||||
| 静态底座(16 张库表) | **共享域对象 / 主数据**(客户资料库、PN物料主库、供应商渠道目录等);写授权按域.对象在契约申报 |
|
||||
| 「转订单履约(ORM)」 | 流程包**显式终点**的输出声明;MVP 以回执与日志代真实 ORM 对接 |
|
||||
| 角色 BD / PM / PRM / FAE | **岗位**;PRM=采购 → 林佩萱,FAE → 王梓名,负责人四策略解析起单 |
|
||||
|
||||
## 已裁定的落地决策(2026-07-26 用户拍板,照此实现)
|
||||
|
||||
1. **A5 定价审批 = 审批点**(流程层内置人裁节点,功能属性四件):样例里的「策略决策」落审批
|
||||
意见与批注;G3「审批结果」网关并入审批点的驳回走向(驳回 → 回 A4 重开新实例)。
|
||||
2. **G2 料号分流 = 并行网关**:三道并行、每边载荷按 Type 过滤条目子集;某类条目为空的分支
|
||||
按「容忍」处置,A4 汇合处的必填映射不得依赖可空分支。
|
||||
3. **A4 成本定价 = flow**(从样例):取价→查表定价→自检的判断全部装进 DMN 决策表确定性
|
||||
求值;实现中一旦出现「由 AI 决定怎么办」,按活动模型 2.1 的上升规则改 loop 或上升为
|
||||
流程层编排。
|
||||
4. **议价回环「有异议 → 返回调整 → A4」= 流程层回边**:人裁决后重开新任务实例
|
||||
(同节点、新任务 ID、留痕关联),不复活旧任务。
|
||||
|
||||
## 前端 UI · 原型 1:1 平移(强制)
|
||||
|
||||
`apps/web` 的界面**不重新设计**:两台原型的前端代码就是实现规格,逐屏平移,
|
||||
验收标准 = 与原型逐屏对照、视觉不可辨差异。平移清单:
|
||||
|
||||
**员工面(workbench,浅色三栏工作面)** —— 源根 `~/coding/JCAI_PRD/workbench/src/app/(proto)/`
|
||||
|
||||
| 源文件 | 是什么 |
|
||||
| --- | --- |
|
||||
| `page.tsx` | 外壳(左轨五要素 + 冯兵徽标)+ 任务四区骨架(任务列表 / 标题区 / 工作区 / 对话区、收展把手) |
|
||||
| `_components/ViewRegion.tsx` | 标题区 + 工作区四页签:待处理(HTML 工单翻页,验收=可修订报告 / 执行=指导书+空表单)、工作成果、任务详情(KPI 带 + 流程链 + 模型扇形图 + 上下文档案)、工作日志 |
|
||||
| `_components/TaskChat.tsx` | 对话区(任务助理):气泡二元制、对话卡族(决策/补全/评价/验收单)、composer 锁、跨栏定位 |
|
||||
| `_components/ModuleWorkspace.tsx` | 审批 / 消息 / 纪要 / 汇报四要素(各配助理对话壳) |
|
||||
| `_components/`(其余) | FileViewer / Ico / ChatAvatar / ScrollArea / Markdown / SettingsButton |
|
||||
| `app.css` + `proto.vendor.css` | **整文件搬**:设计令牌(`.proto-root .app-shell`)+ 全部 `jc-*` 组件样式 + vendor 皮肤(布局骨架,类名被它占用,`jc-` 前缀因此必须保留) |
|
||||
| `_data/model.ts` | 交互模型类型——`@contracts/card.ts` 的参照原型(正式版以 @contracts 为准) |
|
||||
| `public/samples/` | 样例 PDF 报价单等资产(演示用,可选) |
|
||||
|
||||
**管理面(governance,深轨浅面控制台)** —— 源根 `~/coding/JCAI_PRD/governance/src/app/`
|
||||
|
||||
| 源文件 | 是什么 |
|
||||
| --- | --- |
|
||||
| `_components/Governance.tsx` | 九区全体:区头 + 区内页签 + 整页下钻 + 就地确认带(AskBand·影响预览三必答)+ 事件流 + 数据区记录管理器 |
|
||||
| `_flow/`(六文件) | 编排画布:diagram-js 布局引擎(蛇形折行)+ 画笔(三色 skin + 琥珀审批点)+ 编辑器核 |
|
||||
| `theme.css` + `console.css` | 设计令牌 + 治理台组件层(`g-*` + 色调字典 `t-*`),整文件搬 |
|
||||
| `_components/Ico.tsx` · `_data/gov-data.ts` | 图标;mock 数据(字段口径与文案的参照,替换为真实 API) |
|
||||
|
||||
**平移规则**:
|
||||
|
||||
1. **DOM 结构与类名原样保留**(`jc-*` / `g-*` 前缀、vendor 皮肤一并搬);CSS 整文件搬,不重写不「优化」;
|
||||
2. **代码组织按编码规范 §9 重排**(拆进 features、路由改 TanStack Router、数据改 typed-fetch + SSE)——重排只动模块边界与数据来源,**渲染输出保持 1:1**;
|
||||
3. 原型是 Next.js、正式系统是 Vite SPA:去掉 `"use client"` 等 Next 专有件即可,组件均为纯 React 19;
|
||||
4. 原型内嵌的 mock 数据与内存状态(`_data/*`、doneMap 等)全部换成服务端投影;「刷新即重置」的原型缺陷不得带入——正式系统零过程状态、刷新从投影重建(§9.2);
|
||||
5. 平移中发现原型与两卷/编码规范冲突(如原型 `/api/chat` 直连 DeepSeek),以规范为准并报告,不照搬。
|
||||
|
||||
## MVP 之外(明确不做)
|
||||
|
||||
多租户 / 移动端 / 真实 ERP·CRM 对接(用调用契约 + 录制回放替身)/ 活动市场与多组织分发 /
|
||||
两卷中标注「可选」的高级项(如叙述性小结可后置)。治理台九功能在 MVP 里以支撑验收场景为度:
|
||||
每区可用、不追求满配。
|
||||
|
||||
---
|
||||
|
||||
*规格包整理于 2026-07-26。四份文件的任何改动都应回到源头(PRD 工作区)同步,勿在编码仓单方改规格。*
|
||||
@@ -0,0 +1,34 @@
|
||||
# ADR-005 · 工具链与门禁的落地形态
|
||||
|
||||
- 状态:已决(M0)
|
||||
- 日期:2026-07-27
|
||||
- 上下文:编码规范 §11 规定五道门禁(tsc / eslint / depcruise / api-report / test)必须存在且可执行,
|
||||
但未规定 TypeScript 的运行与产出形态。§1 表内已定案的构建件只有 Vite(前端)与 tsup(§8.2 活动编译预设)。
|
||||
|
||||
## 决定
|
||||
|
||||
1. **后端不引新的 TS 运行器**。`apps/api` 以 **tsup**(§8.2 已定案的表内件,esbuild 内核,原生解析 tsconfig `paths`)
|
||||
打包为 ESM 后由 Node 22+ 直跑;开发期 `tsup --watch --onSuccess node dist/main.js`。
|
||||
不引入 `tsx` / `ts-node` / `swc` 等表外依赖(§12.5#3)。
|
||||
2. **tsc 分两个工程**:`tsconfig.node.json`(api / packages / activities / tools,lib ES2023)与
|
||||
`tsconfig.web.json`(web / ui-kit,lib DOM + jsx)。二者共享 `tsconfig.base.json` 的严格开关与
|
||||
§11.1 规定的 `paths`。根 `tsconfig.json` 只做 solution 引用。
|
||||
理由:一份 tsconfig 同时挂 DOM 与 Node 全局会让 §9.2「组件内禁裸 fetch」之类的门禁失去类型依据。
|
||||
3. **契约快照的范围**(`tools/api-report.mjs`):`tsc --emitDeclarationOnly` 出全量声明后,
|
||||
**只保留契约面**落 `api-report/` —— `packages/contracts/**`、各 `packages/<pkg>/src/index.d.ts`、
|
||||
各 `apps/api/src/modules/<m>/{index,contract,port}.d.ts`。
|
||||
由此「改 `internal/` 时 api-report 纹丝不动」(§11.5)成立。
|
||||
配套纪律:模块出口的公开签名必须由 `contract.ts` / `port.ts` 的显式类型承载,
|
||||
不得依赖 `internal/` 的推断类型泄漏(由 `explicit-module-boundary-types` 在 modules/ 下强制)。
|
||||
4. **§11.2 的解析层封装**采用双保险:每个后端模块带 workspace `package.json`(`exports` 只开 `index.ts`),
|
||||
同时保留 §11.1 的 `@modules/*` 路径别名;穿透 `internal/` 的拦截由 ESLint `no-restricted-imports`
|
||||
与 depcruise `no-cross-module-internal` 两道机检承担(§11.3 / §11.4)。
|
||||
5. **tier-order 生成物入库**:`tools/depcruise-tiers.generated.cjs` 由 `tools/gen-depcruise-tiers.ts`
|
||||
从 `tools/module-tiers.json` 生成并提交,`pnpm gates` 首步重新生成 —— 层级表与门禁的漂移在 diff 上可见。
|
||||
|
||||
## 后果
|
||||
|
||||
- 表外依赖为零;门禁全部可离线执行。
|
||||
- 后端产物是打好的 bundle,栈帧靠 sourcemap 还原。
|
||||
- `no-orphans` 对契约面(`index` / `contract` / `port`)、`app/`、`activities/`、`tools/` 与测试放行——
|
||||
这些是合法的无入边文件;其余孤儿一律 error。
|
||||
@@ -0,0 +1,9 @@
|
||||
# 技术债登记簿
|
||||
|
||||
> 编码规范 §17:历史违规集中登记于此——旧路径 `warn`、新代码 `error`,清零后升级。
|
||||
> 例外必须注明原因与预期清理时间;散落的 `eslint-disable` 不算例外,算违规。
|
||||
|
||||
| # | 债 | 原因 | 预期清理 | 状态 |
|
||||
|---|---|---|---|---|
|
||||
| M0-1 | `pnpm db:seed` 只打印种子计划,未真正写库 | 种子数据(五岗位 / 五员工)已在 `apps/api/src/app/seed.ts` 冻结为常量并定义 `OrgSeeder` 端口;写入实现依赖 `org` 模块的 Drizzle schema,属 M1 | M1 | 已清理(M1) |
|
||||
| M0-2 | `packages/{contracts,sfeel,activity-sdk,ui-kit}` 仅有版本常量 | M0 只立骨架,内容按里程碑序填(§15) | M1–M5 | 进行中 |
|
||||
+904
@@ -0,0 +1,904 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>操作系统 · 系统侧规范</title>
|
||||
<style>
|
||||
:root{
|
||||
--desk:#E8ECF2;--paper:#fff;
|
||||
--ink:#1F2329;--ink-2:#3a4452;--ink-3:#646A73;--ink-4:#8F959E;
|
||||
--brand:#3370FF;--brand-deep:#245BDB;--brand-wash:#F0F4FF;--brand-soft:#E1EAFF;
|
||||
--ai:#8A5F1C;--ai-soft:#F7F0E0;--ai-line:#B07D2B;
|
||||
--human:#173A63;--human-soft:#DCEAF7;--human-line:#2F6DB5;
|
||||
--ok:#278717;--ok-soft:#E8F8E4;--warn:#DE7802;--warn-soft:#FFF4E5;--danger:#D83931;--danger-soft:#FEEAE9;
|
||||
--line:#DEE0E3;--line-soft:#EBEDF0;--soft:#F5F6F7;
|
||||
--mono:"SF Mono","JetBrains Mono","Menlo","Roboto Mono",ui-monospace,monospace;
|
||||
--sans:"PingFang SC","Noto Sans SC","Hiragino Sans GB","Microsoft YaHei",system-ui,sans-serif;
|
||||
}
|
||||
*{box-sizing:border-box}html,body{margin:0;padding:0}
|
||||
body{background:var(--desk);color:var(--ink);font-family:var(--sans);font-size:14px;line-height:1.8;-webkit-font-smoothing:antialiased;padding:32px 20px 72px;overflow-wrap:anywhere}
|
||||
.doc{width:1060px;max-width:100%;margin:0 auto;background:var(--paper);padding:52px 56px 64px;border-radius:4px;box-shadow:0 14px 44px -20px rgba(20,27,34,.32)}
|
||||
.hd{border-bottom:2px solid var(--ink);padding-bottom:22px;margin-bottom:8px}
|
||||
.hd .kicker{display:inline-flex;align-items:center;gap:8px;font-family:var(--mono);font-size:10.5px;font-weight:700;letter-spacing:.14em;color:var(--brand-deep);background:var(--brand-wash);border:1px solid var(--brand-soft);border-radius:999px;padding:3px 12px;margin-bottom:14px}
|
||||
.hd h1{font-size:31px;font-weight:700;letter-spacing:-.01em;line-height:1.25;margin:0 0 6px}
|
||||
.hd .sub{font-size:15px;color:var(--ink-3);margin:0}
|
||||
.hd .meta{display:flex;flex-wrap:wrap;gap:8px 22px;margin-top:16px;font-family:var(--mono);font-size:11px;color:var(--ink-4)}
|
||||
.hd .meta b{color:var(--ink-2);font-weight:600}
|
||||
h2.ch{font-size:22px;font-weight:700;letter-spacing:-.005em;margin:52px 0 4px}
|
||||
h2.ch .n{font-family:var(--mono);font-size:.8em;color:var(--brand-deep);margin-right:.55em}
|
||||
.ch-rule{height:2px;background:linear-gradient(90deg,var(--brand),#7F3BF5);border-radius:2px;width:64px;margin:0 0 16px}
|
||||
h3.h3{font-size:15.5px;font-weight:700;margin:28px 0 10px}
|
||||
h3.h3 .n{font-family:var(--mono);font-size:.82em;color:var(--brand-deep);margin-right:.5em}
|
||||
p{margin:0 0 12px}
|
||||
p.lead{font-size:15px;color:var(--ink-2)}
|
||||
b{font-weight:600}
|
||||
ul.tight{margin:6px 0 14px;padding-left:20px}
|
||||
ul.tight li{margin:4px 0}
|
||||
.small{font-size:12px;color:var(--ink-3)}
|
||||
code{font-family:var(--mono);font-size:.9em;background:var(--soft);border:1px solid var(--line-soft);border-radius:5px;padding:1px 6px}
|
||||
.callout{border:1px solid;border-radius:10px;padding:12px 16px;margin:14px 0;font-size:13px;line-height:1.8}
|
||||
.callout.brand{background:var(--brand-wash);border-color:var(--brand-soft);color:var(--brand-deep)}
|
||||
.callout.ok{background:var(--ok-soft);border-color:#bfedb4;color:var(--ok)}
|
||||
.callout.warn{background:var(--warn-soft);border-color:#fbd9a5;color:var(--warn)}
|
||||
.callout.danger{background:var(--danger-soft);border-color:#f6c6c3;color:var(--danger)}
|
||||
.stack{border:1px dashed var(--line);border-radius:16px;background:linear-gradient(180deg,#FAFBFD,#fff);padding:22px;margin:16px 0 20px}
|
||||
.stack .cap{font-family:var(--mono);font-size:10px;letter-spacing:.12em;color:var(--ink-4);margin-bottom:14px;text-transform:uppercase}
|
||||
.layer{display:grid;grid-template-columns:92px 1fr;gap:12px;align-items:stretch;margin-bottom:10px}
|
||||
.layer:last-of-type{margin-bottom:0}
|
||||
.layer .lno{display:flex;flex-direction:column;justify-content:center;align-items:center;gap:2px;border-radius:12px;font-family:var(--mono);font-weight:800;color:#fff;padding:10px 6px;text-align:center}
|
||||
.layer .lno b{font-size:15px}
|
||||
.layer .lno span{font-size:9px;letter-spacing:.08em;opacity:.85;font-weight:600}
|
||||
.layer.l1 .lno{background:linear-gradient(160deg,#3370FF,#245BDB)}
|
||||
.layer.l2 .lno{background:linear-gradient(160deg,#7F3BF5,#5b21cf)}
|
||||
.layer.l3 .lno{background:linear-gradient(160deg,#B07D2B,#8A5F1C)}
|
||||
.layer.l4 .lno{background:linear-gradient(160deg,#0e857d,#0a6a64)}
|
||||
.layer.l5 .lno{background:linear-gradient(160deg,#46586A,#2f3d4c)}
|
||||
.layer .lbody{border:1.5px solid var(--line);border-radius:12px;background:#fff;padding:12px 14px}
|
||||
.layer.l1 .lbody{border-color:var(--brand-soft);background:linear-gradient(180deg,#FBFCFF,#fff)}
|
||||
.layer.l2 .lbody{border-color:#E3D3FC;background:linear-gradient(180deg,#FCFAFF,#fff)}
|
||||
.layer.l3 .lbody{border-color:#E8D9B8;background:linear-gradient(180deg,#FCFAF3,#fff)}
|
||||
.layer.l4 .lbody{border-color:#BFE8E4;background:linear-gradient(180deg,#F8FDFC,#fff)}
|
||||
.layer.l5 .lbody{border-color:#D8DEE6;background:linear-gradient(180deg,#FAFBFC,#fff)}
|
||||
.layer .ltitle{display:flex;flex-wrap:wrap;align-items:baseline;gap:8px;margin-bottom:8px}
|
||||
.layer .ltitle b{font-size:14px}
|
||||
.layer .ltitle span{font-size:11px;color:var(--ink-4)}
|
||||
.mods{display:grid;grid-template-columns:repeat(auto-fit,minmax(150px,1fr));gap:8px}
|
||||
.mod{border:1px solid var(--line-soft);border-radius:9px;background:#fff;padding:7px 10px;font-size:11.5px;line-height:1.5}
|
||||
.mod b{display:block;font-size:11.5px}
|
||||
.mod span{display:block;font-size:10px;color:var(--ink-4)}
|
||||
.mod.dim{border-style:dashed;color:var(--ink-3)}
|
||||
.thru{margin-top:12px;border:1.5px dashed var(--brand-soft);border-radius:12px;background:linear-gradient(180deg,#FBFCFF,#fff);padding:10px 14px;font-size:12px;color:var(--brand-deep);display:flex;gap:10px;align-items:baseline}
|
||||
.thru b{white-space:nowrap}
|
||||
.xcut{margin-top:12px;border:1.5px dashed #F6C6C3;border-radius:12px;background:linear-gradient(180deg,#FFFBFB,#fff);padding:10px 14px;font-size:12px;color:var(--danger);display:flex;gap:10px;align-items:baseline}
|
||||
.xcut b{white-space:nowrap}
|
||||
.tbl{margin:12px 0 18px;border:1px solid var(--line-soft);border-radius:10px;overflow:hidden}
|
||||
table{border-collapse:collapse;width:100%;font-size:12.5px}
|
||||
th{background:var(--soft);color:var(--ink-2);font-weight:700;text-align:left;padding:9px 12px;border-bottom:1.5px solid var(--line);white-space:nowrap}
|
||||
td{padding:9px 12px;border-bottom:1px solid var(--line-soft);vertical-align:top}
|
||||
tr:last-child td{border-bottom:0}
|
||||
td.mono,.mono{font-family:var(--mono);font-size:11.5px}
|
||||
.pill{display:inline-block;font-size:10.5px;font-weight:700;border-radius:999px;padding:1px 9px;border:1px solid;white-space:nowrap}
|
||||
.pill.tool{color:var(--human);background:var(--human-soft);border-color:#B7D1EA}
|
||||
.pill.gate{color:#fff;background:#173A63;border-color:#0F2A4C}
|
||||
.pill.appr{color:#7f3bf5;background:#f4edfe;border-color:#e3d3fc}
|
||||
.checks{margin:8px 0 16px;padding:0;list-style:none}
|
||||
.checks li{position:relative;padding:6px 12px 6px 32px;border-bottom:1px dashed var(--line-soft);font-size:13px}
|
||||
.checks li::before{content:"☐";position:absolute;left:8px;top:6px;color:var(--brand);font-size:14px}
|
||||
.checks li:last-child{border-bottom:0}
|
||||
.toc{border:1px solid var(--line-soft);border-radius:12px;padding:6px 0;margin:18px 0 4px}
|
||||
.toc .row{display:grid;grid-template-columns:52px 1fr;gap:10px;align-items:baseline;padding:7px 16px;border-bottom:1px dashed var(--line-soft);font-size:13px}
|
||||
.toc .row:last-child{border-bottom:0}
|
||||
.toc .row .n{font-family:var(--mono);font-size:11px;color:var(--brand-deep);font-weight:700}
|
||||
.toc .row .t b{font-weight:600}
|
||||
.toc .row .t span{color:var(--ink-4);font-size:11.5px;margin-left:8px}
|
||||
.fig{margin:18px 0 14px;border:1px solid #D8DEE6;padding:10px 14px 12px;background:#fff}
|
||||
.fig .figcap{display:flex;justify-content:space-between;gap:10px;font-family:var(--mono);font-size:9.5px;letter-spacing:.1em;color:#6A7686;padding:2px 4px 10px}
|
||||
.fig svg{display:block;width:100%;height:auto}
|
||||
.ft{margin-top:56px;padding-top:16px;border-top:1px solid var(--line);display:flex;justify-content:space-between;gap:12px;font-family:var(--mono);font-size:10.5px;color:var(--ink-4)}
|
||||
@media (max-width:900px){.doc{padding:32px 22px}.layer{grid-template-columns:64px 1fr}}
|
||||
@media print{body{background:#fff;padding:0}.doc{box-shadow:none;width:auto}}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="doc">
|
||||
|
||||
<header class="hd">
|
||||
<div class="kicker">JCAI · WORK OS · SYSTEM VOLUME</div>
|
||||
<h1>操作系统:五层、引擎与边界</h1>
|
||||
<p class="sub">本卷完整描述<b>系统侧</b>:交互 / 流程 / 引擎 / 调用 / 基座五层,<b>工作流引擎 = 流程引擎 + 活动基座</b>,人类工具四卡,统一事件标准,记忆系统,web + server 运行拓扑,<b>活动与系统的边界</b>,基座与治理。活动是像小程序一样在系统外开发、经活动库安装的 <b>Agent 机制</b>(Case = loop,SOP = flow),其活动侧规范见《活动模型》;本卷只写系统。</p>
|
||||
<div class="meta">
|
||||
<div>版本 <b>V2.15 · 系统规范</b></div>
|
||||
<div>日期 <b>2026-07-24</b></div>
|
||||
<div>读者 <b>Coding Agent</b></div>
|
||||
<div>关系 <b>关联《活动模型》</b></div>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<div class="toc">
|
||||
<div class="row"><span class="n">00</span><span class="t"><b>定位</b><span>两本事实 · AI Native 三重结构 · 部署边界</span></span></div>
|
||||
<div class="row"><span class="n">01</span><span class="t"><b>五层总图</b><span>交互 / 流程 / 引擎 / 调用 / 基座 · 贯穿件与权力线 · 术语速览</span></span></div>
|
||||
<div class="row"><span class="n">02</span><span class="t"><b>交互层</b><span>工作台五要素 · 治理台九功能</span></span></div>
|
||||
<div class="row"><span class="n">03</span><span class="t"><b>流程层</b><span>流程包与工作流 · 编排五要素 · 触发器 · 构件来处</span></span></div>
|
||||
<div class="row"><span class="n">04</span><span class="t"><b>引擎</b><span>流程引擎 + 活动基座六件 · 两范式一套契约 · 调度权分层 · 终态名录</span></span></div>
|
||||
<div class="row"><span class="n">05</span><span class="t"><b>人类工具</b><span>四卡(决策 / 执行 / 补全 / 放行)· 三规矩 · 与审批点分层</span></span></div>
|
||||
<div class="row"><span class="n">06</span><span class="t"><b>事件标准</b><span>信封 · 四类事件 · 归属解析 · 监听声明 · 投递五诺 · 三级消费</span></span></div>
|
||||
<div class="row"><span class="n">07</span><span class="t"><b>调用层</b><span>四类能力 · 工具三来处 · 外部系统 · 工具包规范(契约 / 效应等级 / 注册两审)</span></span></div>
|
||||
<div class="row"><span class="n">08</span><span class="t"><b>记忆系统</b><span>任务记忆 · 活动记忆四层 · 记忆不载权力 · 度量</span></span></div>
|
||||
<div class="row"><span class="n">09</span><span class="t"><b>运行拓扑</b><span>web + server · 过程在后端 · 放行门</span></span></div>
|
||||
<div class="row"><span class="n">10</span><span class="t"><b>活动与系统的边界</b><span>四象限 · 两线一门 · 系统供给 vs 活动定义</span></span></div>
|
||||
<div class="row"><span class="n">11</span><span class="t"><b>基座与治理</b><span>六项存放 · 持久层两分 · 包清单 · 安装两审 · 进化治理</span></span></div>
|
||||
<div class="row"><span class="n">12</span><span class="t"><b>不变量</b><span>十四条</span></span></div>
|
||||
</div>
|
||||
|
||||
<!-- ========== 00 ========== -->
|
||||
<h2 class="ch"><span class="n">00</span>定位</h2>
|
||||
<div class="ch-rule"></div>
|
||||
|
||||
<div class="callout brand"><b>一句话系统:</b>组织的工作被定义为可编排的<b>工作流</b>,工作流由<b>活动</b>编排而成;一个活动是一个<b>完成一项任务的 Agent 机制</b>,像小程序一样基于系统内的<b>活动基座</b>在系统外开发、安装即用;人只在责任点与放行点上出现(调度权分层见 04)。<b>活动是开发态,任务是运行态</b>——同一件东西,开发者交付的叫活动,员工工作台上跑着的叫任务。</div>
|
||||
|
||||
<h3 class="h3"><span class="n">0.1</span>两本事实:生意的事实 vs 工作的事实</h3>
|
||||
<p class="lead">ERP / CRM 记录<b>生意的结果性事实</b>:订单成了、款收了、货发了。但对「这件事是怎么被做成的」,它们一无所知。</p>
|
||||
<p>本系统记录<b>工作的过程性事实</b>:哪个触发器起的单、每一步谁在场、AI 干了哪段、人修订了什么、在哪里监听了三天、驳回过几次、最终谁放的行——即<b>任务记忆与事件流</b>(08)。这份含人机分工与认账链的轨迹,是任何 ERP 都不持有、事后也补不出来的数据;它的首要用途是增强工作质量的确定性(0.2),其次才是合规与复盘。<b>ERP 记生意的事实,本系统记工作的事实</b>——互补不重叠,这也是本系统不与 ERP 争地盘的原因;护城河不在业务数据,而在工作轨迹。</p>
|
||||
|
||||
<div class="fig">
|
||||
<div class="figcap"><span>FIG-01 · 两本事实:生意的事实 vs 工作的事实</span><span>结果性记录 ↔ 过程性记录 · 互补不重叠</span></div>
|
||||
<svg viewBox="0 0 1000 322" role="img" aria-label="ERP/CRM 记录生意的结果性事实,本系统记录工作的过程性事实(任务记忆与事件流),两本事实互补">
|
||||
<style>
|
||||
.oa-t{font-family:'PingFang SC','Noto Sans SC',sans-serif;font-size:12px;font-weight:600;fill:#1F2933}
|
||||
.oa-c{font-family:'PingFang SC','Noto Sans SC',sans-serif;font-size:11px;fill:#3A4452}
|
||||
.oa-m{font-family:'SF Mono',Menlo,monospace;font-size:10px;font-weight:600;letter-spacing:.12em;fill:#6A7686}
|
||||
.oa-s{font-family:'PingFang SC','Noto Sans SC',sans-serif;font-size:9.5px;fill:#6A7686}
|
||||
.oa-ts{font-family:'SF Mono',Menlo,monospace;font-size:8.5px;fill:#98A2B0}
|
||||
</style>
|
||||
<text x="36" y="28" class="oa-m" fill="#46586A">ERP / CRM · 生意的结果性事实</text>
|
||||
<rect x="36" y="44" width="456" height="236" rx="9" fill="#F7F9FB" stroke="#9AA7B6" stroke-width="1.4"/>
|
||||
<rect x="60" y="68" width="408" height="34" rx="6" fill="#FFFFFF" stroke="#D8DEE6"/>
|
||||
<circle cx="80" cy="85" r="7.5" fill="#EAF3EE" stroke="#2F5C45" stroke-width="1.3"/><path d="M76.5,85 l2.6,2.6 l4.6,-5.4" fill="none" stroke="#2F5C45" stroke-width="1.5"/>
|
||||
<text x="98" y="90" class="oa-t">订单 · 已成交</text>
|
||||
<text x="444" y="89" text-anchor="end" class="oa-ts">RESULT</text>
|
||||
<rect x="60" y="112" width="408" height="34" rx="6" fill="#FFFFFF" stroke="#D8DEE6"/>
|
||||
<circle cx="80" cy="129" r="7.5" fill="#EAF3EE" stroke="#2F5C45" stroke-width="1.3"/><path d="M76.5,129 l2.6,2.6 l4.6,-5.4" fill="none" stroke="#2F5C45" stroke-width="1.5"/>
|
||||
<text x="98" y="134" class="oa-t">回款 · 已入库</text>
|
||||
<text x="444" y="133" text-anchor="end" class="oa-ts">RESULT</text>
|
||||
<rect x="60" y="156" width="408" height="34" rx="6" fill="#FFFFFF" stroke="#D8DEE6"/>
|
||||
<circle cx="80" cy="173" r="7.5" fill="#EAF3EE" stroke="#2F5C45" stroke-width="1.3"/><path d="M76.5,173 l2.6,2.6 l4.6,-5.4" fill="none" stroke="#2F5C45" stroke-width="1.5"/>
|
||||
<text x="98" y="178" class="oa-t">发货 · 已签收</text>
|
||||
<text x="444" y="177" text-anchor="end" class="oa-ts">RESULT</text>
|
||||
<rect x="60" y="208" width="408" height="40" rx="6" fill="#FFFFFF" stroke="#B0B8C4" stroke-width="1.2" stroke-dasharray="5 3"/>
|
||||
<text x="80" y="232" class="oa-c" fill="#6A7686">这件事是<tspan font-weight="600">怎么被做成的</tspan>?<tspan fill="#8F3330" font-weight="600"> ——无记录</tspan></text>
|
||||
<text x="60" y="268" class="oa-s">只记「做成了什么」,不持有过程</text>
|
||||
<text x="508" y="28" class="oa-m" fill="#8A5F1C">本系统 · 工作的过程性事实(任务记忆 + 事件流)</text>
|
||||
<rect x="508" y="44" width="456" height="236" rx="9" fill="#FCFAF3" stroke="#B07D2B" stroke-width="1.2"/>
|
||||
<line x1="540" y1="76" x2="540" y2="252" stroke="#E3D5B8" stroke-width="1.5"/>
|
||||
<circle cx="540" cy="80" r="4.5" fill="#FFFFFF" stroke="#46586A" stroke-width="1.5"/>
|
||||
<text x="558" y="84" class="oa-c">触发器起单 · 工作流调起</text><text x="944" y="84" text-anchor="end" class="oa-ts">09:12</text>
|
||||
<circle cx="540" cy="112" r="4.5" fill="#F7F0E0" stroke="#B07D2B" stroke-width="1.6"/>
|
||||
<text x="558" y="116" class="oa-c" fill="#8A5F1C" font-weight="600">AI 草拟产出 · 读取留快照</text><text x="944" y="116" text-anchor="end" class="oa-ts">09:13</text>
|
||||
<circle cx="540" cy="144" r="4.5" fill="#FFFFFF" stroke="#2F6DB5" stroke-width="1.6"/>
|
||||
<text x="558" y="148" class="oa-c" fill="#173A63" font-weight="600">人驳回迭代 · 意见随卡留痕</text><text x="944" y="148" text-anchor="end" class="oa-ts">09:40</text>
|
||||
<circle cx="540" cy="176" r="4.5" fill="#FFFFFF" stroke="#46586A" stroke-width="1.5"/>
|
||||
<text x="558" y="180" class="oa-c">监听客户回件 · 时限三天</text><text x="944" y="180" text-anchor="end" class="oa-ts">+2D</text>
|
||||
<circle cx="540" cy="208" r="4.5" fill="#FFFFFF" stroke="#46586A" stroke-width="1.5"/>
|
||||
<text x="558" y="212" class="oa-c">数据事件到 · 环续跑</text><text x="944" y="212" text-anchor="end" class="oa-ts">11:02</text>
|
||||
<circle cx="540" cy="240" r="4.5" fill="#EAF3EE" stroke="#2F5C45" stroke-width="1.8"/>
|
||||
<text x="558" y="244" class="oa-c" fill="#2F5C45" font-weight="600">放行通过 · 草稿落事实 · 可回放</text><text x="944" y="244" text-anchor="end" class="oa-ts">11:30</text>
|
||||
<text x="532" y="268" class="oa-s">谁在场 · AI 干了哪段 · 依据什么 · 谁放行——逐条留痕</text>
|
||||
<line x1="36" y1="292" x2="964" y2="292" stroke="#ECEFF3"/>
|
||||
<text x="36" y="312" class="oa-c" font-size="11"><tspan font-weight="600">ERP 记生意的事实,本系统记工作的事实</tspan>——互补不重叠;过程事实 = 任务记忆 + 事件流,是任何 ERP 都不持有、事后也补不出来的数据</text>
|
||||
</svg>
|
||||
</div>
|
||||
|
||||
<h3 class="h3"><span class="n">0.2</span>AI Native 的意义:让 AI 的参与增强确定性</h3>
|
||||
<p class="lead">判断类工作的质量,传统上是一个随机变量:取决于谁在做、状态如何、经验是否在场。把 AI 以「加个聊天框」的方式引入,只会再放大它——产出不可复现、无法追因、责任模糊。</p>
|
||||
<p>本系统对「AI Native」的定义与此相反:<b>AI 参与的目标不是替人干活,而是增强工作质量的确定性;人机协作的可审计轨迹正是达成这一目标的机制</b>。非确定性(人与 AI 的判断)被三重结构围住:<b>事前有契约</b>(契约七件,4.1)、<b>事中有门</b>(放行只属于人;流程层另有审批点)、<b>事后有痕</b>(任务记忆与事件流,可回放可归因)。围住之后,质量不取决于个体发挥,而取决于契约与业务模型——可版本化、可审计、可持续进化的<b>组织资产</b>。</p>
|
||||
<div class="callout brand"><b>两级确定性,判据可测:</b><b>结构确定性</b>——无论 AI 怎么走,同一契约、同一活动基座、同一事件标准、同构留痕、有限终点(临场自由,结构铁笼);<b>质量确定性</b>——由两指标检验:自主率(干了多少)与纠正率(干坏了多少),复合为有效自主率 = 自主率 ×(1 − 纠正率)(08)。「AI 越多越确定」不靠宣称,靠仪表。</div>
|
||||
|
||||
<h3 class="h3"><span class="n">0.3</span>部署边界</h3>
|
||||
<p>本系统服务<b>企业</b>:协调<b>员工与 AI</b> 高效开展经营活动。按<b>单次部署 ≤ 50 人、单组织</b>设计:不做多租户,治理角色由组织内兼任,一切机制的复杂度预算以此为上限。系统只对两类主数据拥有事实源——<b>员工</b>与<b>工作</b>(任务、工作流、记忆);客户、物料、订单等业务对象,或在活动声明的台账里(数据可自生长,07),或在外部系统里(以外部系统调用接入,事实源在外)。</p>
|
||||
|
||||
<!-- ========== 01 ========== -->
|
||||
<h2 class="ch"><span class="n">01</span>五层总图</h2>
|
||||
<div class="ch-rule"></div>
|
||||
|
||||
<div class="stack">
|
||||
<div class="cap">WORK OS · 五层总图(交互 / 流程 / 引擎 / 调用 / 基座 + 贯穿件 + 权力线)</div>
|
||||
<div class="layer l1">
|
||||
<div class="lno"><b>交互</b><span>SURFACE</span></div>
|
||||
<div class="lbody">
|
||||
<div class="ltitle"><b>交互层</b><span>员工的责任面;组织的管理与编排面;零业务逻辑</span></div>
|
||||
<div class="mods">
|
||||
<div class="mod"><b>工作台(员工面)</b><span>五要素:任务 · 审批 · 消息 · 纪要 · 汇报 —— 责任被动响应 · 五要素同源投影(02)</span></div>
|
||||
<div class="mod"><b>治理台(管理面)</b><span>九功能:任务 · 员工 · 工作流 · 触发器 · 活动库 · 工具 · 数据 · 记忆 · 系统(含 LLM 实例与通道实例)(02)</span></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layer l2">
|
||||
<div class="lno"><b>流程</b><span>PROCESS</span></div>
|
||||
<div class="lbody">
|
||||
<div class="ltitle"><b>流程层</b><span>工作如何被发起、串联与裁决;编排五要素,流转零 LLM</span></div>
|
||||
<div class="mods">
|
||||
<div class="mod"><b>触发器(平级)</b><span>周期 / 事件 / 登记三类 —— 流程层的系统级事件监听,经调用接口起单(03 / 06)</span></div>
|
||||
<div class="mod"><b>流程包 / 工作流</b><span>流程包 = 调用接口 + 两种活动(声明)+ 审批点 + 两种网关;工作流 = 其运行时实例(03)</span></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layer l3">
|
||||
<div class="lno"><b>引擎</b><span>ENGINE</span></div>
|
||||
<div class="lbody">
|
||||
<div class="ltitle"><b>引擎层</b><span>工作流引擎 = 流程引擎 + 活动基座</span></div>
|
||||
<div class="mods">
|
||||
<div class="mod"><b>流程引擎</b><span>确定性流转:起单 · 调度节点 · 审批点卡工位 · 网关分合 —— 零 LLM;审批与网关模式由它承载</span></div>
|
||||
<div class="mod"><b>活动基座</b><span>六件:契约 · 交互 · 记忆 · 数据 · 工具(调用契约)· LLM 调用 —— Agent 机制的通用运行模式(04)</span></div>
|
||||
<div class="mod"><b>两范式</b><span>Case = loop(临场演绎 · 调度归 AI)· SOP = flow(照谱执行 · 调度归系统)—— 统一套执行契约</span></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layer l4">
|
||||
<div class="lno"><b>调用</b><span>CALL</span></div>
|
||||
<div class="lbody">
|
||||
<div class="ltitle"><b>调用层</b><span>一切能力的注册、授权与内外交互</span></div>
|
||||
<div class="mods">
|
||||
<div class="mod"><b>系统调用</b><span>本系统服务与外部系统(ERP / CRM):读 = 快照留痕,写 = 过放行(07)</span></div>
|
||||
<div class="mod"><b>LLM 工具</b><span>模型能力封装的工具,白名单授权 —— 与基座的 LLM 调用不同物(07)</span></div>
|
||||
<div class="mod"><b>人类工具</b><span>四卡:决策 · 执行 · 补全 · 放行 —— 人在环是被调用的工具(05)</span></div>
|
||||
<div class="mod"><b>通道</b><span>邮件 / IM 收发:入站经归属解析进统一事件流(06)</span></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layer l5">
|
||||
<div class="lno"><b>基座</b><span>BASE</span></div>
|
||||
<div class="lbody">
|
||||
<div class="ltitle"><b>基座层</b><span>事实、记录、能力与工件的存放;零业务逻辑</span></div>
|
||||
<div class="mods">
|
||||
<div class="mod"><b>数据</b><span>主数据:员工 · 岗位 · 权限 · 共享对象目录</span></div>
|
||||
<div class="mod"><b>台账</b><span>活动声明的业务数据表:schema 声明 · 宿主物化 · 统一治理</span></div>
|
||||
<div class="mod"><b>记忆</b><span>任务记忆归档库(单单封卷)· 活动记忆库(跨单持久)(08)</span></div>
|
||||
<div class="mod"><b>工具箱</b><span>功能工具之库 —— 独立开发注册入口(07 / 11)</span></div>
|
||||
<div class="mod"><b>活动库</b><span>已安装活动之库 —— 独立安装卸载入口(11)</span></div>
|
||||
<div class="mod"><b>流程包</b><span>治理台编排的结构定义;工作流 = 其运行时实例(03 / 11)</span></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="thru"><b>贯穿 · 统一事件标准</b><span>系统向活动只以统一信封抛四类事件(数据 / 时间 / 人 / 控制);一条事件流,三级消费:任务监听 → 触发器 → 消息(06)。</span></div>
|
||||
<div class="thru"><b>贯穿 · 外装件两类</b><span>活动包 → 活动库,工具包 → 工具箱 —— 活动在系统外,模式在系统内;<b>改业务 = 换外装件或改流程包,不改系统</b>。</span></div>
|
||||
<div class="xcut"><b>权力线 · 调度权分层</b><span>工作流 → 系统 · flow 活动 → 系统 · loop 活动 → AI · 放行 → 人 —— <b>确定交系统,临场交 AI,落地交人</b>(04)。</span></div>
|
||||
</div>
|
||||
|
||||
<p>交互定呈现与责任,流程定结构与流转,引擎定执行,调用定能力,基座定事实。实现拓扑上,系统是 <b>web + server</b> 两侧(09)。</p>
|
||||
|
||||
<div class="tbl"><table>
|
||||
<tr><th style="width:130px">术语</th><th>定义</th></tr>
|
||||
<tr><td><b>流程包 / 工作流</b></td><td>流程包 = <b>调用接口 + 两种活动 + 审批点 + 两种网关</b>的编排定义:治理台在系统内编排,版本化存放于基座;<b>工作流 = 流程包的运行时实例</b>(03)。</td></tr>
|
||||
<tr><td><b>活动</b></td><td>一个<b>完成一项任务的 Agent 机制</b>的开发态:基于活动基座在系统外开发,经活动库安装,以声明入流;两种:案例活动(loop)与标准活动(flow)。</td></tr>
|
||||
<tr><td><b>任务</b></td><td>活动的<b>运行态</b>:活动被调起的一次运行;恰有一个负责人;工作台「任务」要素的单位。</td></tr>
|
||||
<tr><td><b>Agent 机制</b></td><td>活动完成任务的机制本体,范式两种:loop(临场演绎)与 flow(照谱执行);业务模型、交互内容、技能清单、Harness 与过程工作区皆随活动(《活动模型》)。</td></tr>
|
||||
<tr><td><b>活动基座</b></td><td>落在系统内的通用运行模式,六件:契约 · 交互 · 记忆 · 数据 · 工具(调用契约)· LLM 调用;<b>内容归活动,笼子归系统</b>(04)。</td></tr>
|
||||
<tr><td><b>活动包 / 活动库</b></td><td>活动的交付单元 / 已安装活动之库(独立的安装与卸载入口,11)。</td></tr>
|
||||
<tr><td><b>工具包 / 工具箱</b></td><td>功能工具的交付单元(独立开发的代码包)/ 其注册入口与库(07 / 11)。</td></tr>
|
||||
<tr><td><b>人类工具</b></td><td>调用层四种内置工具:决策 · 执行 · 补全 · 放行——<b>与 LLM 工具同列</b>;经对话流卡片到达人,回传异步(05)。</td></tr>
|
||||
<tr><td><b>审批点</b></td><td>流程层的<b>通用</b>人裁节点:卡到审批人工位,通过 / 驳回,附依据;与活动级的放行不同层(03 / 05)。</td></tr>
|
||||
<tr><td><b>事件信封</b></td><td>系统向活动抛事件的统一标准:ID · 类型 · 关联 · 载荷 · 时间与来源 · 留痕指针;四类:数据 / 时间 / 人 / 控制(06)。</td></tr>
|
||||
<tr><td><b>任务记忆</b></td><td>一单任务的<b>会话历史</b> = 消息历史 + 引擎事件流,同轴按时间全序;只追加;续跑、审计、回放的依据与蒸馏源(08)。</td></tr>
|
||||
<tr><td><b>活动记忆</b></td><td>关于一个活动的跨实例持久事实,四层结构,<b>为优化业务模型而设计</b>;记忆不载权力(08)。</td></tr>
|
||||
<tr><td><b>放行</b></td><td>人对任务成果的落地裁决:放行通过 / 驳回重做 / 驳回迭代;<b>完成只出自放行通过</b>——落地预检过关才发卡,放行即落地,落地收敛终态方成(05 / 7.3 / 09)。</td></tr>
|
||||
<tr><td><b>对话流 / 视图区</b></td><td>工作台-任务的交互结构:对话流是唯一回环输入口;视图区是只读呈现容器,内容由后端流控推送(09)。</td></tr>
|
||||
</table></div>
|
||||
|
||||
<!-- ========== 02 ========== -->
|
||||
<h2 class="ch"><span class="n">02</span>交互层:工作台与治理台</h2>
|
||||
<div class="ch-rule"></div>
|
||||
|
||||
<p class="lead">交互层只有两个面:<b>工作台</b>面向员工,<b>治理台</b>面向组织的管理者。面上零业务逻辑——呈现的一切都来自下层的事实与投影。</p>
|
||||
|
||||
<h3 class="h3"><span class="n">2.1</span>工作台五要素</h3>
|
||||
<p>工作台是员工的<b>责任面</b>:它回答「现在哪些事等我、我裁过什么、与我相关的发生了什么、我们沉淀了什么、我干了什么」。员工不需要在系统里"找工作干"——责任被系统推到工作台上,员工被动响应;主动动作只有一类:维护纪要。</p>
|
||||
<div class="tbl"><table>
|
||||
<tr><th style="width:70px">要素</th><th style="width:150px">性质</th><th>内容</th></tr>
|
||||
<tr><td><b>任务</b></td><td>责任 · 被动响应</td><td>一个活动(<b>标准活动</b>或<b>案例活动</b>)的一次运行,落到恰一名负责人的工作台</td></tr>
|
||||
<tr><td><b>审批</b></td><td>责任 · 被动响应</td><td>工作流中的<b>审批点</b>,卡到审批人工位:通过 / 驳回,附依据</td></tr>
|
||||
<tr><td><b>消息</b></td><td>信息 · 被动响应</td><td>系统通知与<b>跨任务征答</b>:通知(承载触发器的邮件和消息、一般公告、提醒与告警)+ 他人任务发来的人类工具卡(以系统消息送达,就地作答,2.1)</td></tr>
|
||||
<tr><td><b>纪要</b></td><td>团队主动维护上传</td><td>会议纪要等团队沉淀;决议可经<b>登记触发</b>转为工作流的启动(3.1)——登记人即来源</td></tr>
|
||||
<tr><td><b>汇报</b></td><td>自动</td><td>按日、周、月、年自动总结此员工的工作汇报——由本人各任务的<b>任务日志</b>聚合生成(8.1),确认即提交,<b>零手工汇报</b></td></tr>
|
||||
</table></div>
|
||||
<ul class="tight">
|
||||
<li><b>责任与信息分明</b>——任务与审批是责任:有完成与裁决语义,恰有其主;负责人 / 审批人的变更只经治理台改派,改派留痕并通知双方;消息是信息,不产生责任;纪要是团队的主动沉淀;汇报是系统代劳的自动产出。</li>
|
||||
<li><b>活动内的人环不另立要素</b>——活动执行中对人的调用(决策、执行、补全、放行四卡,05)按被调用人分两个到达面:发给<b>负责人</b>的卡出现在该任务自己的对话流里;发给<b>其他人</b>的卡以<b>系统消息</b>送达对方的消息要素,就地作答——任务要素永远只装"我负责的任务",<b>跨人卡是一次性的解答请求,不是责任转移</b>;作答权限只及卡面与决策包,不开放任务对话流。回传经统一入口写回任务,调用与回传全程在任务侧留痕。任务侧不满意可<b>驳回重答:驳回即新发一条系统消息</b>(新卡实例,附驳回理由与原答引用),原卡闭合——每次请求与回答都是独立消息,只增不改。工作台层面的「审批」专指工作流级的审批点。</li>
|
||||
<li><b>五要素同源</b>——做事与留痕是同一个动作:五要素都是同一份过程事实(任务记忆与工作流事件)在员工视角下的投影——汇报是它的时间聚合,消息是它的相关性过滤,不存在"干完活再补记录"。</li>
|
||||
</ul>
|
||||
|
||||
<h3 class="h3"><span class="n">2.2</span>治理台九功能</h3>
|
||||
<p class="lead">治理台功能清单九项——每一项对应架构中的一件,治理台由此覆盖全部五层:</p>
|
||||
<div class="tbl"><table>
|
||||
<tr><th style="width:130px">功能</th><th>管什么</th><th style="width:170px">对应</th></tr>
|
||||
<tr><td><b>任务管理</b></td><td>运行态:任务与工作流(两级运行时实例)的在途监控、干预与控制(叫停 / 暂停 / 终止,即控制事件,06);查看任意任务的<b>任务日志</b>(8.1);<b>改派</b>——在途任务与待答卡片的负责人 / 审批人变更,改派留痕并通知双方</td><td>引擎 · 流程层</td></tr>
|
||||
<tr><td><b>员工管理</b></td><td>员工、岗位、权限——<b>权限按岗位授予</b>:客体三类(数据:域.对象[.字段] / 治理功能 / 任务),动作三种(读 / 写 / 治理);任务负责人与被征答人对所涉内容天然可见;<b>停用前置检查</b>——员工停用前,其在途任务与待答卡须先改派完毕</td><td>基座 · 数据</td></tr>
|
||||
<tr><td><b>工作流管理</b></td><td>设计态:流程包的五要素编排(03)与版本;<b>编排即定契约</b>——画完工作流图可导出活动开发的依赖文件(11)</td><td>流程层 · 基座 · 流程包</td></tr>
|
||||
<tr><td><b>触发器配置</b></td><td>触发器的创建、配置与启停——定义<b>调用工作流的时机</b>(周期规则与事件规则);触发器与工作流平级、不属于工作流,不随流程包版本;触发器 = 流程层的系统级事件监听(06),经调用接口调起流程包</td><td>流程层 · 基座(系统自持)</td></tr>
|
||||
<tr><td><b>活动库管理</b></td><td>活动包的安装、卸载、版本并存与引用查询——独立入口(11);库内按<b>业务分类(一级,组织自定)× 活动类型(标准 / 案例)</b>两维管理,两维平级、相互独立</td><td>基座 · 活动库</td></tr>
|
||||
<tr><td><b>工具管理</b></td><td>工具包注册、白名单与授权、账号 / 密钥 / endpoint 配置</td><td>调用层 · 基座 · 工具箱</td></tr>
|
||||
<tr><td><b>数据管理</b></td><td>主数据、共享对象目录、台账治理(脱敏、保留期、权限)</td><td>基座 · 数据与台账</td></tr>
|
||||
<tr><td><b>记忆管理</b></td><td>任务记忆归档与活动记忆库的治理</td><td>基座 · 记忆</td></tr>
|
||||
<tr><td><b>系统管理</b></td><td>系统配置,含 <b>LLM 实例</b>(创建自定义名称模型:Provider(开发支持的厂商枚举)/ URL / API-Key / Model name;活动以名称声明引用)、<b>通道实例</b>(邮箱、IM 接入;归属键提取规则与默认认领岗位,6.2)与<b>系统用途模型绑定</b>(系统自身的 LLM 消耗点——叙述性小结、汇报生成、蒸馏钩子——绑定专用模型实例与预算,计量入系统账、不占活动预算)管理</td><td>引擎 · 调用层</td></tr>
|
||||
</table></div>
|
||||
<p class="small">治理动作本身留痕入事件流——治理也被治理。</p>
|
||||
|
||||
<!-- ========== 03 ========== -->
|
||||
<h2 class="ch"><span class="n">03</span>流程层:流程包、工作流与触发器</h2>
|
||||
<div class="ch-rule"></div>
|
||||
|
||||
<p class="lead"><b>流程包 = 调用接口 + 两种活动 + 审批点 + 两种网关的流程编排;工作流 = 流程包的运行时实例。</b>包与实例两级对称:<b>流程包 → 工作流,活动 → 任务——包在库,实例在跑</b>。</p>
|
||||
<p>编排层的基础要素有五:<b>活动(声明)、审批、网关、触发器、流程包</b>——活动、审批、网关是流程包内的节点要素,触发器与流程包是平级的顶层要素;治理台的编排就在这五种要素上进行。其中活动以<b>声明</b>入流:编排引用的是<b>活动库</b>中已安装的活动,安装与卸载走活动库的独立入口(11),不在编排中发生。</p>
|
||||
|
||||
<div class="tbl"><table>
|
||||
<tr><th style="width:120px">构件</th><th style="width:180px">职责</th><th>要点</th></tr>
|
||||
<tr><td><b>调用接口</b></td><td>流程包的唯一出入口</td><td>声明<b>输入契约与输出声明</b>;触发器与上游系统一律经此调起;流程包声明<b>显式终点</b>,工作流完成时末端输出载荷按输出声明交付、按来源回执——登记人收消息回执,上游系统收回调</td></tr>
|
||||
<tr><td><b>活动(两种)</b></td><td>责任单元</td><td><b>标准活动</b>(flow)与<b>案例活动</b>(loop);节点以<b>声明</b>引用活动库中已安装的活动,恰有一名负责人;<b>任务 = 活动的运行时实例</b>——活动被调起的一次运行即一单任务</td></tr>
|
||||
<tr><td><b>审批点(通用)</b></td><td>工作流级的人裁节点</td><td>功能属性四件:<b>审批岗位</b>(复用负责人四策略解析)· <b>输入装配映射</b>(审批人所见载荷,复用边机制)· <b>驳回走向</b>(声明式:回指定节点重开新实例(带载荷映射)/ 终止,不由临场决定)· <b>催办阶梯</b>(时限机制复用:提醒 → 升级)</td></tr>
|
||||
<tr><td><b>网关(两种)</b></td><td>路由</td><td><b>并行</b>(AND:分叉与汇合)与<b>异或</b>(XOR:条件路由,判定依据入事件记录);条件声明式、静态可检,不得内嵌自由逻辑</td></tr>
|
||||
</table></div>
|
||||
|
||||
<p><b>边与载荷映射:连线即映射,画图即校验,不闭合不得发布。</b>流程包的每条边携带<b>输入装配映射</b>——上游输出口载荷字段 / 流程变量 / 起单载荷 / 常量 → 下游活动契约的 data 字段,允许 S-FEEL 表达式做转换;与触发器的字段映射同一形式(3.1)。编排画布<b>强制契约前后约束</b>:连一条边即须完成该边映射(编排器就地给出上游载荷与下游必填字段的对照,必填未映射 = 边未完成),类型兼容依两端契约 schema 当场校验;<b>存在未完成边、未满足必填或类型冲突的流程包可存草稿、不得发布</b>。两种连线情形同受此约束:引用已安装活动,对活动库中的契约校验;新活动(未开发),契约的输入输出<b>在编排中就地定义</b>、随边成形——依赖文件的输入输出声明由此生成(11.1)。AND 汇合后的同名字段必须显式指定来源分支,不做隐式合并;message 由编排声明模板(可插值载荷字段),缺省为空。</p>
|
||||
|
||||
<p><b>负责人与审批人解析:编排声明岗位,起单时确定性解析。</b>活动节点与审批点声明<b>岗位</b>与解析策略,策略封闭四选:<b>指定人</b>(直接绑定员工,慎用)/ <b>岗位唯一人</b> / <b>轮值</b>(岗内以在途任务数最少者优先)/ <b>来源跟随</b>(复用同一工作流内该岗位已解析出的人,保持一单一人的连续)。默认:岗位唯一人;岗上多人时按轮值。解析发生在节点起单时,结果与依据留痕;岗位空缺按该节点的失败走向处置,或转治理台待指派;运行中变更走治理台改派(02)。</p>
|
||||
|
||||
<p><b>失败走向:每个活动节点可声明,封闭四选,默认终止流。</b>节点以非完成终态结束(受阻、熔断、耗尽等)时,按其声明的失败走向处置:<b>终止流</b>(默认)——工作流转「异常」,通知治理台 · 任务管理,人工处置;<b>改道</b>——声明一条备选边(失败载荷 = 终态、原因码与说明,备选边同带载荷映射);<b>升审批</b>——失败落到指定审批点,由审批人裁决:重开新任务实例 / 改道 / 终止流;<b>容忍</b>(仅限 AND 分支)——显式声明该分支失败不阻汇合,静态校验其下游映射不得依赖该分支的必填字段。流程层不自动重试活动(过程内重试归 Harness);流级重做一律是人裁决后<b>重开新任务实例</b>——同一节点、新任务 ID、留痕关联,不复活旧任务。</p>
|
||||
|
||||
<h3 class="h3"><span class="n">3.1</span>触发器</h3>
|
||||
<p><b>触发器 = 基于周期、事件或登记触发的工作流启动调用。</b>在统一事件标准下,触发器就是<b>流程层的系统级事件监听</b>(06):消费同一条事件流,动作是起单。三类:<b>周期触发</b>——再分两型:<b>日历型</b>(纯日历规则:对账日、周报周期)与<b>数据日历型</b>(按台账日期字段 + 偏移 + 过滤条件逐行起单,如「合同到期前 N 天」;<b>同一行同一日期只触发一次</b>,字段值变更后可再触发);<b>事件触发</b>(通道入站命中规则、台账数据事件);<b>登记触发</b>——人工起单的统一形态:登记人选择流程包、按调用接口 schema 填写输入(表单由 schema 自动渲染)、提交即起单;纪要决议转起单即经登记触发。</p>
|
||||
<p><b>触发器输入装配</b>——事件触发的触发器配置含声明式<b>字段映射</b>:事件信封与载荷字段 → 调用接口的 data 字段;缺必填字段则起单失败、入死信。周期触发以规则求值结果装配;登记触发以登记表单为输入。</p>
|
||||
<p><b>触发器与工作流是平级概念。</b>触发器的配置定义的是<b>调用工作流的时机</b>——它<b>不属于工作流</b>:不入流程包结构,不随流程包版本,配置与启停在治理台独立进行(02),配置存于基座的系统自持存储(11)。触发器只负责「起单」,经<b>调用接口</b>调起流程包、生成一条工作流;流程包与活动内部不含任何触发逻辑。同一个流程包可以被多个触发器调起,同一个触发器也只知道调用接口、不知流程内部;触发器的增删启停不改流程包的任何版本。<b>凡单必有来源</b>:每条工作流的来源可追溯——触发器即来源;纪要登记起单的,登记人即来源。</p>
|
||||
|
||||
<h3 class="h3"><span class="n">3.2</span>组合语义与构件来处</h3>
|
||||
<ul class="tight">
|
||||
<li><b>两级组合</b>——<b>流程包串活动</b>(运行时即工作流串任务),是责任级组合:每个节点有负责人、有契约、有裁决;<b>活动内 Agent 机制自治</b>,是方法级执行:怎么做由活动自带的范式与业务模型决定(《活动模型》)。流程层的流转本身零 LLM:路由、汇合、审批点的推进全部确定。</li>
|
||||
<li><b>构件来处分两边</b>——<b>活动是经活动库安装进来的外部件</b>;<b>审批点、网关与触发器是系统内置的要素</b>:落在系统内,声明 / 配置即用,零开发。一个流程包里,需要开发的只有活动。</li>
|
||||
<li><b>工作流状态是聚合投影</b>——由流内各任务的状态按固定规则聚合推导,流程层不另设状态机。聚合的计量对象是<b>节点实例</b>(重开产生新实例,旧实例已终,不再入算)。聚合规则:任一节点实例运行中 → <b>运行中</b>;无运行实例且存在待人 / 监听 → <b>等待中</b>;<b>全部已激活的节点实例收敛(完成或已消化)且无在途实例 → 已完成</b>——XOR 未选分支从未激活、不入集合,容忍分支以"已消化"计;被控制事件终止 → <b>已终止</b>;任一实例以非完成终态结束且其失败走向未消化(终止流待人工处置中)→ <b>异常</b>;改道、容忍与升审批一经生效即为消化,不入异常(03 失败走向)。</li>
|
||||
</ul>
|
||||
|
||||
<p><b>声明条件的表达语言</b>——系统侧一切声明式条件(XOR 网关条件、触发器事件规则、监听过滤条件)统一采用 <b>FEEL 表达式子集(S-FEEL)</b>:比较、逻辑、算术、字符串与日期函数,无外部调用,静态可检。求值输入:网关处 = 流转载荷与流程变量;触发器处 = 事件信封与载荷字段;监听处 = 事件信封与载荷字段。周期规则 = 日历表达式 + 日历偏移(支持「日期字段 − N 天」式)。节点间的载荷映射与触发器字段映射同一形式(03 边与载荷映射)。</p>
|
||||
|
||||
<!-- ========== 04 ========== -->
|
||||
<h2 class="ch"><span class="n">04</span>引擎:流程引擎 + 活动基座</h2>
|
||||
<div class="ch-rule"></div>
|
||||
|
||||
<p class="lead"><b>工作流引擎 = 流程引擎 + 活动基座。</b></p>
|
||||
<ul class="tight">
|
||||
<li><b>流程引擎</b>——确定性流转:接收调用接口的起单、按结构调度节点、把审批点卡到人的工位、执行网关的分合、把每次流转记入事件。零 LLM、零临场;审批与网关的模式由它承载。</li>
|
||||
<li><b>活动基座</b>——活动 Agent 机制的<b>通用运行模式</b>,落在操作系统内;引擎为每单任务在基座上运行该活动的 Agent 机制。</li>
|
||||
</ul>
|
||||
|
||||
<h3 class="h3"><span class="n">4.1</span>活动基座六件</h3>
|
||||
<p>活动基座对所有活动同一份。活动在系统外开发时,面对的就是这六件的接口;安装进来,跑在同一副基座上:</p>
|
||||
<div class="tbl"><table>
|
||||
<tr><th style="width:150px">构件</th><th style="width:270px">内容</th><th>职责</th></tr>
|
||||
<tr><td><b>契约</b></td><td><b>契约七件</b>:输入(data + message)· 输出口(必发 / 选择)· 必交付物 · 验收判据(分级标注:L1 形式校验 / L2 机检 / L3 抽验 / L4 独立评审 / L5 人放行,不得谎报等级)· 禁区 · 授权边界 · 资源声明</td><td>活动对外的全部承诺;两种范式同一契约格式——"统一套执行契约"的锚点;《活动模型》自开发视角展开同一份七件清单</td></tr>
|
||||
<tr><td><b>交互</b></td><td>工作台-任务的<b>对话流</b> + <b>视图区容器</b></td><td>交互的结构骨架:对话流是任务的人机时间线、一切回环输入的唯一入口;视图区是活动渲染的只读呈现容器——<b>结构归基座,内容归活动</b>。<b>控制权共同持有、按态转交</b>:活动激活时归活动(视图流控与对话输出由活动驱动),流程流转时归系统(流转、审批与终态呈现由系统驱动);输入侧不转交,永远走系统单入口</td></tr>
|
||||
<tr><td><b>记忆</b></td><td><b>任务记忆</b> + <b>活动记忆</b></td><td>任务记忆 = <b>会话历史</b>(消息历史 + 引擎事件流,同轴按时间全序),框架自动记录、只追加;活动侧唯一接口 = <b>窗口配置</b>(每次 LLM 调用加载多少轮)。活动记忆 = <b>结构化记忆</b>,基座只提供<b>存与取</b>,结构归活动侧,<b>为优化业务模型而设计</b>(08)</td></tr>
|
||||
<tr><td><b>数据(台账)</b></td><td>「数据域.数据对象.字段」三级寻址 + 通用事务性接口</td><td>活动对数据与台账的一切操作按<b>数据域.数据对象.字段</b>声明寻址;数据库提供<b>通用事务性接口</b>(增删改查与事务,对所有活动同一套);安装时系统检查数据表,依活动声明<b>自生长</b>。声明语义:<b>声明的是活动要用什么字段,不是对象该定义什么字段</b>——对象的实际 schema = 全部使用声明的<b>最大化合并</b>(并集);<b>定义只增不破坏</b>:声明永不缩表、不删改已有字段,清理归档是数据管理的治理动作、不经声明发生(11)。同名字段类型不一致时,以能兼容双方的<b>最宽类型</b>落地(放宽即增,不破坏),静态审提示、不阻塞;语义互斥不可兼容的极端情形才拦下,交数据管理裁决。运行中的写入落<b>任务级草稿层</b>,放行时合并入正式版(09)</td></tr>
|
||||
<tr><td><b>工具(调用契约)</b></td><td>白名单工具的调用契约</td><td>活动只经调用契约使用工具;系统调用、LLM 工具、人类工具与通道皆以工具形态自调用层供给(07),功能工具经工具箱注册;授权在白名单与契约,不在活动代码</td></tr>
|
||||
<tr><td><b>LLM 调用(模型)</b></td><td>声明<b>自定义模型名称</b></td><td>活动侧只声明自定义的模型名称(逻辑名);名称在系统侧创建与绑定——<b>Provider(系统通过开发支持的厂商枚举)/ URL / API-Key / Model name</b> 四元配置(治理台 · 系统管理,02);活动不触厂商与密钥;模型与版本记入留痕,行为可归因</td></tr>
|
||||
</table></div>
|
||||
<div class="callout brand"><b>基座即笼子:</b>契约限承诺、工具限能力、交互限入口、记忆与留痕限事实、数据限归属、LLM 调用限模型——<b>内容归活动,笼子归系统</b>。活动代码无环境能力,一切能力经调用契约注入,越权在结构上不可能。</div>
|
||||
<div class="callout warn"><b>系统不提供统一沙箱:</b>过程工作区(草稿箱)由活动按需自设、不与范式绑定;系统不管草稿怎么组织,只认放行门——<b>放行前不落事实</b>(09)。权力边界由调用契约与白名单承担,不依赖运行时隔离。</div>
|
||||
<p><b>预算与熔断由活动基座在环外强制执行</b>——活动仅在 Harness 配置中申报参数,不自查自守。计量口径:<b>步</b> = loop 的一次决策循环 / flow 的一个声明步;<b>token</b> = LLM 调用出入 token 累计;<b>时长</b> = <b>活跃时长</b>(Agent 机制运行与工具执行的时间;挂起、监听等待、待卡回传不计入——熔断不误杀等待中的任务;时限阶梯另用日历时长,06);<b>调人次数</b>按卡计。任一项越限,基座抛控制事件并挂起任务,处置归治理台 · 任务管理(02)。</p>
|
||||
|
||||
<h3 class="h3"><span class="n">4.3</span>任务终态名录(系统裁定)</h3>
|
||||
<p>完成由框架裁定,终态由系统命名——任务终态是封闭枚举,<b>五名</b>:</p>
|
||||
<div class="tbl"><table>
|
||||
<tr><th style="width:110px">终态</th><th>语义</th><th style="width:230px">触发者</th></tr>
|
||||
<tr><td><b>放行完成</b></td><td>唯一成功终态:放行通过且落地收敛,输出口已发射</td><td>放行卡 + 落地执行(7.3)</td></tr>
|
||||
<tr><td><b>受阻待人</b></td><td>无法推进,封卷待治理处置——处置 = 改派 / 重开新实例 / 终止</td><td>Agent 机制申报,或治理台判定</td></tr>
|
||||
<tr><td><b>停滞熔断</b></td><td>停滞检测触发:该动未动、超限仍无推进</td><td>预算执行器(04)</td></tr>
|
||||
<tr><td><b>预算耗尽</b></td><td>步数 / token / 活跃时长 / 调人次数任一越限</td><td>预算执行器(04)</td></tr>
|
||||
<tr><td><b>被终止</b></td><td>控制事件 · 终止,含工作流终止的级联(06)</td><td>治理台 / 负责人</td></tr>
|
||||
</table></div>
|
||||
<p class="small">不是终态:<b>驳回</b>(重做 / 迭代)是环内回转,任务继续;<b>叫停</b>是控制事件,挂起待恢复;<b>落地受阻</b>是运行态(7.3)。非完成终态触发节点的失败走向(03);终态分布入度量(8.3)。</p>
|
||||
|
||||
<h3 class="h3"><span class="n">4.2</span>两范式,一套契约;调度权分层</h3>
|
||||
<p>两种活动的 Agent 机制范式不同——<b>Case 是 loop</b>(装载 CMMN + DMN 临场演绎),<b>SOP 是 flow</b>(按声明步序照谱执行)——但<b>统一套执行契约</b>:活动基座的六件对两种范式完全一致。差异被压缩到唯一一处:<b>Agent 机制的范式与业务模型的形态</b>。对流程层与交互层而言,两种活动不可区分地是"一个节点、一单任务"。</p>
|
||||
<div class="tbl"><table>
|
||||
<tr><th style="width:170px">对象</th><th style="width:110px">调度权</th><th>形态</th></tr>
|
||||
<tr><td><b>工作流</b>(流程层)</td><td><b>系统</b></td><td>流程引擎照结构流转:路由、汇合、审批点推进,零 LLM</td></tr>
|
||||
<tr><td><b>flow 范式活动</b></td><td><b>系统</b></td><td>引擎照声明步序推进,零临场调度</td></tr>
|
||||
<tr><td><b>loop 范式活动</b></td><td><b>AI</b></td><td>Agent 机制在业务模型的结构上临场决断下一步</td></tr>
|
||||
<tr><td><b>放行</b>(处处)</td><td><b>人</b></td><td>任务完成只出自放行通过(05);流程节点间裁决归审批人</td></tr>
|
||||
</table></div>
|
||||
<div class="callout brand"><b>确定交系统,临场交 AI,落地交人。</b>一个活动选 flow 还是 loop,本质就是把这件事的调度权交给系统还是交给 AI——<b>范式的边界即调度权的边界</b>;无论谁调度,放行权都不移交。</div>
|
||||
|
||||
<!-- ========== 05 ========== -->
|
||||
<h2 class="ch"><span class="n">05</span>人类工具:四种通用卡</h2>
|
||||
<div class="ch-rule"></div>
|
||||
|
||||
<p class="lead">活动过程中对人的调用,收敛为四种<b>人类工具</b>。定位上它们与 <b>LLM 工具同列</b>——都是调用层的内置工具(07):AI 在环内调用人,与调用任何工具同构,经调用契约、受白名单与授权约束;差别只在通道与时延——人类工具经<b>对话流</b>到达人(卡片),回传异步。这正是本系统的出发点:<b>人在环是一种被调用的工具</b>——何时调、调哪种,loop 里由 AI 临场判定,flow 里由步序声明给定;<b>人不驱动过程,人被过程调用</b>。卡片结构与回传协议归系统,内容由活动填充。</p>
|
||||
|
||||
<div class="tbl"><table>
|
||||
<tr><th style="width:70px">工具</th><th>AI 输出(卡面)</th><th style="width:270px">人回传</th></tr>
|
||||
<tr><td><b>决策</b></td><td><b>分支条件选择表</b>:可选分支、各自条件与后果、依据快照、AI 建议</td><td>选定分支,可附理由</td></tr>
|
||||
<tr><td><b>执行</b></td><td><b>作业指导书 + 结果回填表格</b>:做什么、怎么做、完成标准</td><td>按表回填结果,凭证随附</td></tr>
|
||||
<tr><td><b>补全</b></td><td><b>补全需求 + 回填表格</b>:缺什么、为何需要、格式要求</td><td>按表回填</td></tr>
|
||||
<tr><td><b>放行</b></td><td><b>成果清单 + 放行选择表</b>:交付物、验收判据与依据</td><td>三选一:<b>放行通过 / 驳回重做 / 驳回迭代</b>,驳回必附意见</td></tr>
|
||||
</table></div>
|
||||
|
||||
<div class="fig">
|
||||
<div class="figcap"><span>FIG-02 · 人类工具四卡协议</span><span>AI 组卡 → 对话流 → 人回传 → 人事件 → 环续跑</span></div>
|
||||
<svg viewBox="0 0 1000 380" role="img" aria-label="人类工具四卡协议:后端 Agent 机制判定需要人并组卡,四种卡经对话流到达人的工位,人作答后回传为人事件投递回任务,环续跑">
|
||||
<style>
|
||||
.ob-t{font-family:'PingFang SC','Noto Sans SC',sans-serif;font-size:11px;font-weight:600;fill:#1F2933}
|
||||
.ob-c{font-family:'PingFang SC','Noto Sans SC',sans-serif;font-size:10px;fill:#3A4452}
|
||||
.ob-m{font-family:'SF Mono',Menlo,monospace;font-size:10px;font-weight:600;letter-spacing:.12em;fill:#6A7686}
|
||||
.ob-s{font-family:'PingFang SC','Noto Sans SC',sans-serif;font-size:9px;fill:#6A7686}
|
||||
</style>
|
||||
<defs>
|
||||
<marker id="obS" markerWidth="9" markerHeight="9" refX="7.5" refY="4.5" orient="auto"><path d="M0,0 L9,4.5 L0,9 Z" fill="#46586A"/></marker>
|
||||
<marker id="obB" markerWidth="9" markerHeight="9" refX="7.5" refY="4.5" orient="auto"><path d="M0,0 L9,4.5 L0,9 Z" fill="#B07D2B"/></marker>
|
||||
<marker id="obH" markerWidth="9" markerHeight="9" refX="7.5" refY="4.5" orient="auto"><path d="M0,0 L9,4.5 L0,9 Z" fill="#2F6DB5"/></marker>
|
||||
</defs>
|
||||
|
||||
<text x="36" y="52" class="ob-m" fill="#8A5F1C">Agent 机制 · server(后端)</text>
|
||||
<rect x="36" y="64" width="210" height="192" rx="10" fill="#F7F0E0" stroke="#B07D2B" stroke-width="1.4"/>
|
||||
<text x="52" y="92" class="ob-t" fill="#8A5F1C">判定需要人</text>
|
||||
<text x="52" y="116" class="ob-s">loop:AI 临场判定</text>
|
||||
<text x="52" y="134" class="ob-s">flow:步序声明给定</text>
|
||||
<text x="52" y="162" class="ob-c">组卡:上下文 + 依据快照</text>
|
||||
<text x="52" y="186" class="ob-s">无上下文的裸调用不得发出</text>
|
||||
<text x="52" y="208" class="ob-s">调用经调用契约 · 白名单授权</text>
|
||||
|
||||
<text x="520" y="52" text-anchor="middle" class="ob-m" fill="#245BDB">对话流 · web(唯一回环输入口)</text>
|
||||
<rect x="400" y="64" width="240" height="36" rx="7" fill="#FFFFFF" stroke="#C9D8F8" stroke-width="1.3"/>
|
||||
<text x="520" y="86" text-anchor="middle" class="ob-c">决策卡 —— 分支条件选择表</text>
|
||||
<rect x="400" y="110" width="240" height="36" rx="7" fill="#FFFFFF" stroke="#C9D8F8" stroke-width="1.3"/>
|
||||
<text x="520" y="132" text-anchor="middle" class="ob-c">执行卡 —— 作业指导书 + 结果回填</text>
|
||||
<rect x="400" y="156" width="240" height="36" rx="7" fill="#FFFFFF" stroke="#C9D8F8" stroke-width="1.3"/>
|
||||
<text x="520" y="178" text-anchor="middle" class="ob-c">补全卡 —— 补全需求 + 回填表格</text>
|
||||
<rect x="400" y="202" width="240" height="40" rx="7" fill="#DCEAF7" stroke="#173A63" stroke-width="1.6"/>
|
||||
<text x="520" y="226" text-anchor="middle" class="ob-c" font-weight="600" fill="#173A63">放行卡 —— 成果清单 + 放行选择表</text>
|
||||
<text x="520" y="258" text-anchor="middle" class="ob-s">放行通过 / 驳回重做 / 驳回迭代 —— 驳回必附意见</text>
|
||||
|
||||
<text x="754" y="52" class="ob-m" fill="#173A63">人 · 工位(异步)</text>
|
||||
<rect x="754" y="64" width="210" height="192" rx="10" fill="#DCEAF7" stroke="#2F6DB5" stroke-width="1.4"/>
|
||||
<text x="770" y="92" class="ob-t" fill="#173A63">卡上作答 · schema 校验</text>
|
||||
<text x="770" y="116" class="ob-s">选择 / 回填 / 三选一</text>
|
||||
<text x="770" y="140" class="ob-s">回传随卡留痕 —— 学习信号:</text>
|
||||
<text x="770" y="158" class="ob-s">补全 = 缺口标注</text>
|
||||
<text x="770" y="176" class="ob-s">决策 + 理由 = 偏好样本</text>
|
||||
<text x="770" y="194" class="ob-s">驳回 + 意见 = 批评信号</text>
|
||||
|
||||
<path d="M246,140 H396" fill="none" stroke="#B07D2B" stroke-width="1.5" marker-end="url(#obB)"/>
|
||||
<text x="320" y="130" text-anchor="middle" class="ob-s" fill="#8A5F1C">调用 · 卡面 = AI 的结构化输出</text>
|
||||
<path d="M640,140 H750" fill="none" stroke="#46586A" stroke-width="1.5" marker-end="url(#obS)"/>
|
||||
<text x="696" y="130" text-anchor="middle" class="ob-s">到达工位</text>
|
||||
<path d="M859,256 V300 H141 V262" fill="none" stroke="#2F6DB5" stroke-width="1.5" marker-end="url(#obH)"/>
|
||||
<text x="500" y="292" text-anchor="middle" class="ob-c" font-weight="600" fill="#173A63">人回传 → 人事件(统一信封,06)→ 投递回任务 → 环续跑</text>
|
||||
|
||||
<line x1="36" y1="322" x2="964" y2="322" stroke="#ECEFF3"/>
|
||||
<text x="36" y="344" class="ob-c" font-size="11"><tspan font-weight="600">三规矩:调用必附上下文 · 回传即留痕 · 完成只出自「放行通过」</tspan> —— 人不驱动过程,人被过程调用</text>
|
||||
<text x="36" y="364" class="ob-s">放行卡是活动级的门;流程层的审批点是另一层裁决 —— 二者不可互相替代(03)</text>
|
||||
</svg>
|
||||
</div>
|
||||
|
||||
<ul class="tight">
|
||||
<li><b>调用必附上下文(必须)</b>——每张卡自带足够的依据与快照,人无需进系统翻找即可作答;无上下文的裸调用不得发出。</li>
|
||||
<li><b>回传即留痕(必须)</b>——谁、何时、答了什么、依据什么,随卡入任务记忆;人的回传天然是学习信号:补全 = 缺口标注,决策 + 理由 = 偏好样本,驳回 + 意见 = 批评信号。</li>
|
||||
<li><b>完成只出自放行(必须)</b>——任务的完成只能出自放行卡的「放行通过」,并在此刻触发草稿态 → 事实态的落地(09);<b>驳回重做</b> = 按原要求重新执行,<b>驳回迭代</b> = 带意见改进现稿后再提。</li>
|
||||
</ul>
|
||||
<div class="callout danger"><b>放行与审批点不可互相替代:</b>放行卡是<b>活动级的门</b>——保证每份产出有人认账,撤了它,产出无主;审批点是<b>流程层的裁决</b>——保证跨任务的关键走向有第三方把关,把它塞进活动,活动就失去独立性。任务完成靠放行,节点间裁决靠审批点。</div>
|
||||
|
||||
<!-- ========== 06 ========== -->
|
||||
<h2 class="ch"><span class="n">06</span>事件:系统向活动抛出的统一标准</h2>
|
||||
<div class="ch-rule"></div>
|
||||
|
||||
<p class="lead">活动以<b>事件监听</b>声明它对外界的一切依赖,系统按<b>统一事件标准</b>投递。监听是接口的契约:活动只声明"听什么、听到了怎么办";挂起、恢复、路由、去重全部归系统。</p>
|
||||
|
||||
<h3 class="h3"><span class="n">6.1</span>事件信封与四类事件</h3>
|
||||
<div class="tbl"><table>
|
||||
<tr><th style="width:130px">信封字段</th><th>内容</th></tr>
|
||||
<tr><td><b>事件 ID</b></td><td>全局唯一,幂等键——重复投递可去重</td></tr>
|
||||
<tr><td><b>类型</b></td><td>四类之一(下表)</td></tr>
|
||||
<tr><td><b>关联</b></td><td>消费目标:<b>目标类型 + 目标 ID</b>(任务 / 触发器 / 工作流 / 消息收件岗位);起因:数据对象 / 卡 ID / 定时器 ID</td></tr>
|
||||
<tr><td><b>载荷</b></td><td>schema 化内容,附原件指针(如邮件原文的存档地址)</td></tr>
|
||||
<tr><td><b>时间与来源</b></td><td>发生时刻 · 来源(通道 / 引擎 / 工位 / 治理台)</td></tr>
|
||||
<tr><td><b>留痕指针</b></td><td>事件存储位置(先持久后投递);投递入任务后另记任务记忆指针——事件流与记忆同轴;无任务目标的事件仅有存储位</td></tr>
|
||||
</table></div>
|
||||
<div class="tbl"><table>
|
||||
<tr><th style="width:90px">类型</th><th>内容</th><th style="width:230px">例</th></tr>
|
||||
<tr><td><b>数据事件</b></td><td>任务相关数据对象的写入与变更;环外回音(邮件、人工代收)经归属解析<b>归一为数据写入</b>后,以数据事件抛出——<b>活动认数据,不认通道</b>;数据事件只由<b>正式版写入</b>产生(系统写与放行写,09),草稿写不抛事件</td><td>客户回信已写入台账,附原件指针</td></tr>
|
||||
<tr><td><b>时间事件</b></td><td>定时器到点:监听时限、约定时点、周期检查</td><td>等待第 3 天未回,时限事件</td></tr>
|
||||
<tr><td><b>人事件</b></td><td>人类工具卡的回传到达(05),与负责人的<b>主动输入</b>——对话流自由输入:写入任务记忆,loop 作为观察,不驱动 flow 步</td><td>放行卡回传:驳回迭代 + 意见;负责人留言「客户来电改期」</td></tr>
|
||||
<tr><td><b>控制事件</b></td><td>治理台与负责人的指令,三种语义:<b>暂停</b> = 可恢复冻结(监听与时限停摆)· <b>叫停</b> = 负责人紧急中断(挂起并记最重档纠正,恢复归负责人)· <b>终止</b> = 不可恢复关闭——工作流终止级联:在途任务终止、待答卡与征答消息作废、审批点撤卡</td><td>负责人叫停</td></tr>
|
||||
</table></div>
|
||||
|
||||
<h3 class="h3"><span class="n">6.2</span>归属解析:入站到事件的规则</h3>
|
||||
<p>通道入站(邮件、IM)到统一事件流之间,由<b>归属解析</b>完成路由。解析依据是通道实例配置中的<b>归属键提取规则</b>(声明式):会话 / 线程 ID、往来地址、正文模式(如单号正则)。匹配次序确定、逐级短路:</p>
|
||||
<ul class="tight">
|
||||
<li><b>① 线程精确匹配</b>——会话 / 线程 ID 精确匹配某在途任务的出站记录,即有主。</li>
|
||||
<li><b>② 关联键匹配监听</b>——提取的关联键命中某任务监听的过滤条件,即有主。</li>
|
||||
<li><b>③ 地址 + 时间窗</b>——往来地址在时间窗内匹配<b>唯一</b>在途任务,即有主;命中多个即无主。</li>
|
||||
</ul>
|
||||
<p class="small">提取失败或歧义一律降级为无主——<b>宁交人,不错投</b>;无主入站的"相关人" = 通道实例配置的<b>默认认领岗位</b>(治理台 · 系统管理)。有主入站归一为数据写入——写入目标由通道实例配置的<b>载荷映射</b>给定(提取字段 → 域.对象.字段,与边映射同一形式),原件存档为附件对象,以数据事件抛出。<b>有主 ≠ 必须唤醒</b>:归属解析命中的任务,事件一律写入其任务数据与任务记忆(记录);是否推进由监听命中决定——零命中时仅记录,不降级为无主、不入消息兜底(它有主,只是当下无人等它;loop 在后续观察窗口内自然可见)。消息兜底只针对无主事件。</p>
|
||||
|
||||
<h3 class="h3"><span class="n">6.3</span>监听声明与投递语义</h3>
|
||||
<p><b>监听声明</b>——活动声明监听,两种立法:<b>静态</b>(随业务模型:loop 的前提条件、flow 的步完成条件)与<b>动态</b>(运行中由 Agent 机制临场登记,如发出报价邮件后登记"等回信"监听)。每条监听 = <b>过滤条件</b>(事件类型 + 关联键,条件用 S-FEEL,03)+ <b>处理语义</b>(loop:事件即观察;flow:事件即步的完成条件)+ <b>时限</b>(必配:到期抛时间事件——无死等,无来源又无时限的监听安装时拒绝)。</p>
|
||||
|
||||
<div class="fig">
|
||||
<div class="figcap"><span>FIG-03 · 一条事件流,三级消费</span><span>事件源 → 归属解析与信封 → 任务监听 / 触发器 / 消息</span></div>
|
||||
<svg viewBox="0 0 1000 430" role="img" aria-label="统一事件流:五类事件源经归属解析装入统一信封并持久化,依次由任务监听、触发器、消息三级消费">
|
||||
<style>
|
||||
.oc-t{font-family:'PingFang SC','Noto Sans SC',sans-serif;font-size:10.5px;font-weight:600;fill:#1F2933}
|
||||
.oc-c{font-family:'PingFang SC','Noto Sans SC',sans-serif;font-size:10px;fill:#3A4452}
|
||||
.oc-m{font-family:'SF Mono',Menlo,monospace;font-size:10px;font-weight:600;letter-spacing:.12em;fill:#6A7686}
|
||||
.oc-s{font-family:'PingFang SC','Noto Sans SC',sans-serif;font-size:9px;fill:#6A7686}
|
||||
</style>
|
||||
<defs>
|
||||
<marker id="ocS" markerWidth="9" markerHeight="9" refX="7.5" refY="4.5" orient="auto"><path d="M0,0 L9,4.5 L0,9 Z" fill="#46586A"/></marker>
|
||||
</defs>
|
||||
|
||||
<text x="36" y="28" class="oc-m">事件源</text>
|
||||
<rect x="36" y="40" width="168" height="44" rx="7" fill="#FFFFFF" stroke="#C6D0DA" stroke-width="1.2"/>
|
||||
<text x="120" y="58" text-anchor="middle" class="oc-t">通道入站</text>
|
||||
<text x="120" y="76" text-anchor="middle" class="oc-s">邮件 · IM 回音</text>
|
||||
<rect x="222" y="40" width="168" height="44" rx="7" fill="#FFFFFF" stroke="#C6D0DA" stroke-width="1.2"/>
|
||||
<text x="306" y="58" text-anchor="middle" class="oc-t">定时器到点</text>
|
||||
<text x="306" y="76" text-anchor="middle" class="oc-s">监听时限 · 周期</text>
|
||||
<rect x="408" y="40" width="168" height="44" rx="7" fill="#FFFFFF" stroke="#C6D0DA" stroke-width="1.2"/>
|
||||
<text x="492" y="58" text-anchor="middle" class="oc-t">人类工具卡回传</text>
|
||||
<text x="492" y="76" text-anchor="middle" class="oc-s">四卡作答</text>
|
||||
<rect x="594" y="40" width="168" height="44" rx="7" fill="#FFFFFF" stroke="#C6D0DA" stroke-width="1.2"/>
|
||||
<text x="678" y="58" text-anchor="middle" class="oc-t">台账数据写入</text>
|
||||
<text x="678" y="76" text-anchor="middle" class="oc-s">含人工代收回填</text>
|
||||
<rect x="780" y="40" width="168" height="44" rx="7" fill="#FFFFFF" stroke="#C6D0DA" stroke-width="1.2"/>
|
||||
<text x="864" y="58" text-anchor="middle" class="oc-t">治理台指令</text>
|
||||
<text x="864" y="76" text-anchor="middle" class="oc-s">叫停 · 暂停 · 终止</text>
|
||||
<path d="M120,84 V108" fill="none" stroke="#46586A" stroke-width="1.3" marker-end="url(#ocS)"/>
|
||||
<path d="M306,84 V108" fill="none" stroke="#46586A" stroke-width="1.3" marker-end="url(#ocS)"/>
|
||||
<path d="M492,84 V108" fill="none" stroke="#46586A" stroke-width="1.3" marker-end="url(#ocS)"/>
|
||||
<path d="M678,84 V108" fill="none" stroke="#46586A" stroke-width="1.3" marker-end="url(#ocS)"/>
|
||||
<path d="M864,84 V108" fill="none" stroke="#46586A" stroke-width="1.3" marker-end="url(#ocS)"/>
|
||||
|
||||
<rect x="36" y="112" width="928" height="58" rx="8" fill="#0F1420"/>
|
||||
<text x="500" y="136" text-anchor="middle" font-family="'SF Mono',Menlo,monospace" font-size="10.5" fill="#DCE3F0">归属解析 → 事件信封:ID(幂等键) · 类型(数据 / 时间 / 人 / 控制) · 关联 · 载荷 + 原件指针 · 时间与来源 · 留痕指针</text>
|
||||
<text x="500" y="156" text-anchor="middle" font-family="'SF Mono',Menlo,monospace" font-size="9.5" fill="#98A2B0">先持久后投递 —— 事件先落存储与任务记忆,再投消费方 · 同任务按序 · 至少一次 + 幂等(去重由基座代劳)</text>
|
||||
|
||||
<text x="500" y="192" text-anchor="middle" class="oc-s">监听与触发独立判定 · 皆未命中 → 消息兜底</text>
|
||||
<path d="M176,170 V204" fill="none" stroke="#46586A" stroke-width="1.3" marker-end="url(#ocS)"/>
|
||||
<path d="M500,170 V204" fill="none" stroke="#46586A" stroke-width="1.3" marker-end="url(#ocS)"/>
|
||||
<path d="M824,170 V204" fill="none" stroke="#46586A" stroke-width="1.3" marker-end="url(#ocS)"/>
|
||||
|
||||
<rect x="36" y="208" width="280" height="118" rx="9" fill="#F7F0E0" stroke="#B07D2B" stroke-width="1.4"/>
|
||||
<text x="52" y="232" class="oc-t" fill="#8A5F1C">① 任务监听 —— 推进旧单</text>
|
||||
<text x="52" y="256" class="oc-s">过滤:类型 + 关联键 · 时限必配</text>
|
||||
<text x="52" y="276" class="oc-s">loop:事件即观察</text>
|
||||
<text x="52" y="296" class="oc-s">flow:事件即步的完成条件</text>
|
||||
<text x="52" y="314" class="oc-s">投递到任务,环续跑</text>
|
||||
<rect x="360" y="208" width="280" height="118" rx="9" fill="#F0F4FF" stroke="#245BDB" stroke-width="1.4"/>
|
||||
<text x="376" y="232" class="oc-t" fill="#245BDB">② 触发器 —— 开新单</text>
|
||||
<text x="376" y="256" class="oc-s">流程层的系统级事件监听</text>
|
||||
<text x="376" y="276" class="oc-s">命中起单规则 → 经调用接口</text>
|
||||
<text x="376" y="296" class="oc-s">调起一单工作流</text>
|
||||
<text x="376" y="314" class="oc-s">同一事件流,不另设通路</text>
|
||||
<rect x="684" y="208" width="280" height="118" rx="9" fill="#F7F9FB" stroke="#9AA7B6" stroke-width="1.4"/>
|
||||
<text x="700" y="232" class="oc-t" fill="#46586A">③ 消息 —— 无主交人</text>
|
||||
<text x="700" y="256" class="oc-s">落相关人的消息要素(02)</text>
|
||||
<text x="700" y="276" class="oc-s">人工认领 / 代收回填</text>
|
||||
<text x="700" y="296" class="oc-s">代收走同一数据写入口</text>
|
||||
<text x="700" y="314" class="oc-s">回填即数据事件,再入流</text>
|
||||
|
||||
<line x1="36" y1="352" x2="964" y2="352" stroke="#ECEFF3"/>
|
||||
<text x="36" y="374" class="oc-c" font-size="11"><tspan font-weight="600">一条事件流,三级消费</tspan> —— 活动认数据,不认通道:环外回音先归一为数据写入,再以数据事件抛给任务</text>
|
||||
<text x="36" y="394" class="oc-s">处理有回执:失败重投,超限入死信 → 系统通知送达消息要素与治理台 · 悬空监听安装时拒绝 —— 无死等</text>
|
||||
</svg>
|
||||
</div>
|
||||
|
||||
<p><b>投递语义</b>——系统侧五条承诺:</p>
|
||||
<ul class="tight">
|
||||
<li><b>先持久后投递</b>——事件落存储与任务记忆,再投活动;任务挂起不丢事件,恢复即补投。</li>
|
||||
<li><b>同任务按序</b>——同一任务的事件按发生序投递。</li>
|
||||
<li><b>至少一次 + 幂等</b>——投递保证至少一次;活动侧按事件 ID 去重由基座代劳,重复投递无副作用。</li>
|
||||
<li><b>处理有回执</b>——处理完成落痕;失败重投,超限入死信——死信以系统通知送达相关人的消息要素(02)与治理台 · 任务管理。</li>
|
||||
<li><b>扇出与幂等</b>——同一事件可命中多个任务监听:系统为每个命中任务生成一份<b>独立投递</b>(各带投递 ID,信封「关联 = 任务 ID」保持单目标);同一事件对同一触发器至多起一单,以事件 ID 为幂等键。</li>
|
||||
</ul>
|
||||
<p>一条事件流,三级消费:<b>任务监听</b>(推进旧单)与<b>触发器</b>(起单规则,开新单)<b>相互独立判定</b>——同一事件可既推进旧单又起新单;<b>消息</b>是兜底:仅当既无监听命中亦无触发命中时,入站事件落相关人的消息要素(02,人工认领 / 代收)。触发器由此获得统一定义:<b>流程层的系统级事件监听</b>——监听同一条事件流,消费动作是"经调用接口调起流程包、生成新工作流"。</p>
|
||||
|
||||
<!-- ========== 07 ========== -->
|
||||
<h2 class="ch"><span class="n">07</span>调用层与工具箱</h2>
|
||||
<div class="ch-rule"></div>
|
||||
|
||||
<p class="lead"><b>系统调用、LLM 工具、人类工具以及通道在调用层。</b>调用层是一切能力的注册与授权之地;能力以工具形态、经活动基座的「工具(调用契约)」供给活动(04):</p>
|
||||
<ul class="tight">
|
||||
<li><b>系统调用</b>——本系统服务与外部系统的调用。ERP / CRM 等企业系统一律以外部调用方式接入——读取即快照留痕;写入即触达外部世界,须过放行,动作集中在放行时点落到事实(09)。</li>
|
||||
<li><b>LLM 工具</b>——以模型能力封装的工具(抽取、翻译、生成等),与其他工具同列白名单、同受授权约束;与基座的「LLM 调用(模型)」不同物——后者驱动 Agent 机制自身的推理,LLM 工具是机制可调用的一种能力。</li>
|
||||
<li><b>人类工具</b>——四种内置工具:决策、执行、补全、放行(05)。调用经卡片到达人(负责人 = 任务对话流;其他人 = 系统消息,2.1),回传异步回环;人是环内可调用的一种能力,同受授权约束——哪些活动能调人、调谁、调用预算(打扰上限),在契约与白名单;「调谁」按<b>岗位</b>声明,收件人以四策略解析(03),缺席走时限阶梯。</li>
|
||||
<li><b>通道</b>——邮件、即时消息等收发通路。出站是触达世界的动作;入站经归属解析进入统一事件流(06)——有主的归一为数据事件抛给任务,无主的走触发器判定与消息兜底。</li>
|
||||
</ul>
|
||||
|
||||
<h3 class="h3"><span class="n">7.1</span>工具三来处与工具箱</h3>
|
||||
<p>调用层四类是<b>供给形态</b>——皆以工具形态经调用契约供给活动;按<b>开发与固化形态</b>,工具分三来处:</p>
|
||||
<div class="tbl"><table>
|
||||
<tr><th style="width:130px">来处</th><th>机制</th><th style="width:250px">治理</th></tr>
|
||||
<tr><td><b>功能工具</b></td><td>系统调用类能力的交付形态:按需开发的业务能力,是<b>独立开发的代码包</b>——经基座的<b>工具箱</b>注册进系统(11),入白名单;账号、密钥与 endpoint 配置随工具归组织;工具包规范见 7.3</td><td>先系统、后活动;活动只声明引用其调用契约</td></tr>
|
||||
<tr><td><b>LLM 工具 · 人类工具</b></td><td><b>固化在系统里</b>,随系统迭代而更新;声明即用</td><td>白名单授权;模型实例与工位由治理台配置</td></tr>
|
||||
<tr><td><b>纯工具</b></td><td>无外效应(计算、转换、操作自持台账),可随活动包自带</td><td>安装时注册进工具表、经运行时调用而留痕,不得内联绕过</td></tr>
|
||||
</table></div>
|
||||
<div class="callout brand"><b>数据可以自生长,权力不可以自生长。</b>台账凭 schema 声明由宿主物化,随活动进来即可"长"出来——安全,因为声明不带能力;功能工具承载权力(授权、密钥、触达世界),永远先系统、后活动。开发时序以<b>契约先行</b>解耦:缺什么工具先定调用契约,活动对着契约开发(本地 mock),平台照契约实现注册,安装静态审收口——缺口只阻塞上架,不阻塞开发。</div>
|
||||
|
||||
<h3 class="h3"><span class="n">7.2</span>外部系统:事实源在外</h3>
|
||||
<p>ERP / CRM 等存量系统:<b>事实源永远在外</b>,以<b>外部系统调用</b>接入——注册在工具箱与白名单上的调用接口,<b>读 = 快照留痕,写 = 过放行</b>;不做库对库同步,不搬事实源。无存量系统承载的对象,以<b>台账声明物化</b>承载,数据资产随运行沉淀——混合是常态:按对象逐个选择「调用接入」或「声明物化」,活动只依赖调用契约与共享对象目录,不依赖任何具体事实源。</p>
|
||||
<p><b>权力边界在此收拢:能力在调用层(注册、白名单、授权),方法在活动内(技能)。</b>技能基于工具、在活动内定义,载方法不载权力——不能扩大任何授权,只沉淀"怎么用好"(《活动模型》)。</p>
|
||||
|
||||
<h3 class="h3"><span class="n">7.3</span>工具包规范</h3>
|
||||
<p class="lead">一个功能工具以一个<b>工具包</b>交付:独立开发的代码包,经工具箱注册进系统。工具承载权力,约束严于活动包,三面分离:<b>契约对活动,实现对系统,凭证对治理台</b>。</p>
|
||||
|
||||
<div class="tbl"><table>
|
||||
<tr><th style="width:150px">构成</th><th>内容</th></tr>
|
||||
<tr><td><b>调用契约</b><br><span class="small">(对活动的唯一暴露面)</span></td><td>工具名(全局唯一逻辑名)· <b>描述</b>(面向 AI 的适用说明:何时用、语义、边界)· 入参 / 出参 schema · <b>效应等级(读 / 写)</b> · 错误约定(结构化错误码 + 可重试标志)· 幂等性声明 · 超时与重试默认值</td></tr>
|
||||
<tr><td><b>实现</b></td><td>server 侧执行代码;运行时受限——只可访问注册申报的连接目标,无其他环境能力</td></tr>
|
||||
<tr><td><b>连接配置声明</b></td><td>endpoint / 账号 / 密钥的<b>键</b>(值不入包):注册时在治理台绑定值,可按环境绑定不同实例——与 LLM 实例的名称间接层同构</td></tr>
|
||||
<tr><td><b>契约测试集</b></td><td>样例入参 → 期望出参形状;注册试运行审与回归的依据</td></tr>
|
||||
</table></div>
|
||||
<p class="small">四件构成合成工具包的<b>包清单(manifest)</b>,与活动包清单同构(11.1);注册两审:静态审读清单,试运行审验代码。</p>
|
||||
|
||||
<p><b>效应等级决定运行时待遇:</b></p>
|
||||
<ul class="tight">
|
||||
<li><b>读类</b>——无外部效应;过程中可自由调用(白名单内),读取即快照留痕。</li>
|
||||
<li><b>写类</b>——触达外部系统与世界;<b>过程中登记为动作意向</b>(入参冻结,存入草稿态),放行后由系统执行落地,执行结果回填任务记忆;契约显式预授权的写类动作可在过程中即时执行,预授权必须逐项列举。</li>
|
||||
<li><b>落地预检(必须)</b>——<b>检查可落地,才允许放行</b>:发放行卡前,系统对全部动作意向执行预检——入参 schema 校验、工具可用(未停用)与授权有效、连接可达、目标预校验(工具契约含 validate 能力时)、<b>数据冲突检查</b>(草稿层所改字段与正式版的并发冲突:他单已改同一字段即预检不过,打回环内基于新正式版重拟);<b>预检全过才发放行卡</b>,卡面呈现的即已验证的动作清单;预检不过的意向打回环内修正,不发卡。放行通过即刻执行(附幂等键);预检与执行之间世界突变导致的残余失败,按工具契约重试,超限转「落地受阻」——<b>落地受阻是任务的运行态,不是终态</b>:处置后仍收敛于契约的终态名录(重试成功 → 放行完成;放弃非必交付项后收敛;叫停走控制事件);失败动作生成<b>落地失败卡</b>送负责人(重试 / 线下完成后回填 / 放弃非必交付项 / 叫停)——落地失败卡是<b>执行卡的系统预置形态</b>(作业指导 = 失败动作与原因,回填 = 处置选择),不构成第五种卡;已成动作留存不回滚;<b>输出口在落地收敛前不发射</b>——下游只见落地完成的任务。</li>
|
||||
</ul>
|
||||
|
||||
<ul class="tight">
|
||||
<li><b>注册两审(必须)</b>——静态审(签名、无动态执行、调用契约 schema 校验、效应等级核验、连接配置声明齐备)+ 试运行审(以 mock 绑定跑契约测试集,全过方可上架)。</li>
|
||||
<li><b>契约演进只增不破坏(必须)</b>——出参只增字段;入参新增字段必为可选;破坏性变更 = 新工具名。版本并存,活动按声明的版本约束解析。</li>
|
||||
<li><b>凭证隔离(必须)</b>——密钥与 endpoint 值只存治理台(工具管理),不入包、不入活动、不入留痕明文。</li>
|
||||
<li><b>停用与下线</b>——有活动声明引用的工具不得删除;可停用——停用后调用返回结构化错误,活动按失败路径处理。</li>
|
||||
<li><b>调用运行时</b>——一切调用经调用契约,入参快照、出参、时延与错误自动留痕入任务记忆;重试由系统按契约执行,写类动作执行时附幂等键;活动 Harness 对超时与重试只可收紧、不可放宽。</li>
|
||||
<li><b>纯工具的简化规格</b>——随活动包交付,无连接配置、无外效应;注册进工具表(活动私有作用域)、经运行时调用留痕;安装静态审核其无环境能力。</li>
|
||||
</ul>
|
||||
|
||||
<!-- ========== 08 ========== -->
|
||||
<h2 class="ch"><span class="n">08</span>记忆系统:任务记忆与活动记忆</h2>
|
||||
<div class="ch-rule"></div>
|
||||
|
||||
<p class="lead">一单任务的智能有两个来源:这一单里发生过什么(<b>任务记忆</b>),与这类事历来是什么样(<b>活动记忆</b>)。框架站在环内一切调用的必经之路上——记录不靠自觉,靠位置。</p>
|
||||
|
||||
<h3 class="h3"><span class="n">8.1</span>任务记忆:一单一本</h3>
|
||||
<p><b>任务记忆 = 会话历史:消息历史 + 引擎事件流</b>,同轴合流、按时间全序——Agent 机制的观察、思考、动作、结果逐条原生,引擎的流转、投递、门与卡裁决逐条结构化。四条性质(必须):</p>
|
||||
<ul class="tight">
|
||||
<li><b>只追加</b>——原始条目不得修改;信号可迟到,以后续条目回链原步(纠正、验收意见、客户回复都是迟到信号)。</li>
|
||||
<li><b>信封盖戳</b>——每条盖版本信封:契约 / 业务模型 / 技能 / 模型版本 + 治理标记——行为可归因、历史可回放的前提。</li>
|
||||
<li><b>治理先行</b>——脱敏、权限、保留期、可学习标记在留痕时刻打上;不合规的记录不得进入学习队列。</li>
|
||||
<li><b>归侧</b>——每条按动作类型自动打四侧标签:机器产出 / 人产出 / 人裁决 / 世界等待——度量的口径来源,零埋点。</li>
|
||||
</ul>
|
||||
<p>职能四:<b>续跑</b>(挂起恢复时由此重建上下文——记忆在,环可断可续)、<b>审计</b>(发生了什么)、<b>回放</b>(换个办法,这单会不会成)、<b>蒸馏源</b>(活动记忆的唯一原料)。生命周期:随单生、只追加长、终态封卷归档(基座 · 记忆,11)。</p>
|
||||
<p><b>基座接口最小:</b>任务记忆由框架自动记录,活动侧唯一可配置项是<b>窗口大小</b>——每次 LLM 调用加载多少轮会话历史;窗口之外的历史不进上下文,但完整在库——续跑、审计与回放永远对全量记录进行。</p>
|
||||
|
||||
<p><b>任务日志:任务记忆的两级投影。</b>日志不是另一份记录——做事与留痕是同一个动作,不存在补写日志;任务日志由任务记忆按需生成:</p>
|
||||
<ul class="tight">
|
||||
<li><b>结构化日志(零 LLM)</b>——以引擎事件流为骨架(启动 · 工具调用 · 卡发出与回传 · 数据写入 · 动作意向 · 放行 · 终态),按事件类型筛选、模板措辞;每条自带谁 · 何时 · 依据 · 留痕指针;任何时刻可重算,口径与源恒一致;归侧标签使其天然分栏——机器做的 / 人做的 / 人裁的 / 在等谁。</li>
|
||||
<li><b>叙述性小结(LLM,可选)</b>——阶段小结与终态封卷摘要;叙述是视图不是事实,每句可溯回原始条目,不入事实库。</li>
|
||||
</ul>
|
||||
<p class="small">消费方:工作台「汇报」按日 / 周 / 月 / 年聚合各任务日志(02);放行卡与审批点的过程摘要取自任务日志;治理台 · 任务管理可查看任意任务的任务日志(02);对话流时间线与日志同源、不同筛选。治理约束:<b>投影不得比源暴露更多</b>——日志继承任务记忆的治理标记,按读者权限裁剪生成。</p>
|
||||
|
||||
<h3 class="h3"><span class="n">8.2</span>活动记忆:一类一本,为优化业务模型而设计</h3>
|
||||
<p>活动记忆是关于<b>这个活动(事类)</b>的持久事实,跨全部任务实例累积——<b>结构化记忆</b>:基座只提供<b>存与取</b>(条目的写入与检索),不解释语义;结构归活动侧,标准由《活动模型》规定。<b>结构为迭代而设计——每类条目对准一个模型作用面</b>:</p>
|
||||
<div class="tbl"><table>
|
||||
<tr><th style="width:90px">层</th><th>存什么</th><th style="width:280px">优化谁</th></tr>
|
||||
<tr><td><b>事实层</b></td><td>环境与对手方的稳定事实:端点脾性、对手方节奏(客户均值 3 天回信)、术语与实体档案</td><td>校准监听时限、判断阈值、DMN 输入项</td></tr>
|
||||
<tr><td><b>模式层</b></td><td>路径统计:动作启用频次与共现序列、阶段耗时分布、技能组合效果</td><td>候选业务模型结构增量(阶段重组、新前提、新里程碑)</td></tr>
|
||||
<tr><td><b>裁决层</b></td><td>纠正沉淀:每次驳回(重做 / 迭代)、叫停与裁决理由,归纳为一般化陈述</td><td>候选新前提条件、收紧验收判据、DMN 新规则行</td></tr>
|
||||
<tr><td><b>例外层</b></td><td>反例与禁忌:已知失败形态、边界案例、「此处留人」标记</td><td>规则适用边界、负向条件、技能适用描述修正</td></tr>
|
||||
</table></div>
|
||||
<ul class="tight">
|
||||
<li><b>条目三件套(必须)</b>——归纳陈述 + 证据链(指回任务记忆的具体片段,可回放)+ 候选增量(可选:落到业务模型 / 技能的具体 diff,状态:候选 / 回放中 / 已放行 / 已否决);无证据链的条目不得入库。</li>
|
||||
<li><b>写入 = 蒸馏(必须)</b>——只经蒸馏钩子(终态封卷、里程碑达成时)从任务记忆归纳;人可修剪;不设直写旁路。蒸馏钩子由<b>封卷流水线</b>(系统侧运行时)在任务终态后执行:模型用系统用途绑定实例(02),失败重试与死信同统一事件标准(06),产物默认候选。</li>
|
||||
<li><b>读出 = 装载</b>——任务启动时按需选摘入 Agent 机制的上下文(渐进披露);流程引擎不读活动记忆(引擎零业务)。</li>
|
||||
</ul>
|
||||
<div class="callout warn"><b>记忆不载权力:</b>活动记忆对行为只有参考力,没有强制力;强制力只有一条路——候选增量经回放与人放行<b>进入业务模型本身</b>(11 进化治理)。记住的影响裁量,放行的才约束行为——<b>记忆的终点不是记住,是成为模型</b>。</div>
|
||||
|
||||
<h3 class="h3"><span class="n">8.3</span>度量:口径挂归侧与事件流</h3>
|
||||
<div class="tbl"><table>
|
||||
<tr><th style="width:110px">指标</th><th>定义</th><th style="width:270px">读法</th></tr>
|
||||
<tr><td><b>自主率</b></td><td>机器产出 ÷(机器产出 + 人产出);裁决与等待不进分母</td><td><b>第一指标</b>:AI 自主完成工作的比例</td></tr>
|
||||
<tr><td><b>纠正率</b></td><td>按<b>提交批次</b>计:每次放行提交 = 一个产出批次;驳回重做 / 驳回迭代 / 叫停 / 裁决推翻记该批纠正;纠正率 = 被纠正批次 ÷ 提交批次</td><td><b>第二指标</b>:自主的质;与自主率成对读——单看任一都会被优化坏</td></tr>
|
||||
<tr><td><b>有效自主率</b></td><td>自主率 ×(1 − 纠正率)</td><td>「AI 越多越确定」的可测判据</td></tr>
|
||||
<tr><td><b>打扰率</b></td><td>每单任务调用人类工具的次数(四卡合计)</td><td>应随资产成熟而下降;人环的带宽成本</td></tr>
|
||||
<tr><td><b>断点率</b></td><td>loop 中因"当下可为与目标所需交集为空"而调人或立监听的频次占比</td><td>断点聚类是业务模型迭代的首要线索</td></tr>
|
||||
<tr><td><b>DMN 覆盖率</b></td><td>确定性求值(DMN 与机检)占判断次数的比例</td><td>「临场搬进确定」的进度表</td></tr>
|
||||
<tr><td><b>单位成本</b></td><td>总消耗(token / 时长 / 调人)÷ 放行通过的任务数</td><td>环是否真在产出</td></tr>
|
||||
<tr><td><b>终态分布</b></td><td>五个终态的占比(名录见 4.3)</td><td>非完成终态偏高 = 契约或资产有缺陷</td></tr>
|
||||
</table></div>
|
||||
<p class="small"><b>计量单位:归侧条目。</b>产出以任务记忆的归侧条目计(机器产出 / 人产出各按其条目数);条目粒度随活动而异但活动内恒定——指标的主用途是<b>同一活动的纵向趋势</b>(口径自洽);跨活动横比仅在同业务分类内作参考,不作考核。口径全部挂在归侧标签与事件流上——零埋点,统计即查询;指标异动是进化的扳机:纠正聚类指向活动记忆的裁决层,断点聚类指向业务模型的结构层,蒸馏候选增量走治理管线(11)。</p>
|
||||
|
||||
<!-- ========== 09 ========== -->
|
||||
<h2 class="ch"><span class="n">09</span>运行拓扑:web + server</h2>
|
||||
<div class="ch-rule"></div>
|
||||
|
||||
<p class="lead"><b>系统是 web + server。</b>分界原则一句话:<b>过程在后端,呈现在 web;放行是草稿态与事实态之间的门。</b></p>
|
||||
<div class="tbl"><table>
|
||||
<tr><th style="width:100px">侧</th><th>承载</th></tr>
|
||||
<tr><td><b>web 侧</b></td><td>呈现与输入面:工作台五要素的呈现、对话流(卡片输入,唯一回环入口)、视图区(渲染后端推送的 HTML)、治理台界面。<b>零活动代码、零过程逻辑</b></td></tr>
|
||||
<tr><td><b>server 侧</b></td><td><b>活动过程集中在后端</b>——Agent 机制的推进、LLM 调用与 LLM 工具、过程草拟(活动自设的工作区)、<b>视图流控</b>(AI 以 HTML 模版组织视图、推送 web)· 流程引擎(工作流流转、审批点、网关)· 触发器与通道 · 系统调用的执行 · 基座存放</td></tr>
|
||||
</table></div>
|
||||
<p>活动过程集中在后端,带来两条直接性质:<b>环不依赖浏览器在线</b>——负责人关掉页面,活动照常推进,任务挂起、事件补投与断点续跑天然成立(06);<b>web 是纯呈现与输入面</b>——视图由后端流控推送,输入经对话流卡片回传,浏览器端不落过程状态。</p>
|
||||
<p><b>落后端系统的动作集中在活动放行时</b>:过程产物无论在活动的工作区里怎么草拟都是草稿态,不碰台账与外部系统;放行前有<b>落地预检</b>(检查可落地才允许放行,7.3),放行一刻动作落到事实——写台账、调外部系统、提交交付物;落地收敛,输出口才发射。「箱内自由,出箱有门」的边界因此是<b>逻辑的而非物理的</b>:门立在草稿态与事实态之间(草稿 → 台账 / 外部系统),与草稿箱的具体形态无关。任务记忆与留痕随过程持续归档,不受门限。</p>
|
||||
|
||||
<p><b>写分三类。</b>①<b>系统写</b>——入站归一、流转记录、留痕:登记的是世界已发生的事实,不过放行门,写入正式版并即时产生数据事件;②<b>草稿写</b>——任务运行中,活动对自持域台账的写入落在<b>台账的任务级草稿层</b>(读己之写:本任务可见、正式版不可见、不产生数据事件)——过程工作区的数据形态即此草稿层;③<b>放行写</b>——放行通过,草稿层合并入正式版、外部动作意向执行(7.3),<b>此刻才产生数据事件</b>;共享域写一律走放行,契约预授权的即时写是显式列举的例外。环内推进读<b>任务视图 = 正式版 + 本任务草稿层</b>,不依赖事件;跨任务监听只认正式版事件——<b>别的任务只见你放行后的事实</b>,这是「箱内自由,出箱有门」的数据语义。</p>
|
||||
|
||||
<p><b>草稿持久,断点可续。</b>草稿层与动作意向持久于 server 的系统自持存储——关闭页面、断线、隔天再开都不丢;没有「保存」动作,写即持久。任务做一半的续跑由三份持久状态共同保证:<b>任务记忆</b>(会话历史,按窗口重建上下文,08)、<b>草稿层</b>(截至断点的全部过程产物与动作意向)、<b>运行时实例状态</b>(loop 的模型定位与就绪集 / flow 的步序位置,11)。过程在后端:「打开任务」只是打开呈现,不是启动过程——过程要么在跑,要么挂起在等(人 / 事件 / 恢复指令);事件到达或人回传即按投递续跑(06),人打开工作台看到的永远是当前状态的投影。</p>
|
||||
|
||||
<!-- ========== 10 ========== -->
|
||||
<h2 class="ch"><span class="n">10</span>活动与系统的边界</h2>
|
||||
<div class="ch-rule"></div>
|
||||
|
||||
<p class="lead">两条轴把系统切成四象限:<b>物理轴</b>(web / server,09)与<b>归属轴</b>(系统 / 活动)。边界清楚,双方才能各自迭代:系统不为业务改一行,活动不越笼子半步。</p>
|
||||
|
||||
<div class="fig">
|
||||
<div class="figcap"><span>FIG-04 · 边界四象限</span><span>物理线 × 归属线 · 交汇处是放行门</span></div>
|
||||
<svg viewBox="0 0 1000 480" role="img" aria-label="边界四象限:web×系统为界面本体,web×活动为内容投影无代码,server×系统为运行时笼子,server×活动为Agent机制内容物;物理线与归属线交汇处是放行门">
|
||||
<style>
|
||||
.od-t{font-family:'PingFang SC','Noto Sans SC',sans-serif;font-size:11px;font-weight:600;fill:#1F2933}
|
||||
.od-m{font-family:'SF Mono',Menlo,monospace;font-size:10px;font-weight:600;letter-spacing:.12em;fill:#6A7686}
|
||||
.od-c{font-family:'PingFang SC','Noto Sans SC',sans-serif;font-size:10px;fill:#3A4452}
|
||||
.od-s{font-family:'PingFang SC','Noto Sans SC',sans-serif;font-size:9.5px;fill:#6A7686}
|
||||
</style>
|
||||
<defs>
|
||||
<marker id="odH" markerWidth="9" markerHeight="9" refX="7.5" refY="4.5" orient="auto"><path d="M0,0 L9,4.5 L0,9 Z" fill="#173A63"/></marker>
|
||||
</defs>
|
||||
|
||||
<text x="302" y="36" text-anchor="middle" class="od-m">系统(平台本体)</text>
|
||||
<text x="761" y="36" text-anchor="middle" class="od-m" fill="#8A5F1C">活动(外装件)</text>
|
||||
<text x="36" y="132" class="od-m" fill="#245BDB">web 侧</text>
|
||||
<text x="36" y="334" class="od-m" fill="#46586A">server 侧</text>
|
||||
|
||||
<rect x="100" y="48" width="404" height="158" rx="10" fill="#F0F4FF" stroke="#C9D8F8" stroke-width="1.4"/>
|
||||
<text x="116" y="74" class="od-t" fill="#245BDB">界面本体 · 系统供给</text>
|
||||
<text x="116" y="100" class="od-s">工作台与治理台界面 · 五要素呈现</text>
|
||||
<text x="116" y="122" class="od-s">对话流卡片渲染 · 唯一回环输入口</text>
|
||||
<text x="116" y="144" class="od-s">视图区容器(净化渲染)</text>
|
||||
<text x="116" y="166" class="od-s">零业务逻辑</text>
|
||||
<rect x="558" y="48" width="406" height="158" rx="10" fill="#FCFAF3" stroke="#B07D2B" stroke-width="1.3" stroke-dasharray="5 3"/>
|
||||
<text x="574" y="74" class="od-t" fill="#8A5F1C">内容投影 · 无代码</text>
|
||||
<text x="574" y="100" class="od-s">视图 HTML —— 后端流控推送,容器渲染</text>
|
||||
<text x="574" y="122" class="od-s">卡片内容 —— schema 渲染</text>
|
||||
<text x="574" y="144" class="od-s">浏览器不装载活动代码</text>
|
||||
<text x="574" y="166" class="od-s">不落过程状态</text>
|
||||
|
||||
<text x="532" y="220" text-anchor="middle" class="od-s">物理线 · web / server —— 跨线只有:视图与卡片下行 · 输入回传上行</text>
|
||||
<line x1="100" y1="228" x2="964" y2="228" stroke="#98A2B0" stroke-width="1.2" stroke-dasharray="6 4"/>
|
||||
|
||||
<rect x="100" y="242" width="404" height="174" rx="10" fill="#F7F9FB" stroke="#46586A" stroke-width="1.4"/>
|
||||
<text x="116" y="268" class="od-t">系统运行时 · 笼子</text>
|
||||
<text x="116" y="294" class="od-s">流程引擎(流转 · 审批点 · 网关)</text>
|
||||
<text x="116" y="316" class="od-s">活动基座六件 · 统一事件标准与投递</text>
|
||||
<text x="116" y="338" class="od-s">调用层四类 · 基座六项存放</text>
|
||||
<text x="116" y="360" class="od-s">放行门(草稿态 → 事实态)</text>
|
||||
<text x="116" y="382" class="od-s">治理台九功能的作用面</text>
|
||||
<rect x="558" y="242" width="406" height="174" rx="10" fill="#F7F0E0" stroke="#B07D2B" stroke-width="1.4"/>
|
||||
<text x="574" y="268" class="od-t" fill="#8A5F1C">Agent 机制的内容物 · 跑在基座上</text>
|
||||
<text x="574" y="294" class="od-s">业务模型(CMMN + DMN / 步序声明)</text>
|
||||
<text x="574" y="316" class="od-s">交互内容 · 技能清单 · Harness</text>
|
||||
<text x="574" y="338" class="od-s">监听声明 · 过程工作区(自设)</text>
|
||||
<text x="574" y="360" class="od-s">纯工具 · 台账 schema · 蒸馏钩子</text>
|
||||
<text x="574" y="382" class="od-s">活动代码无环境能力</text>
|
||||
|
||||
<line x1="531" y1="48" x2="531" y2="416" stroke="#98A2B0" stroke-width="1.2" stroke-dasharray="6 4"/>
|
||||
<text x="531" y="306" text-anchor="middle" class="od-s" font-weight="600" fill="#173A63">放行门</text>
|
||||
<rect x="523" y="314" width="16" height="32" rx="3" fill="#173A63"/>
|
||||
<path d="M558,330 H545" fill="none" stroke="#173A63" stroke-width="1.8"/>
|
||||
<path d="M517,330 H504" fill="none" stroke="#173A63" stroke-width="1.8" marker-end="url(#odH)"/>
|
||||
|
||||
<line x1="36" y1="444" x2="964" y2="444" stroke="#ECEFF3"/>
|
||||
<text x="36" y="466" class="od-c" font-size="11"><tspan font-weight="600">两线一门:物理线管过程与呈现,归属线管内容与笼子;交汇处是放行门</tspan> —— 下游与他任务只见过门的事实,不见半成品</text>
|
||||
</svg>
|
||||
</div>
|
||||
|
||||
<ul class="tight">
|
||||
<li><b>物理线(web / server)</b>——跨线只有两种流量:下行的视图与卡片内容(HTML + schema 数据),上行的对话流输入回传。除此之外什么都不过线,前端零过程状态。</li>
|
||||
<li><b>归属线(系统 / 活动)</b>——在后端,这条线就是<b>活动基座六件的接口</b>:活动只见六件,能力一律经调用契约注入;在前端,这条线是<b>容器边界</b>:系统渲染活动的内容,不装载活动的代码。</li>
|
||||
<li><b>交汇处 = 放行门</b>——草稿态(活动过程)到事实态(台账与外部系统)的唯一通道;门归系统,启门归人。</li>
|
||||
</ul>
|
||||
|
||||
<h3 class="h3"><span class="n">10.1</span>系统供给 vs 活动定义</h3>
|
||||
<div class="tbl"><table>
|
||||
<tr><th>系统供给(笼子,本卷)</th><th>活动定义(内容,《活动模型》)</th></tr>
|
||||
<tr><td>活动基座六件:契约格式 · 交互结构(对话流 + 视图区容器)· 记忆系统 · 数据(「数据域.数据对象.字段」三级寻址 + 通用事务性接口,安装时依声明自生长)· 工具调用契约 · LLM 调用(04)</td><td>契约内容(七件):输入(data + message)/ 输出口(必发 / 选择)/ 必交付物 / 验收判据(分级标注)/ 禁区 / 授权边界 / 资源声明(4.1)</td></tr>
|
||||
<tr><td>人类工具四卡的模式与回传协议(05)</td><td>范式选择:loop 或 flow(04)</td></tr>
|
||||
<tr><td>统一事件标准:信封 · 四类事件 · 归属解析 · 投递五诺(06)</td><td>业务模型:CMMN + DMN 或步序声明(04)</td></tr>
|
||||
<tr><td>调用层四类:系统调用 · LLM 工具 · 人类工具 · 通道;白名单与授权;工具箱(07)</td><td>交互内容:视图模版 · 卡内容 schema · 汇报组织(04 / 09)</td></tr>
|
||||
<tr><td>放行门:草稿态 → 事实态的落地时机与协议(09)</td><td>技能清单(基于工具,载方法不载权力)与监听声明(静态 + 动态,时限必配)(06 / 07)</td></tr>
|
||||
<tr><td>流程层(流程包 / 工作流 · 审批点 · 网关 · 触发器)· 预算执行器(环外强制,04)</td><td>Harness 参数申报:停止条件 · 预算 · 时限 · 恢复——执行归系统(04)</td></tr>
|
||||
<tr><td>基座六项存放 · 治理台九功能 · web 呈现容器(11 / 02 / 09)</td><td>过程工作区(自设)· 纯工具 · 台账 schema(声明物化)· 蒸馏钩子(04 / 08)</td></tr>
|
||||
</table></div>
|
||||
<p class="small">本表与《活动模型》0.2 镜像同表(行数、行序、措辞一一对应,括号内章号各随本卷)——左列是系统的承诺,右列是活动的申报;边界线即活动基座六件的接口。</p>
|
||||
|
||||
<!-- ========== 11 ========== -->
|
||||
<h2 class="ch"><span class="n">11</span>基座与治理</h2>
|
||||
<div class="ch-rule"></div>
|
||||
|
||||
<p class="lead"><b>基座 = 数据、台账、记忆、工具箱、活动库、流程包。</b>基座是存放层,只存事实、记录、能力与工件,零业务逻辑——与活动基座(04)不同物:活动基座是运行时的通用模式(宿主),本章基座是存放(库房)。</p>
|
||||
<div class="tbl"><table>
|
||||
<tr><th style="width:110px">构件</th><th>内容</th></tr>
|
||||
<tr><td><b>数据</b></td><td>主数据:员工、岗位、权限、共享对象目录</td></tr>
|
||||
<tr><td><b>台账</b></td><td>活动声明的业务数据表与台账:schema 声明、宿主物化、统一治理(脱敏、保留期、权限)</td></tr>
|
||||
<tr><td><b>记忆</b></td><td>记忆系统的存放:任务记忆的归档库(单单封卷)与活动记忆库(跨单持久)(08)</td></tr>
|
||||
<tr><td><b>工具箱</b></td><td>功能工具之库,<b>独立的开发与注册入口</b>:工具是独立开发的代码包,由此注册进调用层、入白名单;账号、密钥与 endpoint 配置随工具管理,版本并存;活动以调用契约引用</td></tr>
|
||||
<tr><td><b>活动库</b></td><td>已安装活动之库,<b>独立的安装与卸载入口</b>:活动包(系统外开发,含业务模型与技能初始版)由此进出,版本并存;库内按<b>业务分类(一级,组织自定)× 活动类型(标准 / 案例)</b>两维管理,两维平级、相互独立;每活动两条版本序列:<b>包版本 × 资产版本</b>(11.3);编排层以声明引用库中活动</td></tr>
|
||||
<tr><td><b>流程包</b></td><td>治理台在系统内编排的结构定义,版本化存放;<b>工作流 = 流程包的运行时实例</b></td></tr>
|
||||
</table></div>
|
||||
<p>一切运行都能在基座找到出处:其事实在数据与台账,其记录在记忆,其能力在工具箱,其定义在活动库与流程包。</p>
|
||||
|
||||
<p><b>持久层两分:系统自持 × 活动自生长。</b>基座的一切持久存储按归属分两类:</p>
|
||||
<div class="tbl"><table>
|
||||
<tr><th style="width:110px">归属</th><th>存什么</th><th style="width:300px">schema 谁定 · 怎么变</th></tr>
|
||||
<tr><td><b>系统自持</b></td><td>主数据 · 共享对象目录 · 记忆存放(任务记忆归档库、活动记忆库)· 事件存储(统一事件流,"先持久后投递"的底座,06)· 运行时实例(工作流与任务的状态与投影)· <b>触发器配置</b>(调用工作流的时机规则,独立于流程包)· 工具箱注册表(工具、白名单、密钥与 endpoint)· 活动库与流程包(定义与版本)</td><td>系统 schema,随系统版本迭代、系统自带迁移;活动不可写结构,只经接口读写被允许的内容</td></tr>
|
||||
<tr><td><b>活动自生长</b></td><td>业务台账与数据表:活动以「数据域.数据对象.字段」声明</td><td>使用声明的<b>最大化合并</b>,<b>只增不破坏</b>(版本升级声明多了就长、少了不缩,无迁移);数据随事类不随包版本,在途照旧</td></tr>
|
||||
</table></div>
|
||||
<p class="small">两条补充口径:<b>共享对象 = 共享域的台账</b>,不是第三类外装件——各活动声明各自<b>要用</b>的字段,对象 schema 按最大化合并自生长(首个声明创建、后续声明并入);目录只是数据管理的视图,写授权按域.对象在契约申报、白名单核准——<b>箱只有两个(工具箱、活动库),数据不设箱、数据靠域</b>;<b>过程草稿</b>(工作区,即台账的任务级草稿层与动作意向,09)是任务范围的暂存——持久于系统自持存储(断线不丢稿,写即持久)但<b>非事实</b>:放行前不落台账正式版与外部系统,放行时合并落地,随任务终态封卷处理。</p>
|
||||
|
||||
<h3 class="h3"><span class="n">11.1</span>开发装配流:编排 → 声明 → 编译 → 导入 → 装配</h3>
|
||||
<p><b>工作流编排先于活动开发</b>——编排工作流的过程,就是定义活动契约的过程。闭环五步:</p>
|
||||
<ul class="tight">
|
||||
<li><b>1 · 编排定契约</b>——治理台画工作流图(五要素编排,03):节点的输入输出、依赖的工具与模型随图确定,各活动契约随编排成形;<b>边的载荷映射随图强制闭合</b>——必填未齐、类型冲突不得发布(03)。</li>
|
||||
<li><b>2 · 导出依赖文件</b>——图画完、契约定好,导出开发该工作流活动库的<b>依赖文件(声明 + 编译选项)</b>:所有依赖的接口声明、模型声明、工具声明、输入输出声明。</li>
|
||||
<li><b>3 · 基于声明开发</b>——系统外对着声明开发(本地 mock);按活动的编译选项编译出该工作流的<b>多个活动库 .JS</b>(每活动一个编译产物,即活动包)。</li>
|
||||
<li><b>4 · 导入与管理</b>——活动库 .JS 可批量导入也可单独导入;入系统后在活动库中按<b>业务分类(一级)× 活动类型(标准 / 案例)</b>两维分类与版本管理,版本并存。</li>
|
||||
<li><b>5 · 流程包装配</b>——流程包里按<b>活动名</b>装配:一键自动安装最新版本,或手动控制使用旧版本;安装两审照常收口(11.2)。</li>
|
||||
</ul>
|
||||
<p class="small">契约不是活动开发者单方申报,而是<b>编排给定、开发实现、安装校核</b>——工作流图是契约的母体,三方共读同一份声明。</p>
|
||||
|
||||
<p><b>包清单(manifest):包的自述文件。</b>活动包 = 包清单 + 代码产物(.JS)+ 资产文件;清单机器可读,系统<b>不执行代码即知包为何物</b>——导入登记、安装静态审、编排装配读的都是清单。清单六区:</p>
|
||||
<div class="tbl"><table>
|
||||
<tr><th style="width:130px">区</th><th>内容</th></tr>
|
||||
<tr><td><b>身份</b></td><td>活动名(全局唯一)· 包版本 · 业务分类 · 活动类型(loop / flow)· SDK 版本 · 签名与校验和</td></tr>
|
||||
<tr><td><b>契约</b></td><td>契约七件,声明形式(4.1)</td></tr>
|
||||
<tr><td><b>声明</b></td><td>模型声明(自定义模型名)· 工具声明(调用契约引用 + 版本约束)· 台账与共享域使用声明(域.对象.字段)· 静态监听声明 · Harness 配置</td></tr>
|
||||
<tr><td><b>资产初始版</b></td><td>业务模型(CMMN + 说明书 / 步序声明)· DMN · 技能 · 视图模版 · 卡 schema</td></tr>
|
||||
<tr><td><b>样例集</b></td><td>样例输入 → 期望输出口与载荷形状;首装审与回归依据(11.2)</td></tr>
|
||||
<tr><td><b>代码入口</b></td><td>.JS 产物的入口与校验和</td></tr>
|
||||
</table></div>
|
||||
<p class="small"><b>依赖文件即清单骨架</b>——编排导出定其契约区与声明区,开发补代码与资产,编译合成完整清单;<b>静态审审清单,试运行验代码</b>。工具包同构:身份 + 调用契约 + 连接配置声明 + 契约测试集 + 代码入口(7.3)。</p>
|
||||
|
||||
<h3 class="h3"><span class="n">11.2</span>安装治理:两个独立入口,一套两审</h3>
|
||||
<p>外装件两类、两个独立入口:<b>活动包经活动库</b>安装卸载,<b>工具包经工具箱</b>注册——都不在编排中发生。安装检查两道:<b>静态审</b>(签名、无动态执行、SDK 兼容、所需调用契约与角色齐备、schema 校验)与<b>回放审</b>。安装恒为新增、版本并存;<b>在途任务按其启动时版本跑完,切换零丢单</b>;生效 / 停用 / 卸载由治理台管理。</p>
|
||||
<p><b>回放审 = 确定性断言重跑。</b>新版本对历史任务记忆重演其中<b>可确定判定</b>的部分:契约 schema 校验、业务模型静态检查、DMN 决策表对历史输入重算、监听过滤与时限求值、纯工具重跑——比对新旧版结论。<b>LLM 步不重推理</b>:以历史出入参作录制回放,仅校验历史出参对新版 schema 的兼容;人的回传与外部世界的响应一律取历史录制值;写类动作只校验动作意向的构造,不执行。判定口径:<b>「旧成不坏」是生效硬门</b>——历史成功单在新版下断言全过,方可生效;「旧败能成」(历史失败单中新版断言可拦住者)为<b>报告参考项</b>,列入重演报告、不作门槛;无历史失败单天然通过。<b>首次安装无历史:免回放审,以静态审 + 样例集替代</b>(样例集为包清单一区,11.1)。</p>
|
||||
<p class="small">形态类比小程序:业务装在系统里,以活动包交付——装一个新业务 = 装一个小程序,底座不为它改一行;界面容器、身份权限、记忆与卡片全由系统供给,包内无越权代码;上架有审,上线下线随时可控,包与包互不干扰,在途的单照常办完。</p>
|
||||
|
||||
<h3 class="h3"><span class="n">11.3</span>进化治理:候选 → 回放 → 人放行 → 可回退</h3>
|
||||
<p><b>资产与包分离版本化。</b>活动库对每个活动维护两条版本序列,各有各的门、各自单写者:<b>包版本</b>管代码、契约、交互模版、Harness 声明——变更必须系统外重编,走安装两审(11.2);<b>资产版本</b>管业务模型、DMN 与技能——活动包只携初始版(安装时播种入库),此后的资产新版由本节的进化管线在系统内产生(回放 + 人放行),不重编包、不重签名。任务装载 = 包版本 + 各资产当前生效版,全部入信封,行为可归因;包新版携带的资产初始版<b>不覆盖</b>已有更高的资产版——覆盖只能是显式的资产回退治理动作。</p>
|
||||
<ul class="tight">
|
||||
<li><b>候选从记忆来</b>——指标异动是扳机(08):纠正聚类、模式收敛、例外累积指向活动记忆的对应层,蒸馏出候选增量(业务模型 / 技能的 diff,带证据链)。</li>
|
||||
<li><b>回放先行</b>——新版本对历史任务记忆重演:旧成功单是否仍成、旧失败单是否恰被拦住;重演报告随增量入证据包。</li>
|
||||
<li><b>人放行</b>——增量 diff + 重演报告过治理台;放行即生效为新版本,下一单装载即行为改变,系统零改动。</li>
|
||||
<li><b>可回退</b>——版本谱系完整,行为回退 = 版本回退;每步行为可由版本信封完全归因(08)。</li>
|
||||
<li><b>治理也被治理</b>——治理台的每个动作同样留痕入事件流。</li>
|
||||
</ul>
|
||||
|
||||
<!-- ========== 12 ========== -->
|
||||
<h2 class="ch"><span class="n">12</span>系统不变量</h2>
|
||||
<div class="ch-rule"></div>
|
||||
<ul class="checks">
|
||||
<li><b>调度分层,放行归人</b>——工作流与 flow 活动的调度权归系统,loop 活动的调度权归 AI,放行权只归人:确定交系统,临场交 AI,落地交人。</li>
|
||||
<li><b>责任有主</b>——任务恰一负责人,审批点恰有审批人;责任要素只在工作台出现。</li>
|
||||
<li><b>一个活动 = 一个完成一项任务的 Agent 机制</b>——Case 是 loop,SOP 是 flow;业务模型、交互内容、技能清单、Harness 与过程工作区皆随活动。</li>
|
||||
<li><b>两种范式,一套执行契约</b>——活动基座六件对 loop 与 flow 完全一致;差异只在范式与业务模型形态,对流程层与交互层不可区分。</li>
|
||||
<li><b>编排层五要素</b>——活动(声明)、审批、网关、触发器、流程包;触发器与流程包平级,起单归触发器,结构归流程包,活动以声明入流、不含触发逻辑;<b>流程包 → 工作流,活动 → 任务:包在库,实例在跑</b>。</li>
|
||||
<li><b>做事与留痕同一动作</b>——工作台五要素是同一份过程事实的五种投影。</li>
|
||||
<li><b>能力在系统,方法在活动</b>——功能工具是独立开发的代码包,经工具箱注册、白名单授权;LLM 工具与人类工具固化在系统;活动只经调用契约用工具,技能基于工具在活动内定义,载方法不载权力。<b>数据可以自生长,权力不可以自生长。</b></li>
|
||||
<li><b>活动在系统外,模式在系统内</b>——外装件两类:活动包经活动库安装卸载,工具包经工具箱注册;活动基座与审批、网关、触发器的模式落在系统内;活动代码无环境能力,一切能力经调用契约注入。</li>
|
||||
<li><b>过程在后端,呈现在 web</b>——活动过程(LLM 调用、LLM 工具、过程草拟、视图流控)集中在 server,web 是纯呈现与输入面;落台账与外部系统的动作集中在放行时(契约显式预授权的写类动作除外,7.3),门立在草稿态与事实态之间,记录的归档不受门限。</li>
|
||||
<li><b>人类工具与 LLM 工具同列</b>——决策、执行、补全、放行四种调用层内置工具,经卡片到达人(负责人走任务对话流,其他人走系统消息);系统定卡模式,活动填内容;调用必附上下文,回传即留痕,完成只出自放行通过,驳回必附意见。</li>
|
||||
<li><b>事件驱动,标准统一</b>——系统向活动只以统一信封抛四类事件(数据 / 时间 / 人 / 控制);活动以监听声明依赖,监听必配时限;投递先持久后送、同任务按序、至少一次且幂等;活动认数据,不认通道。</li>
|
||||
<li><b>系统恒定,业务在外装件</b>——改业务 = 换活动包 / 工具包或改流程包,不改系统;交互、引擎与基座零业务逻辑。</li>
|
||||
<li><b>安装与发布恒新增</b>——活动包、工具包与流程包皆版本并存;在途任务按其启动时版本跑完,切换零丢单。</li>
|
||||
<li><b>进化必过治理</b>——候选增量必经回放先行与人放行,版本可回退;治理动作亦留痕——治理也被治理。</li>
|
||||
<li><b>预检放行,落地收敛</b>——检查可落地,才允许放行:预检全过才发放行卡;放行即落地(幂等键),落地收敛输出口才发射——下游只见落地完成的任务。</li>
|
||||
<li><b>写分三类,草稿持久</b>——系统写(登记世界已发生的事实,免门即抛事件)、草稿写(任务级草稿层,读己之写,不抛事件)、放行写(合并落地,此刻抛事件);草稿与动作意向写即持久,断点续跑由任务记忆、草稿层与运行时实例状态三份共同保证。</li>
|
||||
<li><b>包以清单自述</b>——外装件以包清单(manifest)交付,静态审审清单、试运行验代码;资产与包分离版本化,各自单写者、各有各的门。</li>
|
||||
</ul>
|
||||
|
||||
<footer class="ft">
|
||||
<span>JCAI · 操作系统 · 系统侧规范 · V2.15 · 关联《活动模型》</span>
|
||||
<span>2026-07-24</span>
|
||||
</footer>
|
||||
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
+991
@@ -0,0 +1,991 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>活动模型 · 活动侧规范</title>
|
||||
<style>
|
||||
:root{
|
||||
--desk:#E8ECF2;--paper:#fff;
|
||||
--ink:#1F2329;--ink-2:#3a4452;--ink-3:#646A73;--ink-4:#8F959E;
|
||||
--brand:#3370FF;--brand-deep:#245BDB;--brand-wash:#F0F4FF;--brand-soft:#E1EAFF;
|
||||
--ai:#8A5F1C;--ai-soft:#F7F0E0;--ai-line:#B07D2B;
|
||||
--human:#173A63;--human-soft:#DCEAF7;--human-line:#2F6DB5;
|
||||
--ok:#278717;--ok-soft:#E8F8E4;--warn:#DE7802;--warn-soft:#FFF4E5;--danger:#D83931;--danger-soft:#FEEAE9;
|
||||
--line:#DEE0E3;--line-soft:#EBEDF0;--soft:#F5F6F7;
|
||||
--mono:"SF Mono","JetBrains Mono","Menlo","Roboto Mono",ui-monospace,monospace;
|
||||
--sans:"PingFang SC","Noto Sans SC","Hiragino Sans GB","Microsoft YaHei",system-ui,sans-serif;
|
||||
}
|
||||
*{box-sizing:border-box}html,body{margin:0;padding:0}
|
||||
body{background:var(--desk);color:var(--ink);font-family:var(--sans);font-size:14px;line-height:1.8;-webkit-font-smoothing:antialiased;padding:32px 20px 72px;overflow-wrap:anywhere}
|
||||
.doc{width:1060px;max-width:100%;margin:0 auto;background:var(--paper);padding:52px 56px 64px;border-radius:4px;box-shadow:0 14px 44px -20px rgba(20,27,34,.32)}
|
||||
.hd{border-bottom:2px solid var(--ink);padding-bottom:22px;margin-bottom:8px}
|
||||
.hd .kicker{display:inline-flex;align-items:center;gap:8px;font-family:var(--mono);font-size:10.5px;font-weight:700;letter-spacing:.14em;color:var(--brand-deep);background:var(--brand-wash);border:1px solid var(--brand-soft);border-radius:999px;padding:3px 12px;margin-bottom:14px}
|
||||
.hd h1{font-size:31px;font-weight:700;letter-spacing:-.01em;line-height:1.25;margin:0 0 6px}
|
||||
.hd .sub{font-size:15px;color:var(--ink-3);margin:0}
|
||||
.hd .meta{display:flex;flex-wrap:wrap;gap:8px 22px;margin-top:16px;font-family:var(--mono);font-size:11px;color:var(--ink-4)}
|
||||
.hd .meta b{color:var(--ink-2);font-weight:600}
|
||||
h2.ch{font-size:22px;font-weight:700;letter-spacing:-.005em;margin:52px 0 4px}
|
||||
h2.ch .n{font-family:var(--mono);font-size:.8em;color:var(--brand-deep);margin-right:.55em}
|
||||
.ch-rule{height:2px;background:linear-gradient(90deg,var(--brand),#7F3BF5);border-radius:2px;width:64px;margin:0 0 16px}
|
||||
h3.h3{font-size:15.5px;font-weight:700;margin:28px 0 10px}
|
||||
h3.h3 .n{font-family:var(--mono);font-size:.82em;color:var(--brand-deep);margin-right:.5em}
|
||||
p{margin:0 0 12px}
|
||||
p.lead{font-size:15px;color:var(--ink-2)}
|
||||
b{font-weight:600}
|
||||
ul.tight{margin:6px 0 14px;padding-left:20px}
|
||||
ul.tight li{margin:4px 0}
|
||||
.small{font-size:12px;color:var(--ink-3)}
|
||||
code{font-family:var(--mono);font-size:.9em;background:var(--soft);border:1px solid var(--line-soft);border-radius:5px;padding:1px 6px}
|
||||
.callout{border:1px solid;border-radius:10px;padding:12px 16px;margin:14px 0;font-size:13px;line-height:1.8}
|
||||
.callout.brand{background:var(--brand-wash);border-color:var(--brand-soft);color:var(--brand-deep)}
|
||||
.callout.ok{background:var(--ok-soft);border-color:#bfedb4;color:var(--ok)}
|
||||
.callout.warn{background:var(--warn-soft);border-color:#fbd9a5;color:var(--warn)}
|
||||
.callout.danger{background:var(--danger-soft);border-color:#f6c6c3;color:var(--danger)}
|
||||
.tbl{margin:12px 0 18px;border:1px solid var(--line-soft);border-radius:10px;overflow:hidden}
|
||||
table{border-collapse:collapse;width:100%;font-size:12.5px}
|
||||
th{background:var(--soft);color:var(--ink-2);font-weight:700;text-align:left;padding:9px 12px;border-bottom:1.5px solid var(--line);white-space:nowrap}
|
||||
td{padding:9px 12px;border-bottom:1px solid var(--line-soft);vertical-align:top}
|
||||
tr:last-child td{border-bottom:0}
|
||||
td.mono,.mono{font-family:var(--mono);font-size:11.5px}
|
||||
.steps{counter-reset:st;margin:12px 0 18px;padding:0;list-style:none}
|
||||
.steps li{position:relative;padding:10px 14px 10px 46px;border:1px solid var(--line-soft);border-radius:10px;margin-bottom:8px;background:#fff}
|
||||
.steps li::before{counter-increment:st;content:counter(st);position:absolute;left:14px;top:12px;width:20px;height:20px;border-radius:999px;background:var(--brand);color:#fff;font-family:var(--mono);font-size:11px;font-weight:700;display:grid;place-items:center}
|
||||
.checks{margin:8px 0 16px;padding:0;list-style:none}
|
||||
.checks li{position:relative;padding:6px 12px 6px 32px;border-bottom:1px dashed var(--line-soft);font-size:13px}
|
||||
.checks li::before{content:"☐";position:absolute;left:8px;top:6px;color:var(--brand);font-size:14px}
|
||||
.checks li:last-child{border-bottom:0}
|
||||
.toc{border:1px solid var(--line-soft);border-radius:12px;padding:6px 0;margin:18px 0 4px}
|
||||
.toc .row{display:grid;grid-template-columns:52px 1fr;gap:10px;align-items:baseline;padding:7px 16px;border-bottom:1px dashed var(--line-soft);font-size:13px}
|
||||
.toc .row:last-child{border-bottom:0}
|
||||
.toc .row .n{font-family:var(--mono);font-size:11px;color:var(--brand-deep);font-weight:700}
|
||||
.toc .row .t b{font-weight:600}
|
||||
.toc .row .t span{color:var(--ink-4);font-size:11.5px;margin-left:8px}
|
||||
.fig{margin:18px 0 14px;border:1px solid #D8DEE6;padding:10px 14px 12px;background:#fff}
|
||||
.fig .figcap{display:flex;justify-content:space-between;gap:10px;font-family:var(--mono);font-size:9.5px;letter-spacing:.1em;color:#6A7686;padding:2px 4px 10px}
|
||||
.fig svg{display:block;width:100%;height:auto}
|
||||
.ft{margin-top:56px;padding-top:16px;border-top:1px solid var(--line);display:flex;justify-content:space-between;gap:12px;font-family:var(--mono);font-size:10.5px;color:var(--ink-4)}
|
||||
@media (max-width:900px){.doc{padding:32px 22px}}
|
||||
@media print{body{background:#fff;padding:0}.doc{box-shadow:none;width:auto}}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="doc">
|
||||
|
||||
<header class="hd">
|
||||
<div class="kicker">JCAI · ACTIVITY MODEL</div>
|
||||
<h1>活动模型:活动的定义与两范式运行</h1>
|
||||
<p class="sub">本卷完整描述<b>活动侧</b>:一个活动 = 一个<b>完成一项任务的 Agent 机制</b>——怎么定义(契约与业务模型)、怎么运行(<b>loop / flow</b> 两范式)、怎么交互(卡与视图)、怎么沉淀(技能与记忆)、怎么交付(活动包与安装)。系统侧机制(事件投递、流程层、治理台、度量、终态裁定)见《操作系统》;本卷只写活动。</p>
|
||||
<div class="meta">
|
||||
<div>版本 <b>V2.0 · 活动规范</b></div>
|
||||
<div>日期 <b>2026-07-25</b></div>
|
||||
<div>读者 <b>活动开发者(Coding Agent)</b></div>
|
||||
<div>关系 <b>关联《操作系统》</b></div>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<div class="toc">
|
||||
<div class="row"><span class="n">00</span><span class="t"><b>定位与边界</b><span>Agent 机制 · 小程序类比 · 四象限 · 供给与定义两清单</span></span></div>
|
||||
<div class="row"><span class="n">01</span><span class="t"><b>契约:活动的接口</b><span>输入(data + message)· 输出口(必发 / 选择)· 终态五名 · 接口最小性</span></span></div>
|
||||
<div class="row"><span class="n">02</span><span class="t"><b>范式:loop 与 flow</b><span>规范名 · 范式边界即调度权边界 · 选型判据 · 活动内容物</span></span></div>
|
||||
<div class="row"><span class="n">03</span><span class="t"><b>loop · 业务模型</b><span>CMMN + DMN 运行结构 · 构件语义 · 三铁律 · DMN 四则 · 装载</span></span></div>
|
||||
<div class="row"><span class="n">04</span><span class="t"><b>loop · 运行机制</b><span>CMMN 生命周期 · Enabled ≠ Active · 语义引擎 × Agent 回路 · 双向驱动 · 监听映射</span></span></div>
|
||||
<div class="row"><span class="n">05</span><span class="t"><b>flow · 步序声明</b><span>四种步型 · 条件与上升规则 · 事件即步条件 · 失败声明给定</span></span></div>
|
||||
<div class="row"><span class="n">06</span><span class="t"><b>人类工具的调用</b><span>四卡 · 调用时机 · 跨人卡与驳回重答 · 预检放行,落地收敛</span></span></div>
|
||||
<div class="row"><span class="n">07</span><span class="t"><b>交互内容</b><span>视图流控(HTML 模版)· 卡内容 schema · 汇报组织 · web 零活动代码</span></span></div>
|
||||
<div class="row"><span class="n">08</span><span class="t"><b>技能</b><span>封装格式 · 三层软硬 · 装配语义 · 载方法不载权力</span></span></div>
|
||||
<div class="row"><span class="n">09</span><span class="t"><b>记忆与迭代</b><span>任务记忆 · 活动记忆四层 · 蒸馏与装载 · 迭代业务模型即迭代行为</span></span></div>
|
||||
<div class="row"><span class="n">10</span><span class="t"><b>Harness · 验收分级 · 工作区</b><span>预算熔断 · 停滞检测 · 控制三语义 · L1–L5 · 任务级草稿层</span></span></div>
|
||||
<div class="row"><span class="n">11</span><span class="t"><b>活动包与开发</b><span>内容物 · 工具三来处 · 编排先行与依赖文件 · 安装两审 · 暗耦合禁令</span></span></div>
|
||||
<div class="row"><span class="n">12</span><span class="t"><b>合规判据</b><span>通用 17 条 · loop 8 条 · flow 6 条</span></span></div>
|
||||
</div>
|
||||
|
||||
<!-- ========== 00 ========== -->
|
||||
<h2 class="ch"><span class="n">00</span>定位与边界</h2>
|
||||
<div class="ch-rule"></div>
|
||||
|
||||
<p class="lead"><b>一个活动 = 一个完成一项任务的 Agent 机制。</b>活动像小程序:基于系统内<b>活动基座</b>的六件接口(契约 · 交互 · 记忆 · 数据 · 工具调用契约 · LLM 调用)<b>在系统外独立开发</b>,经<b>活动库</b>的独立入口安装进系统,即可被流程层以声明引用;卸载同走此入口,系统内不写活动代码。活动是<b>开发态</b>,任务是<b>运行态</b>——活动被调起的一次运行,即落到恰一名负责人工作台上的一单任务。</p>
|
||||
|
||||
<div class="callout warn"><b>边界声明:活动不含触发器。</b>活动之上是流程层:流程包 = 调用接口 + 两种活动 + 审批点(通用)+ 网关(两种,并行 / 异或);<b>工作流 = 流程包的运行时实例,任务 = 活动的运行时实例</b>——包在库,实例在跑;触发器与流程包平级——触发器是流程层的系统级事件监听,经调用接口调起流程包、生成工作流。活动自<b>输入</b>始(由调用方给定)、至<b>终态</b>止(连同交付物交回调用方);工作流如何被触发、如何衔接,归《操作系统》。活动对调用方只暴露契约,对内完全自治。</div>
|
||||
|
||||
<div class="callout brand"><b>行为公式:行为 = 引擎(契约, 业务模型, 技能, 记忆)。</b>引擎与活动基座是<b>不动点</b>——通用、零业务、对所有活动同一份;一切业务行为差异,必须可归因于契约、业务模型、技能与记忆的版本差异。业务模型按范式取形:loop = CMMN + DMN 案例模型,flow = 步序声明。因此<b>迭代业务模型,就是迭代这个活动的行为</b>:改模型即改行为,零代码;模型增量可 diff、可回放、可放行、可回退(09)。</div>
|
||||
|
||||
<h3 class="h3"><span class="n">0.1</span>活动与系统的边界:四象限</h3>
|
||||
<p>两条轴把全部职责分干净:<b>物理轴</b>(web 前端 / server 后端——过程在后端,呈现在 web)与<b>归属轴</b>(系统平台本体 / 活动外装件)。四个象限,边界各有判据:</p>
|
||||
<div class="tbl"><table>
|
||||
<tr><th style="width:110px"></th><th>系统(平台本体)</th><th>活动(外装件)</th></tr>
|
||||
<tr><td><b>web · 前端</b></td><td>工作台与治理台的界面本体:五要素呈现、对话流时间线与卡片渲染、视图区容器、统一输入入口</td><td><b>无代码,只有内容投影</b>:后端推送的视图 HTML 与卡片内容,由系统容器渲染、净化,无脚本执行权</td></tr>
|
||||
<tr><td><b>server · 后端</b></td><td>流程引擎(流转 · 审批点 · 网关)· 活动基座六件 · 统一事件标准与投递 · 调用层四类工具 · 基座存放 · 放行门</td><td><b>活动的内容物,跑在基座之上</b>:业务模型 · 交互内容(模版)· 技能清单 · Harness · 监听声明 · 纯工具 · 台账 schema · 过程工作区</td></tr>
|
||||
</table></div>
|
||||
<ul class="tight">
|
||||
<li><b>物理线(横)</b>——跨线只有两种流量:下行的视图与卡片内容(HTML + schema 数据),上行的对话流输入回传;前端零过程状态。</li>
|
||||
<li><b>归属线(纵)</b>——后端段是<b>活动基座接口</b>:活动只见六件,能力一律经调用契约注入;前端段是<b>容器边界</b>:系统渲染活动的内容,不装载活动的代码。</li>
|
||||
<li><b>两线交汇 = 放行门</b>——草稿态(活动过程)到事实态(台账与外部系统)的唯一通道;放行前不落事实(10)。</li>
|
||||
</ul>
|
||||
|
||||
<h3 class="h3"><span class="n">0.2</span>系统供给什么,活动定义什么</h3>
|
||||
<div class="tbl"><table>
|
||||
<tr><th style="width:50%">系统供给(模式在系统内,零开发)</th><th>活动定义(内容随活动,系统外开发)</th></tr>
|
||||
<tr><td>活动基座六件:契约格式 · 交互结构(对话流 + 视图区容器)· 记忆系统 · 数据(「数据域.数据对象.字段」三级寻址 + 通用事务性接口,安装时依声明自生长)· 工具调用契约 · LLM 调用</td><td>契约内容(七件):输入(data + message)/ 输出口(必发 / 选择)/ 必交付物 / 验收判据(分级标注)/ 禁区 / 授权边界 / 资源声明(01)</td></tr>
|
||||
<tr><td>人类工具四卡的模式与回传协议(06)</td><td>范式选择:loop 或 flow(02)</td></tr>
|
||||
<tr><td>统一事件标准:信封 · 四类事件 · 归属解析 · 投递五诺(04 / 05)</td><td>业务模型:CMMN + DMN 或步序声明(03 / 05)</td></tr>
|
||||
<tr><td>调用层四类:系统调用 · LLM 工具 · 人类工具 · 通道;白名单与授权;工具箱</td><td>交互内容:视图模版 · 卡内容 schema · 汇报组织(07)</td></tr>
|
||||
<tr><td>放行门:草稿态 → 事实态的落地时机与协议</td><td>技能清单(基于工具,载方法不载权力)与监听声明(静态 + 动态,时限必配)(08 · 04 / 05)</td></tr>
|
||||
<tr><td>流程层(流程包 / 工作流 · 审批点 · 网关 · 触发器)· 预算执行器(环外强制)</td><td>Harness 参数申报:停止条件 · 预算 · 时限 · 恢复——执行归系统(10)</td></tr>
|
||||
<tr><td>基座六项存放 · 治理台九功能 · web 呈现容器</td><td>过程工作区(自设)· 纯工具 · 台账 schema(声明物化)· 蒸馏钩子(10 / 11 / 09)</td></tr>
|
||||
</table></div>
|
||||
<p class="small">本表与《操作系统》10.1 镜像同表——行数、行序、措辞一一对应,括号内章号各随本卷。</p>
|
||||
<p><b>统一套执行契约</b>:上表左列对 loop 与 flow 完全一致——两范式的差异被压缩到唯一一处:<b>Agent 机制的范式与业务模型的形态</b>。对流程层与交互层而言,两种活动不可区分地是"一个节点、一单任务"。</p>
|
||||
|
||||
<div class="fig">
|
||||
<div class="figcap"><span>FIG-01 · 活动与系统的边界 · 四象限</span><span>物理线(web / server) × 归属线(系统 / 活动) · 交汇 = 放行门</span></div>
|
||||
<svg viewBox="0 0 1000 430" role="img" aria-label="四象限:web×系统为界面本体,web×活动为内容投影无代码,server×系统为流程引擎与活动基座等机制,server×活动为跑在基座上的活动内容物;两线交汇处是放行门">
|
||||
<style>
|
||||
.av-t{font-family:'PingFang SC','Noto Sans SC',sans-serif;font-size:10.5px;font-weight:600;fill:#1F2933}
|
||||
.av-c{font-family:'PingFang SC','Noto Sans SC',sans-serif;font-size:10px;fill:#3A4452}
|
||||
.av-m{font-family:'SF Mono',Menlo,monospace;font-size:10px;font-weight:600;letter-spacing:.12em;fill:#6A7686}
|
||||
.av-s{font-family:'PingFang SC','Noto Sans SC',sans-serif;font-size:8.5px;fill:#6A7686}
|
||||
</style>
|
||||
|
||||
<text x="315" y="40" text-anchor="middle" class="av-m" fill="#46586A">系统 · 平台本体</text>
|
||||
<text x="741" y="40" text-anchor="middle" class="av-m" fill="#8A5F1C">活动 · 外装件</text>
|
||||
<text x="70" y="120" text-anchor="middle" class="av-m" fill="#173A63">web</text>
|
||||
<text x="70" y="136" text-anchor="middle" class="av-s">前端 · 呈现</text>
|
||||
<text x="70" y="280" text-anchor="middle" class="av-m" fill="#173A63">server</text>
|
||||
<text x="70" y="296" text-anchor="middle" class="av-s">后端 · 过程</text>
|
||||
|
||||
<rect x="110" y="56" width="410" height="140" rx="10" fill="#F7F9FB" stroke="#9AA7B6" stroke-width="1.3"/>
|
||||
<text x="126" y="82" class="av-t" fill="#173A63">工作台 · 治理台(界面本体)</text>
|
||||
<text x="126" y="104" class="av-s">五要素呈现 · 对话流时间线与卡片渲染</text>
|
||||
<text x="126" y="120" class="av-s">视图区容器 · 统一输入入口</text>
|
||||
<text x="126" y="142" class="av-s" font-weight="600" fill="#3A4452">零活动代码 · 零过程状态</text>
|
||||
|
||||
<rect x="536" y="56" width="410" height="140" rx="10" fill="#FCFAF3" stroke="#B07D2B" stroke-width="1.3"/>
|
||||
<text x="552" y="82" class="av-t" fill="#8A5F1C">内容投影(无代码)</text>
|
||||
<text x="552" y="104" class="av-s">后端推送的视图 HTML 与卡片内容</text>
|
||||
<text x="552" y="120" class="av-s">容器渲染 · 净化 · 无脚本执行权</text>
|
||||
<text x="552" y="142" class="av-s" font-weight="600" fill="#8A5F1C">活动到达前端的是投影,不是程序</text>
|
||||
|
||||
<rect x="110" y="212" width="410" height="150" rx="10" fill="#FFFFFF" stroke="#46586A" stroke-width="1.5"/>
|
||||
<text x="126" y="238" class="av-t" fill="#46586A">系统机制(模式在系统内)</text>
|
||||
<text x="126" y="260" class="av-s">流程引擎(流转 · 审批点 · 网关)· 活动基座六件</text>
|
||||
<text x="126" y="276" class="av-s">统一事件标准与投递 · 调用层四类 · 基座存放</text>
|
||||
<text x="126" y="298" class="av-s" font-weight="600" fill="#3A4452">放行门:草稿态 → 事实态的唯一通道</text>
|
||||
|
||||
<rect x="536" y="212" width="410" height="150" rx="10" fill="#FFF" stroke="#B07D2B" stroke-width="1.5"/>
|
||||
<text x="552" y="238" class="av-t" fill="#8A5F1C">活动的内容物(跑在基座之上)</text>
|
||||
<text x="552" y="260" class="av-s">业务模型(CMMN + DMN / 步序声明)· 交互内容(模版)</text>
|
||||
<text x="552" y="276" class="av-s">技能清单 · Harness · 监听声明 · 纯工具 · 台账 schema</text>
|
||||
<text x="552" y="298" class="av-s" font-weight="600" fill="#8A5F1C">能力一律经调用契约注入 —— 越权在结构上不可能</text>
|
||||
|
||||
<line x1="528" y1="50" x2="528" y2="368" stroke="#98A2B0" stroke-width="1.2" stroke-dasharray="6 4"/>
|
||||
<line x1="104" y1="204" x2="952" y2="204" stroke="#98A2B0" stroke-width="1.2" stroke-dasharray="6 4"/>
|
||||
<circle cx="528" cy="204" r="6" fill="#2F6DB5"/>
|
||||
<text x="542" y="200" class="av-s" font-weight="600" fill="#173A63">放行门(两线交汇)</text>
|
||||
|
||||
<text x="36" y="382" class="av-s">物理线(横):跨线只有下行视图与卡片、上行对话流输入</text>
|
||||
<text x="520" y="382" class="av-s">归属线(纵):后端 = 基座接口 · 前端 = 容器边界</text>
|
||||
<rect x="36" y="392" width="928" height="30" rx="6" fill="#0F1420"/>
|
||||
<text x="500" y="411" text-anchor="middle" font-family="'SF Mono',Menlo,monospace" font-size="10.5" fill="#DCE3F0">过程在后端,呈现在 web · 内容归活动,笼子归系统 · 放行是草稿态与事实态之间的门</text>
|
||||
</svg>
|
||||
</div>
|
||||
|
||||
<!-- ========== 01 ========== -->
|
||||
<h2 class="ch"><span class="n">01</span>契约:活动的接口</h2>
|
||||
<div class="ch-rule"></div>
|
||||
|
||||
<p class="lead">契约是活动对调用方暴露的<b>全部真相</b>,也是对 Agent 机制的全部授权;两种范式同一契约格式——这是「统一套执行契约」的锚点。契约必须在活动启动前冻结;运行中不得变更——变更即新版本。</p>
|
||||
|
||||
<div class="tbl"><table>
|
||||
<tr><th style="width:120px">契约构成</th><th>内容</th><th style="width:230px">要求</th></tr>
|
||||
<tr><td><b>输入口</b></td><td>单一入口:<b>data</b>(结构化载荷,按 schema)+ <b>message</b>(委托消息,自然语言)(1.1)</td><td>data 必须机器可校验,缺项不得启动;message 可为空</td></tr>
|
||||
<tr><td><b>输出口</b></td><td>必发口(完成必发,可多口 → 并行)+ 选择组(恰发一口 → 分支),每口各带交付物 schema(1.2)</td><td>调用方仅凭口名与 schema 即可衔接下游</td></tr>
|
||||
<tr><td><b>必交付物</b></td><td>放行前必须齐备的产出清单——放行卡「成果清单」的来源(06)</td><td>缺一不得提交放行</td></tr>
|
||||
<tr><td><b>禁区</b></td><td>不得做什么的负面清单</td><td>应短而硬;负面清单优于正面枚举</td></tr>
|
||||
<tr><td><b>验收判据</b></td><td>什么算合格,逐条标注验证等级 L1–L5(10);loop 可引用业务模型的完成判据与 DMN 规则(03)</td><td>两个陌生人对同一产出应给出相同判定</td></tr>
|
||||
<tr><td><b>授权边界</b></td><td>AI 可自决的范围(金额、折扣、措辞等);预授权动作清单;调人预算(打扰上限)</td><td>超出边界必须调「人·决策」;预授权必须显式列举</td></tr>
|
||||
<tr><td><b>资源声明</b></td><td>工具调用契约引用、技能引用、业务模型引用、角色,与预算上限(步数 / token / 时长 / 调人次数)</td><td>装配不齐不得启动;预算触顶即熔断(10)</td></tr>
|
||||
</table></div>
|
||||
|
||||
<h3 class="h3"><span class="n">1.1</span>输入:单一入口,data + message</h3>
|
||||
<p>活动必须只声明<b>一个输入口</b>;一单任务恰接收一份输入。输入由两部分构成:</p>
|
||||
<ul class="tight">
|
||||
<li><b>data(结构化载荷)</b>——按契约 input schema 校验,缺项不得启动。这是流程层能静态检查的拼接面:上游输出口的 schema 对得上,活动就接得住。</li>
|
||||
<li><b>message(委托消息)</b>——调用方附带的自然语言说明:意图、背景、特殊要求;可为空。message 计入 Agent 机制的初始观察、全程留痕;它往往承载「这一单的特殊性」。</li>
|
||||
</ul>
|
||||
<div class="callout warn"><b>message 是输入,不是改约:</b>message 不得携带扩大授权的效力——与契约冲突时,契约优先。AI 依 message 调整的只能是路径与语境;禁区、授权边界与验收判据不因 message 而变。</div>
|
||||
<p class="small">设计依据:schema 承载可结构化的确定,message 承载不可结构化的语境;两者合一,活动才既可静态编排、又不失临场委托——如同工单之于表格与备注栏。</p>
|
||||
|
||||
<h3 class="h3"><span class="n">1.2</span>输出口:必发(并行)与选择(分支)</h3>
|
||||
<p>活动的业务产出经<b>输出口</b>交回调用方。契约声明一组输出口,每口:口名 + 交付物 schema + 发射语义。发射语义两类:</p>
|
||||
<div class="tbl"><table>
|
||||
<tr><th style="width:150px">发射语义</th><th>规则</th><th style="width:230px">流程层用途</th></tr>
|
||||
<tr><td><b>必发口(AND)</b></td><td>每次「放行完成」必发;可声明多口,同时发射,各携各的载荷</td><td>并行衔接:多个下游各取所需</td></tr>
|
||||
<tr><td><b>选择组(XOR)</b></td><td>组内恰发一口;选择由环内决断,<b>在放行卡上随放行一并确认</b>(06)</td><td>分支路由:调用方据口名分流</td></tr>
|
||||
</table></div>
|
||||
<p>完成时的发射集合 = 全部必发口 + 每个选择组各一口;每口载荷各过其 schema 与验收判据;<b>发射发生在放行通过且落地收敛之后</b>(06)。非完成终态(受阻 / 熔断 / 耗尽 / 被终止)不发任何业务口,走<b>异常出口</b>(阻因 + 残局快照)。</p>
|
||||
<div class="callout danger"><b>业务分支走输出口,运行异常走终态。</b>「审核拒绝」是业务结局,必须建模为选择组的一口、随放行发射——不得用「受阻」等异常终态编码业务分支;反之,预算耗尽不是业务结局,不得伪装成输出口。终态描述「这次运行怎么收场」,输出口描述「产出流向哪里」。</div>
|
||||
|
||||
<h3 class="h3"><span class="n">1.3</span>终态</h3>
|
||||
<p>终态是<b>契约层的收场名</b>,封闭<b>五名</b>——终态由系统裁定,权威名录见《操作系统》4.3;范式内的状态映射见 04(loop)与 05(flow):</p>
|
||||
<div class="tbl"><table>
|
||||
<tr><th style="width:130px">终态</th><th>语义</th><th style="width:270px">交回调用方的载荷</th></tr>
|
||||
<tr><td><b>放行完成</b></td><td>唯一成功终态:放行通过<b>且落地收敛</b>,输出口已发射(06)</td><td>发射集合(必发口 + 选中口)+ 各口载荷 + 放行记录</td></tr>
|
||||
<tr><td><b>受阻待人</b></td><td>无法推进(监听时限走完 / 断点无解),封卷待治理处置:改派后恢复 / 重开新实例 / 终止</td><td>阻因 + 当前残局快照</td></tr>
|
||||
<tr><td><b>停滞熔断</b></td><td>连续无进展,Harness 强制止损;不可恢复</td><td>停滞证据 + 残局快照</td></tr>
|
||||
<tr><td><b>预算耗尽</b></td><td>任一预算上限触顶;不可恢复</td><td>消耗清单 + 残局快照</td></tr>
|
||||
<tr><td><b>被终止</b></td><td>控制事件 · 终止(负责人 / 治理台;含工作流终止的级联)</td><td>终止原因 + 残局快照</td></tr>
|
||||
</table></div>
|
||||
<p class="small">不是终态:<b>驳回</b>(重做 / 迭代)是放行卡的环内回转——携意见回环,任务继续,不出活动;<b>叫停</b>是控制事件(10)——转挂起待纠偏,处置后恢复,或由负责人终止(→ 被终止),叫停必留痕为最重档纠正信号;<b>落地受阻</b>是运行态——落地失败卡(执行卡的系统预置形态)处置后仍收敛于本名录(06)。</p>
|
||||
<div class="callout brand"><b>接口最小性:</b>调用方与活动之间只有三样东西过界——启动时的<b>输入(data + message)</b>、结束时的<b>终态与输出口载荷</b>、运行中的<b>状态投影(只读)</b>。调用方不得干预环内路径;环不得感知流程拓扑。活动之于流程包,如函数定义之于调用点;任务之于工作流,如一次调用之于一次执行。</div>
|
||||
|
||||
<!-- ========== 02 ========== -->
|
||||
<h2 class="ch"><span class="n">02</span>范式:loop 与 flow</h2>
|
||||
<div class="ch-rule"></div>
|
||||
|
||||
<p class="lead">Agent 机制的范式,规范名两种:<b>loop / flow</b>。范式回答一个问题——<b>这件事的下一步由谁定</b>:</p>
|
||||
<div class="tbl"><table>
|
||||
<tr><th style="width:80px">范式</th><th style="width:130px">活动</th><th>机制</th><th style="width:220px">业务模型</th><th style="width:80px">调度权</th></tr>
|
||||
<tr><td><b>loop</b></td><td>案例活动(Case)</td><td><b>临场演绎</b>:在业务模型给出的结构上感知、决断、行动,循环推进直到判据收敛</td><td>CMMN + DMN 案例模型:事理、前提、判据与可计算判断(03)</td><td><b>AI</b></td></tr>
|
||||
<tr><td><b>flow</b></td><td>标准活动</td><td><b>照谱执行</b>:按声明步序确定推进,零临场调度</td><td>步序声明(05)</td><td><b>系统</b></td></tr>
|
||||
</table></div>
|
||||
|
||||
<div class="callout brand"><b>范式的边界即调度权的边界。</b>一个活动选 flow 还是 loop,本质就是把这件事的调度权交给系统还是交给 AI——确定交系统,临场交 AI,落地交人;无论谁调度,放行权都不移交。放行、留痕、记忆、事件、卡片协议对两范式完全一致(00)。</div>
|
||||
|
||||
<h3 class="h3"><span class="n">2.1</span>选型判据</h3>
|
||||
<div class="tbl"><table>
|
||||
<tr><th style="width:90px">选</th><th>判据</th><th>典型</th></tr>
|
||||
<tr><td><b>flow</b></td><td>路径可枚举且稳定:全部步骤能写成序列,条件能写成任务数据上的确定性谓词,无临场裁量点</td><td>对账、开票、资料归集、例行巡检</td></tr>
|
||||
<tr><td><b>loop</b></td><td>路径须临场:判断、协作、创造类工作,对手方与信息不确定,每单走法不同——但事理可建模(前提、判据、量的推导)</td><td>报价谈判、异常处理、方案撰写、客诉处置</td></tr>
|
||||
</table></div>
|
||||
<ul class="tight">
|
||||
<li><b>两种都是合法终身形态</b>——不设"必然结晶"论:标准活动不是案例活动的归宿,案例活动也不是标准活动的过渡;选哪种由事的性质决定,不由方法论偏好决定。</li>
|
||||
<li><b>一处装不下就用 loop</b>——flow 里只要出现一处"由 AI 决定怎么办",这个活动就不该是 flow(05 的上升规则);反之,loop 中反复走出的确定子序列以技能的结晶片段脚本承载(08),不必改范式。</li>
|
||||
<li><b>改选范式即新版本</b>——范式随活动包版本声明;改范式经活动库安装两审(11),在途任务按其启动版本跑完。</li>
|
||||
</ul>
|
||||
<p class="small">术语约定:flow 是活动内部的步序范式(方法级,中途无责任交接),与流程层的「工作流」(流程包的运行时实例,责任级编排:节点有负责人、有审批点)不同层。本卷以中文「流程包 / 工作流」专指流程层,以英文小写 loop / flow 专指活动范式。</p>
|
||||
|
||||
<h3 class="h3"><span class="n">2.2</span>活动的内容物</h3>
|
||||
<p>无论哪种范式,活动的内容物同一清单——全部随活动定义与交付,跑在基座之上:</p>
|
||||
<ul class="tight">
|
||||
<li><b>业务模型</b>——这件事的结构,按范式取形(上表);业务模型是活动记忆优化的对象——迭代业务模型,就是迭代这个活动的行为(09)。</li>
|
||||
<li><b>交互内容</b>——何时调人、卡里给什么、视图区呈现什么、汇报怎么组织(07)。</li>
|
||||
<li><b>技能清单</b>——基于工具、在活动内定义的方法经验;载方法,不载权力(08)。</li>
|
||||
<li><b>Harness</b>——停止条件、预算与熔断、监听时限、中断与恢复(10);Harness 在活动内,每个活动的确定性边界随活动交付,不依赖外部编排兜底。</li>
|
||||
<li><b>过程工作区(可选)</b>——台账的任务级草稿层,组织由活动自设,不绑范式;写即持久,放行前不落事实(10)。</li>
|
||||
</ul>
|
||||
|
||||
<!-- ========== 03 ========== -->
|
||||
<h2 class="ch"><span class="n">03</span>loop · 业务模型:CMMN + DMN</h2>
|
||||
<div class="ch-rule"></div>
|
||||
|
||||
<p class="lead">技能承载「怎么做」(方法),业务模型承载「这件事是什么、什么决定什么」(事理)。loop 活动的业务模型是<b>案例模型</b>,格式为 <b>CMMN</b>(配套 <b>DMN</b> 承载量与推导)——选共识标准而非私有格式:LLM 天然读写,XML 可校验、可 diff、可版本。案例模型是<b>运行时的权威结构</b>:装载即结构——阶段怎么展开、前提何时满足、计划项处于何态,由语义引擎按 CMMN 规范对着这份 XML 忠实推进(04);AI 坐案例工作者的座位——感知、规划、汇报按任务数据 / 阶段 / 里程碑组织;<b>人给这个座位建的模型,AI 继承</b>。</p>
|
||||
|
||||
<h3 class="h3"><span class="n">3.1</span>构件语义</h3>
|
||||
<div class="tbl"><table>
|
||||
<tr><th style="width:200px">CMMN 构件</th><th>在本卷中承载</th></tr>
|
||||
<tr><td><b>CaseFile / Items</b></td><td><b>任务数据</b>:自持台账与共享对象的映射——事的数据中心;运行中的写入落<b>任务级草稿层</b>(读己之写),放行时合并正式版;正式版写入(系统写与放行写)即<b>数据事件</b>,按统一事件标准抛回活动(04)。</td></tr>
|
||||
<tr><td><b>Stage</b></td><td><b>阶段</b>:生命周期的分组结构(展开即 create 子项)与叙事骨架;多 onPart 汇合即回齐(04)。</td></tr>
|
||||
<tr><td><b>Task + Discretionary</b></td><td><b>合法动作空间</b>:计划项对应工具 / 技能 / 调人;非裁量项由前提推到 Enabled,裁量项从 planning table 由 Agent 临场规划入场;<b>触达世界与关键交付者必须 manualActivationRule = true</b>(04)。</td></tr>
|
||||
<tr><td><b>Milestone</b></td><td><b>里程碑</b>:业务阶段的命名达成——occur 即迁移事件留痕;既是视图与汇报的投影定义源(07),也可被其他前提监听、参与前推(04)。</td></tr>
|
||||
<tr><td><b>EntryCriterion(前提)</b></td><td><b>前提与因果</b>:「先什么后什么」——onPart + ifPart,由语义引擎按规范求值:满足即 Enabled;语义性前提交 Agent 评估(04);L2 机检规则的来源之一(10)。</td></tr>
|
||||
<tr><td><b>ExitCriterion(完成判据)</b></td><td>计划项的 complete / exit 条件;接契约验收判据与放行卡的成果清单。</td></tr>
|
||||
<tr><td><b>Role</b></td><td>岗位绑定:调人时卡投递到哪个工位。</td></tr>
|
||||
<tr><td><b>DecisionTask → DMN</b></td><td><b>量与推导</b>:决策需求图(DRD)即依赖图,决策表(FEEL)承载可计算推导与规则(3.3)。</td></tr>
|
||||
</table></div>
|
||||
|
||||
<p><b>双表示,同版本</b>:<b>CMMN XML</b> 是机器面——语义引擎以它为运行结构:推进生命周期、求值前提、维护 Enabled 集;<b>案例说明书</b>是叙事面——Agent 读它理解业务、组织汇报、向人解释,渐进披露(常驻梗概,按事下钻)。两面同版本发布,不允许分叉:说明书是 XML 的叙事投影,迭代时一起放行。</p>
|
||||
|
||||
<h3 class="h3"><span class="n">3.2</span>三铁律与约束力收缩</h3>
|
||||
<ul class="tight">
|
||||
<li><b>语义归引擎,裁量归 Agent,强制归门(必须)</b>——CMMN 语义由引擎忠实执行:前提满足即 Enabled,这是规范而非越权;manual 项的启动永远归 Agent;强制力只在验收分级与放行处生效(门 = 放行卡与判据,06 / 10)。引擎只推规范、不代裁量、不代把关。</li>
|
||||
<li><b>载事理,不载权力(必须)</b>——白名单、授权边界与禁区在契约;案例模型不得扩大它们。</li>
|
||||
<li><b>叙事框架(应)</b>——AI 的规划与汇报、视图区的呈现结构,应以案例模型的阶段与里程碑组织(07)。</li>
|
||||
</ul>
|
||||
<p><b>约束力收缩机制</b>:纠正与驳回的理由,蒸馏入<b>活动记忆 · 裁决层</b>(09),归纳为候选前提条件 / 完成判据 / DMN 规则 → 回放检验(历史成功单皆满足、失败单恰被拦)→ 人放行 → 入案例模型新版本 → 从此由 L2 机检承担。<b>每挨一次纠正,约束就有机会从人的判断收缩为机器的校验</b>——纠正的减少因此有了因果机制,不只是统计现象。</p>
|
||||
|
||||
<h3 class="h3"><span class="n">3.3</span>DMN:判断的确定性化</h3>
|
||||
<p>DMN 承担一件事:<b>把装得下的判断从 LLM 手里拿走</b>。DRD 声明「定什么需要知道什么」,决策表(FEEL)声明「知道了怎么定」——两者合起来,判断成为确定性求值:</p>
|
||||
<ul class="tight">
|
||||
<li><b>能算的不问 LLM(必须)</b>——输入齐备的决策表由语义引擎确定性求值;同输入必同结论,零方差、零 token。</li>
|
||||
<li><b>DRD 即缺口演绎(应)</b>——输入不齐时,DRD 指出缺什么:可查的调工具、可算的先算上游决策、只有人知道的调人、在世界侧的立监听——双向驱动的后拉遍历(04),主要就是走 DRD。</li>
|
||||
<li><b>决策留痕(必须)</b>——每次求值留痕:输入快照 + 决策表版本 + 命中规则行;决策可回放、可归因。</li>
|
||||
<li><b>结论不可静默覆写(必须)</b>——DMN 结论对 Agent 是约束性输入;认为结论不合理时只有两条路:超出授权的走「人·决策」,规则本身有病的提迭代提案(09)——不允许 LLM 悄悄绕开确定性结论。</li>
|
||||
</ul>
|
||||
<div class="callout brand"><b>智能的分工线:</b>DMN 装得下的,是已经被组织想清楚的判断——确定性执行;LLM 负责的,是 DMN 还装不下的判断——临场推理。<b>迭代的方向是把后者不断搬进前者</b>:每一条从纠正中蒸馏出的决策规则,都是一块从「临场」搬进「确定」的判断。</div>
|
||||
|
||||
<h3 class="h3"><span class="n">3.4</span>装载:一单任务开始时引擎读什么</h3>
|
||||
<div class="tbl"><table>
|
||||
<tr><th style="width:170px">装载件</th><th style="width:180px">来源</th><th>进哪里</th></tr>
|
||||
<tr><td><b>契约</b></td><td>活动包(冻结)</td><td>目标与授权:输入 / 输出口 / 禁区 / 验收判据 / 预算</td></tr>
|
||||
<tr><td><b>案例模型 · XML</b></td><td>活动库(版本)</td><td><b>语义引擎</b>:运行结构本体——生命周期 · 前提 · 判据 · 里程碑</td></tr>
|
||||
<tr><td><b>案例模型 · 说明书</b></td><td>活动库(同版本)</td><td><b>Agent 上下文</b>:叙事面,渐进披露</td></tr>
|
||||
<tr><td><b>DMN(DRD + 决策表)</b></td><td>活动库(版本)</td><td>语义引擎(确定性求值)+ Agent(依赖演绎的参照)</td></tr>
|
||||
<tr><td><b>技能目录</b></td><td>活动库(技能引用)</td><td>Agent:适用描述索引,按事装配正文与脚本(08)</td></tr>
|
||||
<tr><td><b>活动记忆(选摘)</b></td><td>基座 · 记忆库</td><td><b>Agent 上下文</b>:按模型定位选摘持久事实,渐进披露(09);语义引擎不读</td></tr>
|
||||
<tr><td><b>任务数据映射</b></td><td>契约数据声明</td><td>CaseFileItem ↔ 台账与共享对象——模型的数据脚落到真实存储</td></tr>
|
||||
</table></div>
|
||||
<p class="small">版本全部记入信封——从此每一步的行为可完全归因(09 行为可归因公式)。</p>
|
||||
|
||||
<!-- ========== 04 ========== -->
|
||||
<h2 class="ch"><span class="n">04</span>loop · 运行机制</h2>
|
||||
<div class="ch-rule"></div>
|
||||
|
||||
<p class="lead">loop 的运行 = <b>CMMN 语义引擎(下层,零 LLM)× Agent 回路(上层,临场裁量)</b>。状态的权威是 CMMN 规范的标准生命周期:活动不定义状态,模型不发明状态——装载哪个模型,状态空间就是规范为那类计划项规定的那一副;引擎按规范推进,守卫(时限 / 预算 / 预授权 / 监听)仅可参数化。</p>
|
||||
|
||||
<h3 class="h3"><span class="n">4.1</span>生命周期:CMMN 标准</h3>
|
||||
<div class="tbl"><table>
|
||||
<tr><th style="width:150px">案计划(整案)五态</th><th>语义</th></tr>
|
||||
<tr><td><b>Active</b></td><td>运行中:创建即入,整案唯一的做功状态。</td></tr>
|
||||
<tr><td><b>Completed</b></td><td>完成:必要计划项全部收敛,<b>放行通过且落地收敛</b>——判据全绿不等于完成(06 / 10)。</td></tr>
|
||||
<tr><td><b>Suspended</b></td><td>挂起:受阻待组织处置(时限走完 / 断点无解),或叫停后待纠偏;可恢复——恢复由事件驱动(人事件 / 数据事件 / 时间事件 / 控制事件)。</td></tr>
|
||||
<tr><td><b>Terminated</b></td><td>终止:停滞熔断 / 预算耗尽 / 被终止(控制事件 · 终止,含工作流级联);携原因码交回调用方,不可恢复。</td></tr>
|
||||
<tr><td><b>Failed</b></td><td>失败:运行异常;由人恢复重跑或转终止。</td></tr>
|
||||
</table></div>
|
||||
<div class="tbl"><table>
|
||||
<tr><th style="width:150px">计划项八态</th><th>语义</th></tr>
|
||||
<tr><td><b>Available</b></td><td>已随阶段入场,entry 前提未满足。</td></tr>
|
||||
<tr><td><b>Enabled</b></td><td>前提满足、manualActivationRule = true:<b>可启动而未启动</b>——引擎推进的终点,Agent 裁量的起点。</td></tr>
|
||||
<tr><td><b>Disabled</b></td><td>Agent 规划裁量弃用(此单不走这条);可 reenable。</td></tr>
|
||||
<tr><td><b>Active</b></td><td>执行中:Agent 启动(manualStart),或纯机内项自动启动(start)。</td></tr>
|
||||
<tr><td><b>Suspended</b></td><td>挂起(Harness / 叫停 / 随父级);恢复由事件驱动。</td></tr>
|
||||
<tr><td><b>Failed</b></td><td>执行异常;是否重跑由人裁定。</td></tr>
|
||||
<tr><td><b>Completed</b></td><td>完成:exit 判据满足;关键交付项的完成经验收分级与放行(10 / 06)。</td></tr>
|
||||
<tr><td><b>Terminated</b></td><td>终止:exit 前提触发退出,或随父级级联终止。</td></tr>
|
||||
</table></div>
|
||||
<p class="small">里程碑与事件监听器只有一条主迁移:<b>Available →(occur)→ Completed</b>——前提满足 / 件到 / 到点即达成留痕;里程碑达成本身是迁移事件,可被其他前提监听——里程碑因此参与前推(4.3),不只是投影。契约终态(01)的映射:放行完成 = 案计划 Completed(放行通过且落地收敛);受阻待人 = Suspended + 阻因,封卷待治理处置(改派后恢复 / 重开新实例 / 终止);停滞熔断 · 预算耗尽 = Terminated + 原因码;被终止 = Terminated(控制事件 · 终止,含工作流级联);Failed 是规范补齐的运行异常格,与业务终态分开;驳回是迁移不是状态——相关计划项重新入场(repetitionRule 新实例),记为纠正信号。</p>
|
||||
|
||||
<ul class="tight">
|
||||
<li><b>原理一 · Enabled ≠ Active(必须)</b>——「就绪 ≠ 执行」的 CMMN 原生形:引擎按规范推进到 <b>Enabled</b>(可启动)为止;凡触达世界或产出关键交付的计划项必须 <b>manualActivationRule = true</b>,进入 <b>Active</b>(执行)永远出自 Agent 的裁量启动(manualStart,留痕);automatic 仅限纯机内项(只读 / 纯计算)。规范推进不是执行,启动才是执行。</li>
|
||||
<li><b>语义忠实(必须)</b>——生命周期与前提语义严格循 CMMN 规范;引擎不得私改迁移拓扑,活动与模型不得发明状态。</li>
|
||||
<li><b>迁移必留痕(必须)</b>——每次生命周期迁移记入任务记忆:触发者 · 依据(前提 / 裁量 / 放行 / Harness)。</li>
|
||||
<li><b>终局唯放行与 Harness(必须)</b>——案计划 Completed 必经放行卡;Terminated 只出自 Harness 与负责人;AI 不得产生终局迁移。</li>
|
||||
</ul>
|
||||
<div class="callout brand"><b>投影随语义走。</b>调用方与流程层看到的任务状态 = <b>案计划状态 + 原因码</b>的只读投影;业务进展(「报价已发」「等客户确认」)= 里程碑与任务数据的投影,由语义引擎按模型维护、经视图流控呈现(07)。并行支线即多个 Active 的阶段,各持各的计划项状态——聚合语义就是 CMMN 的父子级联本身,不另设规则。</div>
|
||||
|
||||
<h3 class="h3"><span class="n">4.2</span>语义引擎 × Agent 回路</h3>
|
||||
<p>两层的耦合点是<b>任务数据与记忆</b>:任务数据是驱动耦合——Agent 写数据(落任务级草稿层,读己之写),引擎对本任务的前提求值读<b>任务视图 = 正式版 + 本任务草稿层</b>,不依赖事件;跨任务监听只认放行后的正式版事件;任务记忆是记录同轴——引擎的每次迁移与求值、Agent 的每个决断,同轴记入(09)。引擎向上发布 <b>Enabled 集</b>与红绿灯,Agent 向下启动计划项、写任务数据。每一步行动属于且仅属于三型之一:<b>调工具</b>(系统调用与 LLM 工具)、<b>调人</b>(四卡之一,06)、<b>立监听</b>(AI 不能调用世界,对世界只有两种合法姿势:触达它——动作,落在放行;等它——监听,4.4)。</p>
|
||||
|
||||
<div class="tbl"><table>
|
||||
<tr><th style="width:150px">语义引擎(下层)</th><th>内容</th></tr>
|
||||
<tr><td><b>生命周期推进</b></td><td>按 CMMN 规范维护案计划与全部计划项的迁移(4.1)——迁移即事件、事件必留痕;装载的 XML 就是运行结构,引擎不得私改。</td></tr>
|
||||
<tr><td><b>前提求值</b></td><td>onPart 听任务数据变化(环内 = 任务视图的写入;环外回音 = 归属解析后的正式版数据事件)与计划项迁移,ifPart 对<b>任务视图</b>确定性求值:entry 满足 → Enabled;exit 满足 → 完成 / 退出。语义性 ifPart(不可机算的前提)标记「待裁量评估」,交上层。</td></tr>
|
||||
<tr><td><b>DMN 求值</b></td><td>DecisionTask 与判据引用的决策表,输入齐备即确定性求值,结论与命中规则行留痕(03)。</td></tr>
|
||||
<tr><td><b>判据预检</b></td><td>完成判据与验收判据的 L1 / L2 部分持续预检,红绿灯挂在 Enabled 集旁——Agent 与视图区随时可见「还差什么」。</td></tr>
|
||||
<tr><td><b>Enabled 集发布</b></td><td>当下可启动的计划项(含 planning table 上可规划的裁量候选)· 目标缺口(未绿的判据 / 未达的里程碑)· 阶段位置;发布给 Agent 回路与视图流控(07)。</td></tr>
|
||||
</table></div>
|
||||
|
||||
<ol class="steps">
|
||||
<li><b>定位</b>——案计划走到哪里:Active 的阶段、Enabled 集、里程碑与判据的红绿灯。</li>
|
||||
<li><b>择向</b>——判据后拉:目标还缺什么;前提前推:当下能启动什么;取交集(4.3)。</li>
|
||||
<li><b>决断</b>——在交集中定夺:manualStart 某个 Enabled 项(启动留痕)/ 从 planning table 规划裁量项入场 / 评估语义性前提(评估留痕,可回放可归因)/ disable 弃用某项——或判定成果已齐,提交放行(06)。</li>
|
||||
<li><b>行动</b>——执行 Active 的任务:装配技能、调工具、调人;一切能力经调用契约,触达外部世界的动作集中在放行时落地;预算由 Harness 扣减(10)。</li>
|
||||
<li><b>写数据</b>——产出落为任务数据写入:<b>任务级草稿层</b>(读己之写,不抛事件,10),过程同轴入任务记忆;引擎对任务视图求值前提、按规范推进,回到定位。</li>
|
||||
</ol>
|
||||
|
||||
<div class="fig">
|
||||
<div class="figcap"><span>FIG-02 · loop 引擎总图</span><span>装载 → 语义引擎(Enabled 集) × Agent 回路 → 能力与门 → 放行落地 · 事件驱动</span></div>
|
||||
<svg viewBox="0 0 1000 500" role="img" aria-label="loop 引擎总图:契约、案例模型、DMN、技能、活动记忆、任务数据映射装载入引擎;下层 CMMN 语义引擎零 LLM 按规范推进并发布 Enabled 集,上层 Agent 回路定位择向决断行动写数据;能力经调用契约,成果经放行卡落到事实态;统一事件驱动推进">
|
||||
<style>
|
||||
.al-t{font-family:'PingFang SC','Noto Sans SC',sans-serif;font-size:10.5px;font-weight:600;fill:#1F2933}
|
||||
.al-c{font-family:'PingFang SC','Noto Sans SC',sans-serif;font-size:10px;fill:#3A4452}
|
||||
.al-m{font-family:'SF Mono',Menlo,monospace;font-size:10px;font-weight:600;letter-spacing:.12em;fill:#6A7686}
|
||||
.al-s{font-family:'PingFang SC','Noto Sans SC',sans-serif;font-size:8.5px;fill:#6A7686}
|
||||
</style>
|
||||
<defs>
|
||||
<marker id="alS" markerWidth="9" markerHeight="9" refX="7.5" refY="4.5" orient="auto"><path d="M0,0 L9,4.5 L0,9 Z" fill="#46586A"/></marker>
|
||||
<marker id="alB" markerWidth="9" markerHeight="9" refX="7.5" refY="4.5" orient="auto"><path d="M0,0 L9,4.5 L0,9 Z" fill="#B07D2B"/></marker>
|
||||
<marker id="alH" markerWidth="9" markerHeight="9" refX="7.5" refY="4.5" orient="auto"><path d="M0,0 L9,4.5 L0,9 Z" fill="#2F6DB5"/></marker>
|
||||
</defs>
|
||||
|
||||
<text x="36" y="30" class="al-m">装载 · 版本入信封</text>
|
||||
<rect x="36" y="40" width="180" height="272" rx="10" fill="#FFFFFF" stroke="#46586A" stroke-width="1.4"/>
|
||||
<rect x="52" y="56" width="148" height="30" rx="7" fill="#DCEAF7" stroke="#2F6DB5" stroke-width="1.2"/>
|
||||
<text x="126" y="75" text-anchor="middle" class="al-s" font-weight="600" fill="#173A63">契约(冻结)</text>
|
||||
<rect x="52" y="94" width="148" height="38" rx="7" fill="#F7F0E0" stroke="#B07D2B" stroke-width="1.2"/>
|
||||
<text x="126" y="109" text-anchor="middle" class="al-s" font-weight="600" fill="#8A5F1C">案例模型 CMMN</text>
|
||||
<text x="126" y="124" text-anchor="middle" class="al-s">XML + 说明书(同版本)</text>
|
||||
<rect x="52" y="140" width="148" height="30" rx="7" fill="#F7F0E0" stroke="#B07D2B" stroke-width="1.2"/>
|
||||
<text x="126" y="159" text-anchor="middle" class="al-s" font-weight="600" fill="#8A5F1C">DMN(DRD + 决策表)</text>
|
||||
<rect x="52" y="178" width="148" height="30" rx="7" fill="#F7F0E0" stroke="#B07D2B" stroke-width="1.2"/>
|
||||
<text x="126" y="197" text-anchor="middle" class="al-s" font-weight="600" fill="#8A5F1C">技能目录</text>
|
||||
<rect x="52" y="216" width="148" height="30" rx="7" fill="#F7F0E0" stroke="#B07D2B" stroke-width="1.2"/>
|
||||
<text x="126" y="235" text-anchor="middle" class="al-s" font-weight="600" fill="#8A5F1C">活动记忆 · 选摘</text>
|
||||
<rect x="52" y="254" width="148" height="30" rx="7" fill="#F5F6F7" stroke="#C6D0DA" stroke-width="1.2"/>
|
||||
<text x="126" y="273" text-anchor="middle" class="al-s" font-weight="600" fill="#46586A">任务数据映射</text>
|
||||
<text x="52" y="300" class="al-s">七件之要:结构进引擎,叙事进上下文</text>
|
||||
<path d="M216,180 H250" fill="none" stroke="#46586A" stroke-width="1.5" marker-end="url(#alS)"/>
|
||||
|
||||
<rect x="254" y="40" width="420" height="170" rx="10" fill="#FCFAF3" stroke="#B07D2B" stroke-width="1.5"/>
|
||||
<text x="270" y="64" class="al-t" fill="#8A5F1C">Agent 回路(上层)· 调度权归 AI</text>
|
||||
<rect x="270" y="78" width="68" height="26" rx="13" fill="#F7F0E0" stroke="#B07D2B"/><text x="304" y="95" text-anchor="middle" class="al-s" font-weight="600" fill="#8A5F1C">定位</text>
|
||||
<path d="M338,91 H348" stroke="#B07D2B" stroke-width="1.2" marker-end="url(#alB)"/>
|
||||
<rect x="352" y="78" width="68" height="26" rx="13" fill="#F7F0E0" stroke="#B07D2B"/><text x="386" y="95" text-anchor="middle" class="al-s" font-weight="600" fill="#8A5F1C">择向</text>
|
||||
<path d="M420,91 H430" stroke="#B07D2B" stroke-width="1.2" marker-end="url(#alB)"/>
|
||||
<rect x="434" y="78" width="68" height="26" rx="13" fill="#F7F0E0" stroke="#B07D2B"/><text x="468" y="95" text-anchor="middle" class="al-s" font-weight="600" fill="#8A5F1C">决断</text>
|
||||
<path d="M502,91 H512" stroke="#B07D2B" stroke-width="1.2" marker-end="url(#alB)"/>
|
||||
<rect x="516" y="78" width="68" height="26" rx="13" fill="#F7F0E0" stroke="#B07D2B"/><text x="550" y="95" text-anchor="middle" class="al-s" font-weight="600" fill="#8A5F1C">行动</text>
|
||||
<path d="M584,91 H594" stroke="#B07D2B" stroke-width="1.2" marker-end="url(#alB)"/>
|
||||
<rect x="598" y="78" width="60" height="26" rx="13" fill="#F7F0E0" stroke="#B07D2B"/><text x="628" y="95" text-anchor="middle" class="al-s" font-weight="600" fill="#8A5F1C">写数据</text>
|
||||
<text x="270" y="132" class="al-s">manualStart · 语义前提评估 · 技能装配 · 调人 / 立监听 —— 决断留痕</text>
|
||||
<text x="270" y="152" class="al-s">上下文:说明书 + 活动记忆选摘 + 任务记忆窗口</text>
|
||||
<text x="270" y="178" class="al-s" font-weight="600" fill="#8A5F1C">循环推进,直到判据收敛 → 提交放行</text>
|
||||
|
||||
<path d="M330,258 V214" fill="none" stroke="#46586A" stroke-width="1.5" marker-end="url(#alS)"/>
|
||||
<text x="344" y="240" class="al-s">发布 Enabled 集 + 红绿灯</text>
|
||||
<path d="M560,214 V258" fill="none" stroke="#B07D2B" stroke-width="1.5" marker-end="url(#alB)"/>
|
||||
<text x="574" y="240" class="al-s" fill="#8A5F1C">manualStart · 写任务数据</text>
|
||||
|
||||
<rect x="254" y="258" width="420" height="120" rx="10" fill="#FFFFFF" stroke="#161B22" stroke-width="1.5"/>
|
||||
<text x="270" y="282" class="al-t">CMMN 语义引擎(下层)· 零 LLM</text>
|
||||
<text x="270" y="304" class="al-s">生命周期推进 · 前提求值 · DMN 求值 · 判据预检</text>
|
||||
<text x="270" y="322" class="al-s">迁移即事件 · 求值留痕 —— 循规范,不代裁量、不代放行</text>
|
||||
<text x="270" y="344" class="al-s" font-weight="600" fill="#3A4452">数据 / 时间事件驱动推进;Enabled 集持续发布</text>
|
||||
|
||||
<text x="712" y="30" class="al-m">能力与门(经调用契约)</text>
|
||||
<rect x="712" y="40" width="252" height="44" rx="8" fill="#F5F6F7" stroke="#98A2B0" stroke-width="1.2"/>
|
||||
<text x="726" y="58" class="al-s" font-weight="600" fill="#3A4452">工具(调用契约)</text>
|
||||
<text x="726" y="74" class="al-s">系统调用 · LLM 工具 · 通道出站</text>
|
||||
<rect x="712" y="94" width="252" height="44" rx="8" fill="#DCEAF7" stroke="#2F6DB5" stroke-width="1.3"/>
|
||||
<text x="726" y="112" class="al-s" font-weight="600" fill="#173A63">人类工具四卡</text>
|
||||
<text x="726" y="128" class="al-s">决策 · 执行 · 补全 · 放行(06)</text>
|
||||
<rect x="712" y="148" width="252" height="44" rx="8" fill="#F5F6F7" stroke="#98A2B0" stroke-width="1.2"/>
|
||||
<text x="726" y="166" class="al-s" font-weight="600" fill="#3A4452">监听登记</text>
|
||||
<text x="726" y="182" class="al-s">静态(模型)+ 动态(临场)· 时限必配</text>
|
||||
<path d="M674,120 H708" fill="none" stroke="#B07D2B" stroke-width="1.5" marker-end="url(#alB)"/>
|
||||
|
||||
<path d="M838,192 V236" fill="none" stroke="#2F6DB5" stroke-width="1.5" marker-end="url(#alH)"/>
|
||||
<rect x="712" y="240" width="252" height="52" rx="8" fill="#DCEAF7" stroke="#2F6DB5" stroke-width="1.5"/>
|
||||
<text x="726" y="260" class="al-s" font-weight="600" fill="#173A63">放行卡 —— 成果清单 + 放行选择表</text>
|
||||
<text x="726" y="278" class="al-s" fill="#173A63">通过 / 驳回重做 / 驳回迭代(人)</text>
|
||||
<path d="M838,292 V316" fill="none" stroke="#2F6DB5" stroke-width="1.5" marker-end="url(#alH)"/>
|
||||
<rect x="712" y="320" width="252" height="52" rx="8" fill="#E8F8E4" stroke="#278717" stroke-width="1.4"/>
|
||||
<text x="726" y="340" class="al-s" font-weight="600" fill="#278717">事实态:台账 · 外部系统</text>
|
||||
<text x="726" y="358" class="al-s" fill="#2F5C45">放行前不落事实 —— 动作集中在放行时</text>
|
||||
|
||||
<rect x="36" y="340" width="180" height="56" rx="8" fill="#FAFBFC" stroke="#98A2B0" stroke-width="1.1" stroke-dasharray="5 3"/>
|
||||
<text x="52" y="360" class="al-s" font-weight="600" fill="#46586A">统一事件(系统投递)</text>
|
||||
<text x="52" y="378" class="al-s">数据 / 时间 / 人 / 控制</text>
|
||||
<path d="M216,368 H248" fill="none" stroke="#46586A" stroke-width="1.4" marker-end="url(#alS)"/>
|
||||
|
||||
<text x="36" y="430" class="al-s">两层耦合:任务数据 = 驱动耦合 · 任务记忆 = 记录同轴;Enabled ≠ Active —— 规范推进不是执行,启动才是执行</text>
|
||||
<rect x="36" y="444" width="928" height="30" rx="6" fill="#0F1420"/>
|
||||
<text x="500" y="463" text-anchor="middle" font-family="'SF Mono',Menlo,monospace" font-size="10.5" fill="#DCE3F0">行为 = 引擎(契约, 业务模型, 技能, 记忆) —— 引擎与基座不动,模型演进:迭代案例模型,就是迭代这个活动的行为</text>
|
||||
</svg>
|
||||
</div>
|
||||
|
||||
<h3 class="h3"><span class="n">4.3</span>双向驱动:开展与完成</h3>
|
||||
<p>任务如何被结构驱动着<b>开展</b>、又被结构收束着<b>完成</b>——答案是两股方向相反的力:</p>
|
||||
<ul class="tight">
|
||||
<li><b>前提前推(开展)</b>——写任务数据留痕(草稿层),语义按规范传播:任务视图变化 → 前提满足 → 新计划项 Enabled(里程碑 occur 亦是迁移,可再触发前提):可为空间像漏斗一样随进展展开。前推回答「<b>当下能启动什么</b>」。</li>
|
||||
<li><b>判据后拉(完成)</b>——完成判据与里程碑构成目标集;Agent 沿 DMN 依赖图(DRD)与前提依赖反向遍历:目标缺什么 → 缺口由什么推出 → 落到一个 Enabled 的计划项。后拉回答「<b>该启动什么</b>」。</li>
|
||||
</ul>
|
||||
<div class="callout brand"><b>导航即交集,断点即人环。</b>下一步 = 当下可为(Enabled 集)∩ 目标所需——两集有交,择优启动(技能引路);<b>交集为空即断点</b>:目标所需的缺口无法由任何 Enabled 项补足——这正是调人(缺口只有人知道 → 补全卡)或立监听(缺口在世界侧 → 前提与时间监听,从模型给出)的判定时机。<b>调人与监听的时机从「感觉」变成「依赖图上的断点」</b>——可留痕、可回放、可归因。</div>
|
||||
<p><b>完成的收束</b>:判据逐项转绿(L1 / L2 由语义引擎预检,L3 实证、L4 评审按分级执行,10)→ 全绿即提交放行(发卡前过落地预检,06),成果清单 = 判据逐条核对 + 生命周期快照(阶段与里程碑达成)+ 关键步引用 → 放行通过、落地收敛,案计划 Completed,发射输出口。<b>开展是 Enabled 空间的展开,完成是判据缺口的收敛</b>——一开一收,任务被结构从两端夹着走完。</p>
|
||||
|
||||
<div class="fig">
|
||||
<div class="figcap"><span>FIG-03 · 双向驱动</span><span>前提前推(当下可为) × 判据后拉(目标所需) → 交集导航 · 断点即人环</span></div>
|
||||
<svg viewBox="0 0 1000 400" role="img" aria-label="双向驱动:左侧前提前推把满足条件的计划项推入 Enabled,右侧完成判据与里程碑后拉出目标所需,Agent 取交集决定启动哪项,交集为空的断点即调人或立监听的判定点">
|
||||
<style>
|
||||
.ad-t{font-family:'PingFang SC','Noto Sans SC',sans-serif;font-size:10.5px;font-weight:600;fill:#1F2933}
|
||||
.ad-c{font-family:'PingFang SC','Noto Sans SC',sans-serif;font-size:10px;fill:#3A4452}
|
||||
.ad-m{font-family:'SF Mono',Menlo,monospace;font-size:10px;font-weight:600;letter-spacing:.12em;fill:#6A7686}
|
||||
.ad-s{font-family:'PingFang SC','Noto Sans SC',sans-serif;font-size:8.5px;fill:#6A7686}
|
||||
</style>
|
||||
<defs>
|
||||
<marker id="adS" markerWidth="9" markerHeight="9" refX="7.5" refY="4.5" orient="auto"><path d="M0,0 L9,4.5 L0,9 Z" fill="#46586A"/></marker>
|
||||
<marker id="adB" markerWidth="9" markerHeight="9" refX="7.5" refY="4.5" orient="auto"><path d="M0,0 L9,4.5 L0,9 Z" fill="#B07D2B"/></marker>
|
||||
<marker id="adG" markerWidth="9" markerHeight="9" refX="7.5" refY="4.5" orient="auto"><path d="M0,0 L9,4.5 L0,9 Z" fill="#2F5C45"/></marker>
|
||||
</defs>
|
||||
|
||||
<rect x="36" y="36" width="928" height="42" rx="9" fill="#E8F8E4" stroke="#bfedb4" stroke-width="1.3"/>
|
||||
<text x="56" y="62" class="ad-c" font-weight="600" fill="#278717">目标集:判据 A ✓ · 判据 B ✗ · 判据 C ✗ ‖ 里程碑 M1 ✓ · M2 ○ —— 由完成判据与里程碑构成,语义引擎持续预检</text>
|
||||
|
||||
<text x="36" y="116" class="ad-m" fill="#8A5F1C">前提前推 · 当下可为</text>
|
||||
<rect x="36" y="128" width="330" height="190" rx="10" fill="#FCFAF3" stroke="#B07D2B" stroke-width="1.3"/>
|
||||
<text x="52" y="152" class="ad-s">数据事件传播,前提满足即 Enabled:</text>
|
||||
<rect x="52" y="164" width="132" height="28" rx="7" fill="#F7F0E0" stroke="#B07D2B"/><text x="118" y="182" text-anchor="middle" class="ad-s" font-weight="600" fill="#8A5F1C">✓ 成本已核</text>
|
||||
<path d="M184,178 H208" stroke="#B07D2B" stroke-width="1.3" marker-end="url(#adB)"/>
|
||||
<rect x="211" y="164" width="132" height="28" rx="7" fill="#FFFFFF" stroke="#B07D2B" stroke-width="1.2"/><text x="277" y="182" text-anchor="middle" class="ad-s" font-weight="600" fill="#8A5F1C">Enabled:拟报价</text>
|
||||
<rect x="52" y="204" width="132" height="28" rx="7" fill="#F7F0E0" stroke="#B07D2B"/><text x="118" y="222" text-anchor="middle" class="ad-s" font-weight="600" fill="#8A5F1C">✓ 客户已识别</text>
|
||||
<path d="M184,218 H208" stroke="#B07D2B" stroke-width="1.3" marker-end="url(#adB)"/>
|
||||
<rect x="211" y="204" width="132" height="28" rx="7" fill="#FFFFFF" stroke="#B07D2B" stroke-width="1.2"/><text x="277" y="222" text-anchor="middle" class="ad-s" font-weight="600" fill="#8A5F1C">Enabled:查信用</text>
|
||||
<rect x="52" y="244" width="132" height="28" rx="7" fill="#F5F6F7" stroke="#C6D0DA"/><text x="118" y="262" text-anchor="middle" class="ad-s">Available:发报价</text>
|
||||
<text x="52" y="298" class="ad-s">可为空间随进展展开 —— 回答「当下能做什么」</text>
|
||||
|
||||
<text x="634" y="116" class="ad-m" fill="#2F5C45">判据后拉 · 目标所需</text>
|
||||
<rect x="634" y="128" width="330" height="190" rx="10" fill="#F6FBF5" stroke="#7FA98B" stroke-width="1.3"/>
|
||||
<text x="650" y="152" class="ad-s">沿 DRD 与前提依赖,自目标反向遍历:</text>
|
||||
<rect x="650" y="164" width="120" height="28" rx="7" fill="#E8F8E4" stroke="#2F5C45"/><text x="710" y="182" text-anchor="middle" class="ad-s" font-weight="600" fill="#2F5C45">判据 B:价格合规</text>
|
||||
<path d="M770,178 H794" stroke="#2F5C45" stroke-width="1.3" marker-end="url(#adG)"/>
|
||||
<rect x="797" y="164" width="150" height="28" rx="7" fill="#FFFFFF" stroke="#7FA98B"/><text x="872" y="182" text-anchor="middle" class="ad-s">需:报价额(DMN 可算)</text>
|
||||
<path d="M872,192 V204" stroke="#2F5C45" stroke-width="1.2" marker-end="url(#adG)"/>
|
||||
<rect x="797" y="206" width="150" height="28" rx="7" fill="#FFFFFF" stroke="#7FA98B"/><text x="872" y="224" text-anchor="middle" class="ad-s">需:付款条件 ← 客户信用</text>
|
||||
<path d="M795,224 C760,230 740,240 726,248" stroke="#8F3330" stroke-width="1.3" stroke-dasharray="4 3" marker-end="url(#adS)"/>
|
||||
<rect x="650" y="246" width="120" height="34" rx="7" fill="#FEEAE9" stroke="#f6c6c3"/><text x="710" y="261" text-anchor="middle" class="ad-s" font-weight="600" fill="#D83931">缺口:信用未知</text>
|
||||
<text x="710" y="274" text-anchor="middle" class="ad-s" fill="#8F3330">任何可为动作补不了</text>
|
||||
<text x="650" y="298" class="ad-s">目标缺什么、由什么推出 —— 回答「该做什么」</text>
|
||||
|
||||
<rect x="402" y="168" width="196" height="110" rx="12" fill="#F0F4FF" stroke="#C9D8F8" stroke-width="1.4"/>
|
||||
<text x="500" y="194" text-anchor="middle" class="ad-t" fill="#245BDB">Agent · 交集导航</text>
|
||||
<text x="500" y="218" text-anchor="middle" class="ad-c" font-size="9.5">当下可为 ∩ 目标所需</text>
|
||||
<text x="500" y="236" text-anchor="middle" class="ad-c" font-weight="600" font-size="9.5" fill="#245BDB">→ 下一步:查信用</text>
|
||||
<text x="500" y="262" text-anchor="middle" class="ad-s" fill="#8F3330">交集为空 = 断点 → 调人 / 立监听</text>
|
||||
<path d="M366,214 H398" fill="none" stroke="#B07D2B" stroke-width="1.5" marker-end="url(#adB)"/>
|
||||
<path d="M634,214 H602" fill="none" stroke="#2F5C45" stroke-width="1.5" marker-end="url(#adG)"/>
|
||||
|
||||
<line x1="36" y1="344" x2="964" y2="344" stroke="#ECEFF3"/>
|
||||
<text x="36" y="366" class="ad-c" font-size="11"><tspan font-weight="600">开展是就绪空间的展开,完成是判据缺口的收敛</tspan> —— 前推给能做,后拉给该做;断点给出调人与监听的时机,全程留痕</text>
|
||||
<text x="36" y="386" class="ad-s">缺口只有人知道 → 补全卡;缺口在世界侧 → 立监听(前提 + 时间监听从模型给出);缺口可算 → DMN 求值;缺口可查 → 调工具</text>
|
||||
</svg>
|
||||
</div>
|
||||
|
||||
<h3 class="h3"><span class="n">4.4</span>监听映射:CMMN 件 × 统一事件标准</h3>
|
||||
<p>loop 的监听全部落在 CMMN 原生件上,再由系统的<b>统一事件标准</b>(信封 · 四类事件 · 投递五诺,见《操作系统》)投递——<b>前提 = 静态监听</b>(随案例模型声明),<b>临场立监听 = 动态监听</b>(运行中由 Agent 登记,如发出报价邮件后登记"等回信");活动认数据,不认通道:</p>
|
||||
<div class="tbl"><table>
|
||||
<tr><th style="width:110px">监听四问</th><th>CMMN 件 × 事件标准</th></tr>
|
||||
<tr><td><b>听什么</b></td><td><b>前提</b> = onPart(监听哪个任务数据项的写入 / 变更,或哪个计划项的迁移)+ ifPart(内容条件,FEEL 求值)。「凭什么认出就是它」由模型给出——对应事件信封的关联键过滤。</td></tr>
|
||||
<tr><td><b>从哪来</b></td><td><b>数据事件</b>:环外回音(邮件解析 / 人工代收)经系统归属解析<b>归一为任务数据写入</b>后抛出——通道对前提不可见;写入层去重,处理幂等(按事件 ID)。</td></tr>
|
||||
<tr><td><b>听多久</b></td><td><b>时间监听(TimerEventListener)= 时限,必配</b>:到点抛时间事件,按声明走催办(契约预授权的模板催办)→ 换道 → 升级(案计划 Suspended · 受阻待人)。无死等。</td></tr>
|
||||
<tr><td><b>怎么齐</b></td><td><b>Stage 汇合</b>:一个前提多 onPart = 全齐(AND);多个前提 = 任一(OR);定额与多次回件用 repetitionRule。</td></tr>
|
||||
</table></div>
|
||||
<ul class="tight">
|
||||
<li><b>回音四来处,机制归一</b>——工位的人(卡回传 → 人事件,写数据)、世界(客户 / 供应商回件经通道解析写数据)、时间(时限到点)、别的环(其结果由调用方写入任务数据)——全部以事件形态到达,监听只认事件。</li>
|
||||
<li><b>人工代收</b>——环外的话经电话等非结构化途径到达时,相关岗位的人按数据项 schema 代为回填,走同一写入口;<b>代收是转述,不是判断</b>——原话与代收人意见分开留痕。</li>
|
||||
<li><b>监听中是健康态</b>——有时限、有阶梯,与停滞(该动没动)分别对待(10);挂起期间事件不丢,恢复即补投(系统投递承诺)。</li>
|
||||
</ul>
|
||||
<div class="callout warn"><b>悬空监听禁止,安装时拒绝:</b>凡 onPart 监听的数据项,必须存在至少一条可达的写入来源(通道映射 / 卡回传产出 / 环内动作产出 / 调用方回填);凡等环外处,必须配时间监听。无来源又无时限的监听即「幽灵等待」——永不苏醒的支线,安装静态审(11)必须拒绝。</div>
|
||||
|
||||
<!-- ========== 05 ========== -->
|
||||
<h2 class="ch"><span class="n">05</span>flow · 步序声明</h2>
|
||||
<div class="ch-rule"></div>
|
||||
|
||||
<p class="lead">flow 是活动内的确定性范式:业务模型 = <b>步序声明</b>——一条谱;引擎照谱执行,零临场调度,<b>调度权归系统</b>。flow 与 loop 共用同一副基座六件、同一契约格式、同一事件标准、同一记忆与留痕、同一放行——差异只有一处:<b>下一步由声明给定,不由 AI 决断</b>。LLM 在 flow 里可以出现,但只以「被调用的工具」出现,不是调度者。</p>
|
||||
|
||||
<h3 class="h3"><span class="n">5.1</span>步序声明模型</h3>
|
||||
<p>一条步序 = 有序的步列表 + 简单条件。每步声明六件:<b>步名 · 步型 · 入参映射</b>(取自任务数据 / 上步出参)<b>· 出参写入</b>(落任务数据,草稿态)<b>· 完成条件 · 失败策略</b>。步型四种:</p>
|
||||
<div class="tbl"><table>
|
||||
<tr><th style="width:130px">步型</th><th>内容</th><th style="width:250px">完成条件</th></tr>
|
||||
<tr><td><b>工具步</b></td><td>调一个白名单工具:系统调用(读取即快照留痕;触达外部世界者按契约预授权执行,或产出落草稿、集中在放行时落地)</td><td>同步:调用返回即完成</td></tr>
|
||||
<tr><td><b>LLM 步</b></td><td>固定模板 + schema 出参的模型调用(抽取 / 生成 / 转换);<b>模板与出参 schema 随声明版本冻结</b>,出参过 schema 校验</td><td>同步:出参校验通过即完成</td></tr>
|
||||
<tr><td><b>人类工具步</b></td><td>四卡之一,卡内容与出现时机由声明给定——如「步 4:人·执行,作业指导书 + 结果回填表」;末步通常是放行卡(06)</td><td>异步:<b>人事件</b>(卡回传)即步完成条件</td></tr>
|
||||
<tr><td><b>纯工具步</b></td><td>包内纯计算 / 转换 / 对自持台账的操作(无外效应);注册进工具表、经运行时调用而留痕</td><td>同步:返回即完成</td></tr>
|
||||
</table></div>
|
||||
<p><b>异步步的完成条件 = 监听</b>:等外部回件的步声明数据事件监听(如「发出对账单 → 听回执写入」),等人的步以人事件为完成条件,等时点的步以时间事件为完成条件——同一统一事件标准,<b>时限必配</b>:到点抛时间事件,按声明走催办或兜底;无死等。</p>
|
||||
|
||||
<h3 class="h3"><span class="n">5.2</span>顺序、条件与上升规则</h3>
|
||||
<ul class="tight">
|
||||
<li><b>顺序</b>——步按声明序执行;可声明确定的并行组(组内步无依赖、全完成再继续)。</li>
|
||||
<li><b>简单条件</b>——允许条件跳步与条件执行,条件必须是<b>任务数据上的确定性谓词</b>(如「金额 < 1 万 → 跳过步 4」);由引擎求值,零 LLM。</li>
|
||||
<li><b>复杂路由上升(必须)</b>——出现多路业务分支、临场判断的路由、不可谓词化的条件:<b>不得在 flow 内表达</b>。两条出路:上升为流程层的网关与多活动编排(责任级),或该活动改用 loop 范式(方法级临场)。flow 的谱必须全程可静态检查。</li>
|
||||
</ul>
|
||||
|
||||
<h3 class="h3"><span class="n">5.3</span>失败与缺口:声明给定,不临场</h3>
|
||||
<ul class="tight">
|
||||
<li><b>重试策略(必须)</b>——每步声明重试次数与间隔;重试仍败,按声明走下一步:<b>转人兜底</b>(改发人类工具卡:人·执行或人·决策,卡内容随声明)或<b>受阻待人</b>(挂起,携阻因)。</li>
|
||||
<li><b>无临场兜底(必须)</b>——flow 内不得出现「由 AI 决定怎么办」的失败处理;需要临场,即说明该活动不该是 flow(2.1)。</li>
|
||||
<li><b>控制事件同权</b>——叫停 / 暂停 / 终止对 flow 任务同样有效(10);挂起恢复后自当前步续跑,事件补投。</li>
|
||||
</ul>
|
||||
<p class="small">终态映射(01):放行完成 = 末步放行卡「放行通过」;受阻待人 = 声明的兜底转人或时限升级;停滞熔断 / 预算耗尽 = Harness 强制(10);驳回 = 放行卡驳回,按声明回到指定步重做或携意见迭代。</p>
|
||||
|
||||
<h3 class="h3"><span class="n">5.4</span>flow 的留痕、记忆与迭代</h3>
|
||||
<p>每步的执行、入出参、重试与失败,同一任务记忆标准(09):只追加、信封盖戳、治理先行、归侧。flow 活动同样有活动记忆——事实层校准重试与时限参数,裁决层沉淀<b>步序修订候选</b>(步增删、条件阈值、卡内容修订);候选经回放与人放行进入步序声明新版本:<b>修订步序,就是迭代这个活动的行为</b>(09)。</p>
|
||||
|
||||
<div class="fig">
|
||||
<div class="figcap"><span>FIG-04 · flow 步序执行</span><span>四种步型 · 谓词跳步 · 异步步 = 监听 · 失败声明给定 · 末步放行</span></div>
|
||||
<svg viewBox="0 0 1000 404" role="img" aria-label="flow 步序执行:工具步、LLM 步、条件谓词、人类工具步、纯工具步依声明序推进;异步步以事件为完成条件且时限必配;失败按声明重试与兜底;末步放行卡通过后落地事实态并发射输出口">
|
||||
<style>
|
||||
.af-t{font-family:'PingFang SC','Noto Sans SC',sans-serif;font-size:10.5px;font-weight:600;fill:#1F2933}
|
||||
.af-c{font-family:'PingFang SC','Noto Sans SC',sans-serif;font-size:10px;fill:#3A4452}
|
||||
.af-m{font-family:'SF Mono',Menlo,monospace;font-size:10px;font-weight:600;letter-spacing:.12em;fill:#6A7686}
|
||||
.af-s{font-family:'PingFang SC','Noto Sans SC',sans-serif;font-size:8.5px;fill:#6A7686}
|
||||
</style>
|
||||
<defs>
|
||||
<marker id="afS" markerWidth="9" markerHeight="9" refX="7.5" refY="4.5" orient="auto"><path d="M0,0 L9,4.5 L0,9 Z" fill="#46586A"/></marker>
|
||||
<marker id="afB" markerWidth="9" markerHeight="9" refX="7.5" refY="4.5" orient="auto"><path d="M0,0 L9,4.5 L0,9 Z" fill="#B07D2B"/></marker>
|
||||
<marker id="afH" markerWidth="9" markerHeight="9" refX="7.5" refY="4.5" orient="auto"><path d="M0,0 L9,4.5 L0,9 Z" fill="#2F6DB5"/></marker>
|
||||
</defs>
|
||||
|
||||
<text x="36" y="30" class="af-m">步序声明 · 一条谱</text>
|
||||
<text x="964" y="30" text-anchor="end" class="af-s" font-weight="600" fill="#46586A">引擎照谱推进 · 零临场调度 · 调度权归系统</text>
|
||||
|
||||
<rect x="36" y="60" width="140" height="64" rx="9" fill="#F5F6F7" stroke="#98A2B0" stroke-width="1.3"/>
|
||||
<text x="50" y="84" class="af-s" font-weight="600" fill="#3A4452">1 · 工具步</text>
|
||||
<text x="50" y="102" class="af-s">读 ERP · 快照留痕</text>
|
||||
<path d="M176,92 H198" fill="none" stroke="#46586A" stroke-width="1.4" marker-end="url(#afS)"/>
|
||||
<rect x="202" y="60" width="140" height="64" rx="9" fill="#FCFAF3" stroke="#B07D2B" stroke-width="1.3"/>
|
||||
<text x="216" y="84" class="af-s" font-weight="600" fill="#8A5F1C">2 · LLM 步</text>
|
||||
<text x="216" y="102" class="af-s">抽取 · 模板 + schema</text>
|
||||
<path d="M342,92 H364" fill="none" stroke="#46586A" stroke-width="1.4" marker-end="url(#afS)"/>
|
||||
<rect x="368" y="60" width="170" height="64" rx="9" fill="#FFFFFF" stroke="#98A2B0" stroke-width="1.2" stroke-dasharray="5 3"/>
|
||||
<text x="382" y="84" class="af-s" font-weight="600" fill="#3A4452">3 · 条件(确定性谓词)</text>
|
||||
<text x="382" y="102" class="af-s">金额 < 1 万 → 跳过步 4</text>
|
||||
<path d="M538,92 H560" fill="none" stroke="#46586A" stroke-width="1.4" marker-end="url(#afS)"/>
|
||||
<rect x="564" y="60" width="180" height="64" rx="9" fill="#DCEAF7" stroke="#2F6DB5" stroke-width="1.4"/>
|
||||
<text x="578" y="84" class="af-s" font-weight="600" fill="#173A63">4 · 人类工具步 · 执行卡</text>
|
||||
<text x="578" y="102" class="af-s" fill="#173A63">作业指导书 + 结果回填</text>
|
||||
<path d="M744,92 H766" fill="none" stroke="#46586A" stroke-width="1.4" marker-end="url(#afS)"/>
|
||||
<rect x="770" y="60" width="120" height="64" rx="9" fill="#F5F6F7" stroke="#98A2B0" stroke-width="1.3"/>
|
||||
<text x="784" y="84" class="af-s" font-weight="600" fill="#3A4452">5 · 纯工具步</text>
|
||||
<text x="784" y="102" class="af-s">汇总核对</text>
|
||||
<path d="M453,56 C560,24 740,24 830,56" fill="none" stroke="#B07D2B" stroke-width="1.3" stroke-dasharray="5 3" marker-end="url(#afB)"/>
|
||||
<text x="640" y="20" text-anchor="middle" class="af-s" fill="#8A5F1C">跳步(谓词为真)</text>
|
||||
|
||||
<path d="M654,124 V166" fill="none" stroke="#2F6DB5" stroke-width="1.3" stroke-dasharray="4 3" marker-end="url(#afH)"/>
|
||||
<rect x="520" y="170" width="200" height="64" rx="9" fill="#FFFFFF" stroke="#2F6DB5" stroke-width="1.1" stroke-dasharray="5 3"/>
|
||||
<text x="534" y="190" class="af-s" font-weight="600" fill="#173A63">异步步 · 完成条件 = 监听</text>
|
||||
<text x="534" y="208" class="af-s">人事件即步完成 · 时限必配</text>
|
||||
<text x="534" y="224" class="af-s">到点 → 催办 / 兜底(声明给定)</text>
|
||||
|
||||
<path d="M830,124 V166" fill="none" stroke="#2F6DB5" stroke-width="1.5" marker-end="url(#afH)"/>
|
||||
<rect x="740" y="170" width="224" height="56" rx="9" fill="#DCEAF7" stroke="#2F6DB5" stroke-width="1.5"/>
|
||||
<text x="754" y="192" class="af-s" font-weight="600" fill="#173A63">放行卡 —— 成果清单 + 放行选择表</text>
|
||||
<text x="754" y="210" class="af-s" fill="#173A63">通过 / 驳回重做 / 驳回迭代(人)</text>
|
||||
<path d="M852,226 V248" fill="none" stroke="#2F6DB5" stroke-width="1.5" marker-end="url(#afH)"/>
|
||||
<rect x="740" y="252" width="224" height="44" rx="9" fill="#E8F8E4" stroke="#278717" stroke-width="1.4"/>
|
||||
<text x="754" y="278" class="af-s" font-weight="600" fill="#278717">事实态落地(放行时)· 发射输出口</text>
|
||||
|
||||
<rect x="36" y="252" width="464" height="56" rx="9" fill="#FFF4E5" stroke="#fbd9a5" stroke-width="1.3"/>
|
||||
<text x="52" y="274" class="af-s" font-weight="600" fill="#DE7802">失败策略 · 声明给定,不临场</text>
|
||||
<text x="52" y="294" class="af-s" fill="#8a5a10">每步:重试 N 次 → 超限 → 按声明兜底:转人类工具卡 / 受阻待人</text>
|
||||
|
||||
<rect x="36" y="320" width="928" height="34" rx="8" fill="#F5F6F7" stroke="#C6D0DA" stroke-width="1.1"/>
|
||||
<text x="52" y="342" class="af-s" font-weight="600" fill="#3A4452">复杂路由不入 flow:多路分支 · 并行汇合 · 临场判断 → 上升为流程层网关编排,或改用 loop 范式(2.1 / 5.2)</text>
|
||||
|
||||
<rect x="36" y="366" width="928" height="30" rx="6" fill="#0F1420"/>
|
||||
<text x="500" y="385" text-anchor="middle" font-family="'SF Mono',Menlo,monospace" font-size="10.5" fill="#DCE3F0">步序即业务模型 —— 修订步序,即迭代此活动的行为;谱内确定,谱外过放行</text>
|
||||
</svg>
|
||||
</div>
|
||||
|
||||
<!-- ========== 06 ========== -->
|
||||
<h2 class="ch"><span class="n">06</span>人类工具的调用</h2>
|
||||
<div class="ch-rule"></div>
|
||||
|
||||
<p class="lead">人在环是<b>一种被调用的工具</b>——四种人类工具与 LLM 工具同列,都是调用层的内置工具:AI 调用人与调用任何工具同构,经调用契约、受白名单与授权约束;差别只在通道与时延——卡经<b>对话流</b>(负责人)或<b>系统消息</b>(其他人)到达人,回传异步(人事件)。人是工具表里带宽最小、延迟最高、不可并发的工具,但携带两样机器没有的东西:<b>环外的知识,与裁决的权力</b>。卡片结构与回传协议归系统,内容由活动填充(schema 在契约与交互内容中给出,07)。</p>
|
||||
|
||||
<div class="tbl"><table>
|
||||
<tr><th style="width:80px">工具</th><th>AI 输出(卡面)</th><th style="width:250px">人回传</th></tr>
|
||||
<tr><td><b>决策</b></td><td><b>分支条件选择表</b>:可选分支、各自条件与后果、依据快照、AI 建议</td><td>选定分支,可附理由</td></tr>
|
||||
<tr><td><b>执行</b></td><td><b>作业指导书 + 结果回填表格</b>:做什么、怎么做、完成标准</td><td>按表回填结果,凭证随附</td></tr>
|
||||
<tr><td><b>补全</b></td><td><b>补全需求 + 回填表格</b>:缺什么、为何需要、格式要求</td><td>按表回填</td></tr>
|
||||
<tr><td><b>放行</b></td><td><b>成果清单 + 放行选择表</b>:交付物、验收判据逐条核对与依据</td><td>三选一:<b>放行通过 / 驳回重做 / 驳回迭代</b>,驳回必附意见</td></tr>
|
||||
</table></div>
|
||||
|
||||
<ul class="tight">
|
||||
<li><b>调用时机</b>——loop 里由 AI 临场判定(断点即人环:缺口只有人知道 → 补全;超出授权 → 决策;数字化未及 → 执行;成果齐备 → 放行,04);flow 里由步序声明给定(05)。</li>
|
||||
<li><b>到达面两路</b>——发给<b>负责人</b>的卡出现在该任务的对话流;发给<b>其他人</b>的卡以<b>系统消息</b>送达其消息要素、就地作答——跨人卡是<b>一次性的解答请求,不是责任转移</b>:作答权限只及卡面与决策包,不开放任务对话流;「调谁」按<b>岗位</b>声明,收件人由系统按解析策略确定(《操作系统》03),缺席走时限阶梯。回传经统一入口写回任务,调用与回传全程在任务侧留痕。<b>驳回重答 = 新发一条系统消息</b>(新卡实例,附驳回理由与原答引用,原卡闭合)——每次请求与回答都是独立消息,只增不改。</li>
|
||||
<li><b>调用必附上下文(必须)</b>——每张卡自带足够的依据与快照,人无需进系统翻找即可作答;无上下文的裸调用,基座必须拒发。</li>
|
||||
<li><b>回传即留痕、即学习信号(必须)</b>——谁、何时、答了什么、依据什么,随卡入任务记忆;补全 = 缺口标注,决策 + 理由 = 偏好样本,执行回填 = 结果确认,驳回 + 意见 = 批评信号——活动记忆 · 裁决层的原料(09)。</li>
|
||||
<li><b>回传按 schema 校验</b>——经系统单入口协议回环,以<b>人事件</b>抛回活动:loop 中即观察 + 数据写入,flow 中即步完成条件。</li>
|
||||
<li><b>防打扰</b>——调人预算(打扰上限)在契约授权边界;同一缺口攒批调用,能推进的先推进。</li>
|
||||
</ul>
|
||||
|
||||
<div class="callout brand"><b>完成只出自放行,放行必先预检(必须)。</b>任务的完成只能出自放行卡的「放行通过」——判据全绿只是可提交,认账永远是人的动作。发放行卡前,系统对全部待落地动作执行<b>落地预检</b>(schema · 工具可用与授权 · 连接可达 · 数据冲突)——<b>检查可落地,才允许放行</b>:预检全过才发卡,成果清单即已验证的动作清单,预检不过的项打回环内修正。放行通过即刻落地(写台账、调外部系统,附幂等键),<b>落地收敛才发射输出口,终态方成「放行完成」</b>;残余失败转落地失败卡——执行卡的系统预置形态,不构成第五种卡(《操作系统》7.3)。<b>驳回重做</b> = 按原要求重新执行;<b>驳回迭代</b> = 带意见改进现稿后再提。放行卡是活动级的门,与流程层的审批点不同层:任务完成靠放行,节点间裁决靠审批点(《操作系统》)。</div>
|
||||
<p class="small">loop 中的调人落为类型化的 HumanTask 计划项:调用即 Active(阻塞),回传写任务数据 + 抛人事件,完成驱动前提、下游随之解锁——调人与等回音在结构上是同一件事:立一个监听,听人。</p>
|
||||
|
||||
<!-- ========== 07 ========== -->
|
||||
<h2 class="ch"><span class="n">07</span>交互内容</h2>
|
||||
<div class="ch-rule"></div>
|
||||
|
||||
<p class="lead">交互的<b>结构归基座,内容归活动</b>:基座供给对话流(任务的人机时间线、一切回环输入的唯一入口)与视图区容器(只读呈现);活动填充三样内容——<b>视图模版、卡内容 schema、汇报组织</b>。</p>
|
||||
|
||||
<div class="tbl"><table>
|
||||
<tr><th style="width:130px">交互内容</th><th>活动定义什么</th><th style="width:270px">约束</th></tr>
|
||||
<tr><td><b>视图模版</b></td><td>视图区呈现的 <b>HTML 模版</b>:事态全景、进展、成果预览;<b>流控由 AI 在后端执行</b>——按局面选模版、填数据、决定下一屏呈现什么,推送 web</td><td><b>模版是内容不是代码</b>:web 零活动代码,容器渲染净化、无脚本执行权;视图区只读、零回环输入</td></tr>
|
||||
<tr><td><b>卡内容 schema</b></td><td>四卡的内容定义:决策卡的分支与条件怎么列、执行卡的指导书与回填表、补全卡的字段、放行卡的成果清单结构</td><td>卡片骨架与回传协议归系统;无自定义内容的活动必须仍可运行——schema 自动渲染兜底</td></tr>
|
||||
<tr><td><b>汇报组织</b></td><td>过程汇报与汇报工件怎么组织:loop 按案例模型的阶段与里程碑,flow 按步序位置;日 / 周期汇报的素材由任务记忆聚合</td><td>汇报是投影,不是另一份事实——一切汇报可溯回任务记忆与任务数据</td></tr>
|
||||
</table></div>
|
||||
|
||||
<ul class="tight">
|
||||
<li><b>控制权按态转交(必须)</b>——视图区容器与对话区输出框的控制权由<b>活动与系统共同持有</b>:任务激活(Agent 机制运行)时归<b>活动</b>——视图流控与对话输出由活动驱动;流程流转(节点间、审批点、终态前后)时归<b>系统</b>——流转、审批与终态回执由系统呈现。转交随引擎的激活 / 完成事件自动发生,活动不感知交接。</li>
|
||||
<li><b>输入单入口(必须)</b>——输入侧<b>不参与转交</b>:全部人类输入永远经系统的对话流卡片协议回传;视图区不得产生回环输入;浏览性交互(切换 / 筛选 / 展开)由前端容器本地处理,不回后端。</li>
|
||||
<li><b>负责人可主动输入</b>——对话流的自由输入是人事件的第二形态(卡回传之外):写入任务记忆,loop 作为观察进入后续窗口;不驱动 flow 步。叫停等指令走控制事件,不经自由输入(10)。</li>
|
||||
<li><b>视图流控随范式</b>——loop:AI 按定位与局面临场组织视图流;flow:按步序位置推送声明的模版;两者对 web 同构——web 只渲染推来的内容。</li>
|
||||
<li><b>时间线一致(应)</b>——对话流时间线应与任务记忆一致:时间线即任务记忆的可读投影。</li>
|
||||
</ul>
|
||||
|
||||
<!-- ========== 08 ========== -->
|
||||
<h2 class="ch"><span class="n">08</span>技能:方法经验的封装格式</h2>
|
||||
<div class="ch-rule"></div>
|
||||
|
||||
<p class="lead">工具用法的方法经验,以<b>技能(Skill)</b>为封装格式,<b>基于工具、在活动内定义</b>。一个技能 = <b>适用描述</b>(何时适用)+ <b>方法正文</b>(怎么判断、怎么编排工具)+ <b>结晶片段脚本</b>(可选:反复出现的确定性子序列)+ <b>知识引用</b>(可选:深层材料,按需下钻)。白名单回答「能用什么」(权力),技能回答「怎么用好」(方法)——棋子确定,棋谱是资产。</p>
|
||||
|
||||
<div class="callout warn"><b>定位声明:技能不是独立范式。</b>它没有自己的约束体系——留痕、治理、权力边界与生命周期全部继承本规范:内容软(方法正文自由,用不用由 AI 决断),边框硬(装配入信封 · 脚本注册留痕 · 不得扩权 · 版本过进化关口)。技能是活动内部的构件格式,不与活动并立。</div>
|
||||
|
||||
<div class="tbl"><table>
|
||||
<tr><th style="width:110px">层</th><th style="width:190px">性质</th><th>语义</th></tr>
|
||||
<tr><td><b>工具白名单</b></td><td><b>硬约束</b>(权力,契约定)</td><td>不在名单调不动;越权在结构上不可能。</td></tr>
|
||||
<tr><td><b>技能清单</b></td><td><b>软资源</b>(方法,包声明)</td><td>每单任务可装配的技能集合确定、入信封;AI 可用可不用——<b>可以越谱,不可越权</b>;清单版本化,随进化演进。</td></tr>
|
||||
<tr><td><b>临场路径</b></td><td>自由(由事决定,loop)</td><td>受上两层约束;走出的新路,经蒸馏可成新技能(09)。</td></tr>
|
||||
</table></div>
|
||||
|
||||
<ul class="tight">
|
||||
<li><b>装配语义</b>——loop:AI 按适用描述临场装配(渐进披露:常驻上下文仅有技能目录,按事加载正文、按需下钻引用);flow:技能编入步序——结晶片段脚本即纯工具步照谱执行。技能被<b>装配 / 调用</b>,不称「触发」——触发器一词专属流程层。</li>
|
||||
<li><b>载方法,不载权力(必须)</b>——技能不得扩大白名单、授权边界与禁区;技能提及的工具不在本活动白名单者,不可调。与 message 同一逻辑:方法不是改约。</li>
|
||||
<li><b>脚本按纯工具规矩(必须)</b>——技能捆绑的脚本必须注册进工具表、经运行时调用而留痕、无环境能力;不得成为绕过留痕的暗道。</li>
|
||||
<li><b>装配入信封(必须)</b>——每步装配了哪些技能及其版本,记入任务记忆的信封;回放与归因依赖之。</li>
|
||||
<li><b>两级组合不混</b>——流程包串活动(责任级:节点有负责人、有审批点、有契约);环内装配技能(方法级:无门无责任)。需要独立负责人与放行的做活动,纯方法复用做技能;技能不能替代活动,活动不应退化为单技能空壳。</li>
|
||||
</ul>
|
||||
|
||||
<!-- ========== 09 ========== -->
|
||||
<h2 class="ch"><span class="n">09</span>记忆与迭代</h2>
|
||||
<div class="ch-rule"></div>
|
||||
|
||||
<p class="lead">基座的记忆系统两分:<b>任务记忆</b>(会话历史——这一单里发生过什么)× <b>活动记忆</b>(结构化记忆——这类事历来是什么样)。基座的接口最小:任务记忆只有<b>窗口配置</b>,活动记忆只有<b>存与取</b>;框架站在环内一切调用的必经之路上:记录不靠自觉,靠位置。本章讲活动侧怎么用它们:装载、蒸馏,以及记忆如何走向业务模型的迭代。</p>
|
||||
|
||||
<h3 class="h3"><span class="n">9.1</span>任务记忆:当前任务的全过程</h3>
|
||||
<p><b>任务记忆是当前活动实例的会话历史</b>,两股同轴合流、按时间全序:<b>消息历史</b>——Agent 机制的原生逐条记录(观察 · 思考 · 动作 · 结果;flow 中即每步的执行记录),回路跑过即存在;<b>引擎事件流</b>——结构化事件(生命周期迁移 · 前提与 DMN 求值 · 卡与放行裁决 · 步执行)。四条性质:</p>
|
||||
<ul class="tight">
|
||||
<li><b>只追加(必须)</b>——原始条目不得修改;信号可迟到(放行裁决 · 后续修订 · 客户回复),以后续条目<b>回链原步</b>累加,不改写因果。</li>
|
||||
<li><b>信封盖戳(必须)</b>——每条盖版本信封:契约 / 业务模型 / 技能版本 + 定位(loop:阶段 · 目标项;flow:步序位置)+ 治理标记;行为可归因、历史可回放的前提。</li>
|
||||
<li><b>治理先行(必须)</b>——脱敏、权限、保留期、可学习标记在留痕时刻打上;不合规的记录不得进入蒸馏队列。</li>
|
||||
<li><b>归侧(必须)</b>——每条按动作类型自动推导执行侧标签(机器产出 / 人产出 / 人裁决 / 世界等待);度量口径归《操作系统》,零埋点。</li>
|
||||
</ul>
|
||||
<p><b>四项职能</b>:<b>续跑</b>——挂起恢复与事件补投时,由任务记忆重建上下文:记忆在,环可断可续;<b>审计</b>——发生了什么:谁 · 何时 · 依据什么;<b>回放</b>——换个办法,这单会不会成(反事实评估与模型增量的重演底盘,9.3);<b>蒸馏源</b>——活动记忆的唯一原料(9.2)。</p>
|
||||
<p><b>活动侧唯一接口 = 窗口配置</b>——每次 LLM 调用加载多少轮会话历史,由活动声明(随 Harness 配置);窗口之外的历史不进上下文,但完整在库——续跑、审计与回放永远对全量记录进行。</p>
|
||||
<p class="small"><b>生命周期</b>:随单生,只追加长,终态封卷归档。<b>与任务数据之别</b>:任务数据是<b>事的数据</b>(业务事实,引擎推进的依据);任务记忆是<b>过程的记录</b>(怎么走到这里)。数据写入本身作为事件同轴进入任务记忆——一次写,两处义。</p>
|
||||
|
||||
<h3 class="h3"><span class="n">9.2</span>活动记忆:活动的持久事实</h3>
|
||||
<p><b>活动记忆是关于这个活动(事类)的持久事实</b>,跨全部任务实例累积——活动的长期经验体。它的结构不是自由笔记:<b>每类条目对准业务模型的一个作用面,使记忆天然是 CMMN / DMN 与步序声明优化的原料堆</b>:</p>
|
||||
<div class="tbl"><table>
|
||||
<tr><th style="width:96px">层</th><th>存什么</th><th style="width:300px">优化谁</th></tr>
|
||||
<tr><td><b>事实层</b></td><td>环境与对手方的稳定事实:系统端点脾性、对手方节奏(「该客户均值 3 天回信」)、术语与实体档案</td><td>校准时间监听的时限 · 前提 ifPart 阈值 · DMN 输入项;flow 的重试与时限参数</td></tr>
|
||||
<tr><td><b>模式层</b></td><td>路径与组合的统计:裁量项启用频次与共现序列、阶段 / 步耗时分布、技能组合效果</td><td>候选结构增量:裁量项转常项 · 新前提依赖 · 阶段重组 · 新里程碑;flow 的步序修订</td></tr>
|
||||
<tr><td><b>裁决层</b></td><td>纠正的沉淀:每次驳回 / 否决 / 叫停的理由,归纳为一般化陈述</td><td>候选新前提条件 · 收紧完成判据 · DMN 新规则行——约束力收缩的原料堆(03)</td></tr>
|
||||
<tr><td><b>例外层</b></td><td>反例与禁忌:已知失败形态、边界案例、「此处留人」标记</td><td>DMN 规则的适用边界 · 前提负向条件 · 技能适用描述修正——防泛化过度</td></tr>
|
||||
</table></div>
|
||||
<ul class="tight">
|
||||
<li><b>条目三件套(必须)</b>——每条活动记忆 = <b>归纳陈述</b> + <b>证据链</b>(指回任务记忆的具体片段,可回放)+ <b>候选增量</b>(可选:落到业务模型 / 技能的具体 diff,状态:候选 / 回放中 / 已放行 / 已否决)。<b>无证据链的条目不得入库</b>——记忆必须可追溯到经历。</li>
|
||||
<li><b>写入 = 蒸馏(必须)</b>——活动记忆只经蒸馏写入:终态封卷与里程碑达成时,蒸馏钩子从任务记忆归纳;人可修剪。不设直写旁路。</li>
|
||||
<li><b>基座接口 = 存与取</b>——活动记忆是<b>结构化记忆</b>,基座只提供条目的存入与检索、不解释语义;四层结构与条目三件套是本卷规定的活动侧结构标准,由活动经蒸馏与装载维护。</li>
|
||||
<li><b>读出 = 装载</b>——按定位选摘相关条目入 Agent 上下文(渐进披露,3.4);<b>语义引擎不读活动记忆</b>——引擎零业务,记忆是 Agent 侧的输入。</li>
|
||||
<li><b>记忆不载权力(必须)</b>——活动记忆对行为只有参考力,没有强制力;强制力的唯一路径是候选增量经回放与人放行<b>进入业务模型本身</b>(9.3)。<b>记住的影响裁量,放行的才约束行为。</b></li>
|
||||
</ul>
|
||||
|
||||
<div class="fig">
|
||||
<div class="figcap"><span>FIG-05 · 记忆双系:任务记忆 × 活动记忆</span><span>一单一本 × 一类一本 · 蒸馏与装载 · 候选增量 → 回放 → 人放行 → 模型新版</span></div>
|
||||
<svg viewBox="0 0 1000 420" role="img" aria-label="记忆双系:任务记忆按时间记录本单消息历史与引擎事件流,每条盖信封戳,终态封卷归档;经蒸馏写入活动记忆的事实、模式、裁决、例外四层;活动记忆经装载选摘回到下一单上下文;各层产生候选增量,经回放与人放行进入业务模型新版,下一单装载即行为改变">
|
||||
<style>
|
||||
.am-t{font-family:'PingFang SC','Noto Sans SC',sans-serif;font-size:10.5px;font-weight:600;fill:#1F2933}
|
||||
.am-c{font-family:'PingFang SC','Noto Sans SC',sans-serif;font-size:10px;fill:#3A4452}
|
||||
.am-m{font-family:'SF Mono',Menlo,monospace;font-size:10px;font-weight:600;letter-spacing:.12em;fill:#6A7686}
|
||||
.am-s{font-family:'PingFang SC','Noto Sans SC',sans-serif;font-size:8.5px;fill:#6A7686}
|
||||
</style>
|
||||
<defs>
|
||||
<marker id="amS" markerWidth="9" markerHeight="9" refX="7.5" refY="4.5" orient="auto"><path d="M0,0 L9,4.5 L0,9 Z" fill="#46586A"/></marker>
|
||||
<marker id="amB" markerWidth="9" markerHeight="9" refX="7.5" refY="4.5" orient="auto"><path d="M0,0 L9,4.5 L0,9 Z" fill="#B07D2B"/></marker>
|
||||
<marker id="amH" markerWidth="9" markerHeight="9" refX="7.5" refY="4.5" orient="auto"><path d="M0,0 L9,4.5 L0,9 Z" fill="#2F6DB5"/></marker>
|
||||
<marker id="amG" markerWidth="9" markerHeight="9" refX="7.5" refY="4.5" orient="auto"><path d="M0,0 L9,4.5 L0,9 Z" fill="#2F5C45"/></marker>
|
||||
</defs>
|
||||
|
||||
<text x="36" y="30" class="am-m">任务记忆 · 一单一本(消息历史)</text>
|
||||
<rect x="36" y="40" width="380" height="252" rx="10" fill="#FFFFFF" stroke="#46586A" stroke-width="1.4"/>
|
||||
<text x="52" y="62" class="am-s">消息历史 + 引擎事件流 · 同轴合流 · 时间全序</text>
|
||||
<rect x="52" y="74" width="280" height="24" rx="6" fill="#FCFAF3" stroke="#B07D2B" stroke-width="1.1"/>
|
||||
<text x="64" y="90" class="am-s" font-weight="600" fill="#8A5F1C">观察 —— 工具返回 · 人的回传 · 数据快照</text>
|
||||
<rect x="52" y="104" width="280" height="24" rx="6" fill="#FCFAF3" stroke="#B07D2B" stroke-width="1.1"/>
|
||||
<text x="64" y="120" class="am-s" font-weight="600" fill="#8A5F1C">思考 —— 计划摘要 · 有界披露</text>
|
||||
<rect x="52" y="134" width="280" height="24" rx="6" fill="#FCFAF3" stroke="#B07D2B" stroke-width="1.1"/>
|
||||
<text x="64" y="150" class="am-s" font-weight="600" fill="#8A5F1C">动作 / 结果 —— 启动 · 调人 · 写任务数据</text>
|
||||
<rect x="52" y="164" width="280" height="24" rx="6" fill="#EEF3F8" stroke="#9AB0C6" stroke-width="1.1"/>
|
||||
<text x="64" y="180" class="am-s" font-weight="600" fill="#173A63">引擎事件 —— 迁移 · 求值 · 步执行 · 放行裁决</text>
|
||||
<rect x="52" y="194" width="280" height="24" rx="6" fill="#EAF3EE" stroke="#7FA98B" stroke-width="1.1"/>
|
||||
<text x="64" y="210" class="am-s" font-weight="600" fill="#2F5C45">迟到信号 —— 驳回 · 客户回复 ↩ 回链原步</text>
|
||||
<path d="M338,74 V218" fill="none" stroke="#98A2B0" stroke-width="1.2"/>
|
||||
<text x="346" y="140" class="am-s" font-weight="600" fill="#46586A">信封戳</text>
|
||||
<text x="346" y="154" class="am-s">版本 × 治理</text>
|
||||
<text x="52" y="240" class="am-s">归侧:机器产出 / 人产出 / 人裁决 / 世界等待 —— 口径归《操作系统》</text>
|
||||
<text x="52" y="258" class="am-s">治理先行:脱敏 · 权限 · 保留期 · 可学习标记 —— 留痕时刻打上</text>
|
||||
<text x="52" y="278" class="am-s" font-weight="600" fill="#3A4452">只追加 · 终态封卷归档 —— 摘要是视图,不是记忆本体</text>
|
||||
|
||||
<path d="M420,112 H576" fill="none" stroke="#B07D2B" stroke-width="2" marker-end="url(#amB)"/>
|
||||
<text x="498" y="100" text-anchor="middle" class="am-c" font-weight="600" fill="#8A5F1C">蒸馏钩子</text>
|
||||
<text x="498" y="130" text-anchor="middle" class="am-s">终态封卷 / 里程碑达成</text>
|
||||
<path d="M580,196 H424" fill="none" stroke="#46586A" stroke-width="1.6" marker-end="url(#amS)"/>
|
||||
<text x="502" y="184" text-anchor="middle" class="am-c" font-weight="600" fill="#3A4452">装载(3.4)</text>
|
||||
<text x="502" y="214" text-anchor="middle" class="am-s">按定位选摘 · 渐进披露</text>
|
||||
|
||||
<text x="584" y="30" class="am-m">活动记忆 · 一类一本(持久事实)</text>
|
||||
<rect x="584" y="40" width="380" height="252" rx="10" fill="#FFFFFF" stroke="#161B22" stroke-width="1.5"/>
|
||||
<text x="600" y="62" class="am-s">跨单累积 —— 每层对准业务模型的一个作用面</text>
|
||||
<rect x="600" y="74" width="348" height="38" rx="6" fill="#F5F6F7" stroke="#C6D0DA" stroke-width="1.1"/>
|
||||
<text x="612" y="89" class="am-s" font-weight="600" fill="#3A4452">事实层 · 端点脾性 · 对手方节奏 · 术语档案</text>
|
||||
<text x="612" y="104" class="am-s">→ 校准时限 · ifPart 阈值 · DMN 输入项 · 重试参数</text>
|
||||
<rect x="600" y="118" width="348" height="38" rx="6" fill="#FCFAF3" stroke="#B07D2B" stroke-width="1.1"/>
|
||||
<text x="612" y="133" class="am-s" font-weight="600" fill="#8A5F1C">模式层 · 裁量项频次 · 共现序列 · 阶段 / 步耗时</text>
|
||||
<text x="612" y="148" class="am-s">→ 候选结构增量:转常项 · 新前提 · 阶段重组 · 步序修订</text>
|
||||
<rect x="600" y="162" width="348" height="38" rx="6" fill="#DCEAF7" stroke="#2F6DB5" stroke-width="1.1"/>
|
||||
<text x="612" y="177" class="am-s" font-weight="600" fill="#173A63">裁决层 · 驳回 / 否决 / 叫停的理由归纳</text>
|
||||
<text x="612" y="192" class="am-s">→ 候选前提条件 · 收紧判据 · DMN 规则行(03)</text>
|
||||
<rect x="600" y="206" width="348" height="38" rx="6" fill="#FEEAE9" stroke="#f6c6c3" stroke-width="1.1"/>
|
||||
<text x="612" y="221" class="am-s" font-weight="600" fill="#8F3330">例外层 · 失败形态 · 边界案例 · 留人标记</text>
|
||||
<text x="612" y="236" class="am-s">→ 规则适用边界 · 负向条件 · 防泛化过度</text>
|
||||
<text x="600" y="262" class="am-s">条目 = 归纳陈述 + 证据链(指回任务记忆)+ 候选增量</text>
|
||||
<text x="600" y="280" class="am-s" font-weight="600" fill="#3A4452">写入唯蒸馏(人可修剪) · 语义引擎不读 —— Agent 侧输入</text>
|
||||
|
||||
<path d="M875,292 V312" fill="none" stroke="#46586A" stroke-width="1.4" marker-end="url(#amS)"/>
|
||||
<rect x="800" y="316" width="150" height="32" rx="7" fill="#FCFAF3" stroke="#B07D2B" stroke-width="1.3"/>
|
||||
<text x="875" y="336" text-anchor="middle" class="am-s" font-weight="600" fill="#8A5F1C">候选增量(diff)</text>
|
||||
<path d="M796,332 H750" fill="none" stroke="#46586A" stroke-width="1.4" marker-end="url(#amS)"/>
|
||||
<rect x="616" y="316" width="130" height="32" rx="7" fill="#F5F6F7" stroke="#98A2B0" stroke-width="1.2"/>
|
||||
<text x="681" y="336" text-anchor="middle" class="am-s" font-weight="600" fill="#46586A">回放重演(9.3)</text>
|
||||
<path d="M612,332 H566" fill="none" stroke="#46586A" stroke-width="1.4" marker-end="url(#amS)"/>
|
||||
<rect x="432" y="316" width="130" height="32" rx="7" fill="#DCEAF7" stroke="#2F6DB5" stroke-width="1.4"/>
|
||||
<text x="497" y="336" text-anchor="middle" class="am-s" font-weight="600" fill="#173A63">人放行 · 进化关口</text>
|
||||
<path d="M428,332 H382" fill="none" stroke="#2F6DB5" stroke-width="1.4" marker-end="url(#amH)"/>
|
||||
<rect x="168" y="316" width="210" height="32" rx="7" fill="#EAF3EE" stroke="#2F5C45" stroke-width="1.4"/>
|
||||
<text x="273" y="336" text-anchor="middle" class="am-s" font-weight="600" fill="#2F5C45">模型新版:CMMN / DMN / 步序 / 技能</text>
|
||||
<path d="M164,332 H120" fill="none" stroke="#2F5C45" stroke-width="1.4" stroke-dasharray="5 3" marker-end="url(#amG)"/>
|
||||
<text x="38" y="326" class="am-s" fill="#2F5C45">下一单装载</text>
|
||||
<text x="38" y="342" class="am-s" fill="#2F5C45">行为改变(9.3)</text>
|
||||
|
||||
<rect x="36" y="372" width="928" height="30" rx="6" fill="#0F1420"/>
|
||||
<text x="500" y="391" text-anchor="middle" font-family="'SF Mono',Menlo,monospace" font-size="10.5" fill="#DCE3F0">记忆不载权力 —— 记住的影响裁量,放行的才约束行为;记忆的终点不是记住,是成为模型</text>
|
||||
</svg>
|
||||
</div>
|
||||
|
||||
<h3 class="h3"><span class="n">9.3</span>迭代业务模型,即迭代活动行为</h3>
|
||||
<p>引擎与基座是不动点,进化的全部作用面收敛到可版本工件:<b>业务模型</b>(结构与判据)与<b>技能</b>(方法)。迭代单位是<b>模型增量</b>——一份可 diff 的变更:</p>
|
||||
<div class="tbl"><table>
|
||||
<tr><th style="width:210px">模型增量类型</th><th>改变的行为</th></tr>
|
||||
<tr><td><b>+ 前提条件</b>(loop)</td><td>动作解锁时机变化——某些步从此必须等前提;开展的漏斗收紧或放宽</td></tr>
|
||||
<tr><td><b>+ 完成判据 / 收紧判据</b></td><td>目标集变化——后拉方向改变;此前靠人裁的合格线沉为 L2 机检(约束力收缩)</td></tr>
|
||||
<tr><td><b>+ DMN 规则行 / 新决策表</b>(loop)</td><td>一块判断从临场搬进确定</td></tr>
|
||||
<tr><td><b>阶段重组 / 里程碑增删</b>(loop)</td><td>叙事与汇报结构变化;投影定义随之更新</td></tr>
|
||||
<tr><td><b>裁量项转常项 / 动作空间调整</b>(loop)</td><td>裁量域增删(与技能清单、白名单联动核对)</td></tr>
|
||||
<tr><td><b>步序修订</b>(flow)</td><td>步增删、条件阈值、重试与时限参数、卡内容修订——谱变了,照谱的行为随之变</td></tr>
|
||||
</table></div>
|
||||
<ol class="steps">
|
||||
<li><b>蒸馏</b>——驳回、否决、叫停、断点的证据(活动记忆 · 裁决层与模式层),蒸馏为候选模型增量(diff)。</li>
|
||||
<li><b>回放重演</b>——新模型对历史任务记忆重演:旧成功单在新模型下是否仍全绿?旧失败单是否恰被新条件拦住?断点是否减少?——回放先行。</li>
|
||||
<li><b>人放行</b>——增量 diff + 重演报告作为证据包,过进化关口;XML 与步序声明可 diff 审查,说明书同步更新。</li>
|
||||
<li><b>生效</b>——模型新版入活动库;<b>下一单任务装载即行为改变,引擎零改动</b>;在途任务按其信封版本跑完。</li>
|
||||
<li><b>可回退</b>——版本谱系完整;行为回退 = 版本回退。</li>
|
||||
</ol>
|
||||
<div class="callout brand"><b>行为可归因公式:任何一步的行为 = 引擎版本 × 契约版本 × 业务模型版本 × 技能版本 × 输入与任务记忆前缀。</b>各项全部入信封——两单行为不同,必可归因到某一项的差异;模型 diff 完全解释行为 diff。这就是「迭代业务模型 = 迭代活动行为」的可审计形态。</div>
|
||||
|
||||
<!-- ========== 10 ========== -->
|
||||
<h2 class="ch"><span class="n">10</span>Harness · 验收分级 · 过程工作区</h2>
|
||||
<div class="ch-rule"></div>
|
||||
|
||||
<h3 class="h3"><span class="n">10.1</span>Harness:活动的运行框架</h3>
|
||||
<p>Harness 在活动内、随活动交付——每个活动的确定性边界不依赖外部编排兜底。四件:</p>
|
||||
<div class="tbl"><table>
|
||||
<tr><th style="width:150px">件</th><th>内容</th></tr>
|
||||
<tr><td><b>停止条件</b></td><td>什么算走完:loop = 判据收敛提交放行;flow = 谱走完(末步放行);加上五终态的收场判定(01)。</td></tr>
|
||||
<tr><td><b>预算与熔断</b></td><td>步数 / token / 时长 / 调人次数四类上限取自契约资源声明,由基座在环外强制——<b>不得由活动代码自查自守</b>;任一触顶即熔断(预算耗尽)。<b>停滞检测</b>:loop = Enabled 集与任务数据皆无变化、且无监听在等的空转;flow = 当前步长期无进展且无监听在等——转受阻或熔断;错误与耗尽不得计为成功。</td></tr>
|
||||
<tr><td><b>监听时限</b></td><td>一切监听必配时限(04 / 05);监听中是健康态,与停滞分开判定。</td></tr>
|
||||
<tr><td><b>中断与恢复</b></td><td><b>控制事件</b>:叫停(转挂起待纠偏,留痕为最重档纠正信号)、暂停、终止(负责人 / 治理台);恢复由事件驱动——挂起期间事件不丢,恢复即补投、断点续跑(任务记忆重建上下文)。</td></tr>
|
||||
</table></div>
|
||||
|
||||
<h3 class="h3"><span class="n">10.2</span>验收分级:L1–L5</h3>
|
||||
<p>契约的验收判据逐条标注验证等级——这是放行卡「成果清单」上每条核对的成色标记:</p>
|
||||
<div class="tbl"><table>
|
||||
<tr><th style="width:70px">级</th><th style="width:130px">谁验</th><th>什么</th></tr>
|
||||
<tr><td><b>L1</b></td><td>引擎 · 自动</td><td>形式:schema 校验、必交付物齐备、格式完整</td></tr>
|
||||
<tr><td><b>L2</b></td><td>引擎 · 自动</td><td>机检:规则与阈值——loop 的前提 ifPart 与 DMN 判据即 L2 的沉入处;约束力收缩的终点</td></tr>
|
||||
<tr><td><b>L3</b></td><td>环内 · 实证</td><td>抽验:试算、干跑、交叉核对——用证据说话</td></tr>
|
||||
<tr><td><b>L4</b></td><td>独立评审</td><td>LLM 评审者独立评审;<b>生成者不得自评</b>;等级不得谎报(L4 不得标注为 L1–L3)</td></tr>
|
||||
<tr><td><b>L5</b></td><td><b>人 · 放行</b></td><td>责任关:放行卡三选一——质量关可全自动,责任关永远是人</td></tr>
|
||||
</table></div>
|
||||
<p class="small">loop 中 L1 / L2 由语义引擎持续预检(红绿灯);flow 中 L1 / L2 是步完成条件的一部分。L1–L4 是质量关,L5 是责任关——判据全绿只是可提交,完成只出自放行通过(06)。</p>
|
||||
|
||||
<h3 class="h3"><span class="n">10.3</span>过程工作区</h3>
|
||||
<p><b>台账的任务级草稿层——可选、组织自设、不绑范式。</b>任务过程产物落在<b>台账的任务级草稿层</b>:同一套「数据域.数据对象.字段」寻址与事务接口,<b>读己之写</b>——本任务可见、正式版不可见、不产生数据事件;引擎的前提求值读<b>任务视图 = 正式版 + 本任务草稿层</b>(04),跨任务监听只认放行后的正式版事件。要不要草稿、按什么 schema 草拟、怎么组织版本,由活动按需设计;系统只认放行门:<b>放行前不落事实</b>——草稿不碰台账正式版与外部系统,放行通过草稿合并入正式版、动作意向执行(06),此刻才产生数据事件。<b>写即持久,断点可续</b>:草稿层与动作意向持久于系统自持存储,没有「保存」动作;任务做一半的续跑由三份持久状态共同保证——<b>任务记忆</b>(按窗口重建上下文,09)、<b>草稿层</b>(截至断点的过程产物与动作意向)、<b>运行时实例状态</b>(loop 的模型定位与就绪集 / flow 的步序位置);打开任务只是打开呈现,过程在后端要么在跑、要么挂起在等。任务记忆与留痕随过程持续归档,不受门限。</p>
|
||||
|
||||
<!-- ========== 11 ========== -->
|
||||
<h2 class="ch"><span class="n">11</span>活动包与开发</h2>
|
||||
<div class="ch-rule"></div>
|
||||
|
||||
<p class="lead">一个活动以<b>一个活动包</b>交付:系统外独立开发、独立测试、独立版本,经<b>活动库</b>的独立入口安装进系统。原则:<b>内容可以有,权力不能有</b>——包内不得持有任何环境能力,一切能力经活动基座的调用契约注入。</p>
|
||||
|
||||
<h3 class="h3"><span class="n">11.1</span>包内容物</h3>
|
||||
<div class="tbl"><table>
|
||||
<tr><th style="width:170px">内容物</th><th>说明</th></tr>
|
||||
<tr><td><b>契约声明</b></td><td>输入 / 输出口 / 必交付物 / 禁区 / 验收判据(分级标注)/ 授权边界 / 资源声明(01)</td></tr>
|
||||
<tr><td><b>范式与业务模型</b></td><td>loop:CMMN XML + 案例说明书(同版本)+ DMN;flow:步序声明(02 / 03 / 05)</td></tr>
|
||||
<tr><td><b>交互内容</b></td><td>视图 HTML 模版 · 四卡内容 schema · 汇报组织(07)</td></tr>
|
||||
<tr><td><b>技能</b></td><td>技能初始版随包播种,以 ID 引用为主、不内嵌——内嵌会使技能升级被迫走发包流程(08)</td></tr>
|
||||
<tr><td><b>监听声明(静态)</b></td><td>loop 的前提与时间监听 / flow 的步完成条件;时限必配(04 / 05)</td></tr>
|
||||
<tr><td><b>Harness 配置</b></td><td>停止条件 · 预算参数 · 时限阶梯 · 失败策略(10)</td></tr>
|
||||
<tr><td><b>纯工具</b></td><td>无外效应的计算 / 转换 / 自持台账操作;安装时注册进工具表、经运行时调用而留痕,不得内联绕过</td></tr>
|
||||
<tr><td><b>台账 schema</b></td><td>活动数据的使用声明,按<b>数据域.数据对象.字段</b>三级寻址;<b>声明的是要用什么字段,不是对象该定义什么字段</b>——对象 schema = 全部使用声明的最大化合并,<b>只增不破坏</b>(版本升级声明多了就长、少了不缩,无迁移);同名字段类型不一致,以能兼容双方的<b>最宽类型</b>落地(放宽即增,静态审提示不阻塞;语义互斥才拦下,交数据管理裁决);共享域同理;操作走基座的通用事务性接口——<b>数据可以自生长</b></td></tr>
|
||||
<tr><td><b>模型声明</b></td><td>活动使用的 LLM 以<b>自定义模型名称</b>(逻辑名)声明;名称背后的实例在系统侧创建绑定(Provider 枚举 / URL / API-Key / Model name,治理台 · 系统管理)——活动不触厂商与密钥;安装静态审核对名称已绑定</td></tr>
|
||||
<tr><td><b>蒸馏钩子</b></td><td>终态封卷 / 里程碑达成时,从任务记忆归纳活动记忆条目(09)</td></tr>
|
||||
<tr><td><b>样例集</b></td><td>样例输入 → 期望输出口与载荷形状;首次安装审(无历史任务记忆时替代回放审)与回归的依据——与工具包的契约测试集同构</td></tr>
|
||||
</table></div>
|
||||
<div class="callout warn"><b>功能工具不随包。</b>按需开发的业务能力工具是独立开发的代码包,经基座的<b>工具箱</b>注册进系统(工具规范另定),账号 / 密钥 / endpoint 配置随工具归组织;活动只声明引用其<b>调用契约</b>。<b>数据可以自生长(schema 声明、宿主物化),权力不可以自生长</b>——功能工具永远先系统、后活动。<b>LLM 工具与人类工具固化在系统里</b>,随系统迭代而更新,声明即用;纯工具可随包。</div>
|
||||
|
||||
<h3 class="h3"><span class="n">11.2</span>开发时序:编排先行,基于声明开发</h3>
|
||||
<ul class="tight">
|
||||
<li><b>编排定契约</b>——<b>工作流编排先于活动开发</b>:治理台画工作流图(编排五要素),节点的输入输出、依赖的工具与模型随图确定——<b>编排工作流的过程,就是定义活动契约的过程</b>;契约是编排给定、开发实现、安装校核的,工作流图是契约的母体。<b>边的载荷映射随图强制闭合</b>——连一条边即须完成上游载荷 → 下游 data 字段的映射,必填未映射、类型冲突的流程包不得发布;新活动的输入输出声明在编排中就地定义、随边成形(《操作系统》03)。</li>
|
||||
<li><b>导出依赖文件</b>——工作流图画完、契约定好,导出开发该工作流活动库的<b>依赖文件(声明 + 编译选项)</b>:所有依赖的<b>接口声明、模型声明、工具声明、输入输出声明</b>。</li>
|
||||
<li><b>基于声明开发与编译</b>——系统外对着声明开发(本地开发宿主:mock 工具表 + 模拟工位(四卡)+ 回放夹具);按活动的<b>编译选项</b>编译出该工作流的<b>多个活动库 .JS</b>——每活动一个编译产物,即活动包。</li>
|
||||
<li><b>导入与装配</b>——活动库 .JS 可<b>批量导入</b>也可<b>单独导入</b>,在活动库中按<b>业务分类(一级)× 活动类型(标准 / 案例)</b>两维分类与版本管理;流程包里按<b>活动名</b>装配:<b>一键自动安装最新版本,或手动控制使用旧版本</b>。</li>
|
||||
<li><b>工具缺口仍契约先行</b>——缺功能工具先定调用契约,活动对声明开发、平台照契约实现注册,两边并行;缺口只阻塞上架(静态审收口),不阻塞开发。</li>
|
||||
</ul>
|
||||
|
||||
<h3 class="h3"><span class="n">11.3</span>安装:活动库入口与两审</h3>
|
||||
<ul class="tight">
|
||||
<li><b>静态审</b>——声明齐备(契约 / 业务模型 / Harness)、工具调用契约核对(装不齐不上架)、schema 校验、无越权代码(无环境能力、无动态执行)、悬空监听拒绝(4.4)、模版无脚本。</li>
|
||||
<li><b>回放审</b>——新版本先在历史任务记忆上重跑:旧败能成、旧成不坏,方可生效(09 同一重演底盘)。</li>
|
||||
<li><b>版本语义</b>——安装恒为新增、版本并存;在途任务按其启动时版本跑完;生效 / 停用 / 卸载由治理台的活动库管理执行。</li>
|
||||
<li><b>资产与包分离版本化</b>——每活动两条版本序列,各有各的门、各自单写者:<b>包版本</b>管代码 / 契约 / 交互模版 / Harness 声明,变更必系统外重编、走本节两审;<b>资产版本</b>管业务模型 / DMN / 技能——包只携<b>初始版</b>(安装时播种入库),此后资产新版由进化管线在系统内产生(回放 + 人放行,09),不重编包;任务装载 = 包版本 + 各资产当前生效版,全部入信封,行为可归因;包新版携带的资产初始版<b>不覆盖</b>已有更高资产版——覆盖只能是显式的资产回退治理动作。</li>
|
||||
</ul>
|
||||
<div class="callout danger"><b>暗耦合禁令:</b>活动间<b>不得共享自持域的数据表</b>。甲活动写表、乙活动直读,输入 / 输出契约即成谎言——流程层的静态检查被表旁路架空。跨活动的事实只有两条路:经<b>输出口载荷</b>交付(流转的事实),或落<b>共享域</b>(沉淀的事实):`共享域.对象.字段`——各活动声明各自要用的字段,schema 最大化合并自生长;写授权按域.对象在契约申报、白名单核准;目录是治理台数据管理的视图。</div>
|
||||
|
||||
<!-- ========== 12 ========== -->
|
||||
<h2 class="ch"><span class="n">12</span>合规判据</h2>
|
||||
<div class="ch-rule"></div>
|
||||
|
||||
<h3 class="h3"><span class="n">12.1</span>通用判据(两范式同守,17 条)</h3>
|
||||
<ul class="checks">
|
||||
<li><b>契约冻结</b>——必须携带机器可校验的输入 / 输出 schema 与验收判据;运行中不得变更契约,变更即新版本。</li>
|
||||
<li><b>无触发器</b>——活动不得内含触发逻辑;启动只经调用方传入输入。</li>
|
||||
<li><b>输入唯一</b>——恰一个输入口,一单任务恰接收一份输入;data 必过 schema 校验,message 不得扩大授权边界。</li>
|
||||
<li><b>业务分支走输出口</b>——业务性的多路结局必须以输出口(必发 / 选择组)表达并随放行发射;不得用异常终态编码业务分支。</li>
|
||||
<li><b>恰一负责人</b>——每单任务必须绑定恰一个负责人;无人环、多人环不得出现。</li>
|
||||
<li><b>完成只出自放行</b>——完成必须且只能由放行卡「放行通过」产生;判据全绿不等于完成;不得存在其他产生「完成」的路径。</li>
|
||||
<li><b>放行前不落事实</b>——过程产物皆为草稿态;写台账、调外部系统、发射输出口集中在放行时点;契约显式预授权的模板动作除外,预授权必须显式列举。</li>
|
||||
<li><b>预检先于放行,落地收敛方成完成</b>——发放行卡前必须完成落地预检(schema · 工具可用与授权 · 连接可达 · 数据冲突),<b>检查可落地才允许放行</b>,预检不过打回环内、不发卡;放行通过即刻落地(附幂等键),落地收敛输出口才发射、终态方成「放行完成」;残余失败走落地失败卡,不得静默成功。</li>
|
||||
<li><b>调人必附上下文</b>——四卡必须携带依据与快照;裸调用必须被基座拒发;调人预算由契约声明并由 Harness 强制。</li>
|
||||
<li><b>监听必配时限</b>——一切监听必须声明时限;无来源又无时限的监听,安装静态审必须拒绝。</li>
|
||||
<li><b>事件幂等</b>——活动对事件的处理必须按事件 ID 幂等;重复投递无副作用。</li>
|
||||
<li><b>留痕完整</b>——任务记忆只追加、信封盖戳、治理先行、归侧标注;原始条目不得修改,信号以回链累加。</li>
|
||||
<li><b>记忆不载权力</b>——活动记忆只有参考力;约束力只经候选增量 + 回放 + 人放行进入业务模型,不得以记忆条目直接拦截或强制。</li>
|
||||
<li><b>蒸馏唯一写入</b>——活动记忆只经蒸馏钩子写入,条目必挂证据链;无证据链的条目不得入库。</li>
|
||||
<li><b>验收等级不得谎报</b>——每条验收判据必须标注真实等级;L4 不得标注为 L1–L3;生成者不得自评。</li>
|
||||
<li><b>无越权代码</b>——活动包不得持有环境能力;一切能力必须经活动基座的调用契约注入。</li>
|
||||
<li><b>活动数据私有</b>——台账必须以 schema 声明、由宿主物化并施治理;活动间不得共享数据表,跨活动事实经输出口或共享对象。</li>
|
||||
</ul>
|
||||
|
||||
<h3 class="h3"><span class="n">12.2</span>loop 判据(8 条)</h3>
|
||||
<ul class="checks">
|
||||
<li><b>生命周期循 CMMN 规范</b>——案计划 / 计划项 / 里程碑三副标准生命周期;引擎与活动均不得私改迁移拓扑、不得发明状态;守卫仅可参数化。</li>
|
||||
<li><b>Enabled ≠ Active</b>——引擎推进到 Enabled 为止;触达世界与关键交付的计划项必须 manualActivationRule = true,启动必出自 Agent 且留痕。</li>
|
||||
<li><b>语义忠实</b>——语义引擎零 LLM、循规范推进;每次迁移与前提求值留痕;语义性前提的裁量评估作为记录留痕。</li>
|
||||
<li><b>能算的不问 LLM</b>——机算前提与 DMN 由语义引擎确定性求值;同输入必同结论。</li>
|
||||
<li><b>结论不可静默覆写</b>——DMN 结论是约束性输入;异议只走「人·决策」或迭代提案。</li>
|
||||
<li><b>模型载事理不载权力</b>——案例模型不得扩大白名单、授权边界与禁区。</li>
|
||||
<li><b>断点判定留痕</b>——调人与立监听必须以「交集为空」的依赖断点为判定依据,判定过程可回放。</li>
|
||||
<li><b>双表示同版本</b>——CMMN XML 与案例说明书同版本发布,不允许分叉;迭代一起放行。</li>
|
||||
</ul>
|
||||
|
||||
<h3 class="h3"><span class="n">12.3</span>flow 判据(6 条)</h3>
|
||||
<ul class="checks">
|
||||
<li><b>步序声明完整</b>——每步的步型 / 入参映射 / 出参写入 / 完成条件 / 失败策略必须齐备;缺项不得上架。</li>
|
||||
<li><b>零临场调度</b>——运行中不得由 LLM 决定步序、跳步或兜底;LLM 只以被调用工具出现。</li>
|
||||
<li><b>条件必谓词</b>——条件跳步与条件执行必须是任务数据上的确定性谓词,由引擎求值。</li>
|
||||
<li><b>复杂路由上升</b>——多路业务分支、临场判断的路由不得在 flow 内表达;必须上升为流程层网关编排,或改用 loop 范式。</li>
|
||||
<li><b>失败路径声明给定</b>——重试策略与兜底(转人 / 受阻)必须在声明中给定;不得临场发明失败处理。</li>
|
||||
<li><b>LLM 步模板冻结</b>——LLM 步的模板与出参 schema 随声明版本冻结;出参必过 schema 校验。</li>
|
||||
</ul>
|
||||
|
||||
<footer class="ft">
|
||||
<span>JCAI · 活动模型 · 活动侧规范 · V2.0 · 关联《操作系统》</span>
|
||||
<span>2026-07-25</span>
|
||||
</footer>
|
||||
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
+677
@@ -0,0 +1,677 @@
|
||||
# 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`),一起提交。只改配置不改文档 = 规则失效
|
||||
|
||||
|
||||
@@ -0,0 +1,160 @@
|
||||
// @ts-check
|
||||
/**
|
||||
* JCAI ESLint 门禁 —— 编码规范 §11.3 + §12.5 禁止清单的可机检部分。
|
||||
* **约束报错时,改代码,不改约束(§11)。**
|
||||
*/
|
||||
import js from '@eslint/js';
|
||||
import tseslint from 'typescript-eslint';
|
||||
import globals from 'globals';
|
||||
|
||||
const MODULE_DOMAIN = 'apps/api/src/modules/*/internal/domain/**/*.ts';
|
||||
|
||||
export default tseslint.config(
|
||||
{
|
||||
ignores: [
|
||||
'**/dist/**',
|
||||
'**/node_modules/**',
|
||||
'api-report/**',
|
||||
'tools/depcruise-tiers.generated.cjs',
|
||||
'docs/**',
|
||||
],
|
||||
},
|
||||
|
||||
js.configs.recommended,
|
||||
...tseslint.configs.recommended,
|
||||
|
||||
{
|
||||
languageOptions: {
|
||||
ecmaVersion: 2023,
|
||||
sourceType: 'module',
|
||||
globals: { ...globals.node },
|
||||
},
|
||||
linterOptions: { reportUnusedDisableDirectives: 'error' },
|
||||
rules: {
|
||||
// §11.3
|
||||
'no-restricted-imports': [
|
||||
'error',
|
||||
{
|
||||
patterns: [
|
||||
{ group: ['**/internal/**'], message: '禁止穿透模块出口(编码规范 §5.2)' },
|
||||
{
|
||||
group: ['@modules/*/*', '@features/*/*'],
|
||||
message: '只能 import 到模块根(编码规范 §5.2)',
|
||||
},
|
||||
{ group: ['../../../*'], message: '跨模块请用路径别名(编码规范 §11.3)' },
|
||||
],
|
||||
},
|
||||
],
|
||||
'@typescript-eslint/no-explicit-any': 'error',
|
||||
'@typescript-eslint/consistent-type-imports': 'error',
|
||||
'@typescript-eslint/ban-ts-comment': 'error',
|
||||
|
||||
// §12.5#4:禁 as unknown as
|
||||
'no-restricted-syntax': [
|
||||
'error',
|
||||
{
|
||||
selector: 'TSAsExpression > TSAsExpression > TSUnknownKeyword',
|
||||
message: '禁止 as unknown as(编码规范 §12.5#4)—— 改类型,不改断言',
|
||||
},
|
||||
],
|
||||
|
||||
// §12.5#6:禁模块级可变状态
|
||||
'no-var': 'error',
|
||||
'prefer-const': 'error',
|
||||
|
||||
'@typescript-eslint/no-unused-vars': [
|
||||
'error',
|
||||
{ argsIgnorePattern: '^_', varsIgnorePattern: '^_' },
|
||||
],
|
||||
},
|
||||
},
|
||||
|
||||
// 模块出口的公开签名必须显式(ADR-005 #3:契约快照才不被 internal 推断类型带偏)
|
||||
{
|
||||
files: ['apps/api/src/modules/**/*.ts'],
|
||||
rules: {
|
||||
'@typescript-eslint/explicit-module-boundary-types': 'error',
|
||||
},
|
||||
},
|
||||
|
||||
// domain/ 零 IO、零 Date.now / Math.random(§5.3 / §12.5#5)
|
||||
{
|
||||
files: [MODULE_DOMAIN],
|
||||
rules: {
|
||||
'no-restricted-properties': [
|
||||
'error',
|
||||
{ object: 'Date', property: 'now', message: 'domain 零时钟:时钟走 port.Clock(§5.3)' },
|
||||
{
|
||||
object: 'Math',
|
||||
property: 'random',
|
||||
message: 'domain 零随机:随机走 port(§5.3)',
|
||||
},
|
||||
],
|
||||
'no-restricted-globals': [
|
||||
'error',
|
||||
{ name: 'fetch', message: 'domain 零 IO(§5.3)' },
|
||||
{ name: 'process', message: 'domain 零环境能力(§5.3)' },
|
||||
],
|
||||
'no-restricted-syntax': [
|
||||
'error',
|
||||
{
|
||||
selector: 'TSAsExpression > TSAsExpression > TSUnknownKeyword',
|
||||
message: '禁止 as unknown as(编码规范 §12.5#4)',
|
||||
},
|
||||
{
|
||||
selector: 'NewExpression[callee.name="Date"][arguments.length=0]',
|
||||
message: 'domain 零时钟:new Date() 走 port.Clock(§5.3)',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
|
||||
// 活动包:零环境能力(ADR-004 / AM 12.1)
|
||||
{
|
||||
files: ['activities/**/*.ts'],
|
||||
rules: {
|
||||
'no-restricted-globals': [
|
||||
'error',
|
||||
{ name: 'fetch', message: '活动包零环境能力:一切能力经基座六件注入(ADR-004)' },
|
||||
{ name: 'process', message: '活动包零环境能力(ADR-004)' },
|
||||
],
|
||||
},
|
||||
},
|
||||
|
||||
// 前端
|
||||
{
|
||||
files: ['apps/web/**/*.{ts,tsx}', 'packages/ui-kit/**/*.{ts,tsx}'],
|
||||
languageOptions: { globals: { ...globals.browser } },
|
||||
rules: {
|
||||
'no-restricted-syntax': [
|
||||
'error',
|
||||
{
|
||||
selector: 'TSAsExpression > TSAsExpression > TSUnknownKeyword',
|
||||
message: '禁止 as unknown as(编码规范 §12.5#4)',
|
||||
},
|
||||
{
|
||||
selector: 'JSXAttribute[name.name="dangerouslySetInnerHTML"]',
|
||||
message:
|
||||
'feature 不得自行 dangerouslySetInnerHTML:活动 HTML 一律经 @ui 的 ViewContainer(§9.2)',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
|
||||
// 前端 feature 内禁裸 fetch(§9.2)
|
||||
{
|
||||
files: ['apps/web/src/features/**/*.{ts,tsx}'],
|
||||
rules: {
|
||||
'no-restricted-globals': [
|
||||
'error',
|
||||
{ name: 'fetch', message: '服务端交互只经 shared/typed-fetch + @contracts/api(§9.2)' },
|
||||
],
|
||||
},
|
||||
},
|
||||
|
||||
// 工具与配置脚本
|
||||
{
|
||||
files: ['tools/**/*.{ts,mjs,js}', '*.config.{ts,js,mjs}', 'vite.config.ts'],
|
||||
rules: { 'no-restricted-syntax': 'off' },
|
||||
},
|
||||
);
|
||||
@@ -0,0 +1,41 @@
|
||||
{
|
||||
"name": "jcai-wos",
|
||||
"version": "0.0.0",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"engines": {
|
||||
"node": ">=22"
|
||||
},
|
||||
"packageManager": "pnpm@10.33.0",
|
||||
"scripts": {
|
||||
"gen:tiers": "node --experimental-strip-types tools/gen-depcruise-tiers.ts",
|
||||
"typecheck": "tsc --noEmit -p tsconfig.node.json && tsc --noEmit -p tsconfig.web.json",
|
||||
"lint": "eslint .",
|
||||
"depcruise": "depcruise apps packages activities",
|
||||
"api:check": "node tools/api-report.mjs",
|
||||
"test": "vitest run",
|
||||
"gates": "pnpm gen:tiers && pnpm typecheck && pnpm lint && pnpm depcruise && pnpm api:check && pnpm test",
|
||||
"db:up": "docker compose up -d",
|
||||
"db:down": "docker compose down",
|
||||
"db:seed": "pnpm --filter @app/api seed",
|
||||
"dev:api": "pnpm --filter @app/api dev",
|
||||
"dev:web": "pnpm --filter @app/web dev"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@eslint/js": "^9.39.0",
|
||||
"@types/node": "^22.10.2",
|
||||
"dependency-cruiser": "^16.10.4",
|
||||
"drizzle-kit": "^0.31.5",
|
||||
"eslint": "^9.39.0",
|
||||
"globals": "^16.5.0",
|
||||
"tsup": "^8.5.0",
|
||||
"typescript": "^5.9.3",
|
||||
"typescript-eslint": "^8.46.0",
|
||||
"vitest": "^3.2.4"
|
||||
},
|
||||
"pnpm": {
|
||||
"onlyBuiltDependencies": [
|
||||
"esbuild"
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"name": "@sdk",
|
||||
"version": "0.0.0",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"exports": { ".": "./src/index.ts" }
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
/**
|
||||
* @sdk —— 活动开发面(编码规范 §8.2):基座六件接口 + defineActivity() + 本地开发宿主 + 回放夹具。
|
||||
* 活动包 ABI 见 ADR-004。
|
||||
*/
|
||||
export const SDK_VERSION = '0.0.0-m0';
|
||||
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"name": "@contracts",
|
||||
"version": "0.0.0",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"exports": { ".": "./src/index.ts" }
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
/**
|
||||
* @contracts —— 前后端唯一共享点(编码规范 §8.1)。
|
||||
* 只有 zod schema、常量、品牌类型与推导类型,零实现。
|
||||
* 修改本包任何导出 = 契约变更(§12.4)。
|
||||
*/
|
||||
export const CONTRACTS_VERSION = '0.0.0-m0';
|
||||
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"name": "@sfeel",
|
||||
"version": "0.0.0",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"exports": { ".": "./src/index.ts" }
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
/**
|
||||
* @sfeel —— S-FEEL 子集(OS 03 定义域)的解析与求值,纯函数(编码规范 §8.3)。
|
||||
* 被 process / flow-engine / trigger 与前端 gov-process 共用:求值语义一份代码,前后端同源。
|
||||
*/
|
||||
export const SFEEL_VERSION = '0.0.0-m0';
|
||||
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"name": "@ui",
|
||||
"version": "0.0.0",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"exports": { ".": "./src/index.ts" }
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
/**
|
||||
* @ui —— 无业务语义展示组件(卡片原语 / 时间线 / 净化视图容器 ViewContainer)。
|
||||
*/
|
||||
export const UI_KIT_VERSION = '0.0.0-m0';
|
||||
@@ -0,0 +1,31 @@
|
||||
import { describe, expect, it } from 'vitest';
|
||||
import { assertNever, groupBy, isDefined, sortedEntries } from '../src/index.ts';
|
||||
|
||||
describe('@utils', () => {
|
||||
it('isDefined 滤掉 null 与 undefined', () => {
|
||||
expect([1, null, 2, undefined].filter(isDefined)).toEqual([1, 2]);
|
||||
});
|
||||
|
||||
it('groupBy 按键分组', () => {
|
||||
const rows = [
|
||||
{ pn: 'A', type: 'A' as const },
|
||||
{ pn: 'B', type: 'B' as const },
|
||||
{ pn: 'C', type: 'A' as const },
|
||||
];
|
||||
expect(groupBy(rows, (r) => r.type)).toEqual({
|
||||
A: [rows[0], rows[2]],
|
||||
B: [rows[1]],
|
||||
});
|
||||
});
|
||||
|
||||
it('sortedEntries 稳定排序', () => {
|
||||
expect(sortedEntries({ b: 2, a: 1 })).toEqual([
|
||||
['a', 1],
|
||||
['b', 2],
|
||||
]);
|
||||
});
|
||||
|
||||
it('assertNever 抛错', () => {
|
||||
expect(() => assertNever('x' as never)).toThrow('未覆盖的分支');
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"name": "@utils",
|
||||
"version": "0.0.0",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"exports": { ".": "./src/index.ts" }
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
/**
|
||||
* @utils —— 纯函数,零依赖(编码规范 §2 / §5.1:叶子包)。
|
||||
* 无业务语义;有业务语义的东西不属于这里。
|
||||
*/
|
||||
|
||||
/** 穷尽性检查:switch 漏分支时编译期报错 */
|
||||
export function assertNever(value: never, message = '未覆盖的分支'): never {
|
||||
throw new Error(`${message}: ${JSON.stringify(value)}`);
|
||||
}
|
||||
|
||||
/** 类型守卫:滤掉 null / undefined */
|
||||
export function isDefined<T>(value: T | null | undefined): value is T {
|
||||
return value !== null && value !== undefined;
|
||||
}
|
||||
|
||||
/** 按键分组 */
|
||||
export function groupBy<T, K extends string>(items: readonly T[], key: (item: T) => K): Record<K, T[]> {
|
||||
const out = {} as Record<K, T[]>;
|
||||
for (const item of items) {
|
||||
const k = key(item);
|
||||
(out[k] ??= []).push(item);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
/** 稳定排序的键值对遍历(避免 Object.keys 顺序依赖) */
|
||||
export function sortedEntries<V>(record: Readonly<Record<string, V>>): Array<[string, V]> {
|
||||
return Object.entries(record).sort(([a], [b]) => (a < b ? -1 : a > b ? 1 : 0));
|
||||
}
|
||||
Generated
+3752
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,6 @@
|
||||
packages:
|
||||
- 'apps/*'
|
||||
- 'packages/*'
|
||||
- 'activities/*'
|
||||
# §11.2 更硬的封装:每个后端模块是一个 workspace 包,exports 只开 index.ts
|
||||
- 'apps/api/src/modules/*'
|
||||
@@ -0,0 +1,107 @@
|
||||
#!/usr/bin/env node
|
||||
/**
|
||||
* 契约快照门禁 —— 编码规范 §11.5。
|
||||
*
|
||||
* tsc --emitDeclarationOnly 出全量 .d.ts,只留**契约面**落 api-report/:
|
||||
* - packages/contracts/** (前后端唯一共享点,§8.1)
|
||||
* - packages/<pkg>/src/index.d.ts
|
||||
* - apps/api/src/modules/<m>/{index,contract,port}.d.ts
|
||||
* 然后与 git 比对:改 internal/ 时 api-report/ 纹丝不动;碰了公开契约,diff 立刻可见。
|
||||
*/
|
||||
import { execFileSync } from 'node:child_process';
|
||||
import { cpSync, existsSync, mkdirSync, readdirSync, rmSync, statSync } from 'node:fs';
|
||||
import { dirname, join, relative, sep } from 'node:path';
|
||||
import { fileURLToPath } from 'node:url';
|
||||
|
||||
const root = dirname(dirname(fileURLToPath(import.meta.url)));
|
||||
const tmp = join(root, '.api-tmp');
|
||||
const out = join(root, 'api-report');
|
||||
|
||||
function run(cmd, args, opts = {}) {
|
||||
return execFileSync(cmd, args, { cwd: root, encoding: 'utf8', stdio: 'pipe', ...opts });
|
||||
}
|
||||
|
||||
rmSync(tmp, { recursive: true, force: true });
|
||||
|
||||
try {
|
||||
run('node', [
|
||||
join(root, 'node_modules', 'typescript', 'bin', 'tsc'),
|
||||
'-p',
|
||||
'tsconfig.node.json',
|
||||
'--emitDeclarationOnly',
|
||||
'--declaration',
|
||||
'--noEmit',
|
||||
'false',
|
||||
'--outDir',
|
||||
'.api-tmp',
|
||||
]);
|
||||
} catch (err) {
|
||||
process.stderr.write((err.stdout ?? '') + (err.stderr ?? ''));
|
||||
process.stderr.write('\napi:check —— 声明生成失败,先修 tsc。\n');
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
/** 契约面判据:相对 .api-tmp 的路径 */
|
||||
function isContractFace(rel) {
|
||||
const p = rel.split(sep).join('/');
|
||||
if (p.startsWith('packages/contracts/')) return true;
|
||||
if (/^packages\/[^/]+\/src\/index\.d\.ts$/.test(p)) return true;
|
||||
if (/^apps\/api\/src\/modules\/[^/]+\/(index|contract|port)\.d\.ts$/.test(p)) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
function walk(dir, acc = []) {
|
||||
if (!existsSync(dir)) return acc;
|
||||
for (const name of readdirSync(dir)) {
|
||||
const full = join(dir, name);
|
||||
if (statSync(full).isDirectory()) walk(full, acc);
|
||||
else if (full.endsWith('.d.ts')) acc.push(full);
|
||||
}
|
||||
return acc;
|
||||
}
|
||||
|
||||
rmSync(out, { recursive: true, force: true });
|
||||
mkdirSync(out, { recursive: true });
|
||||
|
||||
let kept = 0;
|
||||
for (const file of walk(tmp)) {
|
||||
const rel = relative(tmp, file);
|
||||
if (!isContractFace(rel)) continue;
|
||||
const dest = join(out, rel);
|
||||
mkdirSync(dirname(dest), { recursive: true });
|
||||
cpSync(file, dest);
|
||||
kept += 1;
|
||||
}
|
||||
rmSync(tmp, { recursive: true, force: true });
|
||||
|
||||
process.stdout.write(`api:check —— 契约面 ${kept} 个声明文件 → api-report/\n`);
|
||||
|
||||
if (process.argv.includes('--update')) {
|
||||
process.stdout.write('api:check —— --update:已刷新快照,请连同变更申请一并提交。\n');
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
let status = '';
|
||||
try {
|
||||
status = run('git', ['status', '--porcelain', '--', 'api-report']);
|
||||
} catch {
|
||||
process.stdout.write('api:check —— 非 git 仓库,跳过比对。\n');
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
if (status.trim() === '') {
|
||||
process.stdout.write('api:check —— 公开契约无变化 ✔\n');
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
process.stderr.write('\napi:check —— 公开契约发生变化(§12.4):\n' + status + '\n');
|
||||
try {
|
||||
process.stderr.write(run('git', ['diff', '--', 'api-report']));
|
||||
} catch {
|
||||
/* 首次建立基线时无 diff 可打 */
|
||||
}
|
||||
process.stderr.write(
|
||||
'\n契约变更须:①depcruise 反查下游 ②同步 CONTRACT.md ③本快照单独说明 ④破坏性走三步弃用。\n' +
|
||||
'确认无误后:pnpm api:check --update && git add api-report\n',
|
||||
);
|
||||
process.exit(1);
|
||||
@@ -0,0 +1,237 @@
|
||||
/* eslint-disable */
|
||||
/**
|
||||
* 本文件由 tools/gen-depcruise-tiers.ts 从 tools/module-tiers.json 生成。
|
||||
* 请勿手改 —— 改层级请改 module-tiers.json 与 编码规范.md §4,然后 pnpm gen:tiers。
|
||||
*/
|
||||
module.exports = [
|
||||
{
|
||||
"name": "tier-order-activity-registry",
|
||||
"comment": "模块 activity-registry(L4)只准依赖更低层级模块;同层互需一律 port + app 装配(编码规范 §4 / §5.2)",
|
||||
"severity": "error",
|
||||
"from": {
|
||||
"path": "^apps/api/src/modules/activity-registry/"
|
||||
},
|
||||
"to": {
|
||||
"path": "^apps/api/src/modules/(flow-engine|loop-engine|minute|process|release|report|skill-engine|task|trigger)/"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "tier-order-channel",
|
||||
"comment": "模块 channel(L2)只准依赖更低层级模块;同层互需一律 port + app 装配(编码规范 §4 / §5.2)",
|
||||
"severity": "error",
|
||||
"from": {
|
||||
"path": "^apps/api/src/modules/channel/"
|
||||
},
|
||||
"to": {
|
||||
"path": "^apps/api/src/modules/(activity-registry|flow-engine|human-tool|interaction|loop-engine|memory|message|minute|process|release|report|skill-engine|task|toolbox|trigger)/"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "tier-order-event",
|
||||
"comment": "模块 event(L1)只准依赖更低层级模块;同层互需一律 port + app 装配(编码规范 §4 / §5.2)",
|
||||
"severity": "error",
|
||||
"from": {
|
||||
"path": "^apps/api/src/modules/event/"
|
||||
},
|
||||
"to": {
|
||||
"path": "^apps/api/src/modules/(activity-registry|channel|flow-engine|human-tool|interaction|ledger|llm|loop-engine|memory|message|minute|org|process|release|report|skill-engine|task|toolbox|trigger)/"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "tier-order-flow-engine",
|
||||
"comment": "模块 flow-engine(L5)只准依赖更低层级模块;同层互需一律 port + app 装配(编码规范 §4 / §5.2)",
|
||||
"severity": "error",
|
||||
"from": {
|
||||
"path": "^apps/api/src/modules/flow-engine/"
|
||||
},
|
||||
"to": {
|
||||
"path": "^apps/api/src/modules/(loop-engine|minute|process|report|task|trigger)/"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "tier-order-human-tool",
|
||||
"comment": "模块 human-tool(L3)只准依赖更低层级模块;同层互需一律 port + app 装配(编码规范 §4 / §5.2)",
|
||||
"severity": "error",
|
||||
"from": {
|
||||
"path": "^apps/api/src/modules/human-tool/"
|
||||
},
|
||||
"to": {
|
||||
"path": "^apps/api/src/modules/(activity-registry|flow-engine|interaction|loop-engine|minute|process|release|report|skill-engine|task|trigger)/"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "tier-order-interaction",
|
||||
"comment": "模块 interaction(L3)只准依赖更低层级模块;同层互需一律 port + app 装配(编码规范 §4 / §5.2)",
|
||||
"severity": "error",
|
||||
"from": {
|
||||
"path": "^apps/api/src/modules/interaction/"
|
||||
},
|
||||
"to": {
|
||||
"path": "^apps/api/src/modules/(activity-registry|flow-engine|human-tool|loop-engine|minute|process|release|report|skill-engine|task|trigger)/"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "tier-order-ledger",
|
||||
"comment": "模块 ledger(L1)只准依赖更低层级模块;同层互需一律 port + app 装配(编码规范 §4 / §5.2)",
|
||||
"severity": "error",
|
||||
"from": {
|
||||
"path": "^apps/api/src/modules/ledger/"
|
||||
},
|
||||
"to": {
|
||||
"path": "^apps/api/src/modules/(activity-registry|channel|event|flow-engine|human-tool|interaction|llm|loop-engine|memory|message|minute|org|process|release|report|skill-engine|task|toolbox|trigger)/"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "tier-order-llm",
|
||||
"comment": "模块 llm(L1)只准依赖更低层级模块;同层互需一律 port + app 装配(编码规范 §4 / §5.2)",
|
||||
"severity": "error",
|
||||
"from": {
|
||||
"path": "^apps/api/src/modules/llm/"
|
||||
},
|
||||
"to": {
|
||||
"path": "^apps/api/src/modules/(activity-registry|channel|event|flow-engine|human-tool|interaction|ledger|loop-engine|memory|message|minute|org|process|release|report|skill-engine|task|toolbox|trigger)/"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "tier-order-loop-engine",
|
||||
"comment": "模块 loop-engine(L5)只准依赖更低层级模块;同层互需一律 port + app 装配(编码规范 §4 / §5.2)",
|
||||
"severity": "error",
|
||||
"from": {
|
||||
"path": "^apps/api/src/modules/loop-engine/"
|
||||
},
|
||||
"to": {
|
||||
"path": "^apps/api/src/modules/(flow-engine|minute|process|report|task|trigger)/"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "tier-order-memory",
|
||||
"comment": "模块 memory(L2)只准依赖更低层级模块;同层互需一律 port + app 装配(编码规范 §4 / §5.2)",
|
||||
"severity": "error",
|
||||
"from": {
|
||||
"path": "^apps/api/src/modules/memory/"
|
||||
},
|
||||
"to": {
|
||||
"path": "^apps/api/src/modules/(activity-registry|channel|flow-engine|human-tool|interaction|loop-engine|message|minute|process|release|report|skill-engine|task|toolbox|trigger)/"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "tier-order-message",
|
||||
"comment": "模块 message(L2)只准依赖更低层级模块;同层互需一律 port + app 装配(编码规范 §4 / §5.2)",
|
||||
"severity": "error",
|
||||
"from": {
|
||||
"path": "^apps/api/src/modules/message/"
|
||||
},
|
||||
"to": {
|
||||
"path": "^apps/api/src/modules/(activity-registry|channel|flow-engine|human-tool|interaction|loop-engine|memory|minute|process|release|report|skill-engine|task|toolbox|trigger)/"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "tier-order-minute",
|
||||
"comment": "模块 minute(L8)只准依赖更低层级模块;同层互需一律 port + app 装配(编码规范 §4 / §5.2)",
|
||||
"severity": "error",
|
||||
"from": {
|
||||
"path": "^apps/api/src/modules/minute/"
|
||||
},
|
||||
"to": {
|
||||
"path": "^apps/api/src/modules/(report)/"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "tier-order-org",
|
||||
"comment": "模块 org(L1)只准依赖更低层级模块;同层互需一律 port + app 装配(编码规范 §4 / §5.2)",
|
||||
"severity": "error",
|
||||
"from": {
|
||||
"path": "^apps/api/src/modules/org/"
|
||||
},
|
||||
"to": {
|
||||
"path": "^apps/api/src/modules/(activity-registry|channel|event|flow-engine|human-tool|interaction|ledger|llm|loop-engine|memory|message|minute|process|release|report|skill-engine|task|toolbox|trigger)/"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "tier-order-process",
|
||||
"comment": "模块 process(L7)只准依赖更低层级模块;同层互需一律 port + app 装配(编码规范 §4 / §5.2)",
|
||||
"severity": "error",
|
||||
"from": {
|
||||
"path": "^apps/api/src/modules/process/"
|
||||
},
|
||||
"to": {
|
||||
"path": "^apps/api/src/modules/(minute|report|trigger)/"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "tier-order-release",
|
||||
"comment": "模块 release(L4)只准依赖更低层级模块;同层互需一律 port + app 装配(编码规范 §4 / §5.2)",
|
||||
"severity": "error",
|
||||
"from": {
|
||||
"path": "^apps/api/src/modules/release/"
|
||||
},
|
||||
"to": {
|
||||
"path": "^apps/api/src/modules/(activity-registry|flow-engine|loop-engine|minute|process|report|skill-engine|task|trigger)/"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "tier-order-report",
|
||||
"comment": "模块 report(L8)只准依赖更低层级模块;同层互需一律 port + app 装配(编码规范 §4 / §5.2)",
|
||||
"severity": "error",
|
||||
"from": {
|
||||
"path": "^apps/api/src/modules/report/"
|
||||
},
|
||||
"to": {
|
||||
"path": "^apps/api/src/modules/(minute)/"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "tier-order-skill-engine",
|
||||
"comment": "模块 skill-engine(L4)只准依赖更低层级模块;同层互需一律 port + app 装配(编码规范 §4 / §5.2)",
|
||||
"severity": "error",
|
||||
"from": {
|
||||
"path": "^apps/api/src/modules/skill-engine/"
|
||||
},
|
||||
"to": {
|
||||
"path": "^apps/api/src/modules/(activity-registry|flow-engine|loop-engine|minute|process|release|report|task|trigger)/"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "tier-order-task",
|
||||
"comment": "模块 task(L6)只准依赖更低层级模块;同层互需一律 port + app 装配(编码规范 §4 / §5.2)",
|
||||
"severity": "error",
|
||||
"from": {
|
||||
"path": "^apps/api/src/modules/task/"
|
||||
},
|
||||
"to": {
|
||||
"path": "^apps/api/src/modules/(minute|process|report|trigger)/"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "tier-order-toolbox",
|
||||
"comment": "模块 toolbox(L2)只准依赖更低层级模块;同层互需一律 port + app 装配(编码规范 §4 / §5.2)",
|
||||
"severity": "error",
|
||||
"from": {
|
||||
"path": "^apps/api/src/modules/toolbox/"
|
||||
},
|
||||
"to": {
|
||||
"path": "^apps/api/src/modules/(activity-registry|channel|flow-engine|human-tool|interaction|loop-engine|memory|message|minute|process|release|report|skill-engine|task|trigger)/"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "tier-order-trigger",
|
||||
"comment": "模块 trigger(L7)只准依赖更低层级模块;同层互需一律 port + app 装配(编码规范 §4 / §5.2)",
|
||||
"severity": "error",
|
||||
"from": {
|
||||
"path": "^apps/api/src/modules/trigger/"
|
||||
},
|
||||
"to": {
|
||||
"path": "^apps/api/src/modules/(minute|process|report)/"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "module-registered-in-tiers",
|
||||
"comment": "modules/ 下的每个模块必须登记在 tools/module-tiers.json(编码规范 §16)",
|
||||
"severity": "error",
|
||||
"from": {},
|
||||
"to": {
|
||||
"path": "^apps/api/src/modules/([^/]+)/",
|
||||
"pathNot": "^apps/api/src/modules/(activity-registry|channel|event|flow-engine|human-tool|interaction|ledger|llm|loop-engine|memory|message|minute|org|process|release|report|skill-engine|task|toolbox|trigger)/"
|
||||
}
|
||||
}
|
||||
];
|
||||
@@ -0,0 +1,97 @@
|
||||
/**
|
||||
* 从 tools/module-tiers.json(编码规范 §4 层级表的机器形式)生成 depcruise 的
|
||||
* tier-order 规则,写入 tools/depcruise-tiers.generated.cjs。
|
||||
*
|
||||
* 规则语义(§5.2):模块只准 import §4 表中**层级更低**者的 index.ts;
|
||||
* 同层互不 import(协作走 port + app 装配),更高层当然也不行。
|
||||
*
|
||||
* 运行:pnpm gen:tiers(gates 的第一步,产物入库,diff 即规则变更)
|
||||
*/
|
||||
import { readFileSync, writeFileSync } from 'node:fs';
|
||||
import { fileURLToPath } from 'node:url';
|
||||
import { dirname, join } from 'node:path';
|
||||
|
||||
const here = dirname(fileURLToPath(import.meta.url));
|
||||
const tiersPath = join(here, 'module-tiers.json');
|
||||
const outPath = join(here, 'depcruise-tiers.generated.cjs');
|
||||
|
||||
type TierTable = { tiers: Record<string, string[]> };
|
||||
|
||||
const raw = readFileSync(tiersPath, 'utf8');
|
||||
const table = JSON.parse(raw) as TierTable;
|
||||
|
||||
const modulesBase = '^apps/api/src/modules';
|
||||
|
||||
/** 模块名 → 层级 */
|
||||
const tierOf = new Map<string, number>();
|
||||
for (const [tier, modules] of Object.entries(table.tiers)) {
|
||||
for (const m of modules) {
|
||||
if (tierOf.has(m)) throw new Error(`模块 ${m} 在层级表中重复出现`);
|
||||
tierOf.set(m, Number(tier));
|
||||
}
|
||||
}
|
||||
|
||||
const allModules = [...tierOf.keys()].sort();
|
||||
|
||||
type Rule = {
|
||||
name: string;
|
||||
comment: string;
|
||||
severity: 'error';
|
||||
from: { path: string };
|
||||
to: { path: string };
|
||||
};
|
||||
|
||||
const rules: Rule[] = [];
|
||||
|
||||
for (const from of allModules) {
|
||||
const fromTier = tierOf.get(from)!;
|
||||
// 不得依赖的模块 = 同层其它模块 + 全部更高层模块
|
||||
const forbidden = allModules.filter((to) => to !== from && tierOf.get(to)! >= fromTier);
|
||||
if (forbidden.length === 0) continue;
|
||||
rules.push({
|
||||
name: `tier-order-${from}`,
|
||||
comment:
|
||||
`模块 ${from}(L${fromTier})只准依赖更低层级模块;` +
|
||||
`同层互需一律 port + app 装配(编码规范 §4 / §5.2)`,
|
||||
severity: 'error',
|
||||
from: { path: `${modulesBase}/${from}/` },
|
||||
to: { path: `${modulesBase}/(${forbidden.join('|')})/` },
|
||||
});
|
||||
}
|
||||
|
||||
// 未登记模块拦截:modules/ 下出现层级表里没有的目录即报错(§16 检查清单第一条)
|
||||
const knownGroup = allModules.join('|');
|
||||
|
||||
const banner = `/* eslint-disable */
|
||||
/**
|
||||
* 本文件由 tools/gen-depcruise-tiers.ts 从 tools/module-tiers.json 生成。
|
||||
* 请勿手改 —— 改层级请改 module-tiers.json 与 编码规范.md §4,然后 pnpm gen:tiers。
|
||||
*/
|
||||
`;
|
||||
|
||||
const body =
|
||||
banner +
|
||||
'module.exports = ' +
|
||||
JSON.stringify(
|
||||
[
|
||||
...rules,
|
||||
{
|
||||
name: 'module-registered-in-tiers',
|
||||
comment: 'modules/ 下的每个模块必须登记在 tools/module-tiers.json(编码规范 §16)',
|
||||
severity: 'error',
|
||||
from: {},
|
||||
to: {
|
||||
path: `${modulesBase}/([^/]+)/`,
|
||||
pathNot: `${modulesBase}/(${knownGroup})/`,
|
||||
},
|
||||
},
|
||||
],
|
||||
null,
|
||||
2,
|
||||
) +
|
||||
';\n';
|
||||
|
||||
writeFileSync(outPath, body, 'utf8');
|
||||
process.stdout.write(
|
||||
`gen-depcruise-tiers: ${rules.length + 1} 条规则 → tools/depcruise-tiers.generated.cjs\n`,
|
||||
);
|
||||
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"$comment": "编码规范 §4 后端模块层级表的机器形式。改层级 = 改本文件 + 改 编码规范.md §4,一起提交(§11.4)。",
|
||||
"tiers": {
|
||||
"1": ["event", "org", "llm", "ledger"],
|
||||
"2": ["memory", "toolbox", "channel", "message"],
|
||||
"3": ["interaction", "human-tool"],
|
||||
"4": ["release", "activity-registry", "skill-engine"],
|
||||
"5": ["loop-engine", "flow-engine"],
|
||||
"6": ["task"],
|
||||
"7": ["process", "trigger"],
|
||||
"8": ["minute", "report"]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/tsconfig",
|
||||
"compilerOptions": {
|
||||
"target": "ES2023",
|
||||
"module": "ESNext",
|
||||
"moduleResolution": "bundler",
|
||||
"strict": true,
|
||||
"noUncheckedIndexedAccess": true,
|
||||
"exactOptionalPropertyTypes": true,
|
||||
"noImplicitOverride": true,
|
||||
"noImplicitReturns": true,
|
||||
"noFallthroughCasesInSwitch": true,
|
||||
"noUnusedLocals": true,
|
||||
"noUnusedParameters": true,
|
||||
"verbatimModuleSyntax": true,
|
||||
"isolatedModules": true,
|
||||
"resolveJsonModule": true,
|
||||
"skipLibCheck": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"allowImportingTsExtensions": true,
|
||||
"noEmit": true,
|
||||
"baseUrl": ".",
|
||||
"paths": {
|
||||
"@contracts": ["./packages/contracts/src/index.ts"],
|
||||
"@contracts/*": ["./packages/contracts/src/*"],
|
||||
"@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/*"],
|
||||
"@shared/*": ["./apps/api/src/shared/*"],
|
||||
"@web-shared/*": ["./apps/web/src/shared/*"]
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"extends": "./tsconfig.base.json",
|
||||
"files": [],
|
||||
"references": [{ "path": "./tsconfig.node.json" }, { "path": "./tsconfig.web.json" }]
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
{
|
||||
"extends": "./tsconfig.base.json",
|
||||
"compilerOptions": {
|
||||
"lib": ["ES2023"],
|
||||
"types": ["node"]
|
||||
},
|
||||
"include": [
|
||||
"apps/api/**/*.ts",
|
||||
"packages/contracts/**/*.ts",
|
||||
"packages/activity-sdk/**/*.ts",
|
||||
"packages/sfeel/**/*.ts",
|
||||
"packages/utils/**/*.ts",
|
||||
"activities/**/*.ts",
|
||||
"tools/**/*.ts"
|
||||
],
|
||||
"exclude": ["**/dist/**", "**/node_modules/**"]
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
{
|
||||
"extends": "./tsconfig.base.json",
|
||||
"compilerOptions": {
|
||||
"lib": [
|
||||
"ES2023",
|
||||
"DOM",
|
||||
"DOM.Iterable"
|
||||
],
|
||||
"jsx": "react-jsx"
|
||||
},
|
||||
"include": [
|
||||
"apps/web/**/*.ts",
|
||||
"apps/web/**/*.tsx",
|
||||
"packages/ui-kit/**/*.ts",
|
||||
"packages/ui-kit/**/*.tsx",
|
||||
"apps/web/src/vite-env.d.ts"
|
||||
],
|
||||
"exclude": [
|
||||
"**/dist/**",
|
||||
"**/node_modules/**"
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
import { defineConfig } from 'vitest/config';
|
||||
import { fileURLToPath } from 'node:url';
|
||||
|
||||
const p = (rel: string) => fileURLToPath(new URL(rel, import.meta.url));
|
||||
|
||||
export default defineConfig({
|
||||
resolve: {
|
||||
alias: {
|
||||
'@contracts': p('./packages/contracts/src/index.ts'),
|
||||
'@sdk': p('./packages/activity-sdk/src/index.ts'),
|
||||
'@sfeel': p('./packages/sfeel/src/index.ts'),
|
||||
'@ui': p('./packages/ui-kit/src/index.ts'),
|
||||
'@utils': p('./packages/utils/src/index.ts'),
|
||||
'@modules': p('./apps/api/src/modules'),
|
||||
'@shared': p('./apps/api/src/shared'),
|
||||
},
|
||||
},
|
||||
test: {
|
||||
include: ['{apps,packages,activities}/**/__tests__/**/*.test.ts', '{apps,packages}/**/*.test.ts'],
|
||||
exclude: ['**/node_modules/**', '**/dist/**'],
|
||||
passWithNoTests: true,
|
||||
environment: 'node',
|
||||
},
|
||||
});
|
||||
Reference in New Issue
Block a user