Files
Jyotisha/docs/tasks/TASK-staging-gate-red-20260923.md
T
Jesse_ChenandClaude Opus 5.5 93cd01dbf9 docs(tasks): brief why the staging gate has been red since 09-22
Staging has not deployed since 1bc6a954. Rerunning the shared frontend
failures under Node 22 splits them in two. Three are real, and each passes on
its parent commit and fails from the commit that introduced it: 45ec4617 adds
a 375px breakpoint outside the allowlist, and 2a3013f2 adds two focus() calls
without preventScroll inside the chat panel and changes inputDisabled without
updating the composer's source contract. The rest fail here only because this
machine has no Docker or rsync; the gate has both, so the executor must read
the gate log rather than infer from local runs.

Privacy scan on this tree before push: zero findings.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017eEAG8HD3mm8gsKXgk8uU8
2026-09-23 16:07:12 +08:00

7.1 KiB
Raw Blame History

TASK-staging-gate-red-20260923 · staging 门禁自 09-22 起持续变红

基线 commit

  • 诊断基线:origin/staging = 88e89e10(2026-09-23)
  • 最后一次部署成功:1bc6a954(2026-09-22 01:14)。此后门禁 run 1445(6d06fca0)、1448(3fed71ab)、2853(f77a1b5a)、2854(原 f968cb21)、6294(a12f2c0d)全部红,staging 两天没有新部署
  • 修复分支:codex/staging-gate-red-20260923,从 origin/staging 起

事故实证

在 88e89e10 上用 Node 22(与门禁同版本)逐文件重跑本机与基线共有的前端失败。分成两类:

A · 代码或合同真问题(3 条,本单修)

每一条都在引入提交的父提交上通过、在引入提交上失败,逐条复现:

测试 父提交 引入提交 失败内容
viewport-breakpoint-contract.test.ts · CSS width breakpoints stay on the published allowlist 92e79642 通过 45ec4617(首页入口边框变轻)失败 globals.css 新增 @media (max-width: 375px),375 不在白名单 480 / 640 / 641 / 767 / 768 / 860 / 1023 / 1024
chat-panel-scroll-guard.test.ts · the guard covers every component that renders inside the panel today 6d06fca0 通过 2a3013f2(BUG-1000 聊天人物选择)失败 chat-profile-picker.tsx 两处 triggerRef.current?.focus() 没带 { preventScroll: true },关闭选择器时会滚动聊天面板
chat-composer-queue.test.ts · generating does not disable the textarea 6d06fca0 通过 2a3013f2 失败 (app)/page.tsx 的 inputDisabled 前面多了 subjectDeleted ||(资料已删除的旧会话阻断发送,BUG-1000 的设计),源码合同的正则没跟上

第三条是合同滞后,不是行为错误:它要守的性质——生成中不得禁用输入框(inputDisabled 里不能有 isLoading)——仍然成立。

B · 本机缺工具,门禁环境有(本单不修,但要在门禁上确认)

测试 本机报错 判断
health-deployment 1 条 子进程 status null(spawnSync docker) 本机无 Docker
staging-backend-workflows 2 条 rsync: command not found 本机无 rsync
model-configuration-security、identity-auth-integration、admin-database 各 1 条,以及全部 database-*.test.ts spawnSync docker ENOENT 本机无 Docker

诊断方看不到门禁日志(Gitea job 日志需要 token,不借用)。B 类在门禁上是否通过,本单执行方必须读门禁日志确认,不得据本机推断。其中 database-personal-report-sections.test.ts 已知会在门禁上失败,见 BUG-1011 与 TASK-report-density-fix2-20260923.md,不在本单。

根因

  1. 两次 09-22 的提交(45ec4617、2a3013f2)落 staging 时门禁已经是红的(BUG-1002 那一组),新增的失败被原有红色淹没,没人逐条比对。
  2. 45ec4617 按"新切点必须先改白名单"本应先过 viewport-breakpoint-contract,但直接加了 375。
  3. 2a3013f2 新组件渲染在聊天面板里,没有按 chat-panel-scroll-guard 的规则给 focus() 带 preventScroll;同一提交改了 inputDisabled 却没更新源码合同。

决策记录

  • 375 断点并入既有 480 断点,不扩白名单。 依据 BUG-697 的收敛口径(宁可合并,不新增切点)。那条规则只把入口按钮行与按钮限制为 max-width: 100%,放到 ≤480 时,376–480px 宽度下只会防止溢出、不会改变不溢出时的样子。globals.css 里 .starter-entry 附近已经有一个空的 @media (max-width: 480px) {},放进去即可。这是 Claude 的常规判断;若执行方实测发现 376–480 出现可见变化,停下来报告,不要改成扩白名单。
  • 选择器的 focus() 一律带 { preventScroll: true }。 触发按钮在顶栏,本来就在视口里,preventScroll 不改变焦点落点,只阻止面板被滚动。
  • 更新 chat-composer-queue 的源码合同,把 subjectDeleted || 写进期望,并按 AGENTS.md §7.3 写三栏说明。同时新增一条断言:inputDisabled 表达式里不含 isLoading 与 cancellationPending,让真正要守的性质不依赖整串正则。

硬红线

  1. 不得删测试、跳过测试或把失败测试标 skip;不得放宽 viewport-breakpoint-contract 白名单;不得给 chat-panel-scroll-guard 加豁免。
  2. 不得改 (app)/page.tsx 的逻辑,本单只改测试合同;Home() 的 useState / useRef 数不得变。
  3. 不得改 .gitea/workflows/**,不得为了过门禁在门禁里跳步骤。
  4. 不得动 tests/helpers/postgres-fixture.ts(属于 TASK-report-density-fix2-20260923.md)。
  5. 测试总数不得低于开工时 origin/staging 的实测。

任务分解

H1 · 375 断点并入 480(BUG-1012)

把 @media (max-width: 375px) 里的两条规则移进 .starter-entry 附近那个空的 @media (max-width: 480px),删掉 375 块。改 UI 的同一提交更新 frontend/DESIGN.md。

验收标准:viewport-breakpoint-contract.test.ts 全过;globals.css 中不再有 375 的宽度断点;在 360 / 375 / 390 / 414 / 480 五个宽度下首页入口按钮不溢出(本机 Chrome 无头截图或 docs/testing/ 清单一条)。

H2 · 人物选择器不滚动面板(BUG-1013)

chat-profile-picker.tsx 的两处 triggerRef.current?.focus() 改为 focus({ preventScroll: true })。

验收标准:chat-panel-scroll-guard.test.ts 全过;选择器关闭后焦点仍回到触发按钮(新增或已有测试覆盖)。

H3 · 输入框合同跟上 BUG-1000(BUG-1014)

更新 chat-composer-queue.test.ts 对 inputDisabled 的期望,加三栏说明;新增"表达式不含 isLoading / cancellationPending"断言。

验收标准:该文件全过;把 isLoading || 临时加进 inputDisabled 时新断言变红(变异验证写进进度记录)。

H4 · 门禁确认(对应 B 类)

修完后推 staging,读门禁 run 日志,把失败测试名单(如有)逐条列进进度记录,并与本单 B 类及 BUG-1011 对照。

验收标准:门禁 run 除 BUG-1011 那一条外无失败;若还有别的失败,列出 run 编号与测试名,写成新的 investigating 记录,不得声称门禁已绿。

H5 · 记录

docs/BUG_HISTORY.md 写 BUG-1012~1014,关联 BUG-1000、BUG-1002、BUG-697;docs/tasks/PROGRESS-staging-gate-red-20260923.md 写三栏说明与门禁证据。

让步顺序

H1、H2、H3 都很小,必须一起做;H4 在推送后做;H5 同一提交。

与其他单的关系

与 TASK-report-density-fix2-20260923.md(BUG-1011)文件不重叠,可以并行。两单都合入后门禁才可能全绿。

开工前置命令

git fetch origin --prune
git status -sb
git worktree add -b codex/staging-gate-red-20260923 .worktrees/staging-gate-red-20260923 origin/staging
# 前端测试用 Node 22;本机 Node 20 下有一批子进程 @/ 别名解析失败的误红

BUG 编号

BUG-1012~1014。开工时核对 docs/BUG_HISTORY.md 最大号(当前 1011)。