8e31680b45
Intake stores how sure the user is; rectification now searches that range, offers a one-click widen when event fit is low at the edge, and trisects windows longer than two hours before the minute grid. Co-authored-by: Cursor <cursoragent@cursor.com>
233 lines
8.8 KiB
TypeScript
233 lines
8.8 KiB
TypeScript
import assert from "node:assert/strict";
|
|
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 runnerPath = fileURLToPath(
|
|
new URL("../scripts/db-migrate.mjs", import.meta.url),
|
|
);
|
|
|
|
function dockerAvailable(): boolean {
|
|
const probe = spawnSync("docker", ["version", "--format", "{{.Server.Version}}"], {
|
|
encoding: "utf8",
|
|
stdio: "ignore",
|
|
});
|
|
return probe.status === 0;
|
|
}
|
|
|
|
const skipWithoutDocker = dockerAvailable() ? false : "docker unavailable on this host";
|
|
|
|
function rpcError(error: unknown): string {
|
|
if (!error || typeof error !== "object") return "";
|
|
const value = error as { message?: unknown };
|
|
return typeof value.message === "string" ? value.message : "";
|
|
}
|
|
|
|
const snapshot = {
|
|
birth_date: "1998-03-15",
|
|
birth_place_label: "北京市",
|
|
latitude: 39.9042,
|
|
longitude: 116.4074,
|
|
timezone_id: "Asia/Shanghai",
|
|
timezone_offset: 8,
|
|
birth_time_source: "unknown",
|
|
reported_birth_time: null,
|
|
active_birth_time: null,
|
|
birth_time_period: null,
|
|
uncertainty_before_minutes: null,
|
|
uncertainty_after_minutes: null,
|
|
};
|
|
const fingerprint = "b".repeat(64);
|
|
const fullDay = { start_time: "00:00", end_time: "23:59" };
|
|
const skillName = "jyotish-birth-time-rectification";
|
|
const skillVersion = "9.0.0";
|
|
const blocks = {
|
|
blocks: [
|
|
{ period: "early_morning", start_time: "04:00", end_time: "07:59", relative_support: 12 },
|
|
{ period: "morning", start_time: "08:00", end_time: "11:59", relative_support: 41 },
|
|
{ period: "afternoon", start_time: "12:00", end_time: "17:59", relative_support: 28 },
|
|
{ period: "evening", start_time: "18:00", end_time: "22:59", relative_support: 11 },
|
|
{ period: "late_night", start_time: "23:00", end_time: "03:59", relative_support: 8 },
|
|
],
|
|
};
|
|
|
|
test("block_scan RPCs are service_role-only and advance a declared period", { skip: skipWithoutDocker }, async () => {
|
|
const fixture = startPostgresFixture();
|
|
const schemaUrl = fixture.connectionUrl("schema_owner", "schema-owner-test-password");
|
|
try {
|
|
const migration = spawnSync(process.execPath, [runnerPath], {
|
|
encoding: "utf8",
|
|
env: { ...process.env, SCHEMA_DATABASE_URL: schemaUrl },
|
|
});
|
|
assert.equal(migration.status, 0, migration.stderr);
|
|
|
|
fixture.psqlAs(
|
|
"identity_runtime",
|
|
"identity-runtime-test-password",
|
|
`
|
|
insert into identity.users (name, email, email_verified, email_verified_at)
|
|
values ('Unknown', 'unknown-time@example.com', true, now());
|
|
`,
|
|
);
|
|
const userId = fixture.psql(
|
|
"select id from identity.users where email = 'unknown-time@example.com'",
|
|
);
|
|
fixture.psql(`
|
|
update public.profiles
|
|
set birth_date = '1998-03-15',
|
|
reported_birth_time = null,
|
|
birth_time_source = 'unknown',
|
|
latitude = 39.9042, longitude = 116.4074, timezone_offset = 8,
|
|
birth_time_status = 'reported'
|
|
where id = '${userId}';
|
|
`);
|
|
fixture.psql(`
|
|
with provider as (
|
|
insert into public.model_providers (code, name, provider_type, encrypted_api_key, enabled)
|
|
values ('block-scan-test', 'Block Scan Test', 'openai', 'test-ciphertext', true)
|
|
returning id
|
|
), config as (
|
|
insert into public.model_configs (model_id)
|
|
values ('block-scan-default-model')
|
|
returning id
|
|
)
|
|
insert into public.model_config_versions (
|
|
config_id, version, provider_id, label, provider_model, enabled, is_default, status, published_at
|
|
)
|
|
select config.id, 1, provider.id, 'Default', 'gpt-test', true, true, 'published', now()
|
|
from config cross join provider;
|
|
`);
|
|
|
|
const service = createLocalPostgresDataClient(
|
|
fixture.connectionUrl("service_runtime", "service-runtime-test-password"),
|
|
null,
|
|
"service_role",
|
|
);
|
|
const opened = await service.rpc("open_agentic_rectification_case", {
|
|
p_user_id: userId,
|
|
p_request_id: "aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa",
|
|
p_intent: "homepage",
|
|
p_session_id: null,
|
|
p_skill_name: skillName,
|
|
p_skill_version: skillVersion,
|
|
p_baseline_profile_fingerprint: fingerprint,
|
|
p_baseline_birth_snapshot: snapshot,
|
|
p_candidate_range: fullDay,
|
|
});
|
|
assert.equal(opened.error, null, rpcError(opened.error));
|
|
const caseId = String((opened.data as Record<string, unknown>).case_id);
|
|
|
|
const staged = await service.rpc("set_agentic_rectification_case_stage", {
|
|
p_user_id: userId,
|
|
p_case_id: caseId,
|
|
p_stage: "block_scan",
|
|
});
|
|
assert.equal(staged.error, null, rpcError(staged.error));
|
|
|
|
const written = await service.rpc("write_agentic_rectification_block_scan", {
|
|
p_user_id: userId,
|
|
p_case_id: caseId,
|
|
p_block_scan: blocks,
|
|
});
|
|
assert.equal(written.error, null, rpcError(written.error));
|
|
|
|
const dossier = await service.rpc("get_agentic_rectification_case_dossier", {
|
|
p_user_id: userId,
|
|
p_case_id: caseId,
|
|
});
|
|
assert.equal(dossier.error, null, rpcError(dossier.error));
|
|
const caseRow = (dossier.data as { case?: { stage?: string; block_scan?: unknown } }).case;
|
|
assert.equal(caseRow?.stage, "block_scan");
|
|
assert.ok(caseRow?.block_scan);
|
|
|
|
const advanced = await service.rpc("advance_agentic_rectification_case_from_block_scan", {
|
|
p_user_id: userId,
|
|
p_case_id: caseId,
|
|
p_start_time: "08:00",
|
|
p_end_time: "11:59",
|
|
});
|
|
assert.equal(advanced.error, null, rpcError(advanced.error));
|
|
assert.equal((advanced.data as { stage?: string }).stage, "block_scan");
|
|
assert.deepEqual((advanced.data as { candidate_range?: unknown }).candidate_range, {
|
|
start_time: "08:00",
|
|
end_time: "11:59",
|
|
});
|
|
assert.equal(
|
|
fixture.psql(`select stage from public.agentic_rectification_cases where id = '${caseId}'`),
|
|
"block_scan",
|
|
);
|
|
|
|
const outside = await service.rpc("advance_agentic_rectification_case_from_block_scan", {
|
|
p_user_id: userId,
|
|
p_case_id: caseId,
|
|
p_start_time: "04:50",
|
|
p_end_time: "05:10",
|
|
});
|
|
assert.match(rpcError(outside.error), /agentic_rectification_invalid_block_window/);
|
|
|
|
const narrowed = await service.rpc("advance_agentic_rectification_case_from_block_scan", {
|
|
p_user_id: userId,
|
|
p_case_id: caseId,
|
|
p_start_time: "08:00",
|
|
p_end_time: "09:00",
|
|
});
|
|
assert.equal(narrowed.error, null, rpcError(narrowed.error));
|
|
assert.equal((narrowed.data as { stage?: string }).stage, "minute");
|
|
|
|
const invalidPeriod = await service.rpc("advance_agentic_rectification_case_from_block_scan", {
|
|
p_user_id: userId,
|
|
p_case_id: caseId,
|
|
p_start_time: "08:00",
|
|
p_end_time: "09:00",
|
|
});
|
|
assert.match(rpcError(invalidPeriod.error), /agentic_rectification_not_block_scan/);
|
|
|
|
const widened = await service.rpc("widen_agentic_rectification_case_window", {
|
|
p_user_id: userId,
|
|
p_case_id: caseId,
|
|
p_start_time: "07:30",
|
|
p_end_time: "09:30",
|
|
});
|
|
assert.equal(widened.error, null, rpcError(widened.error));
|
|
assert.deepEqual((widened.data as { candidate_range?: unknown }).candidate_range, {
|
|
start_time: "07:30",
|
|
end_time: "09:30",
|
|
});
|
|
assert.equal(
|
|
fixture.psql(`select adopted_credible_range is null from public.agentic_rectification_cases where id = '${caseId}'`),
|
|
"t",
|
|
);
|
|
|
|
const shrink = await service.rpc("widen_agentic_rectification_case_window", {
|
|
p_user_id: userId,
|
|
p_case_id: caseId,
|
|
p_start_time: "08:00",
|
|
p_end_time: "09:00",
|
|
});
|
|
assert.match(rpcError(shrink.error), /agentic_rectification_invalid_widen_window/);
|
|
|
|
const privileges = fixture.psql(`
|
|
select concat_ws(':',
|
|
has_function_privilege('service_role', 'public.set_agentic_rectification_case_stage(uuid,uuid,text)', 'EXECUTE'),
|
|
has_function_privilege('anon', 'public.set_agentic_rectification_case_stage(uuid,uuid,text)', 'EXECUTE'),
|
|
has_function_privilege('authenticated', 'public.write_agentic_rectification_block_scan(uuid,uuid,jsonb)', 'EXECUTE'),
|
|
has_function_privilege('service_role', 'public.advance_agentic_rectification_case_from_block_scan(uuid,uuid,text,text)', 'EXECUTE'),
|
|
has_function_privilege('service_role', 'public.widen_agentic_rectification_case_window(uuid,uuid,text,text)', 'EXECUTE'),
|
|
has_function_privilege('anon', 'public.widen_agentic_rectification_case_window(uuid,uuid,text,text)', 'EXECUTE')
|
|
)
|
|
`);
|
|
assert.equal(privileges, "t:f:f:t:t:f");
|
|
} finally {
|
|
try {
|
|
await closeLocalPostgresDataPool(
|
|
fixture.connectionUrl("service_runtime", "service-runtime-test-password"),
|
|
);
|
|
} finally {
|
|
fixture.stop();
|
|
}
|
|
}
|
|
});
|