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:
JCAI Main Agent
2026-07-27 00:59:14 +08:00
co-authored by Claude Opus 5
parent 7cd664af3a
commit 14d4fa046a
120 changed files with 15236 additions and 78 deletions
@@ -0,0 +1,79 @@
/** 投递五诺的纯判定部分(OS 6.3 / 编码规范 §7.1) */
import { describe, expect, it } from 'vitest';
import { consumptionKey, decideRetry, fanOutTargets, planConsumption } from '../internal/domain/delivery.ts';
import { deadlineMillis } from '../internal/domain/listener-match.ts';
describe('decideRetry —— 处理有回执', () => {
it('未超限即重投,退避递增', () => {
expect(decideRetry(1)).toEqual({ kind: 'retry', delayMs: 1_000, attempt: 2 });
expect(decideRetry(2)).toEqual({ kind: 'retry', delayMs: 5_000, attempt: 3 });
expect(decideRetry(4)).toEqual({ kind: 'retry', delayMs: 120_000, attempt: 5 });
});
it('超限入死信', () => {
expect(decideRetry(5)).toEqual({ kind: 'dead-letter', attempts: 5 });
});
});
describe('fanOutTargets —— 扇出与幂等', () => {
it('同一任务多条监听命中只产生一份投递', () => {
expect(fanOutTargets([{ taskId: 'a' }, { taskId: 'a' }, { taskId: 'b' }])).toEqual(['a', 'b']);
});
});
describe('planConsumption —— 三级消费', () => {
it('监听与触发独立判定:可既推进旧单又起新单', () => {
const plan = planConsumption({
listenerHits: [{ taskId: 't1' }],
triggerHits: ['tr1'],
ownedTaskId: 't1',
});
expect(plan.taskTargets).toEqual(['t1']);
expect(plan.triggerTargets).toEqual(['tr1']);
expect(plan.messageFallback).toBe(false);
});
it('皆未命中且无主 → 消息兜底', () => {
const plan = planConsumption({ listenerHits: [], triggerHits: [], ownedTaskId: undefined });
expect(plan.messageFallback).toBe(true);
});
it('有主但零监听命中 → 仅记录,不兜底、不降级为无主', () => {
const plan = planConsumption({ listenerHits: [], triggerHits: [], ownedTaskId: 't7' });
expect(plan.messageFallback).toBe(false);
expect(plan.recordOnlyTask).toBe('t7');
expect(plan.taskTargets).toEqual([]);
});
it('有主且监听命中 → 不是仅记录', () => {
const plan = planConsumption({ listenerHits: [{ taskId: 't7' }], triggerHits: [], ownedTaskId: 't7' });
expect(plan.recordOnlyTask).toBeUndefined();
});
it('无主但触发命中 → 不兜底', () => {
const plan = planConsumption({ listenerHits: [], triggerHits: ['tr1'], ownedTaskId: undefined });
expect(plan.messageFallback).toBe(false);
});
});
describe('consumptionKey —— 幂等键', () => {
it('事件 ID × 消费者', () => {
expect(consumptionKey('e1', 'task:t1')).toBe('e1::task:t1');
});
});
describe('deadlineMillis —— 监听时限必配', () => {
it('解析 ISO-8601 duration', () => {
expect(deadlineMillis('P3D')).toBe(3 * 86_400_000);
expect(deadlineMillis('PT30M')).toBe(30 * 60_000);
expect(deadlineMillis('P1DT2H30M')).toBe(86_400_000 + 2 * 3_600_000 + 30 * 60_000);
});
it('非法表达式抛错', () => {
expect(() => deadlineMillis('3天')).toThrow(/非法时限/);
});
it('零时限抛错 —— 无死等', () => {
expect(() => deadlineMillis('PT0S')).toThrow(/大于零/);
});
});