fix(v2): 浏览器端到端验证——修掉模块页在浏览器里渲染不出内容的缺陷

首次用真实 Chrome 打开 /trajectory-center(新增可选脚本 scripts/browser-e2e.cjs),
暴露 5 个源码守卫与生产构建都看不出的缺陷,全部修复:

1. 三个模块页读 `list.items`,而 /projects 返回的是 {projects, identity}——
   项目列表恒为空,prescreen-workbench / experience-center / trajectory-center
   整页渲染不出任何面板,只显示"当前身份没有可访问的项目"这种看着正常的空态。
   (第二/三批引入)改为 list.projects。
2. TrajectoryPanel 没被传 identity,canRecord 恒假 → 会议结果录入表单永不出现。
3. ImprovementPanel 草稿下拉以组件 id 作 key/value,同一组件多版本草稿时撞 React key,
   且选不准要发布哪一版;改以 `组件id@版本` 为键值。
4. JSX 文本里的 `**强调**` 会原样显示星号(JSX 不渲染 Markdown),共 9 处;
   改为 <b>(字符串上下文处直接去掉标记)。
5. 深色导航模块名被 flex 压缩折行("AI 预审"断成两行);
   加 flex:0 0 auto + white-space:nowrap。

另修一个既有测试脆弱点:test_trajectory.py 的更正用例断言"哪条排前面",
两条记录同刻度时排序翻转,曾让 verify.py 偶发失败;改为断言"两条都在、更正指向旧记录"。

回归防线:第 5 项补进 test_module_shell_ui.cjs 源码断言;
test_ui_readability.cjs 的导航字号断言改为不把 min-height 钉在规则首位。

验证:scripts/verify.py 14/14 PASS(backend-unit 572 项),
证据 test-evidence/20261001-030127-ff59d7e/;scripts/browser-e2e.cjs 19/19 PASS
(截图在 test-evidence/e2e-batch4/)。该 E2E 脚本刻意不接入 verify.py。

Co-Authored-By: Claude Code <noreply@anthropic.com>
This commit is contained in:
2026-10-01 03:04:18 +08:00
co-authored by Claude Code
parent ff59d7e8f1
commit 4720d72965
14 changed files with 294 additions and 44 deletions
+4 -2
View File
@@ -43,9 +43,11 @@ export default function ExperienceCenterPage() {
send("GET", "/projects"),
]);
setIdentity(context);
setProjects(list.items || list || []);
// 同上:`/projects` 返回 {projects, identity},读 `list.items || list` 会拿不到数组。
const items = list.projects || [];
setProjects(items);
const requested = new URLSearchParams(location.search).get("project");
const first = (list.items || list || [])[0];
const first = items[0];
if (requested) setProjectId(requested);
else if (first) setProjectId(first.id);
} catch (e: any) {setError(e.message);} finally {setLoaded(true);}
+4 -1
View File
@@ -64,7 +64,10 @@ export default function PrescreenWorkbenchPage() {
request("/projects"),
]);
setIdentity(context);
const items = list.items || list || [];
// `/projects` 返回 {projects, identity},不是 {items}。读 `list.items || list` 拿不到数组,
// 项目列表恒为空、整页只剩"没有可访问的项目"空态——而空态看着是合理页面,
// 所以源码守卫与生产构建都查不出来(第四批浏览器验证才发现)。
const items = list.projects || [];
setProjects(items);
const wanted = new URLSearchParams(location.search).get("project") || items[0]?.id || "";
if (wanted) {setProjectId(wanted); await open(wanted);}
+3 -2
View File
@@ -49,7 +49,8 @@ export default function TrajectoryCenterPage() {
send("GET", "/projects"),
]);
setIdentity(context);
const items = list.items || list || [];
// 同上:`/projects` 返回 {projects, identity},读 `list.items || list` 会拿不到数组。
const items = list.projects || [];
setProjects(items);
const wanted = new URLSearchParams(location.search).get("project") || items[0]?.id || "";
if (wanted) {
@@ -92,7 +93,7 @@ export default function TrajectoryCenterPage() {
{projects.map((item) => <option key={item.id} value={item.id}>{item.id} · {item.customer || ""}</option>)}
</select>
</label>
{project && <TrajectoryPanel key={project.id} project={project} send={send}/>}
{project && <TrajectoryPanel key={project.id} project={project} identity={identity} send={send}/>}
{project && <ImprovementPanel key={`imp-${project.id}`} project={project}
identity={identity} send={send}/>}
</>}