fix(consult): allow reported-time precision and persist receipts
Independent Staging Quality Gate / validate (push) Successful in 12m1s
Independent Staging Quality Gate / publish (push) Successful in 9m50s

This commit is contained in:
Jesse_Chen
2026-08-16 16:59:16 +08:00
parent a8279623aa
commit f12a43ad1d
12 changed files with 87 additions and 45 deletions
+10 -2
View File
@@ -21,13 +21,21 @@ test("chat session schema preserves the safe agent execution receipt", () => {
runtime: "mastra-agentic" as const,
skill: { name: "jyotish-vedic-astrology" as const, loaded: true },
steps: [{ sequence: 1, kind: "skill" as const, name: "jyotish-vedic-astrology", status: "completed" as const }],
workflow: { route: "career", status: "ready", preciseTiming: "blocked", missingLayers: [] },
workflow: { route: "multi-domain", status: "ready", preciseTiming: "allowed", missingLayers: [], domains: ["general", "timing"] },
techniqueTruth: "verified",
};
const workflowReceipt = {
route: "multi-domain",
status: "ready",
preciseTiming: "allowed",
missingLayers: [],
domains: ["general", "timing"] as const,
};
const parsed = chatSessionWriteSchema.parse({
...values,
messages: [{ role: "assistant", text: "回答", agentExecutionReceipt: receipt }],
messages: [{ role: "assistant", text: "回答", workflowReceipt, agentExecutionReceipt: receipt }],
});
assert.deepEqual(parsed.messages[0]?.workflowReceipt, workflowReceipt);
assert.deepEqual(parsed.messages[0]?.agentExecutionReceipt, receipt);
});
@@ -72,7 +72,7 @@ test("context-bound tool keeps legacy single theme compatibility and calculates
assert.deepEqual(captured, { ...serverChart.toolInput, entryMode: "direct_chart", question: "事业如何", theme: "career" });
assert.strictEqual(capturedPlan, plan);
assert.equal(state.consultationToolCallCount, 1);
assert.equal(state.workflowReceipt?.preciseTiming, "blocked");
assert.equal(state.workflowReceipt?.preciseTiming, "allowed");
assert.deepEqual(state.workflowReceipt?.domains, ["career"]);
assert.deepEqual((first as { domains?: string[] }).domains, ["career"]);
});
@@ -19,7 +19,7 @@ test("general-no-birth-time is an explicit server mode that never runs a chart w
assert.equal(shouldRunBirthChartWorkflow("verified_chart"), true);
});
test("unverified chart context can never become confirmed or retain precise timing permission", () => {
test("unverified chart context preserves evidence-owned precise timing permission while retaining provenance", () => {
const original = {
success: true,
consumer_context: {
@@ -35,21 +35,27 @@ test("unverified chart context can never become confirmed or retain precise timi
assert.equal(original.consumer_context.answer_policy.can_answer_precise_timing, true);
assert.deepEqual(guarded.consumer_context.answer_policy, {
can_answer_direction: true,
can_answer_precise_timing: false,
can_answer_precise_timing: true,
birth_time_confidence: "unverified_reported_time",
candidate_is_confirmed: false,
});
});
test("unverified answers keep the timing guard without a repetitive rectification warning", () => {
const transform = createBirthTimeModeOutputGuard("unverified_birth_time", false);
const first = transform("2026年8月适合观察方向。");
const second = transform("你一定会升职。");
test("unverified answers preserve exact dates when server evidence allows precise timing", () => {
const transform = createBirthTimeModeOutputGuard("unverified_birth_time", true);
const answer = transform("Rahu 大运为 2013年11月21日 至 2031年11月22日。");
assert.doesNotMatch(first, new RegExp(UNVERIFIED_BIRTH_TIME_NOTICE));
assert.match(first, /具体时间已省略/);
assert.doesNotMatch(second, /一定会升职/);
assert.doesNotMatch(second, new RegExp(UNVERIFIED_BIRTH_TIME_NOTICE));
assert.equal(answer, "Rahu 大运为 2013年11月21日 至 2031年11月22日。");
assert.doesNotMatch(answer, new RegExp(UNVERIFIED_BIRTH_TIME_NOTICE));
assert.doesNotMatch(answer, /具体时间已省略/);
});
test("evidence-blocked unverified answers still use the deterministic timing guard", () => {
const transform = createBirthTimeModeOutputGuard("unverified_birth_time", false);
const answer = transform("2026年8月适合观察方向。");
assert.match(answer, /具体时间已省略/);
assert.doesNotMatch(answer, new RegExp(UNVERIFIED_BIRTH_TIME_NOTICE));
});
test("general mode deterministically rejects personal chart claims while preserving general knowledge", () => {
+3 -3
View File
@@ -35,12 +35,12 @@ test("rejects a theme outside the consultation allowlist", () => {
);
});
test("server birth-time mode fixes the precision boundary", () => {
test("reported concrete birth time uses the same evidence-owned precision boundary as a verified chart", () => {
assert.equal(createConsultationPlan({
userIntent: "未来什么时候适合行动",
theme: "timing",
consultationMode: "unverified_birth_time",
}).precisionBoundary, "precise_timing_blocked");
}).precisionBoundary, "server_evidence_required");
assert.equal(createConsultationPlan({
userIntent: "什么是上升星座",
theme: "general",
@@ -55,7 +55,7 @@ test("rejects mode or precision tampering", () => {
consultationMode: "unverified_birth_time",
});
assert.throws(
() => validateConsultationPlan({ ...plan, precisionBoundary: "server_evidence_required" }, {
() => validateConsultationPlan({ ...plan, precisionBoundary: "precise_timing_blocked" }, {
consultationMode: "unverified_birth_time",
modelCreditCost: 1,
}),
@@ -25,7 +25,7 @@ test("timing questions use a legal report theme and preserve a timing route hint
assert.ok(request.requiredLayers.includes("negative holdout gate"));
assert.equal(request.claimBoundary, "candidate_day_month_window_only_until_holdout_passes");
assert.equal(request.plan_version, "consultation-plan-v2");
assert.equal(request.precision_boundary, "precise_timing_blocked");
assert.equal(request.precision_boundary, "server_evidence_required");
assert.equal(request.timing_horizon, "next_12_months");
});
@@ -98,7 +98,7 @@ test("timing input projects only legal private workflow fields", async () => {
assert.equal(body.strict_workflow_route, "timing");
assert.ok(body.required_layers.includes("negative holdout gate"));
assert.equal(body.claim_boundary, "candidate_day_month_window_only_until_holdout_passes");
assert.equal(body.precision_boundary, "precise_timing_blocked");
assert.equal(body.precision_boundary, "server_evidence_required");
assert.deepEqual(body.requested_domains, ["timing"]);
assert.deepEqual(body.required_evidence_categories, ["natal_foundation", "timing", "validation"]);
assert.equal(input.question, "未来哪些阶段值得把握?");