bffc74efc5
Foreground still skips the heavy overview stack, but overlaps a timed gateway so official evidence can merge when it finishes in budget. Co-authored-by: Cursor <cursoragent@cursor.com>
250 lines
13 KiB
TypeScript
250 lines
13 KiB
TypeScript
import assert from "node:assert/strict";
|
||
import { readFileSync } from "node:fs";
|
||
import test from "node:test";
|
||
import { createConsultationPlan } from "../src/lib/consultation-plan.ts";
|
||
import { toAgentConsultationContext, toModelOutput } from "../src/mastra/consultation-workflow.ts";
|
||
|
||
|
||
test("passes transparent public-case references into the agent context", () => {
|
||
const workflowSource = readFileSync(new URL("../src/mastra/consultation-workflow.ts", import.meta.url), "utf8");
|
||
const agentSource = readFileSync(new URL("../src/mastra/index.ts", import.meta.url), "utf8");
|
||
|
||
assert.match(workflowSource, /reference_transparency:\s*record\(data\.reference_transparency\)/);
|
||
assert.match(workflowSource, /vedastro_gateway:\s*record\(data\.vedastro_gateway\)/);
|
||
assert.match(workflowSource, /ashtakavarga:\s*chart\.ashtakavarga/);
|
||
assert.match(agentSource, /high_similarity_public_references_available/);
|
||
assert.match(agentSource, /requested_uncovered_domains/);
|
||
assert.match(agentSource, /public_context_only/);
|
||
assert.match(agentSource, /timing_state/);
|
||
assert.match(agentSource, /partial_match/);
|
||
assert.match(agentSource, /narayana_status/);
|
||
assert.match(agentSource, /transit_status/);
|
||
assert.match(agentSource, /Jupiter and Saturn relative houses/);
|
||
assert.match(agentSource, /exact_triggers as technical trigger points/);
|
||
assert.match(agentSource, /production_tuning_allowed=false/);
|
||
assert.match(agentSource, /no_majority_vote/);
|
||
assert.match(agentSource, /method_variant_not_majority_vote/);
|
||
assert.match(agentSource, /Shadbala\/Ashtakavarga component differences/);
|
||
assert.match(agentSource, /D2, D11/);
|
||
assert.match(agentSource, /gender-specific spouse significators are supplements/);
|
||
assert.match(agentSource, /male.*Venus/);
|
||
assert.match(agentSource, /female.*Jupiter\/Mars/);
|
||
});
|
||
|
||
test("keeps strength, Ashtakavarga, and timing evidence available to the answer model", () => {
|
||
const workflowSource = readFileSync(new URL("../src/mastra/consultation-workflow.ts", import.meta.url), "utf8");
|
||
const agentSource = readFileSync(new URL("../src/mastra/index.ts", import.meta.url), "utf8");
|
||
|
||
assert.match(workflowSource, /shadbala: chart\.shadbala/);
|
||
assert.match(workflowSource, /shadbala_boundary:/);
|
||
assert.match(workflowSource, /ashtakavarga: modules\.ashtakavarga/);
|
||
// This line used to pin the misspelling: it asserted the packet read
|
||
// `modules.dasha_boundaries` without anything checking that the engine writes
|
||
// that key. tests/test_consultation_consumer_context.py now compares the names
|
||
// across the boundary; this only pins that timing evidence is still passed.
|
||
assert.match(workflowSource, /dasha_sub_periods: modules\.dasha_sub_periods/);
|
||
assert.match(workflowSource, /varga_spectrum: modules\.varga_spectrum/);
|
||
assert.match(workflowSource, /technique_audit_table: consumerContext\.technique_audit_table/);
|
||
assert.match(agentSource, /evidence_contract\.technique_audit_table/);
|
||
assert.match(workflowSource, /evidence_contract:/);
|
||
assert.match(workflowSource, /missing_route_layers: consumerContext\.missing_route_layers/);
|
||
assert.match(workflowSource, /answer_policy: consumerContext\.answer_policy/);
|
||
assert.match(agentSource, /evidence_contract\.answer_policy/);
|
||
assert.match(agentSource, /can_answer_precise_timing/);
|
||
assert.match(workflowSource, /boundary: "not_auto_rectified"/);
|
||
assert.match(agentSource, /rectification\.boundary=not_auto_rectified/);
|
||
assert.match(workflowSource, /external_engine_evidence:/);
|
||
assert.match(workflowSource, /runtime_truth: record\(data\.runtime_truth\)/);
|
||
assert.match(workflowSource, /numerical_parity: record\(data\.external_parity_gate\)/);
|
||
assert.match(workflowSource, /real_case_calibration: record\(data\.real_case_calibration\)/);
|
||
});
|
||
|
||
test("projects only bounded server-selected evidence to the model", () => {
|
||
const context = toAgentConsultationContext({
|
||
success: true,
|
||
question: "事业如何",
|
||
chart: {
|
||
birth: { date: "1990-01-02", time: "03:04", latitude: 25.03, longitude: 121.56 },
|
||
ascendant: { sign: "Leo", degree: 12.5, reported_time: "private-reported-time" },
|
||
planets: [{ name: "Sun", sign: "Capricorn", degree: 4.2, lng: "private-lng" }],
|
||
houses: { first: { sign: "Leo" } },
|
||
dasha: { current: "Mars", next: "Rahu", utc_offset: "private-utc-offset" },
|
||
shadbala: { planets: { Sun: { total_rupa: 7.1 } } },
|
||
ashtakavarga: { house_scores: { "10": 31 } },
|
||
modules: {
|
||
shadbala: { total: 412 },
|
||
ashtakavarga: { total: 28 },
|
||
varga_spectrum: {
|
||
status: "used",
|
||
mode: "full_spectrum",
|
||
counts: { formal: 20, research_dn: 40, extended: 3, blocked: 0 },
|
||
formal: { D9: { lagna: "Leo", planets: { Sun: "Capricorn" }, name: "Navamsa" } },
|
||
research_dn: { D13: { lagna: "Aries", planets: { Moon: "Taurus" }, boundary: "generic D-N; not a formal named varga" } },
|
||
},
|
||
dasha_sub_periods: {
|
||
current: { antardasha: { lord: "Saturn", start: "2025-10-17", end: "2027-05-18" } },
|
||
boundary_count: 9,
|
||
utc_offset: "private-module-utc-offset",
|
||
},
|
||
narayana_dasha: { current: "Aries" },
|
||
functional_benefic_malefic: {
|
||
status: "used",
|
||
functional_benefics: ["Jupiter"],
|
||
functional_malefics: ["Mercury"],
|
||
},
|
||
kakshya: { status: "observation_only", boundary: "not verified day/month timing" },
|
||
yogas: { status: "executed", count: 1, yogas: [{ name: "Gaja Kesari", planets: ["Jupiter", "Moon"] }] },
|
||
arudha_padas: {
|
||
padas: {
|
||
A10: { name: "Karma Pada (A10)", sign: "Capricorn" },
|
||
UL: { name: "Upapada (UL)", sign: "Libra" },
|
||
},
|
||
},
|
||
gulika: { sign: "Scorpio", claim_boundary: "observation_only" },
|
||
kp_cusps: { houses: { "10": { sign: "Taurus", sublord: "Saturn" } } },
|
||
chara_dasha: {
|
||
status: "executed",
|
||
current: { sign: "Libra", lord: "Venus", duration_years: 8 },
|
||
sequence: [{ sign: "Libra", lord: "Venus", duration_years: 8 }],
|
||
},
|
||
transits: {
|
||
status: "executed",
|
||
sade_sati: { phase: "none", moon_sign: "Taurus", saturn_sign: "Pisces" },
|
||
boundary: "observation windows, not guaranteed events",
|
||
},
|
||
},
|
||
},
|
||
routing: { primary_theme: "career" },
|
||
thematic_report: {
|
||
themes: {
|
||
career: {
|
||
theme: "career",
|
||
summary: "保留这条服务端证据摘要",
|
||
narrative: "事业证据叙事",
|
||
strength: "strong",
|
||
account_balance: "private-account-balance",
|
||
recommendations: ["保持稳健推进"],
|
||
evidence: [{
|
||
technique: "D10-Dashamsha-local",
|
||
chart: "D10",
|
||
conclusion: "D10 事业分盘已进入证据链",
|
||
sentiment: "positive",
|
||
strength: "strong",
|
||
details: {
|
||
source: "chart",
|
||
derived: true,
|
||
entitlements: "private-entitlements",
|
||
access_scopes: "private-access-scopes",
|
||
},
|
||
}],
|
||
},
|
||
},
|
||
},
|
||
consumer_context: {
|
||
route: "career", core_status: "ready", available_layers: ["natal", "timing"],
|
||
missing_route_layers: [], hard_blockers: [],
|
||
technique_truth: { status: "verified", access_scopes: "private-validation-scopes" },
|
||
answer_policy: {
|
||
can_answer_direction: true,
|
||
can_answer_precise_timing: false,
|
||
entitlements: "private-policy-entitlements",
|
||
},
|
||
user_facing_limitation: "精确月份暂不可用",
|
||
technique_audit_table: [
|
||
{ technique: "Formal Vargas D1–D60", status: "executed", system: "jyotish", boundary: "20/20 named traditional charts" },
|
||
{ technique: "Yogas", status: "executed", system: "jyotish" },
|
||
{ technique: "Arudha / UL / A10", status: "executed", system: "jyotish" },
|
||
{ technique: "Narayana Dasha", status: "executed", system: "jyotish" },
|
||
{ technique: "Functional Benefic/Malefic", status: "executed", key_functional_benefics: ["Jupiter"] },
|
||
{ technique: "Western natal (tropical)", status: "executed", system: "western" },
|
||
{ technique: "VedAstro Cloud State", status: "executed", boundary: "official_cloud_evidence_available" },
|
||
{ technique: "MEVG / Global Web Evidence", status: "blocked", boundary: "caps_claims_until_global_web_evidence_runs" },
|
||
],
|
||
varga_spectrum: {
|
||
status: "used",
|
||
counts: { formal: 20, research_dn: 40 },
|
||
formal: { D9: { lagna: "Leo", planets: { Sun: "Capricorn" } } },
|
||
},
|
||
western_spectrum: {
|
||
status: "executed",
|
||
natal: { sun: "Aries", moon: "Taurus", ascendant: "Leo" },
|
||
techniques: { transits: { status: "executed" } },
|
||
},
|
||
vedastro_cross_check: {
|
||
status: "executed",
|
||
official_closure_state: "official_verified",
|
||
natal: { sun: "Leo", moon: "Cancer", ascendant: "Scorpio" },
|
||
},
|
||
},
|
||
reference_transparency: { similar_public_cases: { status: "public_context_only" } },
|
||
rectification: { summary: "none" },
|
||
vedastro_gateway: {
|
||
official_closure_state: "official_verified",
|
||
official_raw_response: { lat: 25.03, lon: 121.56, hour: 3, minute: 4 },
|
||
},
|
||
});
|
||
const output = toModelOutput(context);
|
||
const careerPlan = createConsultationPlan({ userIntent: "事业如何", theme: "career" });
|
||
const careerOutput = toModelOutput(context, careerPlan);
|
||
const serialized = JSON.stringify(output);
|
||
|
||
assert.equal(output.packet_version, "consultation-evidence-packet-v2");
|
||
assert.equal("birth" in output, false);
|
||
assert.equal(serialized.includes("1990-01-02"), false);
|
||
assert.equal(serialized.includes("03:04"), false);
|
||
assert.equal(serialized.includes("25.03"), false);
|
||
assert.equal(serialized.includes("121.56"), false);
|
||
for (const privateValue of [
|
||
"private-reported-time", "private-lng", "private-utc-offset", "private-module-utc-offset",
|
||
"private-account-balance", "private-entitlements", "private-access-scopes",
|
||
"private-validation-scopes", "private-policy-entitlements",
|
||
]) {
|
||
assert.equal(serialized.includes(privateValue), false);
|
||
}
|
||
for (const privateKey of [
|
||
"reported_time", "lng", "utc_offset", "account_balance", "entitlements", "access_scopes",
|
||
]) {
|
||
assert.equal(serialized.includes(`"${privateKey}"`), false);
|
||
}
|
||
assert.equal(serialized.includes("保留这条服务端证据摘要"), true);
|
||
assert.equal(serialized.includes("D10-Dashamsha-local"), true);
|
||
assert.equal(serialized.includes("total_rupa"), true);
|
||
assert.equal(serialized.includes("house_scores"), true);
|
||
assert.equal(serialized.includes('"dasha"'), true);
|
||
assert.equal(serialized.includes("narayana_dasha"), true);
|
||
// Antardasha boundaries are what an answer needs to name a month at all, and
|
||
// they were absent from every packet while this field named a module key the
|
||
// engine never wrote.
|
||
assert.equal(serialized.includes("dasha_sub_periods"), true);
|
||
assert.equal(serialized.includes("2027-05-18"), true);
|
||
assert.equal(serialized.includes('"status":"verified"'), true);
|
||
const answerPolicy = output.evidence_contract.answer_policy as Record<string, unknown>;
|
||
assert.equal(answerPolicy.can_answer_precise_timing, false);
|
||
assert.deepEqual(output.claim_cards.map((card) => card.category), ["natal_foundation", "domain", "timing", "validation"]);
|
||
assert.deepEqual(careerOutput.claim_cards.map((card) => card.category), ["natal_foundation", "domain", "timing", "validation"]);
|
||
assert.equal(JSON.stringify(careerOutput).includes('"dasha"'), true);
|
||
assert.equal(serialized.includes("consultation-evidence-packet-v2"), true);
|
||
assert.equal(serialized.includes("Formal Vargas"), true);
|
||
assert.equal(serialized.includes("varga_spectrum"), true);
|
||
assert.equal(serialized.includes('"D13"'), true);
|
||
assert.equal(serialized.includes("western_spectrum"), true);
|
||
assert.equal(serialized.includes("technique_audit_table"), true);
|
||
assert.equal(serialized.includes("functional_benefics"), true);
|
||
assert.equal(serialized.includes("Jupiter"), true);
|
||
assert.equal(serialized.includes("Gaja Kesari"), true);
|
||
assert.equal(serialized.includes("Karma Pada (A10)"), true);
|
||
assert.equal(serialized.includes("chara_dasha"), true);
|
||
assert.equal(serialized.includes("Venus"), true);
|
||
assert.equal(serialized.includes("sade_sati"), true);
|
||
assert.equal(serialized.includes("Taurus"), true);
|
||
const mustUse = output.evidence_contract.must_use_layers;
|
||
assert.equal(Array.isArray(mustUse), true);
|
||
assert.equal((mustUse as string[]).includes("Yogas"), true);
|
||
assert.equal((mustUse as string[]).includes("Arudha / UL / A10"), true);
|
||
assert.equal((mustUse as string[]).includes("VedAstro Cloud State"), true);
|
||
assert.equal((mustUse as string[]).includes("MEVG / Global Web Evidence"), false);
|
||
assert.equal(serialized.includes("Scorpio"), true);
|
||
assert.equal(serialized.includes("official_verified"), true);
|
||
assert.equal(serialized.includes("https://"), false);
|
||
});
|