17 新增「浏览器验证(第二篇):AI 预审 / 历史经验加工」:覆盖的交互、 点通过程中发现并修掉的 2 个缺陷(预审面板不刷新、候选行同 id 连开多行)、 写演示库的副作用清单,以及本数据集下仍点不到的 3 处(沙盘勾选联动、 来源事件勾选、reviewer 视角的审核发布)与 2 处口径待确认项。 15 第 7 节改为本轮交接:F11 三个表面均已由真实 Chrome 走过;F27/F29/F30 与新证据路径;下一任务只剩需要用户或外部输入的部分。 Co-Authored-By: Claude Code <noreply@anthropic.com>
35 KiB
四批交付记录
口径见 16 交付纠偏规格 §4:每批必须列出页面入口、操作步骤、 实际结果、证据位置、剩余缺口;未接通项标"部分完成"。
第一批:接通正常预审执行链
状态:部分完成(执行链已接通并经真实运行验收;模型类技能已能跑完全程,见文末 「更正记录」;界面点击本身尚未由自动化驱动,材料确认步骤未在浏览器中完整走一遍)。
页面入口
| 入口 | 位置 |
|---|---|
| 发起预审 | /xingbang-workbench?project=DEMO-B「材料与问题」页 → 顶部"开始AI预审"按钮 |
| 查看结果与依据 | 同页「预审与推进沙盘」面板:主审意见、核查结果、核查维度(10)、每条"查看依据" |
操作步骤(实际执行)
- 启动 v2:后端
uvicorn app:app --port 8012(带XINGBANG_DEMO_ROLE_LOGIN=1)、 前端npm run dev -- -p 3212。 - 经前端代理发起预审(与页面按钮同一请求):
POST /api/risk-agent/project-assistant/projects/DEMO-B/runs,角色头manager。 - 等 worker 执行结束(轮询运行状态)。
- 读取
GET .../prescreen/projects/DEMO-B/runs/{run_id}。 - 浏览器打开工作台并渲染面板截图。
实际结果
- 运行结束状态
partial,视图recommendation=supplement,probability=null。 - 维度 10 个:5 已核查 / 2 待核实 / 3 存在阻断项;阶段 1–2
(
corporate.consistency、corporate.cashflow、corporate.assets、corporate.coverage、skill-quality、skill-finance、skill-credit、demo.coverage、rules-corporate、corporate.analysis)。 - 核查结果 4 条(
lease.coverage.below_demo_threshold、lease.asset.duplicate、financial.cashflow.missing、financial.liabilities.conflict),各带依据与组件版本。 - 证据 14 条随视图返回,界面"查看依据"可展开来源与定位。
- 未完成项 1 条:
RUN_STEP_FAILED 金租对公业务综合核查:未配置受信模型,语义核查未执行——模型不可用时如实标未完成,不伪造结论。 - 缺证 2 项:
financial.operating_cashflow、存在尚未人工确认的材料候选。 - 反复发起产生多条记录(本轮 3 条),旧记录仍可读;轨迹引用指向本次运行。
- 呈现判定:10 维超出雷达可读范围 → 界面改用分组列表并保留全部维度(AC-44 真实分支)。
证据位置
| 内容 | 位置 |
|---|---|
| 会话内验证日志 | 本轮运行输出(发起→轮询→读视图) |
| 端到端测试 | backend/test_prescreen_from_run.py(12 项,真实 enqueue + worker 执行) |
| 界面渲染 | claude_use/tmp/v2-batch1-panel.png(本机截图,未入库) |
| 全量验证 | test-evidence/20260930-123451-0228966/(scripts/verify.py 11/11 PASS,531 项单测) |
| 推送状态 | 已推送 origin/main:f118721..c5edb40;git ls-remote origin main 实测与本地 HEAD 一致 |
剩余缺口
- 界面点击未由自动化驱动:本机无 playwright/puppeteer/chromium-cli,发起预审是通过 与页面按钮同一条代理请求完成的;"点按钮"这一步没有脚本化证据。
- 材料确认已走通(部分闭合):通过应用自己的入口补齐演示项目缺的字段——
POST /documents上传按解析器键名书写的材料(operating_cashflow: 1200)→ 项目待确认候选 →POST /supplements带candidate_ids确认 →financial.operating_cashflow等 3 个字段生效(revision 5→6)。 未闭合部分:仍是接口调用而非浏览器点击。 - 演示角色需要
XINGBANG_DEMO_ROLE_LOGIN=1:否则 worker 的authorized()会把 演示角色发起的运行判为"权限已撤销"(运行会失败但可读)。这是配置要求,需写入部署说明。 - 模型已接通并能跑完全程(2026-09-30 第二轮更正,见下方「更正记录」):配置 DeepSeek
(
XINGBANG_LOCAL_MODEL_*)后,模型类技能corporate.analysis真实发起调用。 本轮首测仍报模型引用未知字段——但根因不是缺financial.operating_cashflow; 修复字段表三处缺陷后,模型跑完全程:工具调用 11 次 / 预算 18,降级记录为空。 - 取消中的运行不产出视图(只处理 completed/partial/failed)。
更正记录(2026-09-30 第二轮实测)
更正:本节原先记为"模型已接通,但预算不足",其归因有误。第二轮用真实模型复测后确认:
模型引用未知字段与缺financial.operating_cashflow无关。 "已定义但本次无值"的 字段,键仍然存在(backend/services/assistant_materials.py的apply_candidate无条件建键), 不会触发该守卫;补这个字段因此不可能修好它。实测补件后(revision 2→4,缺证清零)报错照旧。- 真正被拒的是
repayment.*,进而是字段表的三处缺陷:backend/skills/financial-leasing-*/SKILL.md的inputs声明了 8 个 S1 标准字段表里 不存在的字段:还款来源、涉诉、增信、保证金、保险、客户名称;- 字段守卫比对的是"当前恰好有值的字段",而非标准字段表,于是把"标准字段但本次无数据" 误判为未知字段——与提示词自身"缺失资料标 unknown"自相矛盾;
- 模型从未被告知允许使用的字段名,只能靠猜(实测先猜
repayment.annual_amount, 放开后改猜metrics.debt_ratio)。
- 工具预算不是约束:跑通的那次实际只用了 11 次,原值 12 本就够用。
max_tool_calls12→18、超时 120s→180s 保留作余量,但不构成修复。
已修复(4 个文件):
| 文件 | 改动 |
|---|---|
backend/services/assistant_materials.py |
补 8 个标准字段;NUMERIC 排除两个非数值字段;legal.case_count 加非负整数校验 |
backend/services/assistant_model.py |
守卫改为比对标准字段表;向模型下发 standard_fields;提示词加字段约束;删除遮蔽模块级导入的局部导入 |
backend/services/project_assistant.py |
补 insurance.→租赁物、deposit.→增信 维度前缀 |
backend/services/component_registry.py |
方案预算与版本(1.0.0→1.1.0) |
字段表三处是代码层改动,对既有数据库立即生效;预算存放在冻结组件里,需走
POST /components 草稿 → publish 才对既有库生效。
实测结果(一次性临时库 + DeepSeek,演示库未改动):corporate.analysis 由 failed
变为 partial(部分结果为 unknown,属如实标注而非失败),降级记录为空,
核查结果 3 条 → 14 条。证据:test-evidence/20260930-171301-962d425/
(scripts/verify.py 11/11 PASS,531 项单测)。
本轮新发现、尚未修复:skill-quality 的完整性检查只遍历"已存在值的字段"
(backend/services/skill_executor.py),因此从未提供过的字段永远不会被判为缺失——
真实项目下"资料完整性"会漏报。建议单独立项,不并入本批。
运行环境配置(本地演示,2026-09-30 实测)
复现本记录需要以下环境变量。密钥一律不入库、不写入任何文件:本地演示用 shell 变量 展开传入,正式环境请用部署系统的密钥管理。
XINGBANG_DEMO_ROLE_LOGIN=1 # 演示角色发起运行必需,否则 worker 判"权限已撤销"
XINGBANG_LOCAL_MODEL_URL=https://api.deepseek.com/v1
XINGBANG_LOCAL_MODEL_NAME=deepseek-flash # 可换 deepseek-v4-pro(语义核查质量优先)
XINGBANG_LOCAL_MODEL_KEY=<你的 DeepSeek API Key>
# 后端启动前清空代理:实测直连 api.deepseek.com 可用(HTTP 200),
# 系统代理 127.0.0.1:7890 不可用(HTTP 000,与 AGENTS.md 记录的坑一致)
启动:cd backend && venv/Scripts/python.exe -m uvicorn app:app --host 127.0.0.1 --port 8012;
前端:npm run dev -- -p 3212,并设 RISK_AGENT_BACKEND_URL=http://127.0.0.1:8012(v2 隔离端口)。
第二批:完成历史经验加工流程
状态:部分完成。后端闭环(真实提炼入口 → 候选治理 → 卡片进方案并影响运行)已接通, 并经真实执行链测试;本模块页面入口已建并通过生产构建与源码守卫。 未闭合:① 真实模型提炼调用尚未实测(需要模型端点,见"剩余缺口"); ② 界面点击未由自动化驱动(本机无浏览器自动化,沿用第一批 F11 口径)。
覆盖:AC-50/51/52、BR-48/49、E-28;页面入口部分覆盖 BR-50(三个入口中的第一个)。
页面入口
| 入口 | 位置 |
|---|---|
| 历史经验加工 | 顶部导航「历史经验加工」→ /experience-center?project=<项目> |
| 流程四段 | ① 来源:历史过程时间线 → ② 提炼:用真实模型生成候选 → ③ 候选:修订/评测/发布 → ④ 方案:让卡片影响核查 |
操作步骤(实现并按此验收)
- 「从项目材料重建时间线」→
POST /prescreen/projects/{id}/case-timeline(确定性,不调用模型)。 - 勾选来源事件、填写提炼要求 →「请求提炼」→
POST .../knowledge-extractions。 - 候选卡上「自然语言修改适用范围」或「补充独立测试样本」→
PATCH .../knowledge-candidates/{card_id}。 - 「隔离评测」→ 由另一位有发布资格的人「审核发布」→
POST .../knowledge-candidates/{card_id}/transitions。 - 已发布卡「选入新方案」→「评测方案」→「发布方案」→
POST .../review-plans与/review-plans/{id}/transitions。 - 在项目工作台用该方案发起预审;运行结果冻结并记录卡片版本。
实际结果
- 提炼(模型未配置):记录
status=failed,candidate_id=null,degradations 带EXTRACTION_UNAVAILABLE,文案"本次未能完成经验提炼,请稍后重试或改为人工创建"; 提炼跑完后库里一张候选草稿都没有(test_experience_extraction的反例断言)。 这与第一批"模型不可用如实标未完成"同口径。 - 提炼(模型可用):以假传输层走真实
agent_manager.invoke_scoped路径, 产出origin=history_derived且带来源事件 id 的 Skill 候选;记录保存prompt_version=history-extraction.v1与模型名,可核对"确实发起了调用"。 真实模型调用未实测(见剩余缺口)。 - 候选治理:自然语言修订真的发起一次模型调用(测试断言调用次数为 1);
模型不可用时拒绝且卡片一字未改(比对修订前后 revision 与 conditions);
修订后仍为
history_derived且保留来源、状态仍为 draft;已发布后修订升版本并记parent_version。 - 卡片影响核查:同项目两次运行对照——基座方案
corporate.pre-review不含该卡片, 运行里没有该核查项;含卡片的新方案运行里出现 1 条history.repayment.dependency, 其basis_ids=[skill.history.repayment@1.0.0],component_versions含(卡片id, 1.0.0)。 - 依赖门禁:草稿卡片进方案时,发布被 409 拒绝;引用不存在组件时评测
passed=false且发布被拒。
证据位置
| 内容 | 位置 |
|---|---|
| 提炼入口(15 项) | backend/test_experience_extraction.py |
| 候选治理与自然语言修订(15 项) | backend/test_knowledge_governance.py |
| 卡片 → 方案 → 运行(6 项) | backend/test_card_to_run.py |
| 界面源码守卫(新增) | scripts/test_experience_center_ui.cjs(已登记进 scripts/verify.py) |
| 全量验证 | test-evidence/20261001-003148-2e7e194/(scripts/verify.py 12/12 PASS,含 backend-unit 全量 567 项、frontend-build、新增 experience-center-ui 守卫) |
剩余缺口
- 真实模型提炼未实测(P0):AC-50 的"若模型已配置则实际调用"需要一次真实调用证据。
本轮机器上没有设置
XINGBANG_LOCAL_MODEL_*,因此只交付了"不可用路径"与"假传输成功路径"。 实测方法:带XINGBANG_DEMO_ROLE_LOGIN=1与三个模型变量启动后端,再走上面步骤 2; 在此之前不得宣称"真实提炼已跑通"。 - 界面点击未由自动化驱动:本机无 playwright/puppeteer/chromium-cli。界面证据是
"源码守卫 + 生产构建(
/experience-center6.08 kB)+ 代码走查",不是端到端点击证明; 本批的"页面入口/操作步骤"是按实现与接口核对写出的,不是浏览器截图。 - 例外边界未进入可求值条件语言:注册表条件只支持数值阈值算子,
present/absent被既有断言 锁定拒绝,因此模型给出的例外保存为文本exception_note,供专家修订,不作为可执行条件。 - 卡片适用条件不参与运行内逐项判定:
conditions目前只用于域/范围/有效期过滤 (knowledge_cards.effective());运行内条件求值需独立设计,不在本批冒充完成。 - 治理状态只实现 draft/published:
in_review/rejected/withdrawn在注册表没有落地表达, 候选状态机因此只提供evaluate与publish,不造一个假状态掩盖。 - 规则类(Rule)候选不在本批:数值阈值与正式依据门禁(
_check_hard_basis)需要单独设计, 本批只产出 Skill 类候选(可验证的缺件核查动作)。 - 顺带发现、未修:
01-requirements.md的 E-18 写作HARD_RULE_BASIS_REQUIRED, 但代码走的是ValueError→ 422INVALID_REQUEST,错误码未对齐(既有问题,非本批引入)。
第三批:按已确认原型完成新版界面
状态:部分完成。深色导航、三个模块的独立入口、轨迹回放界面已接通并通过 生产构建与源码守卫。未闭合:界面仍未经浏览器点击/截图验证(同 F11,本机无浏览器自动化); 轨迹与会议结果的录入属第四批;工作台旧的「评审经验」页签未下线。
覆盖:AC-53/54/55、BR-50。
页面入口
| 入口 | 位置 |
|---|---|
| 业务工作区首页 | /(三个模块入口卡片;?project= 携带项目上下文) |
| AI 预审 | 深色导航「AI 预审」→ /prescreen-workbench |
| 历史经验加工 | 深色导航「历史经验加工」→ /experience-center(第二批交付) |
| 轨迹复盘 | 深色导航「轨迹复盘」→ /trajectory-center |
| 原落地页内容 | /assistant(保留,不再是默认首页) |
操作步骤(实现并按此核对)
- 打开
/→ 看到三个模块入口卡片与"当前项目上下文"提示。 - 进入任一模块 → 深色导航高亮当前模块;
?project=在模块之间保持。 - AI 预审:选项目 → 选方案 → 填本次要求 → 发起预审 → 下方结果面板给出 概率状态与依据、动态维度、推进沙盘、每条"查看依据"。
- 轨迹复盘:选运行 → 步骤流(序号 / 类型 /
组件@版本/ 状态 / 错误码 / 证据数 / 成本 / 耗时) → 加载更多 → 会议结果只读对照。
实际结果
- 导航为深色(
nav.bg #102B27、选中#244D41、muted #B1C6BE),工作区画布保持浅色#f5f7f9;导航内的身份选择器改用深色变体,避免深底白字不可读。 - 三个模块各有独立路由并各自渲染复用的组件(
PrescreenPanel/ImportBatchPanel/ExperienceCenter/TrajectoryPanel),路由里没有再写一份实现。 - 已合并的旧页
/trajectory、/review-workbench、/report-workbench、/collateral-workbench仍是重定向,没有被复活(AC-55 的防重复页面)。 - 轨迹面板:失败/跳过步骤照常列出并带错误码;成本缺失显示"未记录(不填 0)"; 展示服务端"不包含模型内部推理过程"的说明;无任何写操作。
- 生产构建产物(实测):
/1.98 kB、/prescreen-workbench2.36 kB、/trajectory-center3.87 kB、/experience-center7.48 kB、/assistant6.08 kB。 - 首页入口卡片沿用了既有的
.xb-project-card,但该类此前只用于<button>; 作为<a>会带上浏览器默认下划线,因此补display:block;text-decoration:none(只影响该类,按钮用法不受影响)。 - 现有 7 项界面守卫全部继续通过(可读性、S1 面板、预审面板、加工中心、评审工作台、身份恢复、助手访问)。
证据位置
| 内容 | 位置 |
|---|---|
| 模块壳与三入口源码守卫(新增) | scripts/test_module_shell_ui.cjs(已登记 scripts/verify.py,共 13 项检查) |
| 全量验证 | test-evidence/20261001-005027-ae89462/(scripts/verify.py 13/13 PASS,含 backend-unit 全量 567 项、frontend-build、新增 module-shell-ui 守卫) |
剩余缺口
- 界面仍未经浏览器验证(F11 未变;后由文末「浏览器验证(第二篇)」补齐):深色导航与三个模块都 只有"源码守卫 + 生产构建 + 代码走查"三层证据,没有浏览器点击或截图; 原型本身也没有视觉门禁(04-ui-spec §7 已声明不以原型替代验收)。 深色导航的文字对比度已改为机械断言(守卫内按 WCAG 公式实算,阈值 AA 4.5:1): 未选中 12.03:1、选中 9.49:1、muted 8.37:1、品牌 13.91:1,全部达标——但这证明的是配色可用, 不等于版面在实机上的观感已验收。
- 轨迹与会议结果的录入属第四批:本批只做只读回放与只读对照,界面上写明了这一点。
- 工作台仍保留旧「评审经验」页签(走
assistant_experiences,与第二批的知识卡片治理不是同一套)。 新旧并存会造成"哪里才是正门"的困惑;但删除是用户可见的破坏性动作,本批不擅自下线,留待确认。 AgentLoopFlow.tsx(src/components/trajectory/)仍是零引用死代码:本批没有复用它, 也没有删除——它不挡事,清理不属于本批交付范围。- 原型顶部的演示提示条未实现:原型有"原型演示 · 未连接真实数据与模型"横幅; 本批只做了导航与工作区骨架,未加该横幅(各模块内部已有等价的域与来源标识)。
- 首页默认路由发生变化:
/由聊天页改为业务工作区,原内容移到/assistant。 这是用户可见的行为变化;若部署脚本、书签或外部链接依赖旧的/,需另行确认。
第四批:接通评审反馈与改进发布
状态:部分完成(较本轮初版有实质性推进)。会议结果可从页面录入并与材料版本对照;
改进候选走真实知识发布入口,发布后新运行使用新版本、旧运行仍可回放——两条断言都由
真实执行链(enqueue + worker)证明。本批首次做了真实浏览器端到端验证(F11 对这两个表面已关闭),
并因此发现并修掉 5 个源码守卫与生产构建都看不出的缺陷(见下「浏览器验证发现的问题」)。
未闭合:会议结果是模拟录入,未经真实会议系统;/experience-center 与 /prescreen-workbench
虽在同一次浏览器验证中被顺带修好,但其自身交互仍未逐项点过。
覆盖:AC-56、AC-57、BR-51;并顺带修复 AC-53/AC-55 的运行时缺陷。
页面入口
| 入口 | 位置 |
|---|---|
| 轨迹复盘(既有入口,不新增第四个) | 深色导航「轨迹复盘」→ /trajectory-center |
| 会议结果录入与对照 | 同页 TrajectoryPanel 下半部「会议结果对照」→「追加会议结果」表单 |
| 改进对照与发布 | 同页 ImprovementPanel「改进对照与发布」 |
置于轨迹复盘之内而非新开模块:14 §7 本就把「轨迹、会议记录与反向改进」写在同一节,
AC-53 又要求恰好三个模块入口。AgentNav.tsx 未改动。
操作步骤(实现并按此核对)
- 录入会议结果:选项目 →
TrajectoryPanel底部填原始结果码、会议编号、可从project.runs[].input_snapshot_id选「对应的材料版本」→ 保存。 - 更正:在「更正哪条记录」里选旧记录 → 保存为追加并带
supersedes_id,历史不被覆盖。 - 提改进候选:
ImprovementPanel① 选来源运行/会议结果(必填其一)、改进目标、 要发布的草稿版本、变更说明 → 「提出改进候选」。 - 两道门:② 「对草稿做隔离评测」(发布门禁)与「提交旧/新对照」(候选门禁)是两件事,缺一不可。
- 审核与发布:提交审核 → 由另一位身份「通过审核」→「审核发布」。 发布请求体只有 action,界面不提交任何版本号。
实际结果
- 发布是真的发布(本批核心):端点把
_knowledge_publisher注入improvements.transition, publisher 用候选声明的proposed_revision_ref精确定位草稿(组件id@版本, 不按组件 id 猜"最新草稿",否则会出现"审核的是 A、发布的是 B"),再调knowledge_cards.publish→component_registry.release:自批拒绝、隔离评测门禁、 依赖可解析三道既有保证原样生效,写入不可变component_version并覆盖release指针。 - 不接受自报版本号:release 请求带
released_ref一律 422INVALID_REQUEST, 候选状态不前进、不产生任何组件版本(反例已测)。 - 发布失败保留旧版:未过隔离评测的草稿 → 409
IMPROVEMENT_NOT_VALIDATED,release指针仍指旧版本,候选仍是approved。候选状态与组件版本写在同一个_db()连接/事务里,publisher 抛异常即整体回滚,不会出现"版本已发布、候选没标记"。 - 非知识类目标诚实拒绝:
orchestration/question_profile无真实发布入口 → 409 并说明原因,不用"改状态"冒充发布。 - AC-57 端到端(
test_improvement_release.py,真实 enqueue +DurableWorker.process_next()): 同一个已发布方案,发布前运行的component_versions含卡片@1.0.0、basis_ids=[卡片@1.0.0];经改进候选发布1.0.1后再跑一次得到卡片@1.0.1; 回放第一次运行仍是1.0.0,其冻结版本未被改写(replay.read_only=true)。 - AC-56:会议结果按
matched/unmatched分组;未匹配的单列并显示「不计入分母」, 与服务端denominator()一致(未送审、撤回、附条件、未知与未匹配都不进分母)。 - 真实服务器冒烟(不是单测的替代,脚本
scripts/xingbang_batch4_smoke.py): 对运行中的 uvicorn 按界面同一串请求走通 建卡 → 隔离评测 → 发布 → 结构化修订 → 录入会议结果 → 提候选 → 对照 → 换身份审核 → 发布(不带版本号);服务端返回released_ref=卡片@1.0.1,且release指针实测指向1.0.1。 只用了脚本新建的组件 id,未触碰既有组件的发布指针。 副作用:它在演示库(backend/xingbang_data/project_assistant.sqlite3)新建了若干 「冒烟:回款集中依赖核查」卡片与SMOKE-4会议结果;重复运行会累积。 这些是演示库里的可见脏数据,需要时可删——本记录如实列出,不做隐藏。
证据位置
| 内容 | 位置 |
|---|---|
| AC-57 端到端与四条反例(4 项) | backend/test_improvement_release.py(新增) |
| 自报版本号被拒(API 层) | backend/test_improvements.py test_client_supplied_released_ref_is_rejected |
| 界面源码守卫(新增) | scripts/test_improvement_panel.cjs(已登记 scripts/verify.py,共 14 项检查) |
| 轨迹面板守卫(改:区分「回放只读」与「结果只可追加」) | scripts/test_module_shell_ui.cjs |
| 全量验证 | test-evidence/20261001-030127-ff59d7e/(scripts/verify.py 14/14 PASS,含 backend-unit 全量 572 项) |
| 真实服务器冒烟 | scripts/xingbang_batch4_smoke.py(对 127.0.0.1:8012 实跑,退出码 0) |
| 真实浏览器端到端 | scripts/browser-e2e.cjs(系统 Chrome;19/19 PASS);截图与 result.json 在 test-evidence/e2e-batch4/ |
浏览器验证发现的问题(源码守卫与生产构建都查不出来)
首次用真实 Chrome 打开 /trajectory-center 后暴露的缺陷。「看起来正常的空态」是它们的共同点——
/projects 读错了字段,页面安静地显示"当前身份没有可访问的项目",构建与守卫全都通过。
| # | 问题 | 归属 | 处理 |
|---|---|---|---|
| 1 | 三个模块页读 list.items,而 /projects 返回的是 {projects, identity} → 项目列表恒为空,整个模块页渲染不出任何面板 |
第二/三批引入(prescreen-workbench、experience-center、trajectory-center 三处) | 改为 list.projects |
| 2 | TrajectoryPanel 没被传 identity,canRecord 恒假 → 会议结果录入表单永远不出现 |
本批 | 传入 identity |
| 3 | ImprovementPanel 的草稿下拉以组件 id 作 key/value,同一组件有多个版本草稿时撞 React key,也选不准要发布哪一版 |
本批 | 改以 组件id@版本 为键值 |
| 4 | JSX 文本里写 **强调** 会原样显示星号(JSX 不渲染 Markdown),共 9 处 |
第一/二批 5 处、本批 4 处 | 改为 <b>(字符串上下文处直接去掉标记) |
| 5 | 深色导航的模块名被 flex 压缩折行("AI 预审"断成两行),三个入口读不清 | 第三批 | flex:0 0 auto; white-space:nowrap |
此外还修掉一个既有测试脆弱点:test_trajectory.py 的更正用例断言"哪条排前面",
而两条记录可能落在同一时钟刻度、排序随之翻转,曾让 scripts/verify.py 偶发失败。
改为断言"两条都在、更正指向旧记录",与排序无关;连跑 5 次稳定通过。
回归防线:第 5 项已补进 scripts/test_module_shell_ui.cjs 的源码断言;
scripts/test_ui_readability.cjs 的导航字号断言改为不把 min-height 钉在规则首位
(否则它会因新增属性而误报)。第 1–4 项属于"只有浏览器能看见"的一类,
目前只由 scripts/browser-e2e.cjs 覆盖——该脚本刻意不接入 verify.py。
剩余缺口
- F11 对本批两个表面已关闭,但未全面关闭:
/trajectory-center已由scripts/browser-e2e.cjs在真实 Chrome 里走过(19/19),有截图;/experience-center与/prescreen-workbench当时只验证到"能被本次路由改动修好、能渲染",其自身交互没有逐项点过,当时仍记 F11 未闭合 (这两个表面已在文末「浏览器验证(第二篇)」里逐项点过,并因此修掉 2 个缺陷)。 另外该脚本不在verify.py里,也就是说这条证据不会随强制门禁自动重跑—— 它需要本机 Chrome 与一次性npm i --no-save puppeteer-core。 - 浏览器验证只覆盖到"能走通"这一层:没有做视觉回归(无基线截图比对)、没有多分辨率、 没有键盘可达性与屏幕阅读器检查。深色导航对比度仍是守卫内按 WCAG 实算,不是实测。
- 会议结果是模拟录入:AC-56 验的是"录入后与材料版本对照"的机制,不是真实会议系统对接; 真实标签映射与客户身份权限仍待确认(M5/M6)。
- 对照样本是人工录入的 JSON,不是真实保留集;
evaluation.independent仍是客户端声明 的布尔(既有设计)——界面不把它包装成"已证明独立",但服务端也确实无法自证。 - 改进端点仍无角色门禁:既有
transition_knowledge_candidate/transition_review_plan对 评测与发布有role()门禁,改进端点(propose/evaluate/approve/release)只做项目范围检查。 本批给 release 接上真实发布后这个缺口的后果变重了,但加门禁会改变既有端点行为 (现有 API 测试以manager身份调用),未擅自扩大改动,留待确认。安全上真正关键的 "不自批"已由服务端强制(must_not_self_approve+registry.release()的edited_by == actor)。 - 题库/编排无真实发布入口:已按 409 诚实拒绝,非假接通;需要时另行设计。
- 浏览器 E2E 尚未固化为项目门禁:是否把它接进
verify.py、是否把puppeteer-core写进package.json,是产品/工程决策,本批没有替用户决定,只提供可选脚本。
浏览器验证(第二篇):AI 预审 / 历史经验加工
状态:F11 剩下的两个表面已在真实 Chrome 里逐项点过(第四批只走过 /trajectory-center)。
脚本 scripts/browser-e2e-modules.cjs,42 项检查全通过、0 失败,截图与 result.json 在
test-evidence/browser-e2e-modules/。断言全部来自真实点击与真实执行链,没有接口 mock。
覆盖的交互
| 表面 | 真实动作 | 断言 |
|---|---|---|
/prescreen-workbench |
打开 ?project=DEMO-B |
标题、项目下拉真的有项目、方案下拉有方案 |
| 同上 | 点「开始 AI 预审」 | 入队提示 → 运行跑到终态 → 不刷新页面面板自己出现本次运行 → 刷新后仍可读到、输入快照已换 |
| 同上 | 点核查结果的「查看依据」→「关闭依据」 | 抽屉打开且含"依据与版本";关闭后抽屉消失、焦点回到触发按钮(键盘可达) |
| 同上 | 概率区与降级记录 | 概率数字必须紧邻"演示值/人工设定";未完成项带错误码;"证据阶段 ≠ 审批概率"在页面上 |
| 同上 | 推进沙盘 | 没有可用动作时给诚实空态,不给"点了必然失败"的选项 |
/experience-center |
点「从项目材料重建时间线」 | 徽标给出状态与事件数;无结构化记录时明确标"过程材料不完整 · 0 个事件" |
| 同上 | 空来源、空要求点「请求提炼」 | 服务端 422,界面如实显示拒绝理由(不假装成功、不静默无反应) |
| 同上 | 填提炼要求后点「请求提炼」 | 记录渲染为"提炼未完成"+E-28;候选行数 30→30 不变(BR-48:不产生草稿) |
| 同上 | 点候选卡的「自然语言修改适用范围」 | 只展开被点的那一行;未填要求时「形成草稿修订」保持禁用 |
| 同上 | 换 admin 身份重载 | 出现「隔离评测」(30 个),仍不出现「审核发布」(发布限 reviewer) |
两处修复的全量验证:test-evidence/20261001-093541-c880f40/(scripts/verify.py 14/14 PASS,
backend-unit 全量 572 项;证据绑定提交 c880f40,summary.json 的 status=passed)。
浏览器验证发现的问题(第二篇)
两个都属于"源码守卫 + 生产构建都看不出"的那一类:构建通过、守卫全绿,只有真渲染会暴露。
| # | 问题 | 归属 | 处理 |
|---|---|---|---|
| 1 | /prescreen-workbench 点「开始 AI 预审」、运行结束后结果面板不重载:新运行进不了"查看哪一次运行",面板继续显示上一次运行,而徽标写着"结果会自动刷新"——AC-46 的界面路径因此不成立(此前只有接口驱动能证明)。根因:PrescreenPanel 的 load() 只依赖 project.id。补修时又发现 worker 是先更新 run.status、再另写 prescreen_run 视图(assistant_worker.process_next 的 put(run) 与 save_prescreen_view),两者不在同一事务,只在状态变化时读一次会读到"视图还没落库"的中间态 |
第一批(面板重载时机) | 改为依赖项目里的运行集合,并在最新运行进入视图列表前短时重试(上限 5 次,不做无限轮询);test_prescreen_ui.cjs 补 5 条源码断言 |
| 2 | /experience-center 候选区:key={card.id} 撞 React key,且「自然语言修改适用范围」「补充独立测试样本」按 card.id 开合——点一行连开 4 行面板(同一 card.id 的草稿行与各版本行共享 id)。浏览器控制台同时报 React 重复 key 错误 |
第二批 | 引入行级 rowKey(组件id@版本@状态),key 与两个展开标记都用它;test_experience_center_ui.cjs 补 4 条源码断言 |
副作用(真的写演示库,如实列出)
本脚本每次运行会新建一次预审运行(点「开始 AI 预审」)、重建一次 DEMO-B 时间线(同 id 递增
revision)、并在未配置模型时留下一条 status=failed、candidate_id=null 的提炼记录。
本轮验证(含中途重跑与核对环境)在 backend/xingbang_data/project_assistant.sqlite3 里新增了
6 条 DEMO-B 预审运行、3 条失败提炼记录,并为 DEMO-A/B/C 各重建过一次时间线。
与 F28 同类,重复运行会累积;这些是演示库里的可见数据,需要时可删。
剩余缺口(本轮未闭合)
- 推进沙盘的勾选联动没点到:演示方案的维度里没有假设动作的目标维度(
DC-CASH/DC-TITLE), 服务端available_assumptions因此返回 0 个动作,界面按设计给"当前方案没有可推演的假设动作"空态。 基线的演示值(42%,带"演示值"标注)已实际渲染并断言,但"勾选 → 重算 → 返回基线"这条链 在本数据集下无法用浏览器走通。 - 来源事件勾选没点到:演示项目没有结构化的问询/决定记录,
case-timeline恢复出 0 个事件, 勾选框不存在;本轮因此用"提炼要求"满足服务端的前置条件走通提炼链路。 - reviewer 视角的「审核发布」没点到:演示身份里 reviewer 的
/projects只授权到 DEMO-C, 而 DEMO-C 没有知识候选,浏览器里点不到该按钮。已用 admin 作对照(有「隔离评测」、无「审核发布」)。 - 「请求提炼」在"没有来源也没有要求"时按钮仍可点:服务端按契约 422 并给出理由、界面如实显示; 但同文件里「形成草稿修订」「保存样本到草稿」都会按必填项禁用,口径不一致。按最小改动只验证、未改。
- 候选列表把同一卡片的多个版本行都按"已发布"列出:
knowledge_cards.list_cards同时返回component_draft与component_version行,同一card.id出现 3–4 行(v1.0.0 与 v1.0.1 都标"已发布"), 界面不显示release指针当前指向哪一版。"一行 = 一个存储记录"还是"一行 = 一张卡片的当前状态" 需产品确认后再改,本轮未动。 - 视觉回归(无基线截图比对)、多分辨率、键盘可达性与屏幕阅读器仍未做; 深色导航对比度仍是守卫内按 WCAG 实算,不是实测。
- 脚本仍不在
verify.py里(F27 未决):需本机 Chrome 与一次性npm i --no-save puppeteer-core, 手动node scripts/browser-e2e-modules.cjs。现在共有两个可选脚本 (browser-e2e.cjs走轨迹复盘,browser-e2e-modules.cjs走这两个表面)。