/** * Read-only confirmation-gate projection. * * These blockers are fail-closed honesty, not a scoring change. They never * grant a unique birth minute. VedAstro `not_evaluated` means the official * minute-sensitive layer has not run; that is not a fail. The sealed public * AA holdout stays `not_ready` until a human updates this contract after a * valid passing evaluation — this module does not invent cases. */ import { RECTIFICATION_POLICY } from "../../rectification-policy.ts"; import { indistinguishableWidthMinutes } from "./candidate-plateau.ts"; import sealedHoldout from "../../../../../references/rectification_sealed_holdout.v1.json"; export const SEALED_MINUTE_HOLDOUT = { sealed_benchmark_id: sealedHoldout.sealed_benchmark_id, status: sealedHoldout.status === "ready" ? "ready" : "not_ready", valid_public_aa_cases: sealedHoldout.valid_public_aa_cases, required_cases: sealedHoldout.required_cases, top_1_rate: sealedHoldout.top_1_rate, confirmation_coverage_rate: sealedHoldout.confirmation_coverage_rate, } as const; type GateCandidate = Readonly<{ time: string; rank: number; tiedMinuteCount: number; }>; export type ConfirmationGateBlocker = Readonly<{ id: "vedastro_minute_sensitive" | "adjacent_minutes_indistinguishable" | "public_aa_holdout"; status: string; user_meaning: string; indistinguishable_width_minutes?: number; max_confirmation_width_minutes?: number; required_cases?: number; valid_public_aa_cases?: number; top_1_rate?: number; confirmation_coverage_rate?: number; sealed_benchmark_id?: string; failure_code?: string; }>; export type UniqueMinutePath = "closed_at_representative" | "awaiting_user_consent"; export function uniqueMinutePath(confirmationAllowed: boolean): UniqueMinutePath { return confirmationAllowed ? "awaiting_user_consent" : "closed_at_representative"; } export type ConfirmationGate = Readonly<{ confirmation_allowed: boolean; unique_minute_path: UniqueMinutePath; blockers: readonly ConfirmationGateBlocker[]; }>; export type SessionOutcomeKind = | "collect_evidence" | "discriminate_candidates" | "validate_holdout" | "provisional_range" | "provisional_range_user_stopped" | "completed_with_range" | "validated_range" | "exact_minute_confirmed" | "adopt_representative" | "awaiting_confirmation"; export type SessionOutcome = Readonly<{ kind: SessionOutcomeKind; user_meaning: string; }>; export function sessionOutcomeView(kind: SessionOutcomeKind): SessionOutcome { if (kind === "awaiting_confirmation") { return { kind, user_meaning: "确认门已允许。只有用户明确同意才能写已确认校正时间。", }; } if (kind === "adopt_representative") { return { kind, user_meaning: "可以采用代表性候选作当前排盘;不得把它描述为已确认的唯一出生分钟。", }; } if (kind === "discriminate_candidates") { return { kind, user_meaning: "方法资料已齐,但候选还没拉开。下一步按候选盘面差异反问前事,不要采用时间卡。", }; } if (kind === "validate_holdout") { return { kind, user_meaning: "领先候选还要用尚未计分的前事做独立核对,不能直接采用。", }; } if (kind === "validated_range") { return { kind, user_meaning: "领先候选已通过尚未计分的前事核对。本会话交付可信区间和代表性工作时间,不是唯一分钟确认。", }; } if (kind === "exact_minute_confirmed") { return { kind, user_meaning: "确认门已允许。只有用户明确同意才能写已确认校正时间。", }; } if (kind === "provisional_range") { return { kind, user_meaning: "当前几个候选基本并列。给出的是可信区间的代表点,不是已经分出的赢家。", }; } if (kind === "provisional_range_user_stopped") { return { kind, user_meaning: "用户主动停止收集。当前可信区间和代表性工作时间可以交付,独立核对尚未完成,不是最终校正结果。", }; } if (kind === "completed_with_range") { return { kind, user_meaning: "当前证据只能支持可信区间和代表性工作时间,不能确认唯一分钟。", }; } return { kind: "collect_evidence", user_meaning: "还需要能评分的带日期事件,才能给出可采用的代表性时间。", }; } export function sessionOutcomeFromGate(input: { selectionAllowed: boolean; proposeAllowed?: boolean; confirmationAllowed: boolean; interviewOpen?: boolean; userStopped?: boolean; }): SessionOutcome { if (input.confirmationAllowed) return sessionOutcomeView("awaiting_confirmation"); const userStopped = input.userStopped === true; const interviewOpen = input.interviewOpen === true && !userStopped; if (userStopped && input.selectionAllowed) { return sessionOutcomeView("provisional_range_user_stopped"); } if (input.proposeAllowed === true && !interviewOpen) { return sessionOutcomeView("adopt_representative"); } return sessionOutcomeView("collect_evidence"); } function asRecord(value: unknown): Readonly> | null { return value && typeof value === "object" && !Array.isArray(value) ? value as Readonly> : null; } export function readVedastroMinuteSensitiveStatus( decisionReceipt: Readonly> | null | undefined, ): string { const gates = asRecord(decisionReceipt?.gates); const exact = asRecord(gates?.exact_confirmation); const nested = exact?.external_validation_status; if (typeof nested === "string" && nested.trim()) return nested.trim(); const top = decisionReceipt?.external_validation_status; if (typeof top === "string" && top.trim()) return top.trim(); return "not_evaluated"; } function readVedastroFailureCode( decisionReceipt: Readonly> | null | undefined, ): string | null { const gates = asRecord(decisionReceipt?.gates); const exact = asRecord(gates?.exact_confirmation); const validation = asRecord(exact?.vedastro_event_validation); const failure = asRecord(validation?.failure); return typeof failure?.code === "string" && failure.code.trim() ? failure.code.trim() : null; } function vedastroPassed(status: string): boolean { return status === "passed"; } function vedastroUserMeaning(status: string, failureCode: string | null): string { if (status === "not_evaluated") { return "分钟敏感校验尚未执行;缺少该验证时不能确认唯一分钟。"; } if (status === "passed") { return "分钟敏感校验已通过。"; } if (failureCode) return `分钟敏感校验执行失败(${failureCode}),不能确认唯一分钟。`; return "分钟敏感校验未能区分相邻分钟,不能确认唯一分钟。"; } function adjacentPassed(candidates: readonly GateCandidate[], widthMinutes: number): boolean { if (candidates.length === 0) return false; const top = [...candidates].sort((left, right) => left.rank - right.rank)[0]; return Boolean(top) && top.tiedMinuteCount === 1 && widthMinutes <= RECTIFICATION_POLICY.maxConfirmationWidthMinutes; } function holdoutPassed(): boolean { const holdout: { status: string; valid_public_aa_cases: number; required_cases: number; confirmation_coverage_rate: number; } = SEALED_MINUTE_HOLDOUT; return holdout.status === "ready" && holdout.valid_public_aa_cases >= holdout.required_cases && holdout.confirmation_coverage_rate > 0; } export function buildConfirmationGate(input: { engineConfirmationAllowed: boolean; candidates: readonly GateCandidate[]; decisionReceipt?: Readonly> | null; }): ConfirmationGate { const width = indistinguishableWidthMinutes(input.candidates); const vedastroStatus = readVedastroMinuteSensitiveStatus(input.decisionReceipt); const vedastroFailureCode = readVedastroFailureCode(input.decisionReceipt); const adjacentOk = adjacentPassed(input.candidates, width); const holdoutOk = holdoutPassed(); const confirmationAllowed = input.engineConfirmationAllowed && vedastroPassed(vedastroStatus) && adjacentOk && holdoutOk; return { confirmation_allowed: confirmationAllowed, unique_minute_path: uniqueMinutePath(confirmationAllowed), blockers: [ { id: "vedastro_minute_sensitive", status: vedastroStatus, ...(vedastroFailureCode ? { failure_code: vedastroFailureCode } : {}), user_meaning: vedastroUserMeaning(vedastroStatus, vedastroFailureCode), }, { id: "adjacent_minutes_indistinguishable", status: adjacentOk ? "passed" : "blocked", indistinguishable_width_minutes: width, max_confirmation_width_minutes: RECTIFICATION_POLICY.maxConfirmationWidthMinutes, user_meaning: adjacentOk ? "当前宽度未超过确认门上限。" : "当前是一段不可分区间。代表分钟只是代表性候选,不是唯一出生分钟。", }, { id: "public_aa_holdout", status: SEALED_MINUTE_HOLDOUT.status, required_cases: SEALED_MINUTE_HOLDOUT.required_cases, valid_public_aa_cases: SEALED_MINUTE_HOLDOUT.valid_public_aa_cases, top_1_rate: SEALED_MINUTE_HOLDOUT.top_1_rate, confirmation_coverage_rate: SEALED_MINUTE_HOLDOUT.confirmation_coverage_rate, sealed_benchmark_id: SEALED_MINUTE_HOLDOUT.sealed_benchmark_id, user_meaning: holdoutOk ? "公开密封 holdout 已达发布门槛。" : "公开密封 holdout 未达发布门槛,不能确认唯一分钟或声称已完成精确分钟校准。", }, ], }; }