M3(完成): interaction 与 activity-registry

interaction(L3):
- 控制权按态转交:活动在跑归活动,流转/审批/终态归系统;输入侧永远归系统(单入口)
- 视图区净化门:含 <script> / on* / 外部资源的模版一律拒推 —— 容器无脚本执行权
- 对话流单入口:自由输入同写任务记忆并抛人事件;SSE 单连接 + 按目标失效广播
- 前端零过程状态:对话流与视图都是服务端投影

activity-registry(L4):
- 安装两审:静态审(签名/SDK/工具契约齐备/模型名已绑定/schema/悬空监听/模版无脚本/
  零环境能力/动态执行/验收等级不得谎报)+ 回放审(旧成不坏是硬门,旧败能成只入报告)
- 资产与包分离版本化:包只携资产初始版,不覆盖已有更高资产版;装载 = 包版本 + 生效资产版
- 进化管线状态机:候选 → 回放 → 人放行 → 生效;回退是显式治理动作

245 个测试通过,门禁五道全绿

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 01:36:05 +08:00
co-authored by Claude Opus 5
parent d96c6e6dff
commit 2850e6d4ef
29 changed files with 4339 additions and 4 deletions
@@ -0,0 +1,63 @@
/**
* module: activity-registry —— 本模块要外界提供的能力(编码规范 §10.1 / §5.3)。
*/
import type { ActivityManifest } from '@contracts';
import type { AssetKind, AssetVersion, IncrementState, PackageVersion, ReplayVerdict } from './internal/domain/versioning.ts';
export type Clock = { now(): Date };
export type IdGenerator = { next(): string };
export type RegistryStore = {
savePackage(manifest: ActivityManifest, artifact: string): Promise<void>;
listPackages(activityId?: string): Promise<PackageVersion[]>;
manifest(activityId: string, packageVersion?: string): Promise<ActivityManifest | undefined>;
artifact(activityId: string, packageVersion: string): Promise<string | undefined>;
setEnabled(activityId: string, enabled: boolean): Promise<void>;
setState(activityId: string, version: string, state: PackageVersion['state']): Promise<void>;
enabledOf(activityId: string): Promise<boolean>;
listAssets(activityId: string): Promise<AssetVersion[]>;
saveAsset(asset: AssetVersion, body: string): Promise<void>;
setAssetEffective(activityId: string, kind: AssetKind, version: number): Promise<void>;
saveIncrement(input: {
id: string;
activityId: string;
kind: AssetKind;
diff: string;
evidenceEntryIds: readonly string[];
state: IncrementState;
createdAt: Date;
}): Promise<void>;
getIncrement(id: string): Promise<
| {
id: string;
activityId: string;
kind: AssetKind;
diff: string;
state: IncrementState;
}
| undefined
>;
setIncrementState(id: string, state: IncrementState, report?: ReplayVerdict, by?: string): Promise<void>;
};
/** 工具契约核对 —— app 注入 `toolbox`(L2):装不齐不上架 */
export type ToolContractProbe = {
assertContractsAvailable(names: readonly string[]): Promise<{ ok: boolean; missing: string[] }>;
};
/** 模型名核对 —— app 注入 `llm`(L1) */
export type ModelBindingProbe = {
assertNamesBound(names: readonly string[]): Promise<{ ok: boolean; missing: string[] }>;
};
/** 台账声明合并 —— app 注入 `ledger`(L1):安装时依声明自生长 */
export type LedgerDeclarationApplier = {
applyDeclarations(
declarations: ActivityManifest['declarations']['ledger'],
): Promise<Array<{ applied: boolean; conflicts: ReadonlyArray<{ field: string; message: string }> }>>;
};
/** 模版净化门 —— app 注入 `interaction`(L3) */
export type TemplateGuard = { isSafe(html: string): boolean };