fix(rectification): bump scoring identity to scoring-10 for functional profile v2; dated contract by generation (BUG-1181)
Functional roles feed the *_functional_*_auxiliary rules, so57782aeachanges candidate scores for identical input (memoization fixture 12:00: 8.6274 -> 8.4977). Per the "scoring semantics change => bump ALGORITHM_VERSION" precedent (scoring-7 -> 8 -> 9), the identity moves to scoring-10; policy v3, input contract v5 and Skill versions are unchanged, history is not relabeled. Five frontend sites and one SQL guard tested `=== "...scoring-9"` for the dated candidate-window contract; they now use isDatedScoringAlgorithmVersion / a generation regex (>= 9). Migration 20261002010000 only recreates validate_dated_rectification_candidate (one-line guard change). Memoization golden v2 written by the test's own write_golden; v1 (scoring-8) frozen by sha256. Real-engine scoring-10 cross-midnight golden added. Research records re-frozen per ERR-110 (label functional_v2_2026_10_02) and scripts/functional_benefics.py added to the frozen production identity (ERR-114:57782aeachanged scores without tripping it). Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01N4f2nya58RoRu4yEmJgRGE
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
57782aea8a
commit
3733b9787b
@@ -1,195 +1,217 @@
|
||||
import assert from "node:assert/strict";
|
||||
import { randomUUID } from "node:crypto";
|
||||
import { spawnSync } from "node:child_process";
|
||||
import { fileURLToPath } from "node:url";
|
||||
import test from "node:test";
|
||||
import { closeLocalPostgresDataPool, createLocalPostgresDataClient } from "../src/lib/db/local-postgres-client-core.ts";
|
||||
import { startPostgresFixture } from "./helpers/postgres-fixture.ts";
|
||||
|
||||
const docker = spawnSync("docker", ["version"], { stdio: "ignore" }).status === 0;
|
||||
const runner = fileURLToPath(new URL("../scripts/db-migrate.mjs", import.meta.url));
|
||||
|
||||
// Fictional SQL boundary fixture. Permission booleans are controlled setup, not evidence
|
||||
// that any real engine sample passed confirmation/holdout gates.
|
||||
for (const declaration of [{ date: "2000-06-15", time: "00:10", offset: -1 }, { date: "2000-06-14", time: "23:59", offset: 0 }]) {
|
||||
test(`dated adoption ${declaration.time} persists date/spec atomically and rejects malformed candidates`, { skip: !docker && "docker unavailable" }, async () => {
|
||||
const fixture = startPostgresFixture();
|
||||
const url = fixture.connectionUrl("service_runtime", "service-runtime-test-password");
|
||||
try {
|
||||
const migration = spawnSync(process.execPath, [runner], { encoding: "utf8", env: {
|
||||
...process.env, SCHEMA_DATABASE_URL: fixture.connectionUrl("schema_owner", "schema-owner-test-password"),
|
||||
} });
|
||||
assert.equal(migration.status, 0, migration.stderr);
|
||||
const userId = randomUUID(), sessionId = randomUUID(), caseId = randomUUID();
|
||||
const snapshot = {
|
||||
birth_date: declaration.date, reported_birth_time: declaration.time, active_birth_time: null,
|
||||
birth_time_source: "family_exact", birth_time_period: null,
|
||||
uncertainty_before_minutes: 15, uncertainty_after_minutes: 15,
|
||||
latitude: 40, longitude: -74, timezone_id: "America/New_York", timezone_offset: -4,
|
||||
};
|
||||
const intervals = [{ start_at: "2000-06-14T23:55", end_at: "2000-06-15T00:25" }];
|
||||
const range = { start_time: "23:55", end_time: "00:25", candidate_intervals: intervals };
|
||||
const cluster = [{ segment_index: 0, start_index: 0, end_index: 16, start_offset_minutes: 0,
|
||||
end_offset_minutes: 16, start_at: "2000-06-14T23:55", end_at: "2000-06-15T00:11" }];
|
||||
const candidates = [
|
||||
{ time: "23:55", candidate_date: "2000-06-14", window_index: 0, window_offset_minutes: 0, segment_index: 0 },
|
||||
{ time: "00:11", candidate_date: "2000-06-15", window_index: 16, window_offset_minutes: 16, segment_index: 0 },
|
||||
].map((row, i) => ({ ...row, id: row.time, rank: i + 1, relative_support: 50, tied_minute_count: 1,
|
||||
probability: i ? 0.4 : 0.6, posterior_score: i ? 55 : 60, status: "active",
|
||||
cluster_range: [row.time, row.time], cluster_intervals: [{ segment_index: 0,
|
||||
start_index: row.window_index, end_index: row.window_index,
|
||||
start_offset_minutes: row.window_offset_minutes, end_offset_minutes: row.window_offset_minutes,
|
||||
start_at: `${row.candidate_date}T${row.time}`, end_at: `${row.candidate_date}T${row.time}` }] }));
|
||||
const inference = {
|
||||
revision: 0, range_start: "23:55", range_end: "00:25",
|
||||
candidate_set_id: "dated-v1:23:55-00:25:2000-06-14T23:55@0@0@0,2000-06-15T00:11@16@16@0",
|
||||
candidates, representative_time: "23:55", credible_range: ["23:55", "00:11"], credible_intervals: cluster,
|
||||
};
|
||||
fixture.psqlAs("identity_runtime", "identity-runtime-test-password", `
|
||||
insert into identity.users(id,name,email,email_verified) values ('${userId}','Synthetic Midnight Fixture','${userId}@example.invalid',true);
|
||||
`);
|
||||
fixture.psql(`
|
||||
update public.profiles set birth_date='${declaration.date}',reported_birth_time='${declaration.time}',birth_time_source='family_exact',
|
||||
birth_time_status='reported',uncertainty_before_minutes=15,uncertainty_after_minutes=15,
|
||||
latitude=40,longitude=-74,timezone_id='America/New_York',timezone_offset=-4 where id='${userId}';
|
||||
insert into public.chat_sessions(id,user_id,title,theme,session_type,messages)
|
||||
values('${sessionId}','${userId}','Synthetic boundary','general','birth_time_rectification','[]');
|
||||
insert into public.agentic_rectification_cases(id,user_id,session_id,status,skill_name,skill_version,
|
||||
baseline_profile_fingerprint,baseline_birth_snapshot,candidate_range)
|
||||
values('${caseId}','${userId}','${sessionId}','candidate_ready','jyotish-birth-time-rectification','9.0.0',
|
||||
'${"a".repeat(64)}','${JSON.stringify(snapshot)}','${JSON.stringify(range)}');
|
||||
`);
|
||||
const service = createLocalPostgresDataClient(url, null, "service_role");
|
||||
const persisted = await service.rpc("persist_agentic_rectification_candidate_v2", {
|
||||
p_user_id: userId, p_case_id: caseId, p_engine_result_id: "synthetic-dated-boundary",
|
||||
p_evidence_ledger_fingerprint: "b".repeat(64), p_candidate_range_fingerprint: "c".repeat(64),
|
||||
p_skill_version: "9.0.0", p_algorithm_version: "synthetic-boundary-v1",
|
||||
p_event_contract_version: "rectification-event-contract-v2", p_decision_policy_version: "rectification-candidate-policy-v2",
|
||||
p_candidate_range: range, p_candidates: candidates,
|
||||
p_decision_receipt: { display_allowed: true, accept_allowed: true, confirm_allowed: true,
|
||||
representative_time: "23:55", overall_confidence: "low", margin_percent: 1,
|
||||
candidate_window_contract: "dated-v1", candidate_intervals: intervals,
|
||||
candidate_timezone_offset: -4, candidate_timezone_id: "America/New_York", inference_state: inference },
|
||||
p_execution_ledger: [{ phase: "candidate.score", status: "completed", engine: "synthetic-boundary" }],
|
||||
});
|
||||
assert.equal(persisted.error, null, JSON.stringify(persisted.error));
|
||||
const row = persisted.data as { result_id: string; candidates: { time: string; candidate_id: string }[] };
|
||||
const candidateId = row.candidates.find(c => c.time === "23:55")!.candidate_id;
|
||||
const nextId = row.candidates.find(c => c.time === "00:11")!.candidate_id;
|
||||
const accept = (id = candidateId, requestId = randomUUID()) => service.rpc("accept_agentic_rectification_candidate_for_case_v2", {
|
||||
p_user_id: userId, p_case_id: caseId, p_result_id: row.result_id, p_candidate_id: id, p_request_id: requestId,
|
||||
});
|
||||
assert.ok((await service.rpc("accept_agentic_rectification_candidate_for_case_v2", {
|
||||
p_user_id: randomUUID(), p_case_id: caseId, p_result_id: row.result_id, p_candidate_id: candidateId, p_request_id: randomUUID(),
|
||||
})).error, "dated candidate remains ownership scoped");
|
||||
fixture.psql(`update public.profiles set reported_birth_time='00:12' where id='${userId}'`);
|
||||
assert.ok((await accept()).error, "changed declaration invalidates dated candidates");
|
||||
fixture.psql(`update public.profiles set reported_birth_time='${declaration.time}' where id='${userId}';
|
||||
update public.agentic_rectification_results set invalidated_at=null where id='${row.result_id}';
|
||||
update public.agentic_rectification_cases set status='candidate_ready' where id='${caseId}'`);
|
||||
fixture.psql(`update public.agentic_rectification_candidates set candidate_payload=candidate_payload-'candidate_date' where id='${candidateId}'`);
|
||||
assert.ok((await accept()).error, "dated payload without date must fail closed");
|
||||
fixture.psql(`update public.agentic_rectification_candidates set candidate_payload=candidate_payload || '{"candidate_date":"2000-06-14"}' where id='${candidateId}'`);
|
||||
for (const patch of [
|
||||
{ candidate_date: "2000-06-16" }, { window_offset_minutes: 500 }, { segment_index: 7 },
|
||||
]) {
|
||||
fixture.psql(`update public.agentic_rectification_candidates set candidate_payload=candidate_payload || '${JSON.stringify(patch)}' where id='${candidateId}'`);
|
||||
assert.ok((await accept()).error, "candidate membership cannot be forged");
|
||||
fixture.psql(`update public.agentic_rectification_candidates set candidate_payload='${JSON.stringify(candidates[0])}' where id='${candidateId}'`);
|
||||
}
|
||||
fixture.psql(`update public.agentic_rectification_results set decision_receipt=jsonb_set(decision_receipt,'{candidate_timezone_offset}','-5') where id='${row.result_id}'`);
|
||||
assert.ok((await accept()).error, "candidate offset must match frozen calculation baseline");
|
||||
fixture.psql(`update public.agentic_rectification_results set decision_receipt=jsonb_set(decision_receipt,'{candidate_timezone_offset}','-4') where id='${row.result_id}'`);
|
||||
for (const patch of [{ segment_index: 7 }, { start_index: 3 }, { end_offset_minutes: 500 }]) {
|
||||
const malformed = { ...inference, credible_intervals: [{ ...cluster[0], ...patch }] };
|
||||
fixture.psql(`update public.agentic_rectification_results set decision_receipt=jsonb_set(decision_receipt,'{inference_state}','${JSON.stringify(malformed)}') where id='${row.result_id}'`);
|
||||
assert.ok((await accept()).error, "credible metadata must match the dated cluster envelope");
|
||||
}
|
||||
fixture.psql(`update public.agentic_rectification_results set decision_receipt=jsonb_set(decision_receipt,'{inference_state}','${JSON.stringify(inference)}') where id='${row.result_id}'`);
|
||||
const originalReceipt = fixture.psql(`select decision_receipt from public.agentic_rectification_results where id='${row.result_id}'`);
|
||||
fixture.psql(`update public.agentic_rectification_results set algorithm_version='rectification-v5-matrix-scoring-9',
|
||||
decision_receipt=decision_receipt-'candidate_window_contract'-'candidate_intervals'-'inference_state' where id='${row.result_id}';
|
||||
update public.agentic_rectification_candidates set candidate_payload=candidate_payload-'candidate_date'-'window_index'-'window_offset_minutes'-'segment_index'-'cluster_intervals' where result_id='${row.result_id}'`);
|
||||
const rejectsNewIdentity = fixture.psql(`do $$ begin
|
||||
begin
|
||||
perform public.validate_dated_rectification_candidate(c,r,p,null)
|
||||
from public.agentic_rectification_cases c, public.agentic_rectification_results r, public.agentic_rectification_candidates p
|
||||
where c.id='${caseId}' and r.id='${row.result_id}' and p.id='${candidateId}';
|
||||
raise exception 'expected_rejection_missing';
|
||||
exception when others then
|
||||
if sqlerrm <> 'agentic_rectification_candidate_state_inconsistent' then raise; end if;
|
||||
end;
|
||||
end $$; select 'rejected';`);
|
||||
assert.match(rejectsNewIdentity, /rejected/);
|
||||
fixture.psql(`update public.agentic_rectification_results set algorithm_version='synthetic-boundary-v1',decision_receipt='${originalReceipt}' where id='${row.result_id}';
|
||||
update public.agentic_rectification_candidates set candidate_payload='${JSON.stringify(candidates[0])}' where id='${candidateId}';
|
||||
update public.agentic_rectification_candidates set candidate_payload='${JSON.stringify(candidates[1])}' where id='${nextId}'`);
|
||||
const splitWindows = [
|
||||
{ start_at: "2000-06-14T23:55", end_at: "2000-06-14T23:59" },
|
||||
{ start_at: "2000-06-15T00:05", end_at: "2000-06-15T00:25" },
|
||||
];
|
||||
const splitCandidates = candidates.map((c, i) => ({ ...c, segment_index: i,
|
||||
cluster_intervals: c.cluster_intervals.map(part => ({ ...part, segment_index: i })) }));
|
||||
const splitInference = { ...inference, candidates: splitCandidates, credible_range: null,
|
||||
credible_intervals: splitCandidates.flatMap(c => c.cluster_intervals),
|
||||
candidate_set_id: inference.candidate_set_id.replace("00:11@16@16@0", "00:11@16@16@1") };
|
||||
fixture.psql(`update public.agentic_rectification_cases set candidate_range=jsonb_set(candidate_range,'{candidate_intervals}','${JSON.stringify(splitWindows)}') where id='${caseId}';
|
||||
update public.agentic_rectification_results set decision_receipt=jsonb_set(jsonb_set(decision_receipt,'{candidate_intervals}','${JSON.stringify(splitWindows)}'),'{inference_state}','${JSON.stringify({ ...splitInference, credible_intervals: cluster })}') where id='${row.result_id}';
|
||||
update public.agentic_rectification_candidates set candidate_payload='${JSON.stringify(splitCandidates[1])}' where id='${nextId}'`);
|
||||
assert.ok((await accept()).error, "credible envelope must not bridge separate declared segments");
|
||||
fixture.psql(`update public.agentic_rectification_results set decision_receipt=jsonb_set(decision_receipt,'{inference_state}','${JSON.stringify(splitInference)}') where id='${row.result_id}'`);
|
||||
assert.equal((await accept()).error, null, "separate credible segments remain adoptable");
|
||||
const reportRange = await service.rpc("read_report_candidate_range", { p_user_id: userId, p_rectification_case_id: caseId });
|
||||
assert.equal(reportRange.error, null);
|
||||
assert.deepEqual((reportRange.data as Record<string, unknown>).candidate_intervals, splitInference.credible_intervals);
|
||||
fixture.psql(`update public.agentic_rectification_cases set candidate_range='${JSON.stringify(range)}' where id='${caseId}';
|
||||
update public.agentic_rectification_results set decision_receipt='${originalReceipt}' where id='${row.result_id}';
|
||||
update public.agentic_rectification_candidates set candidate_payload='${JSON.stringify(candidates[1])}' where id='${nextId}'`);
|
||||
// A still-active candidate outside the existing separation lead is not in the credible union.
|
||||
const weakInference = { ...inference, candidates: candidates.map((c, i) => i ? { ...c, posterior_score: 40 } : c),
|
||||
credible_intervals: candidates[0].cluster_intervals, credible_range: ["23:55", "23:55"] };
|
||||
fixture.psql(`update public.agentic_rectification_results set decision_receipt=jsonb_set(decision_receipt,'{inference_state}','${JSON.stringify(weakInference)}') where id='${row.result_id}'`);
|
||||
assert.equal((await accept()).error, null, "separation lead excludes weak active candidate");
|
||||
fixture.psql(`update public.agentic_rectification_results set decision_receipt=jsonb_set(decision_receipt,'{inference_state}','${JSON.stringify(inference)}') where id='${row.result_id}'`);
|
||||
const requestId = randomUUID();
|
||||
const accepted = await accept(candidateId, requestId);
|
||||
assert.equal(accepted.error, null, JSON.stringify(accepted.error));
|
||||
assert.equal((accepted.data as Record<string, unknown>).saved_date, "2000-06-14");
|
||||
assert.equal((accepted.data as Record<string, unknown>).day_offset, declaration.offset);
|
||||
assert.equal(fixture.psql(`select birth_date || ':' || active_birth_date || ':' || active_birth_timezone_offset from public.profiles where id='${userId}'`), `${declaration.date}:2000-06-14:-4`);
|
||||
assert.equal((await accept(candidateId, requestId)).error, null);
|
||||
const switched = await accept(nextId);
|
||||
assert.equal(switched.error, null, JSON.stringify(switched.error));
|
||||
assert.equal((switched.data as Record<string, unknown>).saved_date, "2000-06-15");
|
||||
assert.equal((switched.data as Record<string, unknown>).day_offset, declaration.offset + 1);
|
||||
assert.equal(fixture.psql(`select adopted_credible_range->>'representative_date' || 'T' || (adopted_credible_range->>'representative_time') from public.agentic_rectification_cases where id='${caseId}'`), "2000-06-15T00:11");
|
||||
assert.equal((await accept()).error, null);
|
||||
const turnId = randomUUID();
|
||||
fixture.psql(`insert into public.agentic_rectification_turns(id,case_id,model_name,user_message,assistant_message,status)
|
||||
values('${turnId}','${caseId}','synthetic','Confirm synthetic boundary','Synthetic acknowledgment','completed')`);
|
||||
const confirmed = await service.rpc("confirm_agentic_rectification_candidate_for_case_v2", {
|
||||
p_user_id: userId, p_case_id: caseId, p_result_id: row.result_id, p_candidate_id: candidateId,
|
||||
p_request_id: randomUUID(), p_source_turn_id: turnId, p_consent_quote: "Confirm synthetic boundary",
|
||||
});
|
||||
assert.equal(confirmed.error, null, JSON.stringify(confirmed.error));
|
||||
assert.equal((confirmed.data as Record<string, unknown>).saved_date, "2000-06-14");
|
||||
fixture.psql(`delete from public.agentic_rectification_candidate_decisions where case_id='${caseId}';
|
||||
update public.agentic_rectification_results set selected_candidate_id=null where case_id='${caseId}';
|
||||
delete from public.agentic_rectification_candidates where case_id='${caseId}';
|
||||
delete from public.agentic_rectification_cases where id='${caseId}'`);
|
||||
assert.equal(fixture.psql(`select active_birth_date || ':' || (active_birth_provenance->>'candidate_id') from public.profiles where id='${userId}'`), `2000-06-14:${candidateId}`);
|
||||
for (const mutation of ["active_birth_time='23:56'", "birth_time_status='reported'", "timezone_offset=-5", "birth_date='2000-06-16'"]) {
|
||||
fixture.psql(`update public.profiles set birth_time_status='accepted',active_birth_time='23:55' where id='${userId}';
|
||||
update public.profiles set active_birth_date='2000-06-14',active_birth_timezone_offset=-4,active_birth_provenance='{"contract":"dated-v1"}' where id='${userId}';
|
||||
update public.profiles set ${mutation} where id='${userId}'`);
|
||||
assert.equal(fixture.psql(`select (active_birth_date is null and active_birth_timezone_offset is null and active_birth_provenance is null)::text from public.profiles where id='${userId}'`), "true", mutation);
|
||||
}
|
||||
fixture.psql(`update public.profiles set birth_date='2000-06-16' where id='${userId}'`);
|
||||
assert.equal(fixture.psql(`select (active_birth_date is null and active_birth_timezone_offset is null and active_birth_provenance is null)::text from public.profiles where id='${userId}'`), "true");
|
||||
} finally {
|
||||
await closeLocalPostgresDataPool(url);
|
||||
fixture.stop();
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
import assert from "node:assert/strict";
|
||||
import { randomUUID } from "node:crypto";
|
||||
import { spawnSync } from "node:child_process";
|
||||
import { fileURLToPath } from "node:url";
|
||||
import test from "node:test";
|
||||
import { closeLocalPostgresDataPool, createLocalPostgresDataClient } from "../src/lib/db/local-postgres-client-core.ts";
|
||||
import { startPostgresFixture } from "./helpers/postgres-fixture.ts";
|
||||
|
||||
const docker = spawnSync("docker", ["version"], { stdio: "ignore" }).status === 0;
|
||||
const runner = fileURLToPath(new URL("../scripts/db-migrate.mjs", import.meta.url));
|
||||
|
||||
// Fictional SQL boundary fixture. Permission booleans are controlled setup, not evidence
|
||||
// that any real engine sample passed confirmation/holdout gates.
|
||||
for (const declaration of [{ date: "2000-06-15", time: "00:10", offset: -1 }, { date: "2000-06-14", time: "23:59", offset: 0 }]) {
|
||||
test(`dated adoption ${declaration.time} persists date/spec atomically and rejects malformed candidates`, { skip: !docker && "docker unavailable" }, async () => {
|
||||
const fixture = startPostgresFixture();
|
||||
const url = fixture.connectionUrl("service_runtime", "service-runtime-test-password");
|
||||
try {
|
||||
const migration = spawnSync(process.execPath, [runner], { encoding: "utf8", env: {
|
||||
...process.env, SCHEMA_DATABASE_URL: fixture.connectionUrl("schema_owner", "schema-owner-test-password"),
|
||||
} });
|
||||
assert.equal(migration.status, 0, migration.stderr);
|
||||
const userId = randomUUID(), sessionId = randomUUID(), caseId = randomUUID();
|
||||
const snapshot = {
|
||||
birth_date: declaration.date, reported_birth_time: declaration.time, active_birth_time: null,
|
||||
birth_time_source: "family_exact", birth_time_period: null,
|
||||
uncertainty_before_minutes: 15, uncertainty_after_minutes: 15,
|
||||
latitude: 40, longitude: -74, timezone_id: "America/New_York", timezone_offset: -4,
|
||||
};
|
||||
const intervals = [{ start_at: "2000-06-14T23:55", end_at: "2000-06-15T00:25" }];
|
||||
const range = { start_time: "23:55", end_time: "00:25", candidate_intervals: intervals };
|
||||
const cluster = [{ segment_index: 0, start_index: 0, end_index: 16, start_offset_minutes: 0,
|
||||
end_offset_minutes: 16, start_at: "2000-06-14T23:55", end_at: "2000-06-15T00:11" }];
|
||||
const candidates = [
|
||||
{ time: "23:55", candidate_date: "2000-06-14", window_index: 0, window_offset_minutes: 0, segment_index: 0 },
|
||||
{ time: "00:11", candidate_date: "2000-06-15", window_index: 16, window_offset_minutes: 16, segment_index: 0 },
|
||||
].map((row, i) => ({ ...row, id: row.time, rank: i + 1, relative_support: 50, tied_minute_count: 1,
|
||||
probability: i ? 0.4 : 0.6, posterior_score: i ? 55 : 60, status: "active",
|
||||
cluster_range: [row.time, row.time], cluster_intervals: [{ segment_index: 0,
|
||||
start_index: row.window_index, end_index: row.window_index,
|
||||
start_offset_minutes: row.window_offset_minutes, end_offset_minutes: row.window_offset_minutes,
|
||||
start_at: `${row.candidate_date}T${row.time}`, end_at: `${row.candidate_date}T${row.time}` }] }));
|
||||
const inference = {
|
||||
revision: 0, range_start: "23:55", range_end: "00:25",
|
||||
candidate_set_id: "dated-v1:23:55-00:25:2000-06-14T23:55@0@0@0,2000-06-15T00:11@16@16@0",
|
||||
candidates, representative_time: "23:55", credible_range: ["23:55", "00:11"], credible_intervals: cluster,
|
||||
};
|
||||
fixture.psqlAs("identity_runtime", "identity-runtime-test-password", `
|
||||
insert into identity.users(id,name,email,email_verified) values ('${userId}','Synthetic Midnight Fixture','${userId}@example.invalid',true);
|
||||
`);
|
||||
fixture.psql(`
|
||||
update public.profiles set birth_date='${declaration.date}',reported_birth_time='${declaration.time}',birth_time_source='family_exact',
|
||||
birth_time_status='reported',uncertainty_before_minutes=15,uncertainty_after_minutes=15,
|
||||
latitude=40,longitude=-74,timezone_id='America/New_York',timezone_offset=-4 where id='${userId}';
|
||||
insert into public.chat_sessions(id,user_id,title,theme,session_type,messages)
|
||||
values('${sessionId}','${userId}','Synthetic boundary','general','birth_time_rectification','[]');
|
||||
insert into public.agentic_rectification_cases(id,user_id,session_id,status,skill_name,skill_version,
|
||||
baseline_profile_fingerprint,baseline_birth_snapshot,candidate_range)
|
||||
values('${caseId}','${userId}','${sessionId}','candidate_ready','jyotish-birth-time-rectification','9.0.0',
|
||||
'${"a".repeat(64)}','${JSON.stringify(snapshot)}','${JSON.stringify(range)}');
|
||||
`);
|
||||
const service = createLocalPostgresDataClient(url, null, "service_role");
|
||||
const persisted = await service.rpc("persist_agentic_rectification_candidate_v2", {
|
||||
p_user_id: userId, p_case_id: caseId, p_engine_result_id: "synthetic-dated-boundary",
|
||||
p_evidence_ledger_fingerprint: "b".repeat(64), p_candidate_range_fingerprint: "c".repeat(64),
|
||||
p_skill_version: "9.0.0", p_algorithm_version: "synthetic-boundary-v1",
|
||||
p_event_contract_version: "rectification-event-contract-v2", p_decision_policy_version: "rectification-candidate-policy-v2",
|
||||
p_candidate_range: range, p_candidates: candidates,
|
||||
p_decision_receipt: { display_allowed: true, accept_allowed: true, confirm_allowed: true,
|
||||
representative_time: "23:55", overall_confidence: "low", margin_percent: 1,
|
||||
candidate_window_contract: "dated-v1", candidate_intervals: intervals,
|
||||
candidate_timezone_offset: -4, candidate_timezone_id: "America/New_York", inference_state: inference },
|
||||
p_execution_ledger: [{ phase: "candidate.score", status: "completed", engine: "synthetic-boundary" }],
|
||||
});
|
||||
assert.equal(persisted.error, null, JSON.stringify(persisted.error));
|
||||
const row = persisted.data as { result_id: string; candidates: { time: string; candidate_id: string }[] };
|
||||
const candidateId = row.candidates.find(c => c.time === "23:55")!.candidate_id;
|
||||
const nextId = row.candidates.find(c => c.time === "00:11")!.candidate_id;
|
||||
const accept = (id = candidateId, requestId = randomUUID()) => service.rpc("accept_agentic_rectification_candidate_for_case_v2", {
|
||||
p_user_id: userId, p_case_id: caseId, p_result_id: row.result_id, p_candidate_id: id, p_request_id: requestId,
|
||||
});
|
||||
assert.ok((await service.rpc("accept_agentic_rectification_candidate_for_case_v2", {
|
||||
p_user_id: randomUUID(), p_case_id: caseId, p_result_id: row.result_id, p_candidate_id: candidateId, p_request_id: randomUUID(),
|
||||
})).error, "dated candidate remains ownership scoped");
|
||||
fixture.psql(`update public.profiles set reported_birth_time='00:12' where id='${userId}'`);
|
||||
assert.ok((await accept()).error, "changed declaration invalidates dated candidates");
|
||||
fixture.psql(`update public.profiles set reported_birth_time='${declaration.time}' where id='${userId}';
|
||||
update public.agentic_rectification_results set invalidated_at=null where id='${row.result_id}';
|
||||
update public.agentic_rectification_cases set status='candidate_ready' where id='${caseId}'`);
|
||||
fixture.psql(`update public.agentic_rectification_candidates set candidate_payload=candidate_payload-'candidate_date' where id='${candidateId}'`);
|
||||
assert.ok((await accept()).error, "dated payload without date must fail closed");
|
||||
fixture.psql(`update public.agentic_rectification_candidates set candidate_payload=candidate_payload || '{"candidate_date":"2000-06-14"}' where id='${candidateId}'`);
|
||||
for (const patch of [
|
||||
{ candidate_date: "2000-06-16" }, { window_offset_minutes: 500 }, { segment_index: 7 },
|
||||
]) {
|
||||
fixture.psql(`update public.agentic_rectification_candidates set candidate_payload=candidate_payload || '${JSON.stringify(patch)}' where id='${candidateId}'`);
|
||||
assert.ok((await accept()).error, "candidate membership cannot be forged");
|
||||
fixture.psql(`update public.agentic_rectification_candidates set candidate_payload='${JSON.stringify(candidates[0])}' where id='${candidateId}'`);
|
||||
}
|
||||
fixture.psql(`update public.agentic_rectification_results set decision_receipt=jsonb_set(decision_receipt,'{candidate_timezone_offset}','-5') where id='${row.result_id}'`);
|
||||
assert.ok((await accept()).error, "candidate offset must match frozen calculation baseline");
|
||||
fixture.psql(`update public.agentic_rectification_results set decision_receipt=jsonb_set(decision_receipt,'{candidate_timezone_offset}','-4') where id='${row.result_id}'`);
|
||||
for (const patch of [{ segment_index: 7 }, { start_index: 3 }, { end_offset_minutes: 500 }]) {
|
||||
const malformed = { ...inference, credible_intervals: [{ ...cluster[0], ...patch }] };
|
||||
fixture.psql(`update public.agentic_rectification_results set decision_receipt=jsonb_set(decision_receipt,'{inference_state}','${JSON.stringify(malformed)}') where id='${row.result_id}'`);
|
||||
assert.ok((await accept()).error, "credible metadata must match the dated cluster envelope");
|
||||
}
|
||||
fixture.psql(`update public.agentic_rectification_results set decision_receipt=jsonb_set(decision_receipt,'{inference_state}','${JSON.stringify(inference)}') where id='${row.result_id}'`);
|
||||
const originalReceipt = fixture.psql(`select decision_receipt from public.agentic_rectification_results where id='${row.result_id}'`);
|
||||
fixture.psql(`update public.agentic_rectification_results set algorithm_version='rectification-v5-matrix-scoring-9',
|
||||
decision_receipt=decision_receipt-'candidate_window_contract'-'candidate_intervals'-'inference_state' where id='${row.result_id}';
|
||||
update public.agentic_rectification_candidates set candidate_payload=candidate_payload-'candidate_date'-'window_index'-'window_offset_minutes'-'segment_index'-'cluster_intervals' where result_id='${row.result_id}'`);
|
||||
const rejectsNewIdentity = fixture.psql(`do $$ begin
|
||||
begin
|
||||
perform public.validate_dated_rectification_candidate(c,r,p,null)
|
||||
from public.agentic_rectification_cases c, public.agentic_rectification_results r, public.agentic_rectification_candidates p
|
||||
where c.id='${caseId}' and r.id='${row.result_id}' and p.id='${candidateId}';
|
||||
raise exception 'expected_rejection_missing';
|
||||
exception when others then
|
||||
if sqlerrm <> 'agentic_rectification_candidate_state_inconsistent' then raise; end if;
|
||||
end;
|
||||
end $$; select 'rejected';`);
|
||||
assert.match(rejectsNewIdentity, /rejected/);
|
||||
// BUG-1181: scoring-10 (and later) keeps the dated contract; a stripped receipt is rejected,
|
||||
// while a pre-dated generation (scoring-8) stays a legacy same-day result (null).
|
||||
const setVersion = (version: string) => fixture.psql(`update public.agentic_rectification_results set algorithm_version='${version}' where id='${row.result_id}'`);
|
||||
const rejects = () => fixture.psql(`do $$ begin
|
||||
begin
|
||||
perform public.validate_dated_rectification_candidate(c,r,p,null)
|
||||
from public.agentic_rectification_cases c, public.agentic_rectification_results r, public.agentic_rectification_candidates p
|
||||
where c.id='${caseId}' and r.id='${row.result_id}' and p.id='${candidateId}';
|
||||
raise exception 'expected_rejection_missing';
|
||||
exception when others then
|
||||
if sqlerrm <> 'agentic_rectification_candidate_state_inconsistent' then raise; end if;
|
||||
end;
|
||||
end $$; select 'rejected';`);
|
||||
for (const version of ["rectification-v5-matrix-scoring-10", "rectification-v5-matrix-scoring-11"]) {
|
||||
setVersion(version);
|
||||
assert.match(rejects(), /rejected/, `${version} must not pass as legacy`);
|
||||
}
|
||||
setVersion("rectification-v5-matrix-scoring-8");
|
||||
const legacy = fixture.psql(`select coalesce(public.validate_dated_rectification_candidate(c,r,p,null)::text, 'legacy-null')
|
||||
from public.agentic_rectification_cases c, public.agentic_rectification_results r, public.agentic_rectification_candidates p
|
||||
where c.id='${caseId}' and r.id='${row.result_id}' and p.id='${candidateId}'`);
|
||||
assert.match(legacy, /legacy-null/, "pre-dated generations stay legacy same-day results");
|
||||
fixture.psql(`update public.agentic_rectification_results set algorithm_version='synthetic-boundary-v1',decision_receipt='${originalReceipt}' where id='${row.result_id}';
|
||||
update public.agentic_rectification_candidates set candidate_payload='${JSON.stringify(candidates[0])}' where id='${candidateId}';
|
||||
update public.agentic_rectification_candidates set candidate_payload='${JSON.stringify(candidates[1])}' where id='${nextId}'`);
|
||||
const splitWindows = [
|
||||
{ start_at: "2000-06-14T23:55", end_at: "2000-06-14T23:59" },
|
||||
{ start_at: "2000-06-15T00:05", end_at: "2000-06-15T00:25" },
|
||||
];
|
||||
const splitCandidates = candidates.map((c, i) => ({ ...c, segment_index: i,
|
||||
cluster_intervals: c.cluster_intervals.map(part => ({ ...part, segment_index: i })) }));
|
||||
const splitInference = { ...inference, candidates: splitCandidates, credible_range: null,
|
||||
credible_intervals: splitCandidates.flatMap(c => c.cluster_intervals),
|
||||
candidate_set_id: inference.candidate_set_id.replace("00:11@16@16@0", "00:11@16@16@1") };
|
||||
fixture.psql(`update public.agentic_rectification_cases set candidate_range=jsonb_set(candidate_range,'{candidate_intervals}','${JSON.stringify(splitWindows)}') where id='${caseId}';
|
||||
update public.agentic_rectification_results set decision_receipt=jsonb_set(jsonb_set(decision_receipt,'{candidate_intervals}','${JSON.stringify(splitWindows)}'),'{inference_state}','${JSON.stringify({ ...splitInference, credible_intervals: cluster })}') where id='${row.result_id}';
|
||||
update public.agentic_rectification_candidates set candidate_payload='${JSON.stringify(splitCandidates[1])}' where id='${nextId}'`);
|
||||
assert.ok((await accept()).error, "credible envelope must not bridge separate declared segments");
|
||||
fixture.psql(`update public.agentic_rectification_results set decision_receipt=jsonb_set(decision_receipt,'{inference_state}','${JSON.stringify(splitInference)}') where id='${row.result_id}'`);
|
||||
assert.equal((await accept()).error, null, "separate credible segments remain adoptable");
|
||||
const reportRange = await service.rpc("read_report_candidate_range", { p_user_id: userId, p_rectification_case_id: caseId });
|
||||
assert.equal(reportRange.error, null);
|
||||
assert.deepEqual((reportRange.data as Record<string, unknown>).candidate_intervals, splitInference.credible_intervals);
|
||||
fixture.psql(`update public.agentic_rectification_cases set candidate_range='${JSON.stringify(range)}' where id='${caseId}';
|
||||
update public.agentic_rectification_results set decision_receipt='${originalReceipt}' where id='${row.result_id}';
|
||||
update public.agentic_rectification_candidates set candidate_payload='${JSON.stringify(candidates[1])}' where id='${nextId}'`);
|
||||
// A still-active candidate outside the existing separation lead is not in the credible union.
|
||||
const weakInference = { ...inference, candidates: candidates.map((c, i) => i ? { ...c, posterior_score: 40 } : c),
|
||||
credible_intervals: candidates[0].cluster_intervals, credible_range: ["23:55", "23:55"] };
|
||||
fixture.psql(`update public.agentic_rectification_results set decision_receipt=jsonb_set(decision_receipt,'{inference_state}','${JSON.stringify(weakInference)}') where id='${row.result_id}'`);
|
||||
assert.equal((await accept()).error, null, "separation lead excludes weak active candidate");
|
||||
fixture.psql(`update public.agentic_rectification_results set decision_receipt=jsonb_set(decision_receipt,'{inference_state}','${JSON.stringify(inference)}') where id='${row.result_id}'`);
|
||||
const requestId = randomUUID();
|
||||
const accepted = await accept(candidateId, requestId);
|
||||
assert.equal(accepted.error, null, JSON.stringify(accepted.error));
|
||||
assert.equal((accepted.data as Record<string, unknown>).saved_date, "2000-06-14");
|
||||
assert.equal((accepted.data as Record<string, unknown>).day_offset, declaration.offset);
|
||||
assert.equal(fixture.psql(`select birth_date || ':' || active_birth_date || ':' || active_birth_timezone_offset from public.profiles where id='${userId}'`), `${declaration.date}:2000-06-14:-4`);
|
||||
assert.equal((await accept(candidateId, requestId)).error, null);
|
||||
const switched = await accept(nextId);
|
||||
assert.equal(switched.error, null, JSON.stringify(switched.error));
|
||||
assert.equal((switched.data as Record<string, unknown>).saved_date, "2000-06-15");
|
||||
assert.equal((switched.data as Record<string, unknown>).day_offset, declaration.offset + 1);
|
||||
assert.equal(fixture.psql(`select adopted_credible_range->>'representative_date' || 'T' || (adopted_credible_range->>'representative_time') from public.agentic_rectification_cases where id='${caseId}'`), "2000-06-15T00:11");
|
||||
assert.equal((await accept()).error, null);
|
||||
const turnId = randomUUID();
|
||||
fixture.psql(`insert into public.agentic_rectification_turns(id,case_id,model_name,user_message,assistant_message,status)
|
||||
values('${turnId}','${caseId}','synthetic','Confirm synthetic boundary','Synthetic acknowledgment','completed')`);
|
||||
const confirmed = await service.rpc("confirm_agentic_rectification_candidate_for_case_v2", {
|
||||
p_user_id: userId, p_case_id: caseId, p_result_id: row.result_id, p_candidate_id: candidateId,
|
||||
p_request_id: randomUUID(), p_source_turn_id: turnId, p_consent_quote: "Confirm synthetic boundary",
|
||||
});
|
||||
assert.equal(confirmed.error, null, JSON.stringify(confirmed.error));
|
||||
assert.equal((confirmed.data as Record<string, unknown>).saved_date, "2000-06-14");
|
||||
fixture.psql(`delete from public.agentic_rectification_candidate_decisions where case_id='${caseId}';
|
||||
update public.agentic_rectification_results set selected_candidate_id=null where case_id='${caseId}';
|
||||
delete from public.agentic_rectification_candidates where case_id='${caseId}';
|
||||
delete from public.agentic_rectification_cases where id='${caseId}'`);
|
||||
assert.equal(fixture.psql(`select active_birth_date || ':' || (active_birth_provenance->>'candidate_id') from public.profiles where id='${userId}'`), `2000-06-14:${candidateId}`);
|
||||
for (const mutation of ["active_birth_time='23:56'", "birth_time_status='reported'", "timezone_offset=-5", "birth_date='2000-06-16'"]) {
|
||||
fixture.psql(`update public.profiles set birth_time_status='accepted',active_birth_time='23:55' where id='${userId}';
|
||||
update public.profiles set active_birth_date='2000-06-14',active_birth_timezone_offset=-4,active_birth_provenance='{"contract":"dated-v1"}' where id='${userId}';
|
||||
update public.profiles set ${mutation} where id='${userId}'`);
|
||||
assert.equal(fixture.psql(`select (active_birth_date is null and active_birth_timezone_offset is null and active_birth_provenance is null)::text from public.profiles where id='${userId}'`), "true", mutation);
|
||||
}
|
||||
fixture.psql(`update public.profiles set birth_date='2000-06-16' where id='${userId}'`);
|
||||
assert.equal(fixture.psql(`select (active_birth_date is null and active_birth_timezone_offset is null and active_birth_provenance is null)::text from public.profiles where id='${userId}'`), "true");
|
||||
} finally {
|
||||
await closeLocalPostgresDataPool(url);
|
||||
fixture.stop();
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
+5097
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,75 @@
|
||||
// BUG-1181: the dated candidate-window contract belongs to scoring generation 9 and
|
||||
// every later one. The bump to scoring-10 (functional benefic / malefic profile v2)
|
||||
// must not turn new results into legacy same-day results anywhere in the stack.
|
||||
import assert from "node:assert/strict";
|
||||
import { readFileSync, readdirSync } from "node:fs";
|
||||
import test from "node:test";
|
||||
|
||||
import { FIRST_DATED_SCORING_GENERATION, isDatedScoringAlgorithmVersion } from "../src/lib/rectification-agentic/core/candidate-window.ts";
|
||||
import { v9EngineVersion } from "../src/lib/rectification-agentic/v9/engine-client.ts";
|
||||
import { resultIdentityView } from "../src/lib/rectification-agentic/v9/result-identity.ts";
|
||||
import { parseV9CaseDossier } from "../src/lib/rectification-agentic/v9/tool-service.ts";
|
||||
import { dossierFixture } from "./rectification-v9-test-support.ts";
|
||||
|
||||
test("dated contract is a generation threshold, not one literal", () => {
|
||||
assert.equal(FIRST_DATED_SCORING_GENERATION, 9);
|
||||
for (const version of ["rectification-v5-matrix-scoring-9", "rectification-v5-matrix-scoring-10", "rectification-v5-matrix-scoring-11", "rectification-v5-matrix-scoring-100"]) {
|
||||
assert.equal(isDatedScoringAlgorithmVersion(version), true, version);
|
||||
}
|
||||
for (const version of ["rectification-v5-matrix-scoring-8", "rectification-v5-matrix-scoring-1", "rectification-v5-matrix-scoring-09",
|
||||
"rectification-v5", "rectification-v5-matrix-scoring-10 ", "x-rectification-v5-matrix-scoring-10", "", null, undefined, 10]) {
|
||||
assert.equal(isDatedScoringAlgorithmVersion(version), false, String(version));
|
||||
}
|
||||
});
|
||||
|
||||
test("receipt default and Python identity agree on scoring-10", (t) => {
|
||||
const saved = process.env.RECTIFICATION_ENGINE_VERSION;
|
||||
delete process.env.RECTIFICATION_ENGINE_VERSION;
|
||||
t.after(() => { if (saved === undefined) delete process.env.RECTIFICATION_ENGINE_VERSION; else process.env.RECTIFICATION_ENGINE_VERSION = saved; });
|
||||
assert.equal(v9EngineVersion(), "rectification-v5-matrix-scoring-10");
|
||||
const python = readFileSync(new URL("../../scripts/rectification/scoring_service.py", import.meta.url), "utf8");
|
||||
assert.match(python, /^ALGORITHM_VERSION = "rectification-v5-matrix-scoring-10"$/m);
|
||||
});
|
||||
|
||||
test("no source file compares the algorithm identity with a scoring-N literal", () => {
|
||||
const roots = ["../src/lib/", "../src/mastra/", "../src/app/"];
|
||||
const hits: string[] = [];
|
||||
const walk = (url: URL) => {
|
||||
for (const entry of readdirSync(url, { withFileTypes: true })) {
|
||||
const child = new URL(entry.name + (entry.isDirectory() ? "/" : ""), url);
|
||||
if (entry.isDirectory()) walk(child);
|
||||
else if (/\.(ts|tsx)$/.test(entry.name)) {
|
||||
const text = readFileSync(child, "utf8");
|
||||
for (const line of text.split("\n")) if (/[!=]==?\s*"rectification-v5-matrix-scoring-\d+"/.test(line)) hits.push(`${child.pathname}: ${line.trim()}`);
|
||||
}
|
||||
}
|
||||
};
|
||||
for (const root of roots) walk(new URL(root, import.meta.url));
|
||||
assert.deepEqual(hits, []);
|
||||
});
|
||||
|
||||
test("SQL guard compares the generation too (migration 20261002010000)", () => {
|
||||
const sql = readFileSync(new URL("../supabase/migrations/20261002010000_rectification_dated_algorithm_generation.sql", import.meta.url), "utf8");
|
||||
assert.match(sql, /create or replace function public\.validate_dated_rectification_candidate\(/);
|
||||
assert.match(sql, /coalesce\(p_result\.algorithm_version, ''\) ~ '\^rectification-v5-matrix-scoring-\(9\|\[1-9\]\[0-9\]\+\)\$'/);
|
||||
assert.doesNotMatch(sql, /algorithm_version = 'rectification-v5-matrix-scoring-9'/);
|
||||
// Only the function body changes: no table, column, grant or data statements.
|
||||
assert.doesNotMatch(sql, /^\s*(alter|drop|insert|update|delete|grant|revoke|create table|create index)\b/im);
|
||||
});
|
||||
|
||||
test("a scoring-9 history opens read-only under scoring-10 and offers a recompare (BUG-621 / BUG-984 pattern)", () => {
|
||||
// Real native scoring-9 dated golden as the persisted latest result; only the live identity differs.
|
||||
const historical = JSON.parse(readFileSync(new URL("./fixtures/rectification-midnight-date-anchor.delivery.native.json", import.meta.url), "utf8")).response;
|
||||
assert.equal(historical.algorithm_version, "rectification-v5-matrix-scoring-9");
|
||||
const latest = { ...historical, candidates: historical.candidate_decisions };
|
||||
const dossier = parseV9CaseDossier(dossierFixture({ stage: "minute", latestResult: latest }));
|
||||
assert.ok(dossier);
|
||||
assert.equal(dossier.latestResult?.algorithmVersion, "rectification-v5-matrix-scoring-9", "history keeps its own identity");
|
||||
const policyVersion = historical.decision_policy_version;
|
||||
const underTen = resultIdentityView(dossier, { algorithmVersion: "rectification-v5-matrix-scoring-10", policyVersion });
|
||||
assert.deepEqual([underTen.read_only, underTen.can_recompare, underTen.algorithm_version], [true, true, "rectification-v5-matrix-scoring-9"]);
|
||||
const underNine = resultIdentityView(dossier, { algorithmVersion: "rectification-v5-matrix-scoring-9", policyVersion });
|
||||
assert.deepEqual([underNine.read_only, underNine.can_recompare], [false, false]);
|
||||
// Its candidates still parse as dated (generation >= 9), so the opened history keeps civil dates.
|
||||
assert.ok(dossier.latestResult!.candidates.every((candidate) => typeof candidate.candidate_date === "string"));
|
||||
});
|
||||
@@ -31,10 +31,18 @@ const golden = JSON.parse(readFileSync(new URL(
|
||||
// Historical golden identity stays fixed; it must not be relabeled as the live engine.
|
||||
const CURRENT = "rectification-v5-matrix-scoring-8";
|
||||
const PREVIOUS = "rectification-v5-matrix-scoring-7";
|
||||
const LIVE_CURRENT = "rectification-v5-matrix-scoring-9";
|
||||
// 原值: LIVE_CURRENT = "rectification-v5-matrix-scoring-9"(liveGolden 同时充当「当前版本」)
|
||||
// 新值: LIVE_CURRENT = "...-scoring-10";scoring-9 的 dated golden 留作历史(DATED_HISTORICAL),
|
||||
// 当前版本另有真实引擎生成的 scoring-10 dated golden(currentGolden)
|
||||
// 原因: 功能吉凶 v2 改变同输入分数,按「打分语义变化必须 bump」升算法身份(BUG-1181)
|
||||
const LIVE_CURRENT = "rectification-v5-matrix-scoring-10";
|
||||
const DATED_HISTORICAL = "rectification-v5-matrix-scoring-9";
|
||||
const liveGolden = JSON.parse(readFileSync(new URL(
|
||||
"./fixtures/rectification-midnight-date-anchor.delivery.native.json", import.meta.url,
|
||||
), "utf8"));
|
||||
const currentGolden = JSON.parse(readFileSync(new URL(
|
||||
"./fixtures/rectification-midnight-date-anchor.delivery.scoring-10.native.json", import.meta.url,
|
||||
), "utf8"));
|
||||
const envKeys = [
|
||||
"RECTIFICATION_ENGINE_VERSION", "RECTIFICATION_ALGORITHM_VERSION",
|
||||
"RECTIFICATION_DECISION_POLICY_VERSION",
|
||||
@@ -61,15 +69,18 @@ test("receipt default matches the cross-midnight native scoring version without
|
||||
assert.equal(golden.score.algorithm_version, CURRENT);
|
||||
assert.equal(golden.versions.algorithm_version, CURRENT);
|
||||
const python = readFileSync(new URL("../../scripts/rectification/scoring_service.py", import.meta.url), "utf8");
|
||||
assert.match(python, /ALGORITHM_VERSION = "rectification-v5-matrix-scoring-9"/);
|
||||
assert.equal(liveGolden.response.algorithm_version, LIVE_CURRENT);
|
||||
assert.match(python, /ALGORITHM_VERSION = "rectification-v5-matrix-scoring-10"/);
|
||||
assert.equal(liveGolden.response.algorithm_version, DATED_HISTORICAL);
|
||||
assert.equal(currentGolden.response.algorithm_version, LIVE_CURRENT);
|
||||
const fingerprints = { evidenceLedgerFingerprint: "e".repeat(64), candidateRangeFingerprint: "c".repeat(64) };
|
||||
const live = {
|
||||
algorithmVersion: liveGolden.response.algorithm_version,
|
||||
policyVersion: liveGolden.response.decision_policy_version,
|
||||
algorithmVersion: currentGolden.response.algorithm_version,
|
||||
policyVersion: currentGolden.response.decision_policy_version,
|
||||
};
|
||||
const historical = { ...fingerprints, algorithmVersion: CURRENT, policyVersion: golden.versions.decision_policy_version };
|
||||
assert.equal(cachedEngineScoreIsReusable(historical, fingerprints, live), false);
|
||||
// BUG-1181: a scoring-9 cache (old functional grouping) is not current under scoring-10.
|
||||
assert.equal(cachedEngineScoreIsReusable({ ...historical, algorithmVersion: DATED_HISTORICAL }, fingerprints, live), false);
|
||||
assert.equal(cachedEngineScoreIsReusable({ ...historical, algorithmVersion: LIVE_CURRENT }, fingerprints, live), true);
|
||||
assert.equal(historical.algorithmVersion, CURRENT, "checking live identity never relabels history");
|
||||
// A receipt default must not become an environment override for cache identity.
|
||||
|
||||
@@ -97,8 +97,10 @@ for (const option of ["A", "B", "C", "skip_probe"] as const) test(`D1 initial no
|
||||
assert.equal(midnightSideChoice(current.case.candidate_range), null);
|
||||
});
|
||||
|
||||
test("native golden crosses engine parsing, inference and dated delivery without reanchoring", async () => {
|
||||
const golden = JSON.parse(readFileSync(new URL("./fixtures/rectification-midnight-date-anchor.delivery.native.json", import.meta.url), "utf8"));
|
||||
// BUG-1181: the scoring-10 golden (real engine, functional profile v2) must parse as dated too;
|
||||
// a literal "=== scoring-9" check would have turned it into a legacy same-day result.
|
||||
for (const fixture of ["rectification-midnight-date-anchor.delivery.native.json", "rectification-midnight-date-anchor.delivery.scoring-10.native.json"]) test(`native golden crosses engine parsing, inference and dated delivery without reanchoring (${fixture})`, async () => {
|
||||
const golden = JSON.parse(readFileSync(new URL(`./fixtures/${fixture}`, import.meta.url), "utf8"));
|
||||
const originalFetch = globalThis.fetch;
|
||||
globalThis.fetch = (async () => new Response(JSON.stringify(golden.response), { status: 200 })) as typeof fetch;
|
||||
try {
|
||||
|
||||
Reference in New Issue
Block a user