diff --git a/docs/BUG_HISTORY.md b/docs/BUG_HISTORY.md index c703f44b..b240cd84 100644 --- a/docs/BUG_HISTORY.md +++ b/docs/BUG_HISTORY.md @@ -12193,7 +12193,7 @@ - 修复:四条按「原值 / 新值 / 原因」改写,分别断 layout 与 homepage 注册两端,不得删测试。 - 验证:上述四文件;全量 `npm test` 相对 `cc1a8980` 少这 4 条红。 - 防复发:见 BUG-927。 -- 相关记录:BUG-927、BUG-745 +- 相关记录:BUG-927、BUG-745、BUG-939 - 复发自:无 - 修复版本:待发布 @@ -12285,3 +12285,19 @@ - 相关记录:BUG-214、BUG-268、BUG-282、BUG-937 - 复发自:无 - 修复版本:`8b11ae7d` + +## BUG-939 | 出生时间旅程合同仍读已搬走的 `app/page.tsx`,staging 门禁全红 + +- 状态:resolved +- 首次发现:2026-09-18 +- 最近更新:2026-09-18 +- 影响面:`tests/test_birth_time_journey_contract.py` `_home_surface`;Gitea `backend-quality-gate` `validate`;staging 无法发布 `e4e73f56` 之后的提交 +- 用户现象:staging 门禁从会话列表单起连续失败,最新一次 [run 2763](https://git.copse.top/root/Jyotisha/actions/runs/2763) 停在 Python 快速门。线上仍停在上次绿灯 `dc2f2a16`。 +- 触发条件:push 到 `staging` 且命中门禁路径。pytest 跑 `test_web_onboarding_uses_the_deterministic_free_journey`。 +- 根因:`e4e73f56` 把首页从 `frontend/src/app/page.tsx` 搬进 `(app)` 路由组。BUG-933/934 改了前端四条合同和两条 Python 入口合同,漏了这条已列入 `CORE_PYTEST_TARGETS` 的文件。`_home_surface()` 对缺失文件 `if path.exists()` 静默跳过,于是断言变成「拼盘里找不到 ` None: assert "grant delete" not in sql +PAGE = FRONTEND / "src" / "app" / "(app)" / "page.tsx" +HOME_SURFACE_FILES = ( + PAGE, + FRONTEND / "src" / "lib" / "home-types.ts", + FRONTEND / "src" / "lib" / "home-profile.ts", + FRONTEND / "src" / "lib" / "home-cloud-sync.ts", + FRONTEND / "src" / "components" / "birth-location-fields.tsx", + FRONTEND / "src" / "components" / "profile-fields.tsx", + FRONTEND / "src" / "components" / "onboarding-chat-message.tsx", + FRONTEND / "src" / "components" / "chart-library-panel.tsx", + FRONTEND / "src" / "components" / "starter-home.tsx", +) +OPTIONAL_HOME_HOOKS = ( + FRONTEND / "src" / "hooks" / "use-session-management.ts", + FRONTEND / "src" / "hooks" / "use-consultation-run.ts", + FRONTEND / "src" / "hooks" / "use-profile-onboarding.ts", + FRONTEND / "src" / "hooks" / "use-rectification-surface.ts", +) + + def _home_surface() -> str: - files = [ - FRONTEND / "src" / "app" / "page.tsx", - FRONTEND / "src" / "lib" / "home-types.ts", - FRONTEND / "src" / "lib" / "home-profile.ts", - FRONTEND / "src" / "lib" / "home-cloud-sync.ts", - FRONTEND / "src" / "components" / "birth-location-fields.tsx", - FRONTEND / "src" / "components" / "profile-fields.tsx", - FRONTEND / "src" / "components" / "onboarding-chat-message.tsx", - FRONTEND / "src" / "components" / "chart-library-panel.tsx", - FRONTEND / "src" / "components" / "starter-home.tsx", - FRONTEND / "src" / "hooks" / "use-session-management.ts", - FRONTEND / "src" / "hooks" / "use-consultation-run.ts", - FRONTEND / "src" / "hooks" / "use-profile-onboarding.ts", - FRONTEND / "src" / "hooks" / "use-rectification-surface.ts", - ] - return "".join(path.read_text(encoding="utf-8") for path in files if path.exists()) + parts = [path.read_text(encoding="utf-8") for path in HOME_SURFACE_FILES] + parts.extend( + path.read_text(encoding="utf-8") for path in OPTIONAL_HOME_HOOKS if path.exists() + ) + return "".join(parts) def _mastra_consultation_surface() -> str: @@ -155,6 +164,12 @@ def _mastra_consultation_surface() -> str: ) +def test_home_surface_requires_the_app_route_group_page() -> None: + assert PAGE.is_file() + assert PAGE.parts[-2:] == ("(app)", "page.tsx") + assert not FRONTEND.joinpath("src", "app", "page.tsx").exists() + + def test_web_onboarding_uses_the_deterministic_free_journey() -> None: page = _home_surface() route = (