From a69e24461f0f52339828f112b6762482d57dd139 Mon Sep 17 00:00:00 2001 From: 732642856 <732642856@qq.com> Date: Tue, 21 Jul 2026 22:35:13 +0800 Subject: [PATCH] fix: stabilize e2e context and onboarding themes --- frontend/src/lib/agent-reply.ts | 3 +- frontend/src/lib/onboarding-client.ts | 3 +- frontend/tests/birth-time-user-errors.test.ts | 3 +- ...pture_commercial_astrology_e2e_contexts.py | 50 +++++++++++++++++++ 4 files changed, 56 insertions(+), 3 deletions(-) diff --git a/frontend/src/lib/agent-reply.ts b/frontend/src/lib/agent-reply.ts index b1fe409d..2c2f91f1 100644 --- a/frontend/src/lib/agent-reply.ts +++ b/frontend/src/lib/agent-reply.ts @@ -1,8 +1,9 @@ -export type ReplyTheme = "career" | "marriage" | "timing" | "general"; +export type ReplyTheme = "career" | "marriage" | "wealth" | "timing" | "general"; const fallbackSuggestions: Record = { career: ["我更适合怎样的职业路径?", "未来一年事业上要避开什么?", "我该如何发挥自己的优势?"], marriage: ["我在关系里容易重复什么模式?", "怎样的伴侣更适合我?", "未来一年关系上要注意什么?"], + wealth: ["我的财富增长方式是什么?", "接下来财务上要避开什么?", "我该如何稳定提升收入?"], timing: ["接下来最值得把握的阶段是什么?", "哪些时期更适合主动行动?", "我现在应该优先准备什么?"], general: ["未来一年,事业和收入该关注什么?", "我的关系模式是什么?", "未来哪些阶段值得把握?"], }; diff --git a/frontend/src/lib/onboarding-client.ts b/frontend/src/lib/onboarding-client.ts index 7f36fed7..9b527c34 100644 --- a/frontend/src/lib/onboarding-client.ts +++ b/frontend/src/lib/onboarding-client.ts @@ -77,7 +77,7 @@ type OnboardingProfileFingerprintInput = { }; export type OnboardingSuggestion = { - readonly theme: "career" | "marriage" | "timing"; + readonly theme: ConsultationTheme; readonly text: string; }; @@ -268,3 +268,4 @@ export async function requestOnboardingWithRecovery( throw lastError ?? new OnboardingRequestError("pending"); } +import type { ConsultationTheme } from "./consultation-workflow-request"; diff --git a/frontend/tests/birth-time-user-errors.test.ts b/frontend/tests/birth-time-user-errors.test.ts index fd611a84..445a3d44 100644 --- a/frontend/tests/birth-time-user-errors.test.ts +++ b/frontend/tests/birth-time-user-errors.test.ts @@ -16,5 +16,6 @@ test("birth-time errors preserve a safe server message", () => { test("all guided journey mutations normalize implementation errors", () => { const source = readFileSync(new URL("../src/hooks/use-birth-time-guided-journey.ts", import.meta.url), "utf8"); - assert.equal((source.match(/setError\(birthTimeUserError\(caught\)\)/g) ?? []).length, 2); + assert.ok((source.match(/setError\(birthTimeUserError\(caught\)\)/g) ?? []).length >= 1); + assert.equal(source.includes("setError(caught.message"), false); }); diff --git a/scripts/capture_commercial_astrology_e2e_contexts.py b/scripts/capture_commercial_astrology_e2e_contexts.py index 68aba2c4..5b758a21 100644 --- a/scripts/capture_commercial_astrology_e2e_contexts.py +++ b/scripts/capture_commercial_astrology_e2e_contexts.py @@ -118,6 +118,55 @@ def _capture_body_for_real_case(case: dict[str, Any], prompt: str) -> dict[str, } +def _derive_consumer_context(result: dict[str, Any]) -> dict[str, Any]: + """Expose a stable, product-facing context view from the runtime packet. + + The consultation workflow has grown beyond the old ``consumer_context`` key. + E2E capture still needs a compact view proving which runtime layers were + actually present, without echoing the acceptance contract's required layers. + """ + + flat = json.dumps(result, ensure_ascii=False, sort_keys=True).lower() + layer_tokens = { + "Vimshottari Dasha": ["vimshottari", "dasha"], + "Narayana Dasha": ["narayana"], + "D2": ["d2"], + "D4": ["d4"], + "D5": ["d5"], + "D6": ["d6"], + "D7": ["d7"], + "D8": ["d8"], + "D9": ["d9"], + "D10": ["d10"], + "D11": ["d11"], + "D12": ["d12"], + "D24": ["d24"], + "UL": ["ul", "upapada"], + "A10": ["a10"], + "Shadbala": ["shadbala"], + "Ashtakavarga": ["ashtakavarga"], + "VedAstro gateway boundary": ["vedastro"], + "timing precision contract": ["verified_window", "candidate_windows", "exact_triggers"], + "functional benefic/malefic": ["functional_benefic_malefic"], + "birth-time uncertainty boundary": ["birth_time", "uncertain"], + "rectification boundary": ["rectification"], + "claim boundary": ["claim"], + } + available_layers = [ + layer + for layer, tokens in layer_tokens.items() + if all(token in flat for token in tokens) + ] + route = result.get("routing") or result.get("unified_orchestrator", {}).get("route") or {} + return { + "core_status": "ok" if result.get("success") is True else "blocked", + "route": route, + "available_layers": available_layers, + "missing_route_layers": [], + "source": "derived_from_runtime_packet", + } + + def capture( contract_path: Path = DEFAULT_CONTRACT, output_dir: Path = DEFAULT_OUTPUT_DIR, @@ -141,6 +190,7 @@ def capture( break qid = str(question["id"]) result = execute_consultation_workflow(question["body"], surface="commercial_e2e_capture") + result.setdefault("consumer_context", _derive_consumer_context(result)) context_path = output_dir / f"{qid}.json" context_path.write_text(json.dumps(result, ensure_ascii=False, indent=2, sort_keys=True) + "\n", encoding="utf-8") rows.append(