fix(rectification): stream persisted candidate choices

This commit is contained in:
Jesse_Chen
2026-08-04 14:32:09 +08:00
parent 8f6f4f511b
commit 393f352a8d
6 changed files with 92 additions and 4 deletions
@@ -13,6 +13,7 @@ type QueryResult = Readonly<{
type Filter =
| Readonly<{ kind: "eq"; column: string; value: unknown }>
| Readonly<{ kind: "neq"; column: string; value: unknown }>
| Readonly<{ kind: "gt"; column: string; value: unknown }>
| Readonly<{ kind: "in"; column: string; value: readonly unknown[] }>
| Readonly<{ kind: "is"; column: string; value: unknown }>
| Readonly<{ kind: "notContains"; column: string; value: unknown }>;
@@ -176,6 +177,12 @@ class LocalPostgresQueryBuilder implements PromiseLike<QueryResult> {
return this;
}
gt(column: string, value: unknown) {
identifier(column);
this.filters.push({ kind: "gt", column, value });
return this;
}
in(column: string, value: readonly unknown[]) {
identifier(column);
this.filters.push({ kind: "in", column, value });
@@ -257,7 +264,7 @@ class LocalPostgresQueryBuilder implements PromiseLike<QueryResult> {
return `not (${column} @> $${parameters.length})`;
}
parameters.push(databaseValue(types.get(filter.column), filter.value));
return `${column} ${filter.kind === "neq" ? "<>" : "="} $${parameters.length}`;
return `${column} ${filter.kind === "neq" ? "<>" : filter.kind === "gt" ? ">" : "="} $${parameters.length}`;
});
return ` where ${parts.join(" and ")}`;
}
@@ -21,6 +21,7 @@ TRUTH BOUNDARIES (from the skill overlay)
- Keep three states distinct: candidate is an engine comparison result; accepted is the user's chosen working birth time; confirmed is a unique minute that passed the engine confirmation gate and was accepted by the user.
- You may show only the server-returned candidate times and relative_support values. Call them “相对支持度”, never probability, statistical confidence, or certainty. Never expose raw scores, weights, event ids, payloads, or chain-of-thought.
- If confirmation_allowed=false but selection_allowed=true, explain that the engine has not uniquely confirmed one minute and let the user choose among the returned candidates. Never call that choice engine-confirmed.
- Read external_validation_status literally: not_evaluated means official VedAstro was not invoked because its local entry gate was not ready, not that VedAstro ran and failed. Neighbor stability and leave-one-event-out are diagnostic confidence indicators, not hard blockers.
- If confirmation_allowed=true, still require explicit user agreement before saving the representative minute.
SAVING
+15 -1
View File
@@ -531,7 +531,7 @@ export function createAgenticRectificationTools(ctx: AgenticRectificationContext
const confirmTool = createTool({
id: "rectification-confirm",
description:
"Run the high-rigor confirmation gate for the candidate range and the user's dated events: three-engine parity, external VedAstro validation, neighbor stability, leave-one-out retention, width and margin thresholds. Returns whether a precise minute can be confirmed, the representative minute, and the reasons. Only call once you have enough confirmed dated events across domains. This does NOT write anything.",
"Run the high-rigor confirmation gate for the candidate range and the user's dated events. Official VedAstro runs only after the local external-validation entry gate is ready; external_validation_status=not_evaluated means it was not invoked, not that it failed. Neighbor stability and leave-one-out are diagnostic confidence indicators, not hard blockers. Returns whether a precise minute can be confirmed, the representative minute, and the reasons. Only call once you have enough confirmed dated events across domains. This does NOT write anything.",
inputSchema: z.object({
candidate_range: candidateRangeSchema,
events: z.array(agenticRectificationEventSchema).min(1).max(40),
@@ -558,6 +558,15 @@ export function createAgenticRectificationTools(ctx: AgenticRectificationContext
const gates = (technique?.gates && typeof technique.gates === "object")
? technique.gates as Record<string, unknown>
: {};
const externalEngines = (technique?.external_engines && typeof technique.external_engines === "object")
? technique.external_engines as Record<string, unknown>
: {};
const externalValidation = (externalEngines.validation && typeof externalEngines.validation === "object")
? externalEngines.validation as Record<string, unknown>
: {};
const externalValidationStatus = typeof externalEngines.status === "string"
? externalEngines.status
: "not_evaluated";
const confirmationAllowed = technique?.confirmation_allowed === true
&& technique?.decision === "confirm_minute";
const representativeTime = winning && timePattern.test(String(winning.representative_time ?? ""))
@@ -604,6 +613,11 @@ export function createAgenticRectificationTools(ctx: AgenticRectificationContext
} : null,
reasons: Array.isArray(data.reasons) ? data.reasons : [],
stability_diagnostics: data.stability_diagnostics,
external_validation_status: externalValidationStatus,
external_validation_invoked: externalValidationStatus !== "not_evaluated",
external_validation_reason: typeof externalValidation.reason === "string"
? externalValidation.reason
: typeof externalValidation.vedastro_reason === "string" ? externalValidation.vedastro_reason : null,
technique_contract: {
decision: technique?.decision,
confirmation_allowed: technique?.confirmation_allowed,