import { LANGUAGE_VERSION } from './LanguageScene'; import { validateJevDecision, type AgentVersion, type JevDecision, type Skill } from './protocol'; export const QUALITY_POINTS = { poor: 0, partial: 25, good: 75, excellent: 100 } as const; const REASONS = { unsafe: '检测到不安全因素', insufficient_evidence: '当前阶段证据不足', tracking_error: '动作跟踪或对齐异常', verified_progress: '模型报告已有进展,但仍拒绝继续', } as const; function stopReason(decision: JevDecision): string { const reason = decision.reason; if (reason && reason !== 'none') return REASONS[reason]; return decision.noul === 'uncertain' ? '模型无法确认下一技能安全,未提供具体原因' : '模型拒绝继续,未提供具体原因'; } /** Supervisory advice can veto but cannot grant physical authority. */ export class TaskSupervisor { last?: JevDecision; get qualityScore(): number | undefined { const score = this.last?.score; return score && score !== 'unavailable' ? QUALITY_POINTS[score] : undefined; } inspect( value: unknown, candidates: readonly (Skill | 'stop')[], version: AgentVersion, secure: boolean, ): JevDecision { const decision = validateJevDecision(value, candidates, version); this.last = decision; if (version === LANGUAGE_VERSION && decision.noul !== 'allow') throw new Error(`Noul 拦截(${decision.noul}):${stopReason(decision)}`); if (decision.choice === 'stop' || decision.recovery === 'stop') throw new Error(`Jev 请求安全停止:${stopReason(decision)}`); if (decision.grasp === 'secure' && !secure) throw new Error('Jev 抓持判断与本地物理证据矛盾'); if ( ['carry', 'stop-base'].includes(decision.choice) && (decision.grasp !== 'secure' || !secure) ) throw new Error('搬运前未取得一致抓持证据'); return decision; } }