Files
2026Technology-Competition/docs/superpowers/plans/2026-09-12-sidebar-project-tree.md
T

6.1 KiB
Raw Blame History

侧边栏项目树 + 消息区对齐 + 空态清理 — 实施计划

配套需求:用户 7 条前端优化(侧边栏信息架构重构 + 气泡对齐 + 空态清理) 目标文件:src/genesis/server/static/{chat.html,chat.css,chat.js,chat_state.js} 前端无框架、无构建;后端零改动。

已确认决策

  • D1 气泡对齐到文本输入框:左 16px;右留发送按钮宽度(40+10=50px);删除 assistant 头像点
  • D2 点击侧边栏项目名 = 选中该项目(设为当前项目)+ 展开/收起
  • D3 抽屉左侧项目列表保留(仅删除「+新建项目」项)。
  • D4 侧边栏折叠态隐藏「项目/其他会话」两段
  • D5 req2 的「提示语及提示词」= 空态主标题 + 建议卡,发送后一并清除。

目标侧边栏

[G Genesis 概要设计书做成Agent]
[+ 新会话]
项目                      +        ← 仅"+"hover「追加项目」
  ▾ 股票系统             ⚙        ← 展开显示其会话;⚙ hover「配置」
       · 需求A
       · 需求B
  ▾ 人事系统             ⚙
       · 需求C
其他会话
       · 需求Dproject=""

Task 1chat_state.js 分组纯函数 + node 测试

  • 新增 groupSessionsByProject(sessions){ byProject: { "<name>": [s...] }, other: [s...] }project 为空者入 other)。
  • tests/test_chat_state.js 增加断言:空项目归 other;两项目分别归组。
  • 运行 node --test tests/test_chat_state.js

Task 2chat.html 侧边栏结构 + 移除底部新建项目按钮

  • 删除 <h2>会话历史</h2><div id="session-list"></div>
  • 新增 #sec-projectsside-head:标题「项目」+ #side-add-project「+」)与 #project-tree
  • 新增 #sec-others(标题「其他会话」)与 #other-session-list
  • 删除 #tb-newproject 按钮。

Task 3chat.css 侧边栏树 + 消息区对齐 + 折叠态

  • 新增 .side-section/.side-head/.side-title/.side-add/.proj-group/.proj-row/.proj-caret/.proj-name/.proj-config/.proj-sessions 样式;嵌套 .sess 缩进。
  • 折叠态:#sidebar.collapsed .side-section { display: none; }
  • 消息区:#chat { max-width: none; margin: 0; padding: var(--sp-6) var(--sp-4); }.msg { padding-right: 50px; }.msg .bubble { max-width: 100%; }删除 .msg.assistant::before

Task 4chat.js 分组渲染 + 绑定调整 + 空态清理

  • refreshSessions() 改拉全量并按 groupSessionsByProject 分组 → renderProjectTree() + renderOtherSessions()
  • renderSessItem(s)(复用现有会话行逻辑)。
  • renderProjectTree():项目行点击选中+展开/收起(collapsedProjects SetlocalStorage 持久化);openProjectDrawer(name)
  • #side-add-projectopenProjectDrawer(null)(带脏守卫)。
  • renderProjectSwitcher():删除 ps-manage「项目管理(打开抽屉)」项及绑定。
  • renderDrawerList():删除 di-create「+新建项目」项。
  • send():发消息前 chatEl.querySelector('.empty-state')?.remove()
  • 删除 #tb-newproject 绑定。

Task 5:验证与提交

  • node --checknode --testpython -m pytest(≥99%)。
  • 手动核对:气泡对齐、空态清理、项目树/⚙/+、底部无新建项目、未选项目时新会话入「其他会话」。
  • 更新 _AI_USAGE_LOG.md 并提交。

风险

  • #sidebar.collapsed.sess 旧样式成为死代码(无害)。
  • 分组渲染依赖 GET /api/sessions 全量返回(已支持 project 可选)。
  • 若某会话的 project 已从项目列表删除,仍会以其 project 名建组渲染(保证不丢会话)。

评审结论与计划调整(plan-eng-review

采纳的修正

  • F1(正确性,req 5)显式「不选择项目」持久化
    • chat_state.jsautoBindProject(draftProject, projects, explicitNone = false) —— explicitNone 为真时原样返回 draftProject(不移除用户选择);否则维持原自动绑定逻辑。新增 node 断言。
    • chat.js:读写 localStorage['genesis_project_explicit_none']loadProjects() 传入该标记;选任意项目 → 清除标记;选「不选择项目」→ 设标记。保证「无项目选择 → 新会话进『其他会话』」成立。
  • F2UX)打开会话所在分组高亮
    • renderProjectTree():组内任一会话 session_id === sid 时给 .proj-group.has-active(与 .current = 选中项目 区分)。
  • F3DRY)对齐余量单一来源
    • 新增 CSS 变量:--send-size: 40px--composer-gap: 10px--composer-gutter: calc(var(--send-size) + var(--composer-gap))
    • #send { width/height: var(--send-size) }#composer-inner { gap: var(--composer-gap) }.msg { padding-right: var(--composer-gutter) }
  • F6(清理)删除折叠态死样式
    • 移除 #sidebar.collapsed .sess*#sidebar h2 相关规则(折叠态整段隐藏、h2 已不存在)。

接受现状(标注,不改)

  • F4 project 已删的会话以原 project 名成组渲染(不丢会话)。
  • F5 DOM 渲染层无自动化测试;靠纯函数 groupSessionsByProject 断言 + node --check + 手动。
  • F7 项目行沿用 div.onclick(非键盘可达),与会话行一致。
  • F8 refreshSessions 每次拉全量;规模增大时再考虑限制。

受影响任务更新

  • Task 1 追加:autoBindProject 第三参数 + groupSessionsByProject + node 断言。
  • Task 3 追加:--send-size/--composer-gap/--composer-gutter 变量;删除折叠死样式。
  • Task 4 追加:explicit_none 读写与联动;.has-active 渲染。

GSTACK REVIEW REPORT

  • STATUS: DONE_WITH_CONCERNS
  • REVIEWED: docs/superpowers/plans/2026-09-12-sidebar-project-tree.md
  • FINDINGS: F1 正确性(已采纳修复) / F2 UX(已采纳) / F3 DRY(已采纳) / F6 清理(已采纳)F4/F5/F7/F8 接受
  • KEY DECISION: 显式「不选择项目」持久化修复(否则 req 5 不成立)
  • CONCERN: 渲染层无自动化测试(无 DOM harness);折叠态样式清理后需回归核对
  • NEXT: 待用户批准后实施