fix(consult): check the evidence gate against the route the answer is on
Independent Staging Quality Gate / validate (push) Successful in 7m41s
Independent Staging Quality Gate / publish (push) Successful in 9m39s

七条路由的证据门都不是自己的:route_requirements 的键写成 relationship/finance,而
路由名是 marriage/wealth,另有 5 条路由压根没有条目,全部静默落到 general 的门。
missingLayers: [] 因此不表示证据齐备,只表示没检查过——婚姻的 UL 与财富的 D2 从未
进入检查。

同一函数另有两处判据也没接到权威来源。7 块正则用问题文本重猜领域,而领域早已由模型
声明并写进 route_packet,一句写作「情感」而非表里「感情」的提问在 marriage 路由上完全
拿不到性别解读边界。timing_layers_ready 读的是 missing_route_layers,该列表只装本路由
要求的层,于是对任何不要求 narayana_dasha 的路由恒为真,精确应期在该层根本没算出来时
也照样放行。三处的失败方向都是静默放宽,因此没有任何人报错。

三处都接回权威来源:10 条路由逐条显式列出必需层(层名限定为证据包真实构建的 section,
所以 wealth 不要求引擎不产出的 D11)、领域边界按 route 查表、出生时间边界从矫正闸门的
effective_accuracy 与 Lagna 敏感度派生、就绪判断直接读 section 状态。唯一保留文本探测
的是「用户有没有要一个具体日期」——服务端对此没有权威来源,改为 timing/annual 路由结构
性携带、文本仅作叠加,一次措辞漏判不再能把信号清零。

另外把 skillReferenceReadCount 暴露为回执的 skill.referenceReads(必填)与可观测日志的
skillReferenceReads。它此前数完即丢,而 skill_read 按设计不记成 runtime step,因此「模型
有没有真的翻开方法文档」在运行结束后无处可查。

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Jesse_Chen
2026-08-18 11:50:28 +08:00
co-authored by Cursor
parent 5687182980
commit 10ae149c58
9 changed files with 347 additions and 46 deletions
+10 -2
View File
@@ -681,7 +681,11 @@ export async function POST(request: Request) {
const executionReceipt = (): AgentExecutionReceipt => ({
runId: requestId,
runtime: "mastra-agentic",
skill: { name: "jyotish-vedic-astrology", loaded: state.jyotishSkillLoaded },
skill: {
name: "jyotish-vedic-astrology",
loaded: state.jyotishSkillLoaded,
referenceReads: state.skillReferenceReadCount,
},
steps: publicConsultationRuntimeSteps(state),
stepBudget: consultationStepBudgetReceipt(state),
workflow: workflowReceipt,
@@ -745,7 +749,11 @@ export async function POST(request: Request) {
const executionReceipt = (): AgentExecutionReceipt => ({
runId: requestId,
runtime: "mastra-agentic",
skill: { name: "jyotish-vedic-astrology", loaded: state.jyotishSkillLoaded },
skill: {
name: "jyotish-vedic-astrology",
loaded: state.jyotishSkillLoaded,
referenceReads: state.skillReferenceReadCount,
},
steps: publicConsultationRuntimeSteps(state),
stepBudget: consultationStepBudgetReceipt(state),
workflow: state.workflowReceipt ?? workflowReceipt,
+3
View File
@@ -132,6 +132,9 @@ export const agentObservabilityEventSchema = z.object({
// every attempt. Both are enum-like machine values, never provider text.
modelFinishReason: z.enum(agentModelFinishReasons).optional(),
modelStepCount: countSchema.optional(),
// How many reference documents the model opened after loading the skill. Zero on a run that
// answered a domain question means the method was never consulted, which no other field shows.
skillReferenceReads: countSchema.optional(),
inputTokens: tokenCountSchema.optional(),
outputTokens: tokenCountSchema.optional(),
@@ -51,6 +51,10 @@ export const agentExecutionReceiptSchema = z.object({
name: z.literal("jyotish-vedic-astrology"),
loaded: z.boolean(),
version: z.string().max(120).optional(),
// How many reference documents the model opened after loading the skill. Required rather than
// optional: the count was tracked in runtime state and surfaced nowhere, so "did the model
// consult the method at all" was unanswerable from a finished run. Zero is a real answer.
referenceReads: z.number().int().min(0).max(64),
}).strict(),
steps: z.array(executionStepSchema).max(32),
stepBudget: stepBudgetSchema.optional(),
@@ -123,6 +123,7 @@ export function createConsultationRuntimeState(options: { plannedSteps?: number;
export function consultationModelStepTelemetry(state: ConsultationRuntimeState) {
return {
modelStepCount: state.modelStepCount,
skillReferenceReads: state.skillReferenceReadCount,
...(state.modelFinishReason === undefined ? {} : { modelFinishReason: state.modelFinishReason }),
};
}