feat(rectification): drive questions from candidate contrast
This commit is contained in:
@@ -13,7 +13,7 @@ import { generateOpeningQuestion, regenerateQuestionRealization } from "../recti
|
||||
import { calculationSpecHash, evidenceSetHash } from "./fingerprints.ts";
|
||||
import { hasPolicyInvalidScoreableEvents } from "./evidence-ledger.ts";
|
||||
import { openingQuestion } from "./opening-question.ts";
|
||||
import type { RectificationV4Store } from "./store.ts";
|
||||
import { canResumeRectificationCase, type RectificationV4Store } from "./store.ts";
|
||||
|
||||
const regenerationInFlight = new Map<string, Promise<RectificationV4Case | null>>();
|
||||
|
||||
@@ -58,7 +58,10 @@ export function createRectificationV4CaseService(
|
||||
|
||||
const specHash = calculationSpecHash(input.calculationSpec);
|
||||
const active = await store.findActiveCase(input.userId);
|
||||
if (active?.calculationSpecHash === specHash) {
|
||||
const activeJob = active?.status === "processing" ? await store.loadActiveJob(input.userId, active.id) : null;
|
||||
if (active?.calculationSpecHash === specHash
|
||||
&& active.algorithmVersion === rectificationV4AlgorithmVersion
|
||||
&& canResumeRectificationCase(active, Boolean(activeJob))) {
|
||||
return response(input.userId, await store.createCase({ case: active, actionId: input.actionId }));
|
||||
}
|
||||
|
||||
|
||||
@@ -4,7 +4,11 @@ export const rectificationV4Protocol = "rectification-evidence-v4" as const;
|
||||
export const rectificationAgentV5Protocol = "rectification-evidence-v5" as const;
|
||||
export const rectificationDeploymentModeSchema = z.enum(["v4_legacy", "v5_shadow", "v5_agent"]);
|
||||
export type RectificationDeploymentMode = z.infer<typeof rectificationDeploymentModeSchema>;
|
||||
export const rectificationV4AlgorithmVersion = "rectification-v5-matrix-scoring-1" as const;
|
||||
export const rectificationV4AlgorithmVersion = "rectification-v5-matrix-scoring-2" as const;
|
||||
const rectificationLegacyAlgorithmVersions = [
|
||||
"rectification-v4-range-scoring-1",
|
||||
"rectification-v5-matrix-scoring-1",
|
||||
] as const;
|
||||
|
||||
export const rectificationV4CaseStatusSchema = z.enum([
|
||||
"awaiting_answer",
|
||||
@@ -182,7 +186,7 @@ const candidateSnapshotBaseSchema = z.object({
|
||||
caseVersion: z.number().int().nonnegative(),
|
||||
evidenceSetHash: z.string().regex(/^[a-f0-9]{64}$/),
|
||||
calculationSpecHash: z.string().regex(/^[a-f0-9]{64}$/),
|
||||
algorithmVersion: z.literal(rectificationV4AlgorithmVersion),
|
||||
algorithmVersion: z.enum([...rectificationLegacyAlgorithmVersions, rectificationV4AlgorithmVersion]),
|
||||
candidates: z.array(candidateMinuteSchema).min(1).max(1_440),
|
||||
clusters: z.array(candidateClusterSchema).max(20),
|
||||
robustness: robustnessSchema,
|
||||
|
||||
@@ -11,7 +11,7 @@ import type {
|
||||
RectificationV4Store,
|
||||
RectificationV4Turn,
|
||||
} from "./store.ts";
|
||||
import { RectificationV4StoreError } from "./store.ts";
|
||||
import { canResumeRectificationCase, RectificationV4StoreError } from "./store.ts";
|
||||
import { evidenceSetHash } from "./fingerprints.ts";
|
||||
|
||||
export function createRectificationV4MemoryStore(): RectificationV4Store & {
|
||||
@@ -93,7 +93,10 @@ export function createRectificationV4MemoryStore(): RectificationV4Store & {
|
||||
if (replay) return owned(input.case.userId, replay.caseId);
|
||||
const active = [...cases.values()].find((value) => value.userId === input.case.userId
|
||||
&& value.status !== "abandoned" && value.acceptedRange === null);
|
||||
if (active?.calculationSpecHash === input.case.calculationSpecHash) {
|
||||
const hasActiveJob = active ? [...jobs.values()].some((job) => job.caseId === active.id && ["pending", "processing"].includes(job.status)) : false;
|
||||
if (active?.calculationSpecHash === input.case.calculationSpecHash
|
||||
&& active.algorithmVersion === input.case.algorithmVersion
|
||||
&& canResumeRectificationCase(active, hasActiveJob)) {
|
||||
actionResults.set(`${input.case.userId}:${input.actionId}`, { caseId: active.id, jobId: null });
|
||||
return active;
|
||||
}
|
||||
|
||||
@@ -12,6 +12,11 @@ import type {
|
||||
} from "./contracts.ts";
|
||||
export type { RectificationV4Turn } from "./contracts.ts";
|
||||
|
||||
export function canResumeRectificationCase(caseValue: RectificationV4Case, hasActiveJob: boolean): boolean {
|
||||
return (caseValue.status === "awaiting_answer" && caseValue.currentQuestion !== null)
|
||||
|| (caseValue.status === "processing" && hasActiveJob);
|
||||
}
|
||||
|
||||
export type ClaimedRectificationV4Job = Readonly<{
|
||||
job: RectificationV4Job;
|
||||
case: RectificationV4Case;
|
||||
|
||||
@@ -97,7 +97,7 @@ function caseValue(row: Row, latestSnapshot: CandidateSnapshot | null): Rectific
|
||||
narrationModelId: row.narration_model_id ? String(row.narration_model_id) : null,
|
||||
skillVersion: row.skill_version ? String(row.skill_version) : "birth-time-rectification-v5",
|
||||
promptVersion: row.prompt_version ? String(row.prompt_version) : "rectification-agent-v5-1",
|
||||
algorithmVersion: row.algorithm_version ? String(row.algorithm_version) : "rectification-v5-matrix-scoring-1",
|
||||
algorithmVersion: row.algorithm_version ? String(row.algorithm_version) : "rectification-v5-matrix-scoring-2",
|
||||
deploymentMode: row.deployment_mode === "v5_agent" || row.deployment_mode === "v5_shadow" ? row.deployment_mode : "v4_legacy",
|
||||
agentMode: row.agent_mode === "agent" ? "agent" : "deterministic_fallback",
|
||||
featureSnapshotId: row.feature_snapshot_id ? String(row.feature_snapshot_id) : null,
|
||||
|
||||
Reference in New Issue
Block a user