11 KiB
11 KiB
title, task_id, status, created, updated, owner, task_type, task_tier, policy_revision, branch, worktree, base_dev_sha, write_scope, allowed_environments, head_sha, mutex, review_state, integration_state, deployment, cleanup, cleanup_owner, cleanup_trigger, remote_sync
| title | task_id | status | created | updated | owner | task_type | task_tier | policy_revision | branch | worktree | base_dev_sha | write_scope | allowed_environments | head_sha | mutex | review_state | integration_state | deployment | cleanup | cleanup_owner | cleanup_trigger | remote_sync | ||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 前端 demo fallback 在真实 dev 环境产生 404/403 | frontend-demo-fallback-2026-09-27-r2 | done | 2026-09-27 | 2026-09-27 | pi | implementation | small | agent-governance-2026-09-21-r1 @ dev 56928ac206 |
fix/frontend-demo-fallback-2026-09-27 | .worktrees/frontend-demo-fallback-2026-09-27 | 56928ac206 |
|
|
db038aa7a7 |
web-chat-fallback | not_required | merged | passed | done | 独立集成/维护执行者 | owner 退出且 dev 合入+验收证据齐备 | not_requested |
前端 demo fallback 在真实 dev 环境产生 404/403
用户目标与授权
- 用户目标/授权来源:用户报告 dev 页面(frp-mix.com:58880)登录后控制台 7 个 API 404/403;会话中明确授权"按照规范进行修复,测试完成后合入 dev,清理 worktree"。
- 交付终点:修复合入 dev、dev 实际运行验证通过、worktree 清理。
- 禁止项:不 push 远端;不动 test/main;不改后端(本 bug 根因在前端 fallback)。
- 例外:无。
问题事实与根因(2026-09-27 排查)
- 现象:登录后首屏
GET /api/v1/projects/1、/projects/1/settings、/chat/messages/window|categories|dates|unread?session_id=sess-001404;/intent-plans/active?project_id=1403。 - 链路核实:frp-mix.com:58880 → vite dev :3100(proxy /api → 127.0.0.1:8080)→
bin/agent-server(ENV=dev,2026-09-26 构建/启动,裸进程非 compose)。后端路由全部存在。 - 数据核实(dev PG :5433 只读):
projects20 行无 id=1;project_members无 project 1 成员;chat_sessions80 行无sess-001;user_id=4=系统管理员(真实登录用户)。 - 根因:demo seeds 关闭模式(vite 未设
VITE_ENABLE_DEMO_SEEDS,后端SEED_DEMO_USERS=false)下,前端残留 demo 假设硬编码:web/src/App.tsx:138loadActiveSessionId('sess-001')——无本地会话时激活不存在的 demo 会话;web/src/App.tsx:206currentProjectIdfallback1——找不到会话项目时默认不存在的项目 1。
- 为何防护未拦:
storage.tslegacy 清理只过滤 messages 的 legacy sessionId(:121),不清activeSessionId;purgeDemoSeedsFromLocalStorage清 localStorage 但 fallback 常量会再生成假请求。 - 状态码差异属既有设计:
projects/:id对"不存在或无权限"统一 404;intent-plans/active走 authorizer 映射 403。 - 功能影响:新登录用户首屏噪音 + chat 回退本地缓存;无数据损坏证据。
同类排查
- grep 全前端:
sess-001残留仅 App.tsx:138 一处(storage.ts:121 为正确防御);projectId fallback1仅 App.tsx:206 一处。 - 观察不扩大范围:
App.tsxactiveDocId fallback 的doc-001/5201/3 为 demo 残留,但仅影响本地文档选择、不发 API 请求,不属于本 bug(控制台 404 均为 API 请求);记录待后续清理。 - ISSUES.md 无同类记录(检索 404/demo 残留/purge 无命中)。
相关问题与经验
- issue_ids:本次新增 ISSUE-20260927-demo-fallback(登记于 ISSUES.md)。
- 开工检索:
404 fallback、sess-001、demo 残留,lessons 无命中;采纳验证契约"问题修复回归范围"节。 - 收口经验:见闭环更新(ISSUES.md + 本文档验证节)。
修复方案(A:改共用 fallback 机制)
App.tsx:138loadActiveSessionId('sess-001')→loadActiveSessionId():demo 开启时仍取NEUROPULSE_ACTIVE_SESSION_ID,关闭时为''(disabled 模式导出空串)。App.tsx:203-208currentProjectIdfallback1→0,注释同步。- 不需新增空态分支:
chatBlockedNoProject(App.tsx:249)已含currentProjectId <= 0,ChatColumn 渲染"请先创建或加入项目后再开始对话";会话纠正 effect(App.tsx:268-277)在可见会话出现时自动恢复 activeSessionId。 - 下游 guard 已核(空 sessionId/projectId=0 不发请求):getProject/settings/lineage effect(:397,:421)、useChatWindow(:120)、useUnreadMarks(fetchUnread 顶部)、categories/dates effect(:1037)、intent-plans effect(:1060)。
步骤与验收
- 根因与同类排查 — 本文档上文。
- 实施修复 — App.tsx 两处改动(:138 fallback 去常量、:206 projectId fallback 0)。
web/npm test、npm run build— 全绿(含 demo on/off 双模式构建)。- 真实浏览器验证 — 修复前 9 假请求复现 / 修复后 0(author+member 双账号);老用户回归无新增 404/403。
- 合入 dev — integrate prepare/validate/integrate 规范流程;dev
56928ac2→0de657f0(--no-ff,first parent=D)。 - dev 实际运行验证 — 主目录 vite :3100(frp 用户入口同一 server)热载新代码,空 storage 登录 phantom=0、404/403=0、工作台正常。
- 清理 worktree、收口 — 详见收口节。
验证与证据
验证日期 2026-09-27;被测代码:worktree fix/frontend-demo-fallback-2026-09-27(基准 dev 56928ac2 + 本修复);环境:本机 dev 后端 127.0.0.1:8080(ENV=dev,agent-server 裸进程)+ 独立 vite :3101(worktree 代码,proxy 同源配置)。浏览器:Playwright chromium headless(brew 用户态补齐运行库);账号:dev 本地审计 e2e 账号(凭证不入库,来源 .doc/test-reports/assets/2026-09-26-full-system-browser-e2e/audit-login-credentials.md)。
| 范围 | 命令与环境 | 预期 | 实际 / 判定 | 证据 |
|---|---|---|---|---|
| 前端单测 | npm test(worktree,node_modules 链接主目录) |
全绿 | PASS:tsx 512 pass/0 fail;vitest 34 pass/0 fail | 控制台输出(本节记录) |
| 前端构建(demo off) | npm run build |
成功 | PASS:built 无错误,66 组产物预压缩 | 控制台输出 |
| 前端构建(demo on) | VITE_ENABLE_DEMO_SEEDS=true npm run build |
成功(alias 切换不破坏类型) | PASS:✓ built in 9.40s | 控制台输出 |
| 原例复现(修复前对照) | 空 localStorage 登录主目录 :3100(旧代码) | 复现假请求 | 复现:9 个 phantom(projects/1×4→403、sess-001×4→404、intent-plans 403);与用户报告一致 | Network 抓取清单(下附) |
| 原例修复(修复后) | 空 localStorage 登录 worktree :3101(新代码) | 零假请求 | PASS:phantom=0,404/403=0,工作台正常渲染,84 个真实 API 全 2xx | 同上 |
| 同类变体(第二角色) | member 账号同样流程 :3101 | 零假请求 | PASS:phantom=0,404/403=0,83 API 全 2xx | 同上 |
| 正常行为回归(老用户) | 同一 author 账号在 :3101 登录后真实会话/项目加载 | 不受损 | PASS:会话纠冀 effect 选真实会话,项目/文档/血缘 API 全 2xx | 同上 |
| 边界:demo enabled fallback | 代码审查 loadActiveSessionId() 无参路径 |
demo 开启时仍回退 NEUROPULSE_ACTIVE_SESSION_ID | PASS:`fallback |
修复前对照抓取(:3100,旧代码,author 账号):
phantom: /api/v1/projects/1, /projects/1/settings, /projects/1/lineage,
/projects/1/documents?category=workflow, /chat/messages/window?session_id=sess-001&days=7,
/chat/unread?session_id=sess-001&user_id=60, /chat/categories?session_id=sess-001,
/chat/dates?session_id=sess-001, /intent-plans/active?project_id=1&session_id=sess-001
→ 403×5(project 1 无权限), 404×4(sess-001 不存在)
修复后(:3101,新代码,同账号 + member 变体):phantom=0;404/403=0;workbench 正常渲染。
注:临时验证脚本未入库(/tmp 与 web/ 下临时文件已删);worktree 独立 vite :3101 已停。用户报障中 projects/1→404 与本地复现 →403 的差异仅因报障账号(user 4 系统管理员)对该项目访问落在本项目不存在分支,两状态码均属既有「不存在或无权限」映射,非另改行为。
经验小结
- 触发条件:前端存在 demo/生产双模式(构建期 alias 切换)且模式专属常量进入运行时 fallback 路径。
- 机制:fallback 优先级高于模式开关清理逻辑;purge/legacy 清理只处理 storage 残留,无法阻止常量重新生成假 ID,首屏即对真实后端发请求。
- 应做检查:关闭模式的默认值必须是空值/由服务端数据驱动,不得硬编码业务对象 ID;模式常量 grep 其在非模式代码(App/入口/hooks)的引用;新用户首屏用空 storage 真实浏览器验证 Network。
- 错误做法与原因:只加 storage 清理不清理 fallback 常量(本例现状);只验证 demo 开启路径。
- 验证方法:修复前后同流程对照(本任务 before 9/after 0)+ 双模式构建 + 第二角色变体。
- 适用边界:前端双模式常量;同类见 App.tsx activeDocId 的 doc-001/5201/3 残留(仅本地选择无 API 请求,待后续清理)。
- 独立 lesson 文件待后续覆盖
.doc/ops/lessons/scope 的任务补登;本节为可检索替代。
收口与交接
- 剩余工作:无(授权范围验收全部满足)。后续可选项:activeDocId 的 doc-001/5201/3 本地选择残留(无 API 请求,非本 bug);独立 lesson 文件补登(需覆盖 lessons/ scope 的任务)。
- 状态分别记录:
- 本地提交:
db038aa7(任务分支 fix/frontend-demo-fallback-2026-09-27)+ 本收口提交。 - dev 集成:merged,dev
0de657f0(validate 收据 run 85420f37-2e99-4c9b-b72c-277d7203efe9,SHA0de657f0)。 - 部署制品:dev 前端为主目录 vite dev server(热载,无镜像制品);后端二进制未变更(纯前端修复)。
- 远端:not_requested(用户未要求 push;本地 dev 前进,origin/dev 未动)。
- cleanup:任务与 integrate 两个 worktree 均按规范 remove + 分支删除。
- 本地提交:
- 本次影响:App.tsx 两处 fallback;新登录用户首屏不再发 9 个假请求;demo 开启构建不受影响。
相关链接
- ISSUES.md 新增条目:ISSUE-20260927-demo-fallback。