/** * 任务生命周期与终态五名裁定 —— 纯逻辑,零 IO(编码规范 §5.3;语义出处 OS 4.3,AM 01/10)。 * * 「**完成由框架裁定,终态由系统命名**」—— 终态是封闭枚举,活动不得增删。 */ import type { ControlSemantic, TaskRuntimeState, TerminalState } from '@contracts'; export type TaskSnapshot = { readonly runtime: TaskRuntimeState; readonly terminal?: TerminalState; readonly reason?: string; }; export const RUNNING: TaskSnapshot = { runtime: 'running' }; /* ── 控制三语义(OS 06) ────────────────────────────────────────────── */ export type ControlOutcome = /** 暂停 = 可恢复冻结(监听与时限停摆) */ | { readonly kind: 'suspended'; readonly resumable: true } /** 叫停 = 负责人紧急中断:挂起并**记最重档纠正**,恢复归负责人 */ | { readonly kind: 'halted'; readonly resumable: true; readonly correctionSignal: 'heaviest' } /** 终止 = 不可恢复关闭 */ | { readonly kind: 'terminated'; readonly resumable: false; readonly terminal: TerminalState }; export function applyControl(semantic: ControlSemantic): ControlOutcome { switch (semantic) { case 'pause': return { kind: 'suspended', resumable: true }; case 'halt': return { kind: 'halted', resumable: true, correctionSignal: 'heaviest' }; case 'terminate': return { kind: 'terminated', resumable: false, terminal: 'terminated' }; } } /** 叫停**不是终态** —— 转挂起待纠偏,处置后恢复,或由负责人终止 */ export function isTerminalControl(semantic: ControlSemantic): boolean { return semantic === 'terminate'; } /* ── 终态裁定 ───────────────────────────────────────────────────────── */ export type TerminalCause = /** 放行通过且落地收敛,输出口已发射 —— **唯一成功终态** */ | { readonly kind: 'released' } /** 无法推进,封卷待治理处置 */ | { readonly kind: 'blocked'; readonly reason: string } | { readonly kind: 'stalled'; readonly evidence: string } | { readonly kind: 'exhausted'; readonly detail: string } | { readonly kind: 'terminated'; readonly reason: string }; export function decideTerminal(cause: TerminalCause): { terminal: TerminalState; reason: string } { switch (cause.kind) { case 'released': return { terminal: 'released', reason: '放行通过且落地收敛,输出口已发射' }; case 'blocked': return { terminal: 'blocked', reason: cause.reason }; case 'stalled': return { terminal: 'stalled', reason: cause.evidence }; case 'exhausted': return { terminal: 'exhausted', reason: cause.detail }; case 'terminated': return { terminal: 'terminated', reason: cause.reason }; } } export function isSuccess(terminal: TerminalState): boolean { return terminal === 'released'; } /** 非完成终态触发流程层的**失败走向**(OS 03) */ export function triggersFailureDisposition(terminal: TerminalState): boolean { return terminal !== 'released'; } /* ── 「不是终态」的三样(OS 4.3) ──────────────────────────────────── */ /** 驳回是**环内回转**,任务继续 —— 不出活动 */ export function rejectionKeepsRunning(): TaskSnapshot { return { runtime: 'running' }; } /** 落地受阻是**运行态**,处置后仍收敛于终态名录 */ export function landingBlocked(reason: string): TaskSnapshot { return { runtime: 'landing-blocked', reason }; } /* ── 断点续跑:三份持久状态(OS 09) ──────────────────────────────── */ export const RESUME_SOURCES = ['task-memory', 'draft-layer', 'runtime-state'] as const; export type ResumeSource = (typeof RESUME_SOURCES)[number]; export type ResumeReadiness = { readonly ready: boolean; readonly missing: readonly ResumeSource[]; }; /** * 「任务做一半的续跑由三份持久状态**共同**保证: * 任务记忆(按窗口重建上下文)、草稿层(截至断点的过程产物与动作意向)、 * 运行时实例状态(loop 的模型定位与就绪集 / flow 的步序位置)。」 */ export function resumeReadiness(present: Readonly>): ResumeReadiness { const missing = RESUME_SOURCES.filter((s) => !present[s]); return { ready: missing.length === 0, missing }; } /** 「打开任务只是打开呈现,不是启动过程」—— 过程要么在跑,要么挂起在等 */ export function isPassiveOpen(state: TaskRuntimeState): boolean { return state !== 'running'; }