Files
Jyotisha/frontend/tests/rectification-opening-projection.test.ts
T
66f087b588 feat(rectification): submit varga-resolution implementation for review
Review-only snapshot for BUG-1115 through BUG-1117; not merge-ready. New opening and append-turn PostgreSQL permission failures remain blocked. Persisted joint replay has zero completed questions; segment ordering remains off by default. The existing offline replay JSON is retained stale and unchanged after a denied overwrite, including its CRLF line endings. Browser/provider validation and final serial gates remain pending. No deployment, role permission changes, or staging/main push.

Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-10-01 08:04:04 +08:00

63 lines
4.6 KiB
TypeScript

import assert from "node:assert/strict";
import test from "node:test";
import { dossierResponse } from "../src/lib/rectification-agentic/v9/case-dossier-response.ts";
import { choiceCardFromCaseDossier } from "../src/lib/rectification-agentic/v9/interview-state.ts";
import { buildSegmentSummary } from "../src/lib/rectification-agentic/core/segment-summary.ts";
import { parseV9CaseDossier } from "../src/lib/rectification-agentic/v9/tool-service.ts";
import { dossierFixture, activeFocusFixture, conversationSummaryFixture } from "./rectification-v9-test-support.ts";
import { AA_RANGE, buildGoldenLatest } from "./rectification-grounding-support.ts";
// Real public AA score for identity checks; explicitly fictional focus/unique
// controls below verify projection only, not engine calibration or SQL.
test("actual dossier projection preserves read-only gates and hides collect cards only for delivered consistency", async () => {
const { latest, scored } = await buildGoldenLatest();
const raw = dossierFixture({ candidateRange: AA_RANGE, latestResult: latest,
conversationSummary: conversationSummaryFixture({ activeFocus: activeFocusFixture({ intent: "collect_method_evidence", targetKind: "career_change",
expectedAnswerSchema: { collect: true, prompt: "请说出第一次工作变化发生的年份。" } }) }) });
const dossier = parseV9CaseDossier(raw)!;
const identity = { status: "verified", requiresSkillAdoption: false } as never;
const live = { algorithmVersion: scored.algorithmVersion, policyVersion: scored.policyVersion };
const writable = dossierResponse(dossier, [], identity, { liveIdentity: live });
assert.equal(writable.case.result_identity.read_only, false);
assert.ok(writable.current_question);
assert.deepEqual(writable.choice_card, choiceCardFromCaseDossier(dossier), "normal projection keeps the production tap/time mutual-exclusion decision");
const tapRaw = dossierFixture({ candidateRange: AA_RANGE, latestResult: latest,
conversationSummary: conversationSummaryFixture({ activeFocus: activeFocusFixture({
intent: "collect_method_evidence", questionId: "collect:targeted:career", targetKind: "targeted:career",
expectedAnswerSchema: { collect: true, prompt: "工作这条线有没有发生过明显变化?" },
}) }) });
const tapDossier = parseV9CaseDossier(tapRaw)!;
const tap = dossierResponse(tapDossier, [], identity, { liveIdentity: live });
assert.ok(tap.current_question);
assert.ok(tap.choice_card, "the actual production projection must retain a valid persisted collect tap card");
assert.equal(tap.choice_card.scoring, false);
const readOnlyTap = dossierResponse(tapDossier, [], identity, { liveIdentity: { ...live, algorithmVersion: "synthetic-old-version" } });
assert.equal(readOnlyTap.current_question, null);
assert.equal(readOnlyTap.choice_card, null, "read-only removes a proven renderable card, not just an already-null fixture");
const readOnly = dossierResponse(dossier, [], identity, { liveIdentity: { ...live, algorithmVersion: "synthetic-old-version" } });
assert.equal(readOnly.case.result_identity.read_only, true);
assert.equal(readOnly.current_question, null);
assert.equal(readOnly.choice_card, null);
assert.equal(readOnly.latest_result?.can_adopt, false);
assert.equal(readOnly.latest_result?.confirmationAllowed, false);
const range = { start_time: "09:00", end_time: "09:20" };
const minutes = Array.from({ length: 21 }, (_, offset) => ({ offset, date: "2000-06-14", time: `09:${String(offset).padStart(2, "0")}`,
signs: { D1: 1, D9: 2, D10: 3 } }));
const summary = buildSegmentSummary({ minutes, candidates: [], targets: ["D1", "D9", "D10"], windowMinutes: 21, scanComplete: true });
const closedRaw = dossierFixture({ candidateRange: range, status: "closed", latestResult: null,
conversationSummary: raw.conversation_summary });
Object.assign(closedRaw.case, { rectification_domain: "general",
checks: { contract: "segment-opening-v1", domain: "general", range_fingerprint: "a".repeat(64),
status: "complete", summary, delivered_turn_id: "synthetic-opening-turn" } });
const closed = parseV9CaseDossier(closedRaw)!;
const projected = dossierResponse(closed, [], identity, { liveIdentity: live });
assert.equal(projected.current_question, null);
assert.equal(projected.choice_card, null);
assert.equal(projected.latest_result, null);
assert.equal(projected.step_state.headline, "盘型一致,不用校正");
assert.equal(projected.next_user_action.id, "start_consultation");
assert.equal(projected.case.accepted_time, null);
assert.equal(projected.case.confirmed_time, null);
});