АРЧ АП11 - Выделить truth и answer-shape policy в assistant runtime
This commit is contained in:
@@ -8,6 +8,7 @@ import {
|
||||
type FinalizeAssistantAddressTurnInput
|
||||
} from "./assistantAddressTurnFinalizeRuntimeAdapter";
|
||||
import { attachAssistantRuntimeContractShadow } from "./assistantRuntimeContractResolver";
|
||||
import { attachAssistantTruthAnswerPolicy } from "./assistantTruthAnswerPolicyRuntimeAdapter";
|
||||
|
||||
export interface RunAssistantAddressLaneResponseRuntimeInput<ResponseType = AssistantMessageResponsePayload> {
|
||||
sessionId: string;
|
||||
@@ -251,6 +252,10 @@ export function runAssistantAddressLaneResponseRuntime<ResponseType = AssistantM
|
||||
userMessage: input.userMessage,
|
||||
addressRuntimeMeta: input.llmPreDecomposeMeta
|
||||
});
|
||||
const debugWithTruthAnswerPolicy = attachAssistantTruthAnswerPolicy(debugWithRuntimeContracts, {
|
||||
addressRuntimeMeta: input.llmPreDecomposeMeta,
|
||||
replyType: normalizeAddressReplyType(input.addressLane.reply_type)
|
||||
});
|
||||
const finalization = finalizeAddressTurnSafe({
|
||||
sessionId: input.sessionId,
|
||||
userMessage: input.userMessage,
|
||||
@@ -258,7 +263,7 @@ export function runAssistantAddressLaneResponseRuntime<ResponseType = AssistantM
|
||||
assistantReply: safeAddressReply,
|
||||
replyType: normalizeAddressReplyType(input.addressLane.reply_type),
|
||||
addressLaneDebug: normalizeAddressLaneDebug(input.addressLane.debug),
|
||||
debug: debugWithRuntimeContracts,
|
||||
debug: debugWithTruthAnswerPolicy,
|
||||
carryoverMeta: normalizeCarryoverMeta(input.carryoverMeta),
|
||||
llmPreDecomposeMeta: normalizeLlmPreDecomposeMeta(input.llmPreDecomposeMeta),
|
||||
appendItem: input.appendItem,
|
||||
@@ -271,6 +276,6 @@ export function runAssistantAddressLaneResponseRuntime<ResponseType = AssistantM
|
||||
|
||||
return {
|
||||
response: finalization.response as ResponseType,
|
||||
debug: debugWithRuntimeContracts
|
||||
debug: debugWithTruthAnswerPolicy
|
||||
};
|
||||
}
|
||||
|
||||
@@ -24,6 +24,7 @@ import type {
|
||||
TemporalGuardAudit
|
||||
} from "./assistantRuntimeGuards";
|
||||
import { attachAssistantRuntimeContractShadow } from "./assistantRuntimeContractResolver";
|
||||
import { attachAssistantTruthAnswerPolicy } from "./assistantTruthAnswerPolicyRuntimeAdapter";
|
||||
import { buildStage4AnswerContractAuditV1 } from "./assistantStage4AnswerContractAudit";
|
||||
|
||||
type RetrievalStatusItem = AssistantDebugPayload["retrieval_status"][number];
|
||||
@@ -174,8 +175,14 @@ export function buildDeepAnalysisDebugPayload(input: DeepAnalysisDebugPayloadInp
|
||||
investigation_state_snapshot: input.investigationStateSnapshot,
|
||||
normalized: input.normalizedPayload
|
||||
} as unknown as AssistantDebugPayload;
|
||||
return attachAssistantRuntimeContractShadow(debugPayload as unknown as Record<string, unknown>, {
|
||||
const debugWithRuntimeContracts = attachAssistantRuntimeContractShadow(debugPayload as unknown as Record<string, unknown>, {
|
||||
addressRuntimeMeta: input.addressRuntimeMetaForDeep as unknown as Record<string, unknown> | null | undefined,
|
||||
groundingStatus: input.groundingCheck.status
|
||||
});
|
||||
return attachAssistantTruthAnswerPolicy(debugWithRuntimeContracts, {
|
||||
addressRuntimeMeta: input.addressRuntimeMetaForDeep as unknown as Record<string, unknown> | null | undefined,
|
||||
groundingStatus: input.groundingCheck.status,
|
||||
coverageReport: input.coverageReport as unknown as Record<string, unknown>,
|
||||
replyType: "deep_analysis"
|
||||
}) as unknown as AssistantDebugPayload;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,408 @@
|
||||
import {
|
||||
ASSISTANT_TRUTH_ANSWER_POLICY_RUNTIME_SCHEMA_VERSION,
|
||||
type AssistantAnswerShapeKind,
|
||||
type AssistantAnswerShapeReplyType,
|
||||
type AssistantCarryoverDepth,
|
||||
type AssistantCoverageStatus,
|
||||
type AssistantEvidenceGrade,
|
||||
type AssistantGroundingStatus,
|
||||
type AssistantRuntimeContractShadowDecision,
|
||||
type AssistantTruthAnswerPolicyRuntimeContract,
|
||||
type AssistantTruthGateContractStatus,
|
||||
type AssistantTruthMode
|
||||
} from "../types/assistantRuntimeContracts";
|
||||
import { resolveAssistantRuntimeContractShadow } from "./assistantRuntimeContractResolver";
|
||||
|
||||
export interface ResolveAssistantTruthAnswerPolicyRuntimeInput {
|
||||
addressDebug?: Record<string, unknown> | null;
|
||||
addressRuntimeMeta?: Record<string, unknown> | null;
|
||||
groundingStatus?: unknown;
|
||||
coverageReport?: Record<string, unknown> | null;
|
||||
replyType?: unknown;
|
||||
}
|
||||
|
||||
export interface AssistantTruthAnswerPolicyRuntimeFields {
|
||||
assistant_truth_answer_policy_v1: AssistantTruthAnswerPolicyRuntimeContract;
|
||||
coverage_gate_contract: AssistantTruthAnswerPolicyRuntimeContract["truth_gate"];
|
||||
answer_shape_contract: AssistantTruthAnswerPolicyRuntimeContract["answer_shape"];
|
||||
truth_mode: AssistantTruthMode;
|
||||
carryover_eligibility: AssistantCarryoverDepth;
|
||||
answer_shape: AssistantAnswerShapeKind;
|
||||
}
|
||||
|
||||
function toRecordObject(value: unknown): Record<string, unknown> | null {
|
||||
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
||||
return null;
|
||||
}
|
||||
return value as Record<string, unknown>;
|
||||
}
|
||||
|
||||
function toNonEmptyString(value: unknown): string | null {
|
||||
if (value === null || value === undefined) {
|
||||
return null;
|
||||
}
|
||||
const text = String(value).trim();
|
||||
return text.length > 0 ? text : null;
|
||||
}
|
||||
|
||||
function asNumber(value: unknown): number | null {
|
||||
if (typeof value === "number" && Number.isFinite(value)) {
|
||||
return value;
|
||||
}
|
||||
if (typeof value === "string" && value.trim().length > 0) {
|
||||
const parsed = Number(value);
|
||||
return Number.isFinite(parsed) ? parsed : null;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
function toStringList(value: unknown): string[] {
|
||||
if (!Array.isArray(value)) {
|
||||
return [];
|
||||
}
|
||||
return value
|
||||
.map((item) => toNonEmptyString(item))
|
||||
.filter((item): item is string => Boolean(item));
|
||||
}
|
||||
|
||||
function isGroundingStatus(value: string | null): value is AssistantGroundingStatus {
|
||||
return (
|
||||
value === "grounded" ||
|
||||
value === "partial" ||
|
||||
value === "route_mismatch_blocked" ||
|
||||
value === "no_grounded_answer" ||
|
||||
value === "unsupported"
|
||||
);
|
||||
}
|
||||
|
||||
function isEvidenceGrade(value: string | null): value is AssistantEvidenceGrade {
|
||||
return value === "weak" || value === "medium" || value === "strong" || value === "none";
|
||||
}
|
||||
|
||||
function normalizeReplyType(value: unknown): AssistantAnswerShapeReplyType {
|
||||
if (value === "factual" || value === "partial_coverage" || value === "deep_analysis") {
|
||||
return value;
|
||||
}
|
||||
return "unknown";
|
||||
}
|
||||
|
||||
function groundingStatusFrom(
|
||||
debug: Record<string, unknown>,
|
||||
input: ResolveAssistantTruthAnswerPolicyRuntimeInput,
|
||||
truthGateStatus: AssistantTruthGateContractStatus
|
||||
): AssistantGroundingStatus {
|
||||
const explicit =
|
||||
toNonEmptyString(input.groundingStatus) ??
|
||||
toNonEmptyString(toRecordObject(debug.answer_grounding_check)?.status);
|
||||
if (isGroundingStatus(explicit)) {
|
||||
return explicit;
|
||||
}
|
||||
if (truthGateStatus === "blocked_route_expectation_failure") {
|
||||
return "route_mismatch_blocked";
|
||||
}
|
||||
if (truthGateStatus === "full_confirmed") {
|
||||
return "grounded";
|
||||
}
|
||||
if (truthGateStatus === "partial_supported" || truthGateStatus === "limited_temporal_or_contextual") {
|
||||
return "partial";
|
||||
}
|
||||
if (truthGateStatus === "blocked_missing_anchor" || truthGateStatus === "blocked_execution_error") {
|
||||
return "no_grounded_answer";
|
||||
}
|
||||
const rowsMatched = asNumber(debug.rows_matched);
|
||||
if (rowsMatched !== null && rowsMatched > 0) {
|
||||
return "grounded";
|
||||
}
|
||||
return "unsupported";
|
||||
}
|
||||
|
||||
function coverageStatusFrom(
|
||||
debug: Record<string, unknown>,
|
||||
input: ResolveAssistantTruthAnswerPolicyRuntimeInput,
|
||||
truthGateStatus: AssistantTruthGateContractStatus,
|
||||
groundingStatus: AssistantGroundingStatus
|
||||
): AssistantCoverageStatus {
|
||||
if (truthGateStatus === "full_confirmed") {
|
||||
return "full";
|
||||
}
|
||||
if (truthGateStatus === "partial_supported" || truthGateStatus === "limited_temporal_or_contextual") {
|
||||
return "partial";
|
||||
}
|
||||
if (truthGateStatus.startsWith("blocked")) {
|
||||
return "blocked";
|
||||
}
|
||||
if (toStringList(debug.missing_required_filters).length > 0 || groundingStatus === "route_mismatch_blocked" || groundingStatus === "no_grounded_answer") {
|
||||
return "blocked";
|
||||
}
|
||||
|
||||
const coverageReport = toRecordObject(input.coverageReport) ?? toRecordObject(debug.coverage_report);
|
||||
if (coverageReport) {
|
||||
const total = asNumber(coverageReport.requirements_total);
|
||||
const covered = asNumber(coverageReport.requirements_covered) ?? 0;
|
||||
const uncovered = toStringList(coverageReport.requirements_uncovered);
|
||||
const partial = toStringList(coverageReport.requirements_partially_covered);
|
||||
const clarification = toStringList(coverageReport.clarification_needed_for);
|
||||
const outOfScope = toStringList(coverageReport.out_of_scope_requirements);
|
||||
if (total !== null && total > 0) {
|
||||
if (covered >= total && uncovered.length === 0 && partial.length === 0 && clarification.length === 0 && outOfScope.length === 0) {
|
||||
return "full";
|
||||
}
|
||||
if (covered > 0 || partial.length > 0) {
|
||||
return "partial";
|
||||
}
|
||||
return "blocked";
|
||||
}
|
||||
}
|
||||
|
||||
const rowsMatched = asNumber(debug.rows_matched);
|
||||
if (rowsMatched !== null && rowsMatched > 0) {
|
||||
return "full";
|
||||
}
|
||||
return groundingStatus === "partial" ? "partial" : "blocked";
|
||||
}
|
||||
|
||||
function truthModeFrom(input: {
|
||||
coverageStatus: AssistantCoverageStatus;
|
||||
groundingStatus: AssistantGroundingStatus;
|
||||
truthGateStatus: AssistantTruthGateContractStatus;
|
||||
debug: Record<string, unknown>;
|
||||
}): AssistantTruthMode {
|
||||
if (input.truthGateStatus === "blocked_missing_anchor" || toStringList(input.debug.missing_required_filters).length > 0) {
|
||||
return "clarification_required";
|
||||
}
|
||||
if (input.truthGateStatus === "full_confirmed" || (input.coverageStatus === "full" && input.groundingStatus === "grounded")) {
|
||||
return "confirmed";
|
||||
}
|
||||
if (input.truthGateStatus === "partial_supported" || input.truthGateStatus === "limited_temporal_or_contextual" || input.coverageStatus === "partial") {
|
||||
return "limited";
|
||||
}
|
||||
return "unsupported";
|
||||
}
|
||||
|
||||
function evidenceGradeFrom(
|
||||
debug: Record<string, unknown>,
|
||||
coverageStatus: AssistantCoverageStatus,
|
||||
groundingStatus: AssistantGroundingStatus,
|
||||
truthGateStatus: AssistantTruthGateContractStatus
|
||||
): AssistantEvidenceGrade {
|
||||
const explicit = toNonEmptyString(debug.evidence_strength);
|
||||
if (isEvidenceGrade(explicit)) {
|
||||
return explicit;
|
||||
}
|
||||
if (coverageStatus === "blocked") {
|
||||
return "none";
|
||||
}
|
||||
if (truthGateStatus === "full_confirmed" || groundingStatus === "grounded") {
|
||||
return "strong";
|
||||
}
|
||||
const rowsMatched = asNumber(debug.rows_matched);
|
||||
if (rowsMatched !== null && rowsMatched > 0) {
|
||||
return "medium";
|
||||
}
|
||||
return coverageStatus === "partial" ? "weak" : "none";
|
||||
}
|
||||
|
||||
function normalizeReasonCode(value: string): string | null {
|
||||
const normalized = value
|
||||
.trim()
|
||||
.replace(/[^\p{L}\p{N}_.:-]+/gu, "_")
|
||||
.replace(/^_+|_+$/g, "")
|
||||
.toLowerCase();
|
||||
return normalized.length > 0 ? normalized.slice(0, 120) : null;
|
||||
}
|
||||
|
||||
function pushReason(target: string[], value: unknown): void {
|
||||
const text = toNonEmptyString(value);
|
||||
if (!text) {
|
||||
return;
|
||||
}
|
||||
const normalized = normalizeReasonCode(text);
|
||||
if (normalized && !target.includes(normalized)) {
|
||||
target.push(normalized);
|
||||
}
|
||||
}
|
||||
|
||||
function collectReasonCodes(input: {
|
||||
debug: Record<string, unknown>;
|
||||
coverageReport: Record<string, unknown> | null;
|
||||
shadow: AssistantRuntimeContractShadowDecision;
|
||||
truthMode: AssistantTruthMode;
|
||||
truthGateStatus: AssistantTruthGateContractStatus;
|
||||
}): string[] {
|
||||
const reasons: string[] = [];
|
||||
pushReason(reasons, `truth_gate_${input.truthGateStatus}`);
|
||||
pushReason(reasons, `truth_mode_${input.truthMode}`);
|
||||
input.shadow.transition_contract_reason.forEach((item) => pushReason(reasons, item));
|
||||
input.shadow.capability_contract_reason.forEach((item) => pushReason(reasons, item));
|
||||
toStringList(input.debug.missing_required_filters).forEach((item) => pushReason(reasons, `missing_filter_${item}`));
|
||||
toStringList(input.debug.limitations).forEach((item) => pushReason(reasons, item));
|
||||
toStringList(input.debug.reasons).forEach((item) => pushReason(reasons, item));
|
||||
pushReason(reasons, input.debug.route_expectation_reason);
|
||||
toStringList(toRecordObject(input.debug.answer_grounding_check)?.reasons).forEach((item) => pushReason(reasons, item));
|
||||
toStringList(input.coverageReport?.requirements_uncovered).forEach((item) => pushReason(reasons, `coverage_uncovered_${item}`));
|
||||
toStringList(input.coverageReport?.requirements_partially_covered).forEach((item) => pushReason(reasons, `coverage_partial_${item}`));
|
||||
toStringList(input.coverageReport?.clarification_needed_for).forEach((item) => pushReason(reasons, `coverage_clarification_${item}`));
|
||||
return reasons.slice(0, 32);
|
||||
}
|
||||
|
||||
function explanationFor(
|
||||
truthGateStatus: AssistantTruthGateContractStatus,
|
||||
truthMode: AssistantTruthMode,
|
||||
coverageStatus: AssistantCoverageStatus
|
||||
): string | null {
|
||||
if (truthGateStatus === "full_confirmed" && truthMode === "confirmed") {
|
||||
return null;
|
||||
}
|
||||
if (truthGateStatus === "blocked_missing_anchor" || truthMode === "clarification_required") {
|
||||
return "required_anchor_missing";
|
||||
}
|
||||
if (truthGateStatus === "blocked_route_expectation_failure") {
|
||||
return "route_expectation_failed";
|
||||
}
|
||||
if (truthGateStatus === "blocked_execution_error") {
|
||||
return "execution_failed";
|
||||
}
|
||||
if (truthGateStatus === "limited_temporal_or_contextual") {
|
||||
return "temporal_or_contextual_limit";
|
||||
}
|
||||
if (truthGateStatus === "partial_supported" || truthMode === "limited" || coverageStatus === "partial") {
|
||||
return "evidence_or_coverage_is_partial";
|
||||
}
|
||||
return "truth_gate_not_confirmed";
|
||||
}
|
||||
|
||||
function answerShapeFrom(input: {
|
||||
coverageStatus: AssistantCoverageStatus;
|
||||
truthMode: AssistantTruthMode;
|
||||
truthGateStatus: AssistantTruthGateContractStatus;
|
||||
}): AssistantAnswerShapeKind {
|
||||
if (input.truthMode === "confirmed") {
|
||||
return "confirmed_factual";
|
||||
}
|
||||
if (input.truthMode === "limited") {
|
||||
return "limited_with_reason";
|
||||
}
|
||||
if (input.truthMode === "clarification_required") {
|
||||
return "clarification_required";
|
||||
}
|
||||
if (input.coverageStatus === "blocked" || input.truthGateStatus.startsWith("blocked")) {
|
||||
return "blocked_no_answer";
|
||||
}
|
||||
return input.truthGateStatus === "unknown" ? "unknown" : "unsupported_boundary";
|
||||
}
|
||||
|
||||
function requiredSectionsFor(shape: AssistantAnswerShapeKind): string[] {
|
||||
if (shape === "confirmed_factual") {
|
||||
return ["direct_answer", "evidence_basis"];
|
||||
}
|
||||
if (shape === "limited_with_reason") {
|
||||
return ["direct_answer", "evidence_window", "limitations"];
|
||||
}
|
||||
if (shape === "clarification_required") {
|
||||
return ["clarifying_question", "missing_anchors"];
|
||||
}
|
||||
if (shape === "blocked_no_answer") {
|
||||
return ["blocked_reason", "safe_next_step"];
|
||||
}
|
||||
if (shape === "unsupported_boundary") {
|
||||
return ["boundary_reason", "safe_next_step"];
|
||||
}
|
||||
return ["safe_next_step"];
|
||||
}
|
||||
|
||||
export function resolveAssistantTruthAnswerPolicyRuntime(
|
||||
input: ResolveAssistantTruthAnswerPolicyRuntimeInput
|
||||
): AssistantTruthAnswerPolicyRuntimeContract {
|
||||
const debug = toRecordObject(input.addressDebug) ?? {};
|
||||
const shadow = resolveAssistantRuntimeContractShadow({
|
||||
addressDebug: debug,
|
||||
addressRuntimeMeta: input.addressRuntimeMeta,
|
||||
groundingStatus: input.groundingStatus
|
||||
});
|
||||
const truthGateStatus = shadow.truth_gate_contract_status;
|
||||
const groundingStatus = groundingStatusFrom(debug, input, truthGateStatus);
|
||||
const coverageStatus = coverageStatusFrom(debug, input, truthGateStatus, groundingStatus);
|
||||
const truthMode = truthModeFrom({
|
||||
coverageStatus,
|
||||
groundingStatus,
|
||||
truthGateStatus,
|
||||
debug
|
||||
});
|
||||
const evidenceGrade = evidenceGradeFrom(debug, coverageStatus, groundingStatus, truthGateStatus);
|
||||
const coverageReport = toRecordObject(input.coverageReport) ?? toRecordObject(debug.coverage_report);
|
||||
const reasonCodes = collectReasonCodes({
|
||||
debug,
|
||||
coverageReport,
|
||||
shadow,
|
||||
truthMode,
|
||||
truthGateStatus
|
||||
});
|
||||
const shape = answerShapeFrom({
|
||||
coverageStatus,
|
||||
truthMode,
|
||||
truthGateStatus
|
||||
});
|
||||
const carryoverEligibility =
|
||||
coverageStatus === "blocked" || truthMode === "unsupported" ? "none" : shadow.carryover_eligibility;
|
||||
|
||||
const truthGate = {
|
||||
schema_version: ASSISTANT_TRUTH_ANSWER_POLICY_RUNTIME_SCHEMA_VERSION,
|
||||
policy_owner: "assistantTruthAnswerPolicyRuntimeAdapter",
|
||||
coverage_status: coverageStatus,
|
||||
evidence_grade: evidenceGrade,
|
||||
grounding_status: groundingStatus,
|
||||
truth_mode: truthMode,
|
||||
carryover_eligibility: carryoverEligibility,
|
||||
reason_codes: reasonCodes,
|
||||
source_truth_gate_status: truthGateStatus,
|
||||
blocked_or_limited_explanation: explanationFor(truthGateStatus, truthMode, coverageStatus)
|
||||
} satisfies AssistantTruthAnswerPolicyRuntimeContract["truth_gate"];
|
||||
|
||||
const answerShape = {
|
||||
schema_version: ASSISTANT_TRUTH_ANSWER_POLICY_RUNTIME_SCHEMA_VERSION,
|
||||
policy_owner: "assistantTruthAnswerPolicyRuntimeAdapter",
|
||||
answer_shape: shape,
|
||||
reply_type: normalizeReplyType(input.replyType),
|
||||
capability_contract_id: shadow.capability_contract_id,
|
||||
transition_contract_id: shadow.transition_contract_id,
|
||||
may_state_confirmed_facts: truthMode === "confirmed" || truthMode === "limited",
|
||||
must_include_limitation: truthMode !== "confirmed",
|
||||
may_power_followup: carryoverEligibility !== "none" && coverageStatus !== "blocked",
|
||||
required_sections: requiredSectionsFor(shape),
|
||||
downgrade_only: true
|
||||
} satisfies AssistantTruthAnswerPolicyRuntimeContract["answer_shape"];
|
||||
|
||||
return {
|
||||
schema_version: ASSISTANT_TRUTH_ANSWER_POLICY_RUNTIME_SCHEMA_VERSION,
|
||||
policy_owner: "assistantTruthAnswerPolicyRuntimeAdapter",
|
||||
truth_gate: truthGate,
|
||||
answer_shape: answerShape
|
||||
};
|
||||
}
|
||||
|
||||
export function buildAssistantTruthAnswerPolicyRuntimeFields(
|
||||
input: ResolveAssistantTruthAnswerPolicyRuntimeInput
|
||||
): AssistantTruthAnswerPolicyRuntimeFields {
|
||||
const policy = resolveAssistantTruthAnswerPolicyRuntime(input);
|
||||
return {
|
||||
assistant_truth_answer_policy_v1: policy,
|
||||
coverage_gate_contract: policy.truth_gate,
|
||||
answer_shape_contract: policy.answer_shape,
|
||||
truth_mode: policy.truth_gate.truth_mode,
|
||||
carryover_eligibility: policy.truth_gate.carryover_eligibility,
|
||||
answer_shape: policy.answer_shape.answer_shape
|
||||
};
|
||||
}
|
||||
|
||||
export function attachAssistantTruthAnswerPolicy<T extends Record<string, unknown>>(
|
||||
debugPayload: T,
|
||||
input: Omit<ResolveAssistantTruthAnswerPolicyRuntimeInput, "addressDebug">
|
||||
): T & AssistantTruthAnswerPolicyRuntimeFields {
|
||||
return {
|
||||
...debugPayload,
|
||||
...buildAssistantTruthAnswerPolicyRuntimeFields({
|
||||
...input,
|
||||
addressDebug: debugPayload
|
||||
})
|
||||
};
|
||||
}
|
||||
@@ -18,7 +18,10 @@ import type {
|
||||
import type { AccountingGraphBuildResult } from "./stage4Graph";
|
||||
import type { AddressNavigationState } from "./addressNavigation";
|
||||
import type {
|
||||
AssistantAnswerShapeKind,
|
||||
AssistantRuntimeContractShadowDecision,
|
||||
AssistantTruthAnswerPolicyRuntimeContract,
|
||||
AssistantTruthMode,
|
||||
AssistantTransitionClassId
|
||||
} from "./assistantRuntimeContracts";
|
||||
|
||||
@@ -454,6 +457,12 @@ export interface AssistantDebugPayload {
|
||||
transition_contract_id?: AssistantTransitionClassId | null;
|
||||
capability_contract_id?: string | null;
|
||||
truth_gate_contract_status?: AssistantRuntimeContractShadowDecision["truth_gate_contract_status"];
|
||||
assistant_truth_answer_policy_v1?: AssistantTruthAnswerPolicyRuntimeContract;
|
||||
coverage_gate_contract?: AssistantTruthAnswerPolicyRuntimeContract["truth_gate"];
|
||||
answer_shape_contract?: AssistantTruthAnswerPolicyRuntimeContract["answer_shape"];
|
||||
truth_mode?: AssistantTruthMode;
|
||||
carryover_eligibility?: AssistantTruthAnswerPolicyRuntimeContract["truth_gate"]["carryover_eligibility"];
|
||||
answer_shape?: AssistantAnswerShapeKind;
|
||||
execution_lane?: "address_query" | "deep_analysis";
|
||||
llm_decomposition_applied?: boolean;
|
||||
llm_decomposition_attempted?: boolean;
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import type { AddressIntent } from "./addressQuery";
|
||||
|
||||
export const ASSISTANT_RUNTIME_CONTRACTS_SCHEMA_VERSION = "assistant_runtime_contracts_v1" as const;
|
||||
export const ASSISTANT_TRUTH_ANSWER_POLICY_RUNTIME_SCHEMA_VERSION = "assistant_truth_answer_policy_runtime_v1" as const;
|
||||
|
||||
export type AssistantLivingMode = "address_data" | "assistant_data_scope" | "chat" | "meta_followup" | "clarification";
|
||||
export type AssistantFrameStatus = "active" | "suspended" | "closed" | "blocked";
|
||||
@@ -15,6 +16,26 @@ export type AssistantStateSlice =
|
||||
| "answer_context_state";
|
||||
export type AssistantCarryoverDepth = "full" | "root_only" | "object_only" | "meta_only" | "none";
|
||||
export type AssistantAnswerMode = "confirmed" | "limited" | "clarification" | "boundary" | "meta" | "recap";
|
||||
export type AssistantCoverageStatus = "full" | "partial" | "blocked";
|
||||
export type AssistantEvidenceGrade = "none" | "weak" | "medium" | "strong";
|
||||
export type AssistantGroundingStatus = "grounded" | "partial" | "route_mismatch_blocked" | "no_grounded_answer" | "unsupported";
|
||||
export type AssistantTruthMode = "confirmed" | "limited" | "clarification_required" | "unsupported";
|
||||
export type AssistantTruthGateContractStatus =
|
||||
| "full_confirmed"
|
||||
| "partial_supported"
|
||||
| "blocked_missing_anchor"
|
||||
| "blocked_route_expectation_failure"
|
||||
| "blocked_execution_error"
|
||||
| "limited_temporal_or_contextual"
|
||||
| "unknown";
|
||||
export type AssistantAnswerShapeKind =
|
||||
| "confirmed_factual"
|
||||
| "limited_with_reason"
|
||||
| "clarification_required"
|
||||
| "unsupported_boundary"
|
||||
| "blocked_no_answer"
|
||||
| "unknown";
|
||||
export type AssistantAnswerShapeReplyType = "factual" | "partial_coverage" | "deep_analysis" | "unknown";
|
||||
|
||||
export interface AssistantDateScopeState {
|
||||
as_of_date: string | null;
|
||||
@@ -58,14 +79,42 @@ export interface AssistantClarificationState {
|
||||
}
|
||||
|
||||
export interface AssistantCoverageGateState {
|
||||
coverage_status: "full" | "partial" | "blocked";
|
||||
evidence_grade: "none" | "weak" | "medium" | "strong";
|
||||
grounding_status: "grounded" | "partial" | "route_mismatch_blocked" | "no_grounded_answer" | "unsupported";
|
||||
truth_mode: "confirmed" | "limited" | "clarification_required" | "unsupported";
|
||||
coverage_status: AssistantCoverageStatus;
|
||||
evidence_grade: AssistantEvidenceGrade;
|
||||
grounding_status: AssistantGroundingStatus;
|
||||
truth_mode: AssistantTruthMode;
|
||||
carryover_eligibility: AssistantCarryoverDepth;
|
||||
reason_codes: string[];
|
||||
}
|
||||
|
||||
export interface AssistantTruthGateRuntimeContract extends AssistantCoverageGateState {
|
||||
schema_version: typeof ASSISTANT_TRUTH_ANSWER_POLICY_RUNTIME_SCHEMA_VERSION;
|
||||
policy_owner: "assistantTruthAnswerPolicyRuntimeAdapter";
|
||||
source_truth_gate_status: AssistantTruthGateContractStatus;
|
||||
blocked_or_limited_explanation: string | null;
|
||||
}
|
||||
|
||||
export interface AssistantAnswerShapeRuntimeContract {
|
||||
schema_version: typeof ASSISTANT_TRUTH_ANSWER_POLICY_RUNTIME_SCHEMA_VERSION;
|
||||
policy_owner: "assistantTruthAnswerPolicyRuntimeAdapter";
|
||||
answer_shape: AssistantAnswerShapeKind;
|
||||
reply_type: AssistantAnswerShapeReplyType;
|
||||
capability_contract_id: string | null;
|
||||
transition_contract_id: AssistantTransitionClassId | null;
|
||||
may_state_confirmed_facts: boolean;
|
||||
must_include_limitation: boolean;
|
||||
may_power_followup: boolean;
|
||||
required_sections: string[];
|
||||
downgrade_only: true;
|
||||
}
|
||||
|
||||
export interface AssistantTruthAnswerPolicyRuntimeContract {
|
||||
schema_version: typeof ASSISTANT_TRUTH_ANSWER_POLICY_RUNTIME_SCHEMA_VERSION;
|
||||
policy_owner: "assistantTruthAnswerPolicyRuntimeAdapter";
|
||||
truth_gate: AssistantTruthGateRuntimeContract;
|
||||
answer_shape: AssistantAnswerShapeRuntimeContract;
|
||||
}
|
||||
|
||||
export interface AssistantSessionAggregateState {
|
||||
schema_version: typeof ASSISTANT_RUNTIME_CONTRACTS_SCHEMA_VERSION;
|
||||
living_mode_state: {
|
||||
@@ -160,13 +209,6 @@ export interface AssistantRuntimeContractShadowDecision {
|
||||
transition_contract_reason: string[];
|
||||
capability_contract_id: string | null;
|
||||
capability_contract_reason: string[];
|
||||
truth_gate_contract_status:
|
||||
| "full_confirmed"
|
||||
| "partial_supported"
|
||||
| "blocked_missing_anchor"
|
||||
| "blocked_route_expectation_failure"
|
||||
| "blocked_execution_error"
|
||||
| "limited_temporal_or_contextual"
|
||||
| "unknown";
|
||||
truth_gate_contract_status: AssistantTruthGateContractStatus;
|
||||
carryover_eligibility: AssistantCarryoverDepth;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user