/** * owner-review.ts — PRI-629 统一 Owner Decision 策略层(纯函数 + 窄事实读取)。 * * 职责(单一深模块,Console/CLI/Runner 共用,禁止各自再推导): * - collectOwnerDecisionFacts 读取 durable facts(task/lineage/artifact) * - deriveOwnerDecisionCapability 纯策略:该 NHR 任务是否 decision-capable、 * 允许哪些 Owner 动作(INV-01 的唯一依据) * - buildOwnerReviewKey 裁决事实快照的稳定 hash(stale 防护) * - resolveEffectiveRunnerDecision effective decision 的唯一解析点 * - classifyHumanReviewAttention owner_decision vs recovery(fail closed) * * 不变式(SPEC PRI-629/630): * - machine verdict 永不被覆盖(runnerDecision 只读) * - allowedActions.length === 0 ⇔ 不进 Owner Inbox、不阻止 Recover * - 未知 reasonCode / 模糊 legacy 事实 → recovery(fail closed) * - reviewKey 绑定 (taskId, epoch, run, artifact, hash, verdict, reason) */ import type { TaskRecord } from '../task-status.js'; import type { PITaskRecord } from './peer-runner-contracts.js'; import { type OwnerResolutionAction, type OwnerResolutionRecord, type RunnerDecision } from './pitask-metadata.js'; /** * needs_human_review 的结构化原因码(PRI-629)。写入侧由 runner 使用常量; * 解析侧接受任意非空串(前向兼容),分类侧只认 DECISION_CAPABLE 集合, * 其余一律 recovery。 */ export declare const HUMAN_REVIEW_REASON: { /** Evaluator 修复预算耗尽(2 轮已用完)— Owner 可裁决 */ readonly evaluatorRepairBudgetExhausted: 'evaluator_repair_budget_exhausted'; /** Rollout 修订预算耗尽 — Owner 可裁决 */ readonly rolloutRevisionBudgetExhausted: 'rollout_revision_budget_exhausted'; /** Rollout 语义批准但激活候选缺失 — Owner 可裁决(无 accept:候选不存在,无可批准物) */ readonly rolloutActivationCandidateUnresolved: 'rollout_activation_candidate_unresolved'; /** * PRI-703 Phase 2 (Owner 决策 2026-09-07): 重放失败全部为 v2-context 模板 * case 对 v1 (action-only) 规则的审判 — FAILED_TEST 归因(通道设计限制, * 非产物缺陷)。修复轮结构性不可收敛,直接进入 Owner 裁决: * accept_current(接受 v1 通道限制)/ 通道升级 / 原则修订。 * decision-capable:Owner 的裁决是唯一有意义的出口。 */ readonly evaluatorTestOutOfScope: 'evaluator_test_out_of_scope'; /** * PRI-843 (SPEC v1.1): Evaluator 基于 formation evidence 判定 Principle * 不解决源 Pain(r6 review P2-1 起:结构化 evaluation.mismatchFindings * 字段为唯一路由信号;concerns 文本不路由)——原则级缺陷。repair pipeline 只能再生成 Rule,结构性不可收敛(同 * evaluator_test_out_of_scope 的死锁形状),且 requiredChanges 禁止承载 * 原则级诉求。直接进入 Owner 裁决:accept_current(原则其实可用)/ * 原则修订(rollout→scribe 窄路)/ reject_current。 * decision-capable:Owner 的裁决是唯一有意义的出口。 */ readonly principlePainMismatch: 'principle_pain_mismatch'; readonly evaluatorRepairSeedFailed: 'evaluator_repair_seed_failed'; readonly rolloutDispatchNotWired: 'rollout_dispatch_not_wired'; readonly rolloutDispatchRefused: 'rollout_dispatch_refused'; readonly rolloutRevisionTargetUnresolved: 'rollout_revision_target_unresolved'; readonly rolloutRevisionRoutingNotWired: 'rollout_revision_routing_not_wired'; readonly rolloutRevisionReopenFailed: 'rollout_revision_reopen_failed'; readonly rolloutRevisionIterationMissing: 'rollout_revision_iteration_missing'; readonly workspaceDirtyStall: 'workspace_dirty_stall'; }; export type HumanReviewReasonCode = typeof HUMAN_REVIEW_REASON[keyof typeof HUMAN_REVIEW_REASON]; /** decision-capable 原因集合 — 只有这些允许 Owner verdict override。 */ export declare const DECISION_CAPABLE_HUMAN_REVIEW_REASONS: ReadonlySet; /** * candidate-unresolved 类原因:机器已 approve 但激活候选缺失,accept_current 无 * 可批准对象 — 这类原因的任务不允许 accept,只允许 revise_once / reject_current。 */ export declare const NO_ACCEPT_HUMAN_REVIEW_REASONS: ReadonlySet; /** legacy(无 humanReviewContext)判定后使用的原因码,携带 _legacy 后缀以示证据来源。 */ export declare const LEGACY_EVALUATOR_BUDGET_EXHAUSTED = "evaluator_repair_budget_exhausted_legacy"; export declare const LEGACY_ROLLOUT_BUDGET_EXHAUSTED = "rollout_revision_budget_exhausted_legacy"; /** 事实读取所需的最窄接口 — RuntimeStateManager 天然满足前两项。 */ export interface OwnerDecisionFactStore { getTask(taskId: string): Promise; listArtifactsBySourceTask(taskId: string): Promise; } export interface DecisionArtifactRecord { readonly artifactId: string; readonly artifactKind: string; readonly validationStatus: string; readonly contentJson: string; /** Review projection lineage fields; optional for legacy fact-store adapters. */ readonly sourceTaskId?: string; readonly lineageArtifactIds?: readonly string[]; readonly createdAt?: string; } /** 决策输出 artifact(evaluator/rollout 名下的 kind='principle' 评审输出)。 */ export interface DecisionArtifactFacts { readonly artifactId: string; readonly contentHash: string; } /** collectOwnerDecisionFacts 的产物 — capability 的全部输入。 */ export interface OwnerDecisionFacts { readonly task: PITaskRecord; /** 决策输出 artifact(pi-art--);不存在 = null */ readonly decisionArtifact: DecisionArtifactFacts | null; /** 决策 artifact 的确定性安全门(adversarial hard gate)失败 — accept 禁止 */ readonly hardGateFailed: boolean; /** evaluator: 依赖链上 artificer 的 repairPayload.repairIteration(无 payload 的首轮 artificer = 0;无 artificer = null) */ readonly dependencyRepairIteration: number | null; /** evaluator: 依赖 artificer 的 taskId(revise_once 的 reopen 目标;无 = null) */ readonly dependencyArtificerTaskId: string | null; /** rollout: rolloutRevisionPayload 已 APPLIED 的修订轮数 */ readonly rolloutRevisionAppliedCount: number | null; /** 依赖链可解析(evaluator: 依赖 artificer 任务存在;rollout: 依赖 evaluator 任务存在) */ readonly lineageResolvable: boolean; } /** 对 artifact contentJson 计算 sha256 hex(reviewKey / stale 防护的事实输入)。 */ export declare function computeArtifactContentHash(contentJson: string): string; /** evaluator/rollout 输出 artifact 的确定性 id(与 runner 写入约定一致)。 */ export declare function decisionArtifactIdFor(taskId: string, runId: string): string; /** * 从 durable facts 还原裁决事实快照: * 1. humanReviewContext 存在 → 直接采用(它由 runner 在 NHR 落库时原子写入); * 2. legacy → completionIntent.sourceRunId + 确定性 artifact id + 内容 hash。 * 决策 artifact 必须真实存在且可读 — 缺失即 capability 失败(recovery)。 */ /** * 硬确定性安全门判定(SPEC §20):evaluator V2 输出携带 adversarialResult * 且 passed=false → 确定性对抗门失败,Owner 不得 accept(可 revise/reject)。 * 此处只读 metadata 可达的事实;artifact 内容级判定在 apply 阶段由 runner * 的既有 deterministic gates 兜底(RuleHostWriter.canActivate / sandbox replay)。 */ /** * verdict override 的 effective decision 映射(SPEC §10/§14/§16)。 * 注意 rollout accept → 'approve_rollout'(不是 'approved')— 高风险部署 * 审批由 ActivationDispatcher 在下游强制,Owner review 不穿透。 */ export declare function effectiveDecisionFor(taskKind: string, action: OwnerResolutionAction): RunnerDecision | undefined; export interface OwnerOverrideResumePlan { readonly resolution: OwnerResolutionRecord; readonly overrideDecision: RunnerDecision; } /** * Runner 入口恢复门的第一优先级检查(SPEC §10): * pending Owner Resolution → pending Completion Intent → normal LLM。 * 当前 epoch 存在 verdict override resolution(pending 或 applied 均可 — * applied 但任务未 terminal 的 crash 窗口同样由此收敛)→ 返回 override 计划。 */ export declare function planOwnerVerdictOverrideResume(piTask: PITaskRecord): OwnerOverrideResumePlan | null; /** * runner 侧 detail reason string → 规范化 humanReviewContext.reasonCode。 * 保留 detail 原串在事件里(可观测),context 携带规范码(可分类)。 */ export declare function canonicalHumanReviewReasonCode(detail: string): string; /** * 硬确定性安全门判定(SPEC §9.1/§20):evaluator V2 输出携带 * adversarialResult 且 passed=false → 确定性对抗门失败 → accept_current * 不允许(revise/reject 仍可用)。从决策 artifact contentJson 做有界解析。 */ export declare function detectHardGateFailureFromArtifact(contentJson: string): boolean; export declare function collectOwnerDecisionFacts(store: OwnerDecisionFactStore, taskId: string): Promise; export interface ReviewKeyFacts { readonly taskId: string; readonly revisionEpoch: number; readonly sourceRunId: string; readonly sourceArtifactId: string; readonly sourceArtifactHash: string; readonly machineDecision: string; readonly humanReviewReason: string; } /** * Owner Decision Item 的稳定身份:裁决事实快照的 sha256。任何一个事实变化 * (新一轮 run / 新 artifact / 新 epoch / 不同 verdict)都会产生新 key — * Owner 只能批准自己实际看到的那个版本(stale 防护,SPEC §6)。 */ export declare function buildOwnerReviewKey(facts: ReviewKeyFacts): string; /** * effective decision 的唯一解析点(SPEC §8): * 当前 revision epoch 存在合法、applied 的 Owner verdict override → * effectiveDecision;否则 → runnerDecision(机器判定,永不改写)。 * * Internalization transition / orchestrator / 任何消费方必须经由本函数; * Console / HTTP route / 各 runner 禁止自行计算。 */ /** 当前 epoch 内最新一条 owner resolution(pending 或 applied),无则 null。 */ export declare function findOwnerResolutionForCurrentEpoch(piTask: PITaskRecord): OwnerResolutionRecord | null; /** * P0 评审修复: 当前 epoch 内是否有 **pending**(等待 runner 应用)的 resolution。 * Recover guard 只拒 pending——applied resolution 表示裁决已被执行(即使下游 * 治理转移因技术原因落在 recovery NHR),此时 Recover 是合法的技术重试出口 * (resume 门会基于 applied override 确定性重放,不重问 LLM)。 */ export declare function findPendingOwnerResolutionForCurrentEpoch(piTask: PITaskRecord): OwnerResolutionRecord | null; /** 当前 epoch 内最新 applied verdict override(accept/reject)— resolver 的输入。 */ export declare function findAppliedVerdictOverrideResolution(piTask: PITaskRecord): OwnerResolutionRecord | null; export declare function resolveEffectiveRunnerDecision(piTask: PITaskRecord): RunnerDecision | undefined; export type HumanReviewAttention = 'owner_decision' | 'recovery'; export interface OwnerDecisionCapability { /** true ⇔ allowedActions.length > 0(INV-01 Actionability Truth) */ readonly eligible: boolean; /** 规范化原因码(legacy 判定带 _legacy 后缀) */ readonly reasonCode: string; readonly attention: HumanReviewAttention; readonly legacy: boolean; readonly reviewKey?: string; readonly allowedActions: readonly OwnerResolutionAction[]; readonly blockers: readonly string[]; } /** * 规范化人工裁决原因: * - 有 humanReviewContext → 其 reasonCode(未知码 → attention=recovery,fail closed); * - legacy → 按 durable facts 推断(SPEC §23): * evaluator: needs_revision + dep artificer repairIteration>=2 + 同 epoch * pending intent → budget exhausted (legacy) * rollout: needs_revision + applied revision count>=2 → budget exhausted (legacy) * - 事实不足/歧义 → recovery(不得猜)。 */ export declare function classifyHumanReviewAttention(facts: OwnerDecisionFacts): { attention: HumanReviewAttention; reasonCode: string; legacy: boolean; }; export declare function deriveOwnerDecisionCapability(facts: OwnerDecisionFacts): OwnerDecisionCapability; /** resolution 标 applied(幂等,单调 pending→applied;并发同值写安全)。 */ export interface MarkOwnerResolutionAppliedCtx { readonly updateDiagnosticJson: (taskId: string, json: string) => Promise; readonly getTask: (taskId: string) => Promise; readonly taskId: string; readonly resolutionId: string; readonly appliedAt: string; } export declare function markOwnerResolutionApplied(ctx: MarkOwnerResolutionAppliedCtx): Promise; //# sourceMappingURL=owner-review.d.ts.map