Archived
M1: 底座 —— @contracts 首版 + event / ledger / org / llm
@contracts 首版(§8.1 九个文件): - id 品牌 ID / terminal 终态五名与归侧四标签 / envelope 信封六字段与四类事件 - card 工单两模式 + 对话卡族(形状对齐 2026-07-26 原型定稿) - contract7 契约七件 / ledger 三级寻址与写三分 / process-package 流程包 DSL 与触发器三类 - manifest 活动包清单六区(含 CMMN·DMN·步序声明的资产形状)/ org / api 路由契约 模块(L1): - event 信封存储、归属解析三级短路、投递五诺、监听注册表、三级消费裁定 - ledger schema 自生长(最大化合并/最宽类型/只增不破坏)、任务视图叠加、写三分、冲突检查 - org 岗位授权(客体三类×动作三种)、停用前置检查、会话、种子播种 - llm 四元绑定、ModelGateway 三模式(live/record/replay)—— 两缝之一 app 装配:Hono 服务 + 鉴权中间件 + 治理台/工作台路由;drizzle 迁移;AES-256-GCM 凭证密封 ADR-007 工具链与门禁 · ADR-008 投递队列 · ADR-009 凭证加密 (ADR 编号自 007 续:编码规范 §14 已用到 006,README 写「从 005 续」是笔误) 门禁五道全绿;96 个测试通过,含对真实 PG 的 ledger 集成测试 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KeDBx2PHLavbURXB8LJJ7m
This commit is contained in:
co-authored by
Claude Opus 5
parent
7cd664af3a
commit
14d4fa046a
@@ -0,0 +1,180 @@
|
||||
/**
|
||||
* 契约七件(编码规范 §8.1;语义出处 OS 4.1,AM 01)。
|
||||
*
|
||||
* 契约是活动对调用方暴露的全部真相,也是对 Agent 机制的全部授权;
|
||||
* 两种范式同一契约格式 —— 这是「统一套执行契约」的锚点。
|
||||
* 契约必须在活动启动前冻结;运行中不得变更 —— 变更即新版本。
|
||||
*
|
||||
* ADR-003:**声明层 = JSON Schema 2020-12 子集**(活动声明是运行时数据,可 diff 可版本),
|
||||
* 代码层 = zod。本文件用 zod 描述「声明的形状」,声明里的 schema 字段本身是 JSON Schema。
|
||||
*/
|
||||
import { z } from 'zod';
|
||||
import { acceptanceLevelSchema } from './terminal.ts';
|
||||
import { activityIdSchema, skillIdSchema } from './id.ts';
|
||||
|
||||
/** JSON Schema 2020-12 子集的运行时形态 —— 由 ajv 校验,不在编译期展开 */
|
||||
export const jsonSchemaSchema = z.record(z.string(), z.unknown());
|
||||
export type JsonSchema = z.infer<typeof jsonSchemaSchema>;
|
||||
|
||||
/* ── ① 输入口:单一入口,data + message ──────────────────────────────── */
|
||||
|
||||
export const contractInputSchema = z.object({
|
||||
/** data:结构化载荷,按 schema 校验,缺项不得启动 */
|
||||
data: jsonSchemaSchema,
|
||||
/** message:委托消息(自然语言),可为空;**不得携带扩大授权的效力** */
|
||||
messageAllowed: z.boolean().default(true),
|
||||
messageHint: z.string().optional(),
|
||||
});
|
||||
export type ContractInput = z.infer<typeof contractInputSchema>;
|
||||
|
||||
/* ── ② 输出口:必发(AND)与选择组(XOR) ──────────────────────────── */
|
||||
|
||||
export const outputPortSchema = z.object({
|
||||
name: z.string().min(1),
|
||||
/** 交付物 schema —— 调用方仅凭口名与 schema 即可衔接下游 */
|
||||
payload: jsonSchemaSchema,
|
||||
description: z.string().optional(),
|
||||
});
|
||||
export type OutputPort = z.infer<typeof outputPortSchema>;
|
||||
|
||||
export const outputPortsSchema = z.object({
|
||||
/** 必发口:每次「放行完成」必发;可多口,同时发射 */
|
||||
mandatory: z.array(outputPortSchema).default([]),
|
||||
/** 选择组:组内恰发一口;选择由环内决断,在放行(验收工单)上一并确认 */
|
||||
selective: z
|
||||
.array(
|
||||
z.object({
|
||||
group: z.string().min(1),
|
||||
ports: z.array(outputPortSchema).min(2),
|
||||
}),
|
||||
)
|
||||
.default([]),
|
||||
});
|
||||
export type OutputPorts = z.infer<typeof outputPortsSchema>;
|
||||
|
||||
/* ── ③ 必交付物 ─────────────────────────────────────────────────────── */
|
||||
|
||||
export const requiredDeliverableSchema = z.object({
|
||||
key: z.string().min(1),
|
||||
label: z.string(),
|
||||
/** 缺一不得提交放行 —— 验收工单「成果清单」的来源 */
|
||||
schema: jsonSchemaSchema.optional(),
|
||||
});
|
||||
export type RequiredDeliverable = z.infer<typeof requiredDeliverableSchema>;
|
||||
|
||||
/* ── ④ 验收判据:逐条标注真实等级 L1–L5 ───────────────────────────── */
|
||||
|
||||
export const acceptanceCriterionSchema = z.object({
|
||||
key: z.string().min(1),
|
||||
label: z.string(),
|
||||
level: acceptanceLevelSchema,
|
||||
/** L1/L2 的机检表达式(S-FEEL);L3–L5 由环内实证 / 独立评审 / 人放行承担 */
|
||||
predicate: z.string().optional(),
|
||||
/** loop 可引用业务模型的完成判据或 DMN 决策 */
|
||||
modelRef: z.string().optional(),
|
||||
});
|
||||
export type AcceptanceCriterion = z.infer<typeof acceptanceCriterionSchema>;
|
||||
|
||||
/* ── ⑤ 禁区 ─────────────────────────────────────────────────────────── */
|
||||
|
||||
export const prohibitionSchema = z.object({
|
||||
key: z.string().min(1),
|
||||
/** 应短而硬;负面清单优于正面枚举 */
|
||||
statement: z.string().min(1),
|
||||
});
|
||||
export type Prohibition = z.infer<typeof prohibitionSchema>;
|
||||
|
||||
/* ── ⑥ 授权边界 ─────────────────────────────────────────────────────── */
|
||||
|
||||
export const authorizationBoundarySchema = z.object({
|
||||
/** AI 可自决的范围:金额 / 折扣 / 措辞等,以 S-FEEL 谓词或叙述给出 */
|
||||
discretion: z.array(z.object({ key: z.string(), statement: z.string() })).default([]),
|
||||
/** 预授权动作清单 —— 必须逐项列举,方可在过程中即时执行写类动作(OS 7.3) */
|
||||
preauthorizedActions: z
|
||||
.array(z.object({ tool: z.string(), operation: z.string(), limit: z.string().optional() }))
|
||||
.default([]),
|
||||
/** 调人预算(打扰上限) */
|
||||
humanCallBudget: z.number().int().min(0),
|
||||
});
|
||||
export type AuthorizationBoundary = z.infer<typeof authorizationBoundarySchema>;
|
||||
|
||||
/* ── ⑦ 资源声明 ─────────────────────────────────────────────────────── */
|
||||
|
||||
/** 预算四类上限 —— 由基座在环外强制,不得由活动代码自查自守(AM 10.1) */
|
||||
export const budgetCapsSchema = z.object({
|
||||
steps: z.number().int().min(1),
|
||||
tokens: z.number().int().min(1),
|
||||
/** 活跃时长(分钟);挂起、监听等待、待卡回传不计入 */
|
||||
activeMinutes: z.number().int().min(1),
|
||||
humanCalls: z.number().int().min(0),
|
||||
});
|
||||
export type BudgetCaps = z.infer<typeof budgetCapsSchema>;
|
||||
|
||||
export const resourceDeclarationSchema = z.object({
|
||||
/** 工具调用契约引用 + 版本约束 */
|
||||
tools: z
|
||||
.array(z.object({ name: z.string().min(1), version: z.string().optional() }))
|
||||
.default([]),
|
||||
skills: z.array(skillIdSchema).default([]),
|
||||
/** 活动使用的 LLM,以自定义模型名(逻辑名)声明;活动不触厂商与密钥 */
|
||||
models: z.array(z.string().min(1)).default([]),
|
||||
/** 岗位:调人时卡投递到哪个工位 */
|
||||
roles: z.array(z.string().min(1)).default([]),
|
||||
budget: budgetCapsSchema,
|
||||
});
|
||||
export type ResourceDeclaration = z.infer<typeof resourceDeclarationSchema>;
|
||||
|
||||
/* ── 七件合体 ───────────────────────────────────────────────────────── */
|
||||
|
||||
export const sevenPartContractSchema = z.object({
|
||||
activityId: activityIdSchema,
|
||||
version: z.string().min(1),
|
||||
input: contractInputSchema,
|
||||
output: outputPortsSchema,
|
||||
requiredDeliverables: z.array(requiredDeliverableSchema).default([]),
|
||||
acceptanceCriteria: z.array(acceptanceCriterionSchema).default([]),
|
||||
prohibitions: z.array(prohibitionSchema).default([]),
|
||||
authorization: authorizationBoundarySchema,
|
||||
resources: resourceDeclarationSchema,
|
||||
});
|
||||
export type SevenPartContract = z.infer<typeof sevenPartContractSchema>;
|
||||
|
||||
/**
|
||||
* 完成时的发射集合 = 全部必发口 + 每个选择组各一口(AM 1.2)。
|
||||
* 纯函数,前后端同源:前端预演、后端裁决。
|
||||
*/
|
||||
export function emissionPortNames(
|
||||
ports: OutputPorts,
|
||||
selected: Readonly<Record<string, string>>,
|
||||
): string[] {
|
||||
const out = ports.mandatory.map((p) => p.name);
|
||||
for (const group of ports.selective) {
|
||||
const choice = selected[group.group];
|
||||
if (choice !== undefined) out.push(choice);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
/** 选择组必须恰选一口 —— 未选或选了组外的口即非法 */
|
||||
export function validateSelection(
|
||||
ports: OutputPorts,
|
||||
selected: Readonly<Record<string, string>>,
|
||||
): string[] {
|
||||
const errors: string[] = [];
|
||||
for (const group of ports.selective) {
|
||||
const choice = selected[group.group];
|
||||
if (choice === undefined) {
|
||||
errors.push(`选择组「${group.group}」未选出口`);
|
||||
continue;
|
||||
}
|
||||
if (!group.ports.some((p) => p.name === choice)) {
|
||||
errors.push(`选择组「${group.group}」的出口「${choice}」不在组内`);
|
||||
}
|
||||
}
|
||||
return errors;
|
||||
}
|
||||
|
||||
/** 验收等级不得谎报:L4 不得标注为 L1–L3;生成者不得自评(AM 12.1) */
|
||||
export function machineCheckable(criterion: AcceptanceCriterion): boolean {
|
||||
return criterion.level === 'L1' || criterion.level === 'L2';
|
||||
}
|
||||
Reference in New Issue
Block a user