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
74 lines
2.9 KiB
TypeScript
74 lines
2.9 KiB
TypeScript
/**
|
|
* 控制权按态转交 —— 纯逻辑,零 IO(编码规范 §5.3;语义出处 OS 4.1,AM 07)。
|
|
*
|
|
* 「视图区容器与对话区输出框的控制权由活动与系统**共同持有**:
|
|
* 任务激活(Agent 机制运行)时归**活动** —— 视图流控与对话输出由活动驱动;
|
|
* 流程流转(节点间、审批点、终态前后)时归**系统** —— 流转、审批与终态回执由系统呈现。
|
|
* 转交随引擎的激活 / 完成事件自动发生,活动不感知交接。
|
|
* **输入侧不参与转交**:全部人类输入永远经系统的对话流卡片协议回传。」
|
|
*/
|
|
|
|
export const CONTROL_HOLDERS = ['activity', 'system'] as const;
|
|
export type ControlHolder = (typeof CONTROL_HOLDERS)[number];
|
|
|
|
/** 任务在交互层的态 —— 决定输出侧控制权归谁 */
|
|
export const INTERACTION_PHASES = [
|
|
'activating',
|
|
'active',
|
|
'awaiting-human',
|
|
'awaiting-event',
|
|
'approving',
|
|
'transitioning',
|
|
'terminal',
|
|
] as const;
|
|
export type InteractionPhase = (typeof INTERACTION_PHASES)[number];
|
|
|
|
/** 输出侧控制权:活动在跑就归活动,其余一律归系统 */
|
|
export function outputControl(phase: InteractionPhase): ControlHolder {
|
|
switch (phase) {
|
|
case 'active':
|
|
case 'awaiting-human':
|
|
case 'awaiting-event':
|
|
return 'activity';
|
|
case 'activating':
|
|
case 'approving':
|
|
case 'transitioning':
|
|
case 'terminal':
|
|
return 'system';
|
|
}
|
|
}
|
|
|
|
/** 输入侧**永远**归系统 —— 单入口,不参与转交 */
|
|
export function inputControl(): ControlHolder {
|
|
return 'system';
|
|
}
|
|
|
|
/** 转交是否发生 —— 引擎的激活 / 完成事件驱动;活动不感知 */
|
|
export function handoverHappens(from: InteractionPhase, to: InteractionPhase): boolean {
|
|
return outputControl(from) !== outputControl(to);
|
|
}
|
|
|
|
/* ── 视图区:只读呈现容器,无脚本执行权(AM 07) ────────────────────── */
|
|
|
|
export type TemplateViolation = { readonly code: 'script' | 'event-handler' | 'external-resource'; readonly message: string };
|
|
|
|
const SCRIPT = /<\s*script\b/i;
|
|
const EVENT_HANDLER = /\son[a-z]+\s*=/i;
|
|
const EXTERNAL = /(src|href)\s*=\s*["']?\s*(https?:)?\/\//i;
|
|
|
|
/**
|
|
* 模版无脚本 —— 安装静态审与推送前都用它。
|
|
* 「模版是**内容**不是代码:web 零活动代码,容器渲染净化、无脚本执行权。」
|
|
*/
|
|
export function checkTemplate(html: string): TemplateViolation[] {
|
|
const out: TemplateViolation[] = [];
|
|
if (SCRIPT.test(html)) out.push({ code: 'script', message: '视图模版不得含 <script>' });
|
|
if (EVENT_HANDLER.test(html)) out.push({ code: 'event-handler', message: '视图模版不得含 on* 事件处理器' });
|
|
if (EXTERNAL.test(html)) out.push({ code: 'external-resource', message: '视图模版不得引用外部资源' });
|
|
return out;
|
|
}
|
|
|
|
export function templateIsSafe(html: string): boolean {
|
|
return checkTemplate(html).length === 0;
|
|
}
|