Files
Jyotisha/frontend/src/lib/rectification-agentic/v9/confirmation-gate.ts
T
Jesse_Chen f3327235ea
Independent Staging Quality Gate / validate (push) Successful in 10m50s
Independent Staging Quality Gate / publish (push) Successful in 13m29s
fix(rectification): remove static interview fallbacks
2026-08-27 16:40:47 +08:00

265 lines
9.6 KiB
TypeScript

/**
* 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<Record<string, unknown>> | null {
return value && typeof value === "object" && !Array.isArray(value)
? value as Readonly<Record<string, unknown>>
: null;
}
export function readVedastroMinuteSensitiveStatus(
decisionReceipt: Readonly<Record<string, unknown>> | 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<Record<string, unknown>> | 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<Record<string, unknown>> | 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 未达发布门槛,不能确认唯一分钟或声称已完成精确分钟校准。",
},
],
};
}