import { createDynamicTurnPersistence } from "../src/lib/birth-time-journey-dynamic-persistence.ts"; import { dynamicPrivateStateSchema } from "../src/lib/birth-time-journey-dynamic-state.ts"; import type { DynamicStoredRectificationCase, LegacyStoredRectificationCase } from "../src/lib/birth-time-journey-service.ts"; export const caseId = "45857b75-4718-4590-aaf5-7113a03ea765"; export const ownerId = "12dc56f0-1f17-4a2f-86bf-1056ab78def9"; export const actionId = "a9890e09-d535-46f0-9a36-86017515a5a1"; export const currentRange = { startTime: "05:00", endTime: "06:00" } as const; export const snapshot = { state: "rectifying", assistantIntent: "continue_rectification_questions", input: "rectification_questions", route: "rectification", confidence: null, canApply: false, activeTime: null, reportedRange: { label: "05:00—06:00", startTime: "05:00", endTime: "06:00" }, } as const; export const persistedQuestion = { questionId: "11111111-1111-4111-8111-111111111111", opportunityId: "career-window", dimensionCode: "career_change", estimatedInformationGain: 0.7, scoringVersion: "birth-time-choice-scoring-v2", source: "fallback", questionFingerprint: "question-fingerprint", candidatePartitionFingerprint: "partition-fingerprint", prompt: "哪一个时间段更接近这次工作变化?", options: [ { optionId: "22222222-2222-4222-8222-222222222222", label: "较早阶段", kind: "primary", partitionId: "window-a", candidateScores: { "05:10": 0.8 }, }, { optionId: "33333333-3333-4333-8333-333333333333", label: "较晚阶段", kind: "primary", partitionId: "window-b", candidateScores: { "05:50": 0.7 }, }, { optionId: "44444444-4444-4444-8444-444444444444", label: "不确定 / 不记得", kind: "unknown", partitionId: null, candidateScores: null, }, { optionId: "55555555-5555-4555-8555-555555555555", label: "都不符合", kind: "unmatched", partitionId: null, candidateScores: null, }, ], } as const; export const dynamicTurnState = { journeyProtocol: "dynamic-choice-v2", turnVersion: 7, nextAction: { kind: "ask_dynamic_choice", question: { questionId: persistedQuestion.questionId, prompt: persistedQuestion.prompt, options: persistedQuestion.options.map(({ optionId, label, kind }) => ({ optionId, label, kind })), }, }, progress: { phase: "question", answeredCount: 1, effectiveAnswerCount: 1, currentRange, previousRange: null, plateauCount: 0, }, permissions: { canConfirmCandidate: false }, } as const; export const dynamicControl = { asOfDate: "2026-07-18", answeredCount: 1, effectiveAnswerCount: 1, plateauCount: 0, questionFingerprints: [persistedQuestion.questionFingerprint], partitionFingerprints: [persistedQuestion.candidatePartitionFingerprint], dismissedOpportunityIds: [], recentRanges: [currentRange], pausedAction: null, } as const; const publicRow = { id: caseId, user_id: ownerId, journey_protocol: "dynamic-choice-v2", journey_snapshot: snapshot, questionnaire: {}, answers: { legacy: "A" }, scoring_result: {}, reported_date: "1993-04-17", life_events: [], candidate_result: {}, turn_version: 7, turn_state: dynamicTurnState, evidence_draft: null, processed_action_ids: [], adaptive_round: 0, asked_domains: [], }; export const privateRow = { case_id: caseId, user_id: ownerId, candidate_model: { candidates: ["05:10", "05:50"] }, current_choice_question: persistedQuestion, choice_answers: [{ questionId: "prior-question", optionId: "prior-option", kind: "primary", opportunityId: "prior-opportunity", answeredAt: "2026-07-18T08:00:00.000Z", }], choice_evidence: [{ questionId: "prior-question", opportunityId: "prior-opportunity", partitionId: "prior-partition", dimensionCode: "relocation_change", candidateScores: { "05:10": 0.6, "05:50": 0.2 }, informationGain: 0.4, }], dynamic_control: dynamicControl, agent_context: ["用户只记得大概阶段"], }; export function loadClient( privateState: typeof privateRow | null, omitProcessedActions = false, publicTurnVersion = publicRow.turn_version, ) { const { processed_action_ids: ignoredReceipts, ...rowWithoutReceipts } = publicRow; void ignoredReceipts; return { from(table: string) { const row = table === "birth_time_rectification_cases" ? omitProcessedActions ? rowWithoutReceipts : { ...publicRow, turn_version: publicTurnVersion } : table === "birth_time_rectification_dynamic_state" ? privateState : { latitude: 31.2304, longitude: 121.4737, timezone_offset: 8 }; const query = { select() { return query; }, eq() { return query; }, async maybeSingle() { return { data: row, error: null }; }, }; return query; }, }; } export function dynamicCase(): DynamicStoredRectificationCase { return { id: caseId, userId: ownerId, journeyProtocol: "dynamic-choice-v2", snapshot, questionnaire: null, answers: { legacy: "A" }, lifeEvents: [], candidateResult: null, turnVersion: 7, turnState: null, dynamicTurnState, evidenceDraft: null, processedActionIds: [], persistedProgress: { adaptiveRound: 0, askedDomains: [] }, candidateModel: privateRow.candidate_model, currentChoiceQuestion: persistedQuestion, choiceAnswers: [], choiceEvidence: [], dynamicControl, agentContext: privateRow.agent_context, }; } export function rpcPersistence() { let saved = dynamicCase(); const calls: { readonly name: string; readonly args: Readonly> }[] = []; return { calls, persistence: createDynamicTurnPersistence({ async rpc(name: string, args: Readonly>) { calls.push({ name, args }); const receivedAction = String(args.p_action_id ?? ""); if (saved.processedActionIds.includes(receivedAction)) { return { data: saved.turnVersion, error: null }; } if (args.p_expected_version !== saved.turnVersion) { return { data: null, error: { message: "stale_birth_time_dynamic_turn" } }; } const privateState = dynamicPrivateStateSchema.parse(args.p_private_state); saved = { ...saved, ...privateState, turnVersion: saved.turnVersion + 1, dynamicTurnState: { ...saved.dynamicTurnState, turnVersion: saved.turnVersion + 1 }, processedActionIds: [...saved.processedActionIds, receivedAction], }; return { data: saved.turnVersion, error: null }; }, }, async () => saved, () => "2026-07-18"), }; } export function legacyCase(active: boolean): LegacyStoredRectificationCase { return { id: caseId, userId: ownerId, journeyProtocol: "legacy-guided-v1", snapshot, questionnaire: null, answers: { q1: "A" }, lifeEvents: [{ id: "event-1", domain: "career", precision: "year", date: "2019" }], candidateResult: null, turnVersion: 4, turnState: { turnVersion: 4, nextAction: active ? { kind: "ask_baseline_evidence", question: { questionId: "legacy-question", phase: "baseline", domain: "career", requestedPrecision: ["year"], allowUnknown: true, purposeCode: "legacy", plannerVersion: "legacy-v1", }, } : { kind: "present_low_result", resultId: null }, progress: { phase: active ? "baseline" : "result", baselineDomainCount: 1, confirmedEvidenceCount: 1, adaptiveRound: 0, maxAdaptiveRounds: 3, }, permissions: { canConfirmCandidate: false }, evidenceDraft: null, }, evidenceDraft: null, processedActionIds: [], persistedProgress: { adaptiveRound: 0, askedDomains: ["career"] }, }; }