fix(frontend): repair staging breakpoint and focus contracts
Independent Staging Quality Gate / validate (push) Failing after 12m24s
Independent Staging Quality Gate / publish (push) Skipped

Merge entry overflow rules into the existing 480px breakpoint, restore picker focus without scrolling, and sync composer and entry contracts without changing page logic. Add AST generation-state guard and both picker close-path regressions.

Validation: targeted 33/33; Chrome isolated components 145 checks; tsc and lint zero errors. Node22 full suite 3706 tests, no lost names or new failures; three target failures fixed, 88 baseline environment/contract failures unchanged. Windows build remains blocked by symlink EPERM. Changed-file privacy check: 11 files, no findings, not a full-repository pass. BUG-1011 remains separate.

Co-Authored-By: Claude Code <noreply@anthropic.com>
This commit is contained in:
jesse-ux
2026-09-23 16:31:10 +08:00
co-authored by Claude Code
parent 93cd01dbf9
commit 36a737616c
11 changed files with 187 additions and 18 deletions
+48
View File
@@ -13441,3 +13441,51 @@
- 相关记录:BUG-1005、BUG-1009
- 复发自:无
- 修复版本:—
## BUG-1012 | 首页入口新增 375px 断点违反既有白名单
- 状态:investigating(定向及隔离浏览器/变异验证通过,待新门禁确认)
- 首次发现:2026-09-23
- 最近更新:2026-09-23
- 影响面:首页入口响应式样式与 staging 门禁。
- 用户现象:无独立已复现线上现象;新增切点导致断点合同失败,阻断发布。
- 触发条件:运行 viewport-breakpoint-contract 的 CSS width breakpoints stay on the published allowlist。
- 根因:45ec4617 新增 375px 规则,未遵守 BUG-697 收敛口径;此前红色门禁掩盖新增失败。
- 修复:按任务决策将两条防溢出规则并入既有空 480px 块,不扩白名单,不更改按钮尺寸。
- 验证:修复前真实 run 2856 / job 6345 证实失败;修复后测试和五宽度浏览器证据见 PROGRESS-staging-gate-red-20260923.md。
- 防复发:保留断点白名单测试;360/375/390/414/480 宽度核对溢出,376~480 若出现可见变化须停止报告。
- 相关记录:BUG-697、BUG-1002;TASK-staging-gate-red-20260923.md。
- 复发自:BUG-697 断点收敛合同仍在,红色门禁下未逐项辨别新增失败。
- 修复版本:本轮工作树,尚未部署。
## BUG-1013 | 聊天人物选择器恢复焦点可能滚动面板
- 状态:investigating(定向及隔离浏览器/变异验证通过,待新门禁确认)
- 首次发现:2026-09-23
- 最近更新:2026-09-23
- 影响面:普通聊天人物选择器关闭后的焦点与面板滚动。
- 用户现象:恢复顶栏入口焦点时浏览器可能自动滚动聊天面板;scroll guard 合同失败。
- 触发条件:选择器关闭或 Escape 后调用 triggerRef.current.focus。
- 根因:2a3013f2 两处新增 focus() 未携带 preventScroll,旧滚动守卫仍有效但失败被已有红色淹没。
- 修复:两处均显式 focus({ preventScroll: true }),不改变焦点落点或选择人物的业务。
- 验证:修复前真实 run 2856 / job 6345 证实失败;修复后 guard、焦点回归与浏览器证据见本轮 PROGRESS。
- 防复发:保留全组件 scroll guard,不增加豁免;picker 两条恢复路径都必须带 preventScroll。
- 相关记录:BUG-1000、BUG-1002;TASK-staging-gate-red-20260923.md。
- 复发自:聊天面板既有 focus 防滚动合同的新增组件遗漏。
- 修复版本:本轮工作树,尚未部署。
## BUG-1014 | 输入框源码合同未跟上已删除人物的发送限制
- 状态:investigating(定向及隔离浏览器/变异验证通过,待新门禁确认)
- 首次发现:2026-09-23
- 最近更新:2026-09-23
- 影响面:chat-composer-queue 源码合同,不是输入框业务回归。
- 用户现象:源码正则仍期待旧表达式,门禁失败;生成中可输入的业务性质仍成立。
- 触发条件:BUG-1000 在 inputDisabled 加入 subjectDeleted || 后运行旧合同。
- 根因:合同固定整个旧串,没有同步合理的已删除资料限制,且未独立检查禁止生成态禁用的性质。
- 修复:只更新测试期望,保留 page.tsx 业务;新增 inputDisabled 不含 isLoading/cancellationPending 的检查。
- 验证:修复前真实 run 2856 / job 6345 证实失败;正常/变异验证及原值、新值、原因见本轮 PROGRESS。
- 防复发:原测试名和断言目的保留;临时注入 isLoading || 时新检查必须失败,不通过修改业务迎合源码测试。
- 相关记录:BUG-1000、BUG-1002;TASK-staging-gate-red-20260923.md。
- 复发自:无;源码合同落后于授权业务改动。
- 修复版本:本轮工作树,尚未部署。
@@ -0,0 +1,55 @@
# PROGRESS-staging-gate-red-20260923
## 基线与授权
- 用户要求执行已推到 staging 的修复单;范围为 H1~H5,包含推送后读取 Gitea 门禁,不包含 BUG-1011 修复、workflow、DNS 或 main。
- fetch 后实际基线 `93cd01dbf9631557d747ea04966c963e3a1fc2dc`;独立工作树 `.worktrees/staging-gate-red-20260923`,分支 `codex/staging-gate-red-20260923`。
- 开工核对最大 Bug 编号为 BUG-1011,本单使用预留的 BUG-1012~1014。
- 基线全量测试在既有干净 `a12f2c0d` 工作树运行:已核对到本轮基线的差异仅为五个文档文件,没有产品或测试代码差异。Node 22.23.2。新树独立复制同一锁文件依赖,不安装或升级依赖,不使用链接依赖。
- 不读受保护 pending packets,不运行跨库 quick/隐私扫描,不清理其他会话 Docker 网络,不借用登录账号。此次是纯前端与测试修复,沿用已读预检台账及本轮 fetch/远端验证,不把未运行的综合预检写成通过。
## 修复前真实门禁证据
使用用户已配置并授权的 Gitea token,仅在请求头内使用,不输出或落盘。实际 API:`a12f2c0d` 对应 run **2856**(run_number 1451)、validate job **6345**,不是任务书所写 run 6294。publish job 6346 为 skipped。
| 项 | Linux 门禁实测 |
| --- | --- |
| Node 测试 | 3,760 tests / 3,756 pass / 4 fail |
| 失败 1 | `generating does not disable the textarea; Enter queues instead of dropping`(H3) |
| 失败 2 | `the guard covers every component that renders inside the panel today`(H2) |
| 失败 3 | `personal report sections enforce owner-read RLS and service-owned durable transitions`(BUG-1011,另单) |
| 失败 4 | `CSS width breakpoints stay on the published allowlist`(H1) |
B 类工具相关测试不能依据诊断机推断:已实际读取该 job 日志,其余测试均通过,包括 health deployment、工作流、身份集成、管理数据库和其他数据库测试;仅上述四条失败。修复后的新 run 须另验,旧 run 不能充当本轮成功证据。
## 实现与断言三栏
H1~H3 已定稿。`page.tsx` 业务、断点白名单、scroll guard 豁免、postgres-fixture 和 workflow 均未修改。
| 原值 | 新值 | 原因 |
| --- | --- | --- |
| `inputDisabled={sessionMessagesLoading || rectificationSurfaceOpen || activeRectificationSession || (!profileComplete && ...)}` 的整串正则 | 开头增加既有业务的 `subjectDeleted ||` | BUG-1000 已删除资料的历史会话只读;本单只修合同,不改行为 |
| picker 焦点合同匹配 `triggerRef.current?.focus()` | 匹配 `focus({ preventScroll: true })` | 仍回到同一按钮,只禁止浏览器连带滚动 |
| starter-entry-soften 合同要求防溢出规则在375px媒体块 | 同一规则要求在480px媒体块 | H1明确合并断点,首次全量发现遗漏的相关源码合同;不删测试、不改按钮/悬停/3px焦点等其他断言 |
新增两个测试名称:picker 两条关闭路径的焦点恢复;所有 ChatComposer inputDisabled 表达式不含 isLoading/cancellationPending。后者使用 TypeScript AST 读取完整 JSX 表达式,不受变量顺序、换行或嵌套花括号影响。原测试名和其他断言保留。
执行代理隔离变异:正常表达式通过;isLoading/cancellationPending 前缀及换行、嵌套对象后变量等五种变异均被新断言拒绝。没有改共享 page.tsx,其 SHA256 前后不变。
## 本轮验证
| 检查 | 状态 |
| --- | --- |
| 同机全量基线 | Node22:3,704 tests / 3,613 pass / 91 fail;Windows 环境,不冒充 Linux 门禁 |
| H1~H3 定向 / 变异 | 主会话最终独立33/33通过(含Home增长、首屏与starter-entry-soften合同);执行代理最终五文件26/26,五种隔离变异均变红 |
| 五宽度真实组件 Chrome / 焦点 | Chrome153 共145项通过、0运行异常;360/375/390/414/480,两种入口模式共10场景无溢出;390/414/480共6对基线几何与整页PNG字节完全相同。Escape/换人/重选/外点四条路径均返回触发按钮,对话滚动420→420,panel/document/window均0→0。仅隔离组件,不是登录E2E |
| TypeScript / lint / build | tsc0错,lint0error/119既有warning;webpack与构建内tsc通过,页面数据阶段因 Windows SKILL.md symlink EPERM 退出1,Static/gzip未完成,不能记构建通过 |
| 修复版首次全量名称对比 | 3,706 tests / 3,617 pass / 89 fail;名称消失0、新增2均通过。原三项转绿,88项旧失败完整诊断归一后逐项一致;新增1失败为 starter-entry-soften 仍要求375px,属于H1漏同步合同,待补修复验 |
| 修复版最终全量名称对比 | 3,706 tests / 3,618 pass / 88 fail;相对基线名称消失0、增加2均通过,原三项转绿、新失败0,88项完整失败诊断归一后逐项一致。相对首次候选仅starter-entry-soften转绿,其余不变;cancelled/skipped/todo均0 |
| 提交 / staging / 新 Gitea run | 本轮代码与记录将按修复单授权一并提交并快进推送,随后记录新run真实结果,不预写绿灯 |
本轮失败、环境缺口和部署状态将按实际证据更新,不预写门禁全绿。
隐私检查限定本轮11个变更文件,调用既有仓库 marker 规则,0命中;未加载可选本地规则,没有读取保护目录,也不是全库隐私门通过。完整门以 Gitea 新 run 为准。
浏览器证据位于忽略目录 `scratch/browser-h1-h2-20260923-acceptance/`,含可复跑 `verify.mjs`、`browser-evidence.json`、24张截图;不提交浏览器 profile 或临时资产。
+1 -1
View File
@@ -215,7 +215,7 @@
| 任务书 | 进度 | 主题 | 状态 | 落点 |
| --- | --- | --- | --- | --- |
| `TASK-staging-gate-red-20260923.md` | — | **staging 门禁自 09-22 起持续红、两天无新部署(BUG-1012~1014)**:Node 22 逐条复现并二分到提交:`45ec4617` 新增 375px 断点不在白名单;`2a3013f2`(BUG-1000 人物选择器)两处 `focus()` 未带 `preventScroll`、`inputDisabled` 多了 `subjectDeleted` 而源码合同未跟上(行为正确、合同滞后)。决策:375 并入既有空 480 块、不扩白名单;focus 带 preventScroll;合同加三栏并改守「不含 isLoading」。其余本机失败为缺 Docker / rsync,须读门禁日志确认。与 BUG-1011 单文件不重叠可并行 | **待领取** | — |
| `TASK-staging-gate-red-20260923.md` | `PROGRESS-staging-gate-red-20260923.md` | **staging 门禁修复(BUG-1012~1014)**:375px 并入 480px;人物选择器恢复焦点禁止滚动;输入框合同跟上资料删除限制并独立守住生成态可输入。修复后须读真实 Gitea 门禁,BUG-1011 另单 | **执行中** | codex/staging-gate-red-20260923 |
| `TASK-repo-hygiene-20260903.md` | `PROGRESS-repo-hygiene-20260903.md` | 岁差默认 Raman + 用户设置可选、参考集锁口径、发布门本地可复现、注册表白名单、仓库地址、早期日志搬家、远端分支清理 | 已验收(带修复单) | `b6a70aa7`、`2415e751`、`01a45363`(BUG-511);验收结论见修复单附录 |
| `TASK-repo-hygiene-fix-20260903.md` | `PROGRESS-repo-hygiene-fix-20260903.md` | Gulika 全局岁差泄漏(P1)、设置类名无样式、提示语对齐校正现状、剩余 lahiri 字面量、测试不写仓库 | 已验收 | `027e4b08`、`c1e3f32a`(BUG-512/513);Gulika 泄漏实验已复核为不泄漏,全量 pytest 后仓库干净 |