Skip to content
This repository was archived by the owner on Sep 2, 2026. It is now read-only.

docs: 新增 fusion-api 与 fusion-ui 合并为 monorepo 的实施计划 - #83

Merged
HyxiaoGe merged 10 commits into
masterfrom
claude/requirement-assessment-qkkonb
Aug 31, 2026
Merged

HyxiaoGe merged 10 commits into
masterfrom
claude/requirement-assessment-qkkonb

Conversation

@HyxiaoGe

@HyxiaoGe HyxiaoGe commented Aug 31, 2026 •

Copy link
Copy Markdown
Owner

概述

新增一份实施计划文档,评估把 fusion-api 与 fusion-ui 合并为单一仓库的可行性并给出分阶段方案。

只新增一个文件,不含任何代码改动:

docs/implementation-plans/2026-08-31-monorepo-merge.md

目标仓库为新建的 HyxiaoGe/fusion,两个应用分别下沉到 apps/api 与 apps/ui。

四轮评审(9 + 6 + 5 + #84 的 2 条)已全部受理,均写入 Task / Global Constraints / 验收 / 回退表本身,并附实测证据。逐条核实见 第一轮 · 第二轮 · 第三轮 回复与文档末尾的「评审修订记录」。

基线

fusion-api@43cee73 / fusion-ui@77b7fc2(2026-08-31 复核)。初版基于已过期的 c5b0775,现已 merge master 并重算全部数字。

核心结论

代码层零耦合,成本全在流水线。 516 个 .py(699 文件)与 524 个 .ts/.tsx(636 文件),交叉计数为 0。无共享包、无 workspace 依赖、无交叉 import。两边 .git 分别 5.5M / 2.8M,merge --allow-unrelated-histories 即可保留完整历史。

deploy.yml 的体量是内联 shell,不是 YAML 编排。 全文 2563 行中 deploy-dev 单个 job 占 2339 行(L189–L2527),其中四个步骤合计 1757 行(占该 job 的 75%):

步骤 行数
Pull and restart fusion-api 693
Roll back failed deployment 476
Capture current deployment for rollback 307
Verify health 281

这套逻辑当前不可本地执行、不可单测,唯一验证方式是向 master 推送。

两条流水线的形状已被手工写了两遍。 逐字相同的步骤名 14 个(去重后),另有 3 对同职能不同名。

目录下沉不是纯路径替换。 path inventory 三类:

  • A 类 宿主机持久化状态 —— 5 处 cd ~/project/fusion、4 处 ./fusion-api/storage/files bind mount、${HOME}/project/fusion/.env、cost-sync systemd unit 的 checkout 耦合。严重程度取决于宿主机 .env 中 STORAGE_BACKEND 的实际取值(local/minio/oss),Task 0 判定
  • B 类 测试硬读根 .github —— API 侧 5 个文件 25 处(含一处 CWD 相对,失效方式不同),UI 侧 12 处且 filesUnder() 会枚举整个 workflows 目录
  • C 类 Action 与构建上下文 —— 本地 composite action、release-safety contract、Dockerfile context、cache-dependency-path

方案要点

六个 Task,顺序本身是方案的一部分:

Task 内容
0 新仓基建与恢复点:非 check 类保护复制、新增 runner 并加应用标签、secrets 重注入、平台使用状态清点、bundle + 未提交资产归档、STORAGE_BACKEND 判定
1 历史合并与目录下沉;产出 _deploy-api.yml / _deploy-ui.yml 两份 workflow_call 外壳;changes/gate 与回滚契约。只验 PR CI 与镜像构建,不做发布
2 受控 cutover:宿主机状态迁出 checkout + 6 步 runbook,唯一改变生产行为的一步
3 抽 shell 到 ops/deploy/,配 fixture/dry-run/contract test
4 参数化 _deploy-app.yml、per-app 发布台账语义、required context 迁移、平台绑定收尾
5 文档台账合并、平台元数据边界、旧仓归档

关键约束:

  • 搬迁、切换、重写分三阶段,不得合并 —— 混做则故障无法二分定位
  • 旧仓在最终验收前保持完整发布与回滚能力,runner 保留至 Task 5
  • 宿主机持久化状态必须迁出 checkout 树:上传文件 ~/.local/share/fusion/api/storage/files、运行时配置 ~/.config/fusion/runtime.env
  • 不使用 event-level paths: —— 被跳过的 workflow 不产出结论会使 required check 永久 Pending,且 changed-files 有 300 文件上限而首次搬迁涉及 1300+ 文件
  • 跨应用顺序由顶层 orchestrator DAG 保证,concurrency 只防并发不承担顺序语义
  • flock 范围限于新仓与宿主机操作(实测两旧仓 workflow 的 flock 调用数为 0);跨仓互斥由 Task 2 的 drain 门禁承担
  • disable 不等于停止 —— 每次 enable/disable 切换前须 drain 至三仓在途 run 归零
  • secrets 不可复制,一律从原始凭据源重新注入,不可得则轮换
  • 真实发布与回滚只在 Task 边界执行

文档中显式排除的范围

  • 不改任何业务代码。唯一例外是 apps/ui/src/scripts/buildAndDeployWorkflow.test.ts(B 类,需限定扫描范围)
  • 不引入 npm/pnpm workspace、Nx、Turborepo(零共享代码,工具链只增复杂度)
  • 不合并 docker-compose.yml(api 侧有 middleware/litellm_net/flyai 三个网络)
  • 不把两应用镜像并入同一个 ACR repository —— 已天然区分,初版的 <app>-<sha> tag 方案已撤销
  • 不迁移旧仓 Issues 与 PR 历史
  • OpenAPI 契约同步另开 plan

与 #84 的配套调整(7df9b1c)

#84 清理了已弃用的 superpowers 遗留文档并确立 docs/implementation-plans/ 为插件无关的落位目录。本 PR 相应:

⚠️ 合并本 PR 会触发一次真实发布

deploy.yml 为 on.push.branches: [master] 且无 paths 过滤。即便本 PR 只新增文档,合并仍会触发 publish(构建推 ACR)+ deploy-dev(alembic 迁移 + 容器重启)。文档中已单列「关于本 PR 自身的合并边界」章节。

说明

  • 文档中所有数字均来自对两仓当前状态的实测,可复核
  • 第一轮标注为「未独立核实」的 runner / Environment / secrets 分层信息,已由 owner 在第二轮通过 GitHub API 复核确认属实,标注已结清
  • 本计划整体按"有真实生产环境"校准。若实际部署目标仅为开发服务器,Task 2 的 6 步 runbook、drain 门禁与回退演练可相应减负 —— 该校准调整尚未纳入本文档

🤖 Generated with Claude Code

https://claude.ai/code/session_01QR4stz9sbfVRS6xgriQ9kQ

评估两仓合并可行性并给出分阶段方案。目标为新建 fusion 仓库,
两个应用分别下沉到 apps/api 与 apps/ui。

核心结论:代码层零耦合(505 个 .py 与 522 个 .ts/.tsx 无交集),
成本集中在约 3600 行的发布流水线。deploy.yml 的 2553 行中
deploy-dev 单 job 占 2339 行,其中四个步骤的内联 shell 合计
1757 行,当前不可本地执行也不可单测。

方案分五个 Task:先搬迁(CI 只改路径并加 paths 过滤),
再把 shell 抽到 ops/deploy 使其可测,之后才做参数化合并与
可复用 workflow。搬迁与重写不得在同一次变更内完成,
以保证发布故障可二分定位。同时修正合并后
"回滚到 SHA X" 语义失效的问题,镜像 tag 改为 <app>-<sha>。

Co-Authored-By: Claude <noreply@anthropic.com>
@chatgpt-codex-connector

Copy link
Copy Markdown

Codex usage limits have been reached for code reviews. Please check with the admins of this repo to increase the limits by adding credits.
Credits must be used to enable repository wide code reviews.

@HyxiaoGe

Copy link
Copy Markdown
Owner Author

我支持把 fusion-api 与 fusion-ui 合并成 monorepo,apps/api + apps/ui、新建 fusion 仓库、初期不引入 Nx/Turborepo,以及“搬迁与流水线重写分阶段”这些方向都合理。

但这份 plan 当前还不能作为执行合同,建议 Claude Code 按下面问题逐项复核并更新后再合并:

P0:当前会阻断迁移或回退的问题

  1. 计划基线已经过期

    PR commit 的父提交是 fusion-api@c5b0775,当前 master 是 43cee73,中间相差 57 个提交,PR 当前也是 BEHIND。例如文档写 deploy.yml 2553 行,当前已经是 2563 行,而且这期间 .github/scripts/*、workflow、Skills/runtime 等迁移面都有变化。

    请先 rebase/merge 当前 master,并基于 fusion-api@43cee73、fusion-ui@77b7fc2 重新生成文件数、同名文件、workflow 体量、路径依赖与 Skills 清单。当前 PR CI 通过只能证明文档提交没有破坏现有容器校验,不能证明迁移方案成立。

  2. Task 1 与 Task 4 的顺序互相矛盾

    Task 1 要求新仓库完成真实发布和回滚,但新仓库的 secrets、Environment、branch policy、self-hosted runner 到 Task 4 才迁移。没有这些配置,Task 1 的验收无法执行。

    当前实际状态是:

    • 两仓各有独立的 repo-scoped Linux/Windows runner;
    • runner 标签只有通用的 self-hosted/Linux/Windows/X64;
    • dev Environment 仅允许 master;
    • secrets/variables 分布在 repo 与 Environment 两层。

    直接把现有 runner 重新注册到新仓库,会让旧仓库失去发布/回退能力;把四个 runner 都注册进新仓库但不加应用标签,又会让 job 随机落到 API/UI runner。

    建议新增 Task 0:创建新仓库、复制 Environment 与 branch policy、安装额外 runner 实例或建立可共享 runner,并增加 fusion-api / fusion-ui 专用标签。旧仓 runner 必须保留到最终切换完成。

  3. 跨应用 concurrency 只能互斥,不能保证 API → UI

    两个 workflow 使用同一 concurrency group 可以避免并发,但不能保证跨应用提交一定先发布 API 再发布 UI;GitHub 的 concurrency 等待顺序不等于提交分发顺序,默认还可能替换已有 pending run。

    对同时修改两边的提交,应由一个顶层 orchestrator 建立明确 DAG:detect changes → deploy API → deploy UI。只改一边时才跳过另一边。环境级 concurrency 只负责防并发,不能代替依赖顺序。

  4. PR workflow 直接使用 paths: 会与 required checks 冲突

    GitHub 对被 path filter 跳过的 workflow 不会生成成功结果;如果该 workflow 是 required check,PR 会一直 Pending。

    建议:

    • PR workflow 始终触发;
    • 由首个 changes job 判断 API/UI/shared 路径;
    • API/UI job 使用 if 条件跳过;
    • 最后提供一个始终存在的 required gate;
    • 明确根 .github/**、ops/**、根配置和共享文档分别触发哪一侧或两侧;
    • 不依赖 event-level path filter 处理首次大规模迁移,GitHub changed-files 过滤还有 300 文件上限。
  5. 部署脚本包含真实宿主机路径和持久化数据,不能只改 checkout 工作目录

    当前 API workflow 多处 cd ~/project/fusion,并把 ./fusion-api/storage/files 挂载到容器;LiteLLM systemd unit 也引用 %h/project/fusion/fusion-api。UI workflow 同样在 ~/project/fusion 下生成 compose。

    如果直接换成 apps/api / apps/ui,可能出现:

    • API 上传文件目录变成新的空目录;
    • systemd worker 找不到脚本或 WorkingDirectory;
    • 回滚继续引用旧宿主机路径;
    • 两套 runner 工作目录与持久化目录混在一起。

    请在 plan 中把“代码 checkout 路径”和“宿主机持久化状态路径”拆开,增加数据备份、稳定 data 目录、兼容软链接、systemd 更新与回退验证。这个迁移不能归到普通 workflow 路径替换。

P1:方案论证和影响面需要修正

  1. 镜像 tag 的歧义判断不成立

    API 与 UI 当前使用不同 ACR repository:fusion-api:<sha> 和 fusion-ui:<sha> 已经天然区分应用。monorepo 后同一 SHA 同时对应两个镜像也不歧义。

    真正的问题是 path-filtered 发布后,每个应用的 last deployed SHA 会分叉。建议保留各自 repository 内的 <sha> tag,新增 per-app 发布台账/manifest。只有打算把两个应用放进同一个 ACR repository 时,<app>-<sha> 才有必要。

  2. “目录下沉后相对路径均不变”过于乐观

    当前至少还要处理:

    • UI 本地 Action:.github/actions/windows-docker-build;
    • actions/setup-node 的 cache-dependency-path;
    • 两边 .github/release-safety.yml 与 contract script;
    • API Python 测试直接读取根 .github/workflows/*;
    • UI Vitest 直接读取根 workflow/action;
    • .github/scripts/*;
    • ops/systemd 文件中的旧路径;
    • 文档绝对路径和跨仓相对路径。

    defaults.run.working-directory 只影响 shell step,不会自动修正 uses: ./...、Action cache、测试读取路径或 composite action 的执行上下文。请形成逐项 path inventory 和对应测试。

  3. 每抽一个脚本就向 master 发布并回滚,验证成本和风险过高

    当前 master 是发布通道,不适合作为每个 shell 搬运步骤的唯一测试环境。建议每个脚本先做 fixture/dry-run/contract test,Task 边界再各做一次真实部署与回滚;迁移与切换阶段保留一次完整 API → UI 验收。

  4. 补充 GitHub/平台元数据迁移边界

    Git 历史合并不会迁移 Issues、PR、Actions runs、releases、webhooks、deploy keys、Environment protection、branch rules 等元数据。旧仓归档可以保留这些记录,但 plan 应明确:

    • 哪些复制;
    • 哪些只在旧仓保留;
    • commit message 中 #NN 在新仓的引用语义;
    • 原仓 runner 与平台绑定何时退役;
    • Vercel/Railway 切换与 GitHub Actions dev 切换是否属于同一个 cutover。

建议重排

  • Task 0:更新当前 HEAD、git bundle/恢复点、路径与数据清单、新仓基础设置、额外 runner 和 Environment。
  • Task 1:历史合并与目录下沉,只验证 PR CI 和构建,不改部署行为。
  • Task 2:受控 cutover,顶层 workflow 明确 API → UI,完成真实发布、回滚和旧仓回退。
  • Task 3:抽 shell、补单测。
  • Task 4:参数化 reusable workflow、per-app 发布台账和平台绑定收尾。
  • Task 5:真实验收后归档旧仓。

请 Claude Code 不要只改文字结论,最好对每个 P0 给出当前文件/配置证据、修订后的具体步骤和可执行验收条件。

Claude and others added 2 commits August 31, 2026 09:47
Co-Authored-By: Claude <noreply@anthropic.com>
基线刷新至 fusion-api@43cee73 / fusion-ui@77b7fc2,全部数字重算。
9 条评审意见全部受理,逐条给出核实结果与处理,见文末修订记录。

主要变更:

- 新增 Task 0 承载新仓基建与恢复点,解决原 Task 1 要求真实发布
  但 secrets/runner/Environment 到 Task 4 才就绪的顺序矛盾。采用
  新增 runner 实例加应用标签,旧仓 runner 保留至 Task 5。
- 移除 event-level paths 过滤,改为始终触发加 changes job 加恒定
  required gate,避免被跳过的 workflow 使 required check 永久
  Pending,同时规避 changed-files 300 文件上限。
- 跨应用顺序改由顶层 orchestrator DAG 保证,concurrency 只防并发。
- 新增路径与状态清单,A 类为宿主机持久化状态(5 处 cd
  ~/project/fusion、4 处 storage/files bind mount、cost-sync unit
  的 checkout 耦合),独立为 Task 2 受控 cutover;B/C 类为 25 处
  API 测试与 12 处 UI 测试对根 .github 的硬引用,其中 UI 侧
  filesUnder 会枚举整个 workflows 目录。
- 撤销 <app>-<sha> 镜像 tag 方案,原判断有误:两应用已使用不同
  ACR repository,同 SHA 不产生歧义。改为新增 per-app 发布台账
  解决 last deployed SHA 分叉。
- 真实发布与回滚收敛到 Task 边界,不在每个脚本搬运后执行。
- Task 5 补充平台元数据迁移边界与旧仓退役时点。

Co-Authored-By: Claude <noreply@anthropic.com>

Copy link
Copy Markdown
Owner Author

9 条全部受理并已推送修订(a5ad5b5)。基线已 merge 至 fusion-api@43cee73 / fusion-ui@77b7fc2,全部数字重算。逐条核实结果如下,文档末尾新增「评审修订记录」表可对照。

P0 逐条核实

P0-1 基线过期 — 成立。 实测 c5b0775..43cee73 相差 57 个提交,deploy.yml 2553 → 2563 行。重算后:.py 505 → 516,文件总数 678 → 699,.ts/.tsx 522 → 524。deploy-dev 仍为 2339 行(L189–L2527),四个大步骤 1757 行占比 75% 不变。

P0-2 Task 顺序矛盾 — 成立。 已新增 Task 0 承载新仓基建、Environment/branch policy 复制、runner 准备与 git bundle 恢复点。采纳"新增 runner 实例 + fusion-api/fusion-ui 应用标签"而非迁移旧仓 runner;旧仓四个 runner 保留至 Task 5。Task 1 降级为只验证 PR CI 与镜像构建,不做发布。

P0-3 concurrency 不保证顺序 — 成立。 改为顶层 orchestrator DAG detect changes → deploy API → deploy UI,并写入 Global Constraints:concurrency 只负责防并发,不承担顺序语义。

P0-4 paths: 与 required check 冲突 — 成立。 已移除 event-level paths:,改为始终触发 + changes job 判定 + 应用 job if 跳过 + 末尾恒定 required gate。300 文件上限这点对首次迁移提交尤其致命(单次搬迁涉及 1300+ 文件),已在约束中标注。

P0-5 宿主机路径与持久化数据 — 成立。 实测清单:

位置 内容
deploy.yml L587/L658/L1994、build-and-deploy.yml L282/L391 cd ~/project/fusion(两应用共用同一宿主机目录)
deploy.yml L1036/1042/1077/1206 ./fusion-api/storage/files bind mount(用户上传文件)
deploy.yml L1819 ${HOME}/project/fusion/.env
fusion-litellm-cost-sync.service L5/L6/L13 %h/project/fusion/fusion-api

已独立为 Task 2「受控 cutover」,含备份、稳定 data 目录、软链接兼容、systemd 更新、上传文件切换前后读写校验,以及旧仓回退演练。

这里修正一处我自己的计数:初稿写"3 个 systemd unit 引用 %h/project/fusion/fusion-api"是错的(那条 grep 把 WorkingDirectory 关键字一并计入了)。逐个核实后实际只有 cost-sync 一个耦合仓库 checkout;governance 与 model-management 的 WorkingDirectory 已指向 %h/.local/share/fusion/*-current 暂存目录。

这反而给出了更好的处理方式:仓库内已有解耦范式,Task 2 应把 cost-sync 收敛到同一模式,而不是替换路径字面量。

P1 逐条核实

P1-6 镜像 tag — 成立,我原判断有误。 实测 seanfield/fusion-api 与 seanfield/fusion-ui 已是不同 ACR repository,同 SHA 不产生歧义。已撤销 <app>-<sha> 方案,保留各自 <sha> tag,改为新增 per-app 发布台账解决 last deployed SHA 分叉。

P1-7 相对路径 — 成立,且可量化。 已形成 path inventory 分 A/B/C 三类。B 类实测:

  • API 侧 5 个测试文件共 25 处硬读根 .github。其中 test_knowledge_deploy_config.py:15 用 Path(".github/...") 是 CWD 相对,与其余 ROOT / ".github/..." 的失效方式不同,需分别处理。
  • UI 侧 buildAndDeployWorkflow.test.ts 12 处。补充一个评审未点到的:该文件 L168–L169 通过 filesUnder() 枚举整个 .github/workflows 与 .github/actions 目录并对全部结果做断言 —— 合并到共享根 .github/ 后会扫到 API 侧 workflow 并失败。需改为按应用限定扫描范围,不是路径替换能解决的。

P1-8 每脚本发布回滚 — 成立。 改为每脚本 fixture/dry-run/contract test(覆盖正常路径、SHA 非法、回滚锚点缺失),真实发布与回滚只在 Task 边界执行,Task 3 末尾保留一次完整 API → UI 验收。

P1-9 平台元数据边界 — 成立。 Task 5 已补:复制项(Environment protection、branch rules、secrets/variables、webhooks)、仅旧仓保留项(Issues、PR、Actions run 历史、releases)、#NN 在新仓不再解析且归档说明标注旧仓地址、旧仓 runner 与 workflow 的退役时点。

Task 重排

已采纳你建议的顺序:Task 0 基建 → Task 1 搬迁(只验 CI) → Task 2 受控 cutover → Task 3 抽 shell → Task 4 reusable workflow 与平台绑定 → Task 5 归档。

未独立核实的项

P0-2 中关于 runner 为 repo-scoped、标签仅为通用值、dev Environment 仅允许 master、secrets 分布于 repo 与 Environment 两层 —— 这些我没有通过 API 独立验证,按你的评审陈述采纳。已在文档末尾显式标注,Task 0 第 5 步会在执行时逐项确认实际配置。


Generated by Claude Code

@HyxiaoGe

Copy link
Copy Markdown
Owner Author

第二轮复核结论:a5ad5b5 已经实质吸收第一轮 9 条意见,基线刷新、Task 0、API → UI DAG、恒定 required gate、路径清单、持久化 cutover、镜像 tag 修正和元数据边界都成立。当前 PR 状态 CLEAN,PR container validation 已通过。

另外,文末标记为“未独立核实”的 runner / Environment 信息,我已通过 GitHub API 复核,结论属实:

  • API runners:dev-server-fusion-api、windows-build-api-01;UI runners:dev-server-fusion-ui、windows-build-01;均为 repo-scoped,当前标签只有通用的 self-hosted/Linux/Windows/X64。
  • 两仓 dev Environment 都使用 custom branch policy,当前只允许 master。
  • API repo 层有 LITELLM_MODEL_ADMISSION_WORKER_TOKEN;API/UI 的 ACR、飞书、Pushgateway 等 secrets 位于各自 dev Environment,确实存在 repo/Environment 两层分布。

不过在真正执行前,还需要补齐以下第二轮问题:

P0-10:跨仓 cutover 仍缺少真正的互斥机制与最终状态闭环

GitHub concurrency group 只在同一个 repository 内协调,无法阻止旧 fusion-api、旧 fusion-ui 与新 fusion 的 workflow 同时操作同一台 dev server。新仓 orchestrator 的 concurrency 不能覆盖旧仓发布。

Task 2 应加入明确的 cutover runbook:

  1. 冻结三个仓库的 master 合并和手动发布;
  2. 在宿主机获取跨仓共享的部署锁,例如 flock;
  3. disable 旧仓 workflow,再 enable 新仓 orchestrator;
  4. 发布、验证、记录新仓部署所有权;
  5. 回退演练时先 disable 新仓,再 enable 旧仓;
  6. 旧仓回退验证成功后,必须再次 disable 旧仓、enable 新仓、重新部署新仓当前 SHA,并验证最终镜像 ID、台账与发布所有权都归新仓。

否则当前验收步骤可能以“旧仓重新发布成功”结束,最终运行态实际上停在旧仓版本。

P0-11:GitHub secrets 不能从旧仓直接复制

GitHub API 只能列出 secret 名称和元数据,不能读回 secret 值;Task 0/Task 5 中的“复制 secrets”无法按字面执行。webhook secret 与 deploy key 私钥也有同类问题。

请改成:

  • 通过 API 导出 secret 名称清单;
  • 从密码管理器、部署主机安全配置或原始凭据源向新仓重新注入;
  • 找不到原始值的 secret 必须轮换,不能从旧 workflow 日志或运行环境反向导出;
  • 新仓验证只能检查存在性、权限边界和目标服务连通性,禁止输出 secret 值;
  • Task 0 验收应逐项登记“来源、注入位置、验证结果、是否轮换”。

官方说明:https://docs.github.com/en/rest/actions/secrets

P0-12:持久化状态仍未真正脱离代码 checkout

Task 2 给出的示例 ~/project/fusion/data/api/storage/files 仍位于计划中的新仓 checkout 根 ~/project/fusion 下;${HOME}/project/fusion/.env 也继续与 checkout 混放。这与 Global Constraint 中“持久化状态与代码 checkout 分离”矛盾,后续 clone、清理或目录切换仍可能影响真实数据。

建议固定为仓库外路径,例如:

  • 上传文件:~/.local/share/fusion/api/storage/files
  • 运行时配置:~/.config/fusion/runtime.env
  • systemd release/current:继续使用 ~/.local/share/fusion/*-current
  • 旧路径仅保留有明确退役时间的过渡软链接

验收除单文件下载外,还应记录迁移前后文件数量、总字节数、权限/owner,并对文件清单生成校验摘要。

P0-13:Task 2 与 Task 4 的外部平台 cutover 边界仍需前移判定

Task 2 切换 GitHub Actions 发布权,但 Vercel/Railway root directory 到 Task 4 才修改。如果这些平台当前仍跟踪旧仓,Task 2 完成后整体发布链并未真正切到新仓。

Task 0 应先产出平台使用状态清单:每个 Vercel/Railway 服务是否活跃、跟踪哪个 repo/branch、负责 dev 还是 production、是否自动部署。所有仍活跃且影响运行态的绑定必须纳入 Task 2 的同一次受控 cutover;只有不影响当前运行态或纯重构项才能留在 Task 4。

P0-14:git bundle 不保护当前未提交资产

当前本地 fusion-api 仍有 9 个未跟踪的 plan/spec 文件,git bundle 只包含 refs 与可达 Git objects,不会包含这些未跟踪文件。Task 0 需要增加:

  • 两仓 dirty/untracked 精确清单;
  • 未提交文件的独立可恢复归档与哈希;
  • bundle 使用完整 refs 创建并执行 git bundle verify;
  • bundle 和未提交资产都在临时目录做一次还原验证;
  • 迁移分支只从精确 HEAD 创建,不在旧仓 master 上执行目录下沉提交。

官方格式说明:https://git-scm.com/docs/bundle-format

P1-15:Task 0 不需要无改动地重复真实发布与回滚

Task 0 只新增新仓基础设施,不修改旧仓 runner/workflow。此时要求两个旧仓各真实发布和回滚一次,风险和成本高于收益,也与“不要把 master 当单步试验场”的修订原则不一致。

建议 Task 0 只验证旧 runner 在线、旧 workflow 配置未变、最近成功记录与只读 smoke;真实旧仓回退演练集中到 Task 2 的 cutover runbook 中执行一次。

合并 PR 本身的发布边界

当前 fusion-api/.github/workflows/deploy.yml 对所有 master push 触发。虽然 PR #83 只新增文档,合并仍会触发 API master 发布流水线,不是操作层面的无副作用文档合并。合并时应按一次正式发布处理,并单独记录 CI、部署与运行态结果。

建议 Claude Code 将 P0-10~P0-14 写入 plan 的具体 Task、Global Constraints、验收与回退表,而不是只追加评审记录。修订后这份计划才具备完整的跨仓 cutover 闭环。

6 条意见全部受理,并按要求写入 Task、Global Constraints、验收与
回退表本身,不只追加评审记录。文档 195 行增至 258 行。

主要变更:

- 跨仓互斥:GitHub concurrency 只在单 repository 内协调,无法阻止
  三仓同时操作同一台 dev server。新增宿主机 flock 约束,Task 0
  部署锁文件与获取脚本。
- Cutover 闭环:Task 2 新增 6 步 runbook,第 6 步回切收尾为强制项,
  验镜像 ID、发布台账与部署所有权三项归属新仓,避免验收停在
  旧仓重新发布成功而运行态仍在旧仓。
- Secrets:GitHub API 不能读回 secret 值,复制无法按字面执行。改为
  名称清单导出加原始凭据源重新注入,不可得则轮换,禁止从日志或
  运行环境反向导出,逐项登记来源与验证结果。
- 持久化路径:原方案示例仍位于新仓 checkout 根之下,与自身约束
  矛盾。固定为 ~/.local/share/fusion/api/storage/files 与
  ~/.config/fusion/runtime.env,验收增加文件数、总字节数、
  权限 owner 与校验摘要四项比对。
- 平台绑定判定前移:Task 0 新增平台使用状态清单,活跃且影响运行态
  的绑定并入 Task 2 同一次 cutover,Task 4 收窄为不影响运行态的项。
- 恢复点:git bundle 不含未跟踪文件,Task 0 增加 dirty 清单、
  未提交资产独立归档与哈希、bundle verify 与还原验证。
- Task 0 移除无改动的真实发布与回滚,改为只读核验,旧仓回退演练
  集中到 Task 2 runbook 执行一次。
- 新增本 PR 自身的合并边界章节:deploy.yml 无 paths 过滤,合并将
  触发完整 API 发布,应按一次正式发布处理。

Co-Authored-By: Claude <noreply@anthropic.com>

Copy link
Copy Markdown
Owner Author

6 条全部受理,已推送 5263f57。按你的要求写进 Task、Global Constraints、验收与回退表本身,不只追加评审记录。文档 195 → 258 行。

先谢谢你把 runner / Environment / secrets 那几项复核了 —— 文档里"未独立核实"的标注已结清,runner 名称也补进了 Task 0。

P0-10 跨仓互斥与最终状态闭环 — 成立

concurrency 只在单 repository 内协调这点是对的,我原方案默认了它能跨仓,是错的。

  • Global Constraints 新增两条:宿主机 flock 跨仓互斥(三仓部署入口共用一把锁);cutover 必须以「运行态归属新仓」收尾
  • Task 0 增加锁文件与获取脚本的部署
  • Task 2 新增 6 步 cutover runbook,你说的第 6 步回切收尾标为不可省略,并在正文点明:缺了它验收会停在"旧仓重新发布成功",而运行态实际停在旧仓版本
  • 验收明确要求回切后镜像 ID、发布台账、部署所有权三项均指向新仓

P0-11 secrets 不能复制 — 成立

"复制 secrets"确实无法按字面执行。已改为:名称清单导出(repo 层与 Environment 层分别)→ 从密码管理器/主机安全配置/原始凭据源重新注入 → 原始值不可得的一律轮换 → 新仓只验存在性、权限边界与连通性,禁止输出值 → 逐项登记「来源、注入位置、验证结果、是否轮换」。webhook secret 与 deploy key 私钥同此处理。也写进了 Global Constraints,含"禁止从 workflow 日志或运行环境反向导出"。

P0-12 持久化状态仍在 checkout 内 — 成立,是我方案自相矛盾

初稿示例 ~/project/fusion/data/api/storage/files 就在新仓 checkout 根 ~/project/fusion 之下,和我自己写的 Global Constraint 直接冲突。已按你给的固定为仓库外路径:

内容 目标路径
上传文件 ~/.local/share/fusion/api/storage/files
运行时配置 ~/.config/fusion/runtime.env
systemd release/current ~/.local/share/fusion/*-current

约束措辞也改成"必须迁出 checkout 树,而不只是换一个子目录"。验收增加文件数、总字节数、权限/owner、校验摘要四项比对,单文件下载验证保留为附加项。过渡软链接要求写明退役时间。

P0-13 平台 cutover 边界前移 — 成立

Task 0 新增第 7 步平台使用状态清单(活跃性 / 跟踪 repo 与 branch / dev 还是 production / 是否自动部署),并据此判定每个绑定归 Task 2 还是 Task 4。活跃且影响运行态的并入 Task 2 同一次 cutover;Task 4 收窄为"不影响运行态的项",并注明本 Task 不得留有影响运行态的绑定。

P0-14 bundle 不含未提交资产 — 原理成立,但计数不适用于仓库当前状态

git bundle 只含 refs 与可达 object、不含未跟踪文件,这点对,防护已加:Task 0 增加 dirty/untracked 精确清单、未提交文件独立归档 + 哈希、--all 创建 bundle 并 git bundle verify、两者各做还原验证、迁移分支只从精确 HEAD 创建。

需要说明一处:"9 个未跟踪的 plan/spec 文件"在本会话的 checkout 里不成立。 在 a5ad5b5 上 git status --porcelain --untracked-files=all 返回 0 项,工作区干净。那应该是你本机工作区的状态 —— 由于迁移会从你本机执行,这个防护仍然必要,所以照单采纳了,只是在修订记录里如实标注了核实结果,没有把它写成仓库的当前事实。

P1-15 Task 0 不必重复发布回滚 — 成立

Task 0 不动旧仓 runner/workflow,无改动发布确实风险大于收益。验收改为只读核验(runner 在线、workflow 配置未变、最近成功记录存在),真实旧仓回退演练收敛到 Task 2 runbook 第 5 步执行一次。

本 PR 自身的合并边界 — 已确认并单列成章节

实测 deploy.yml 为 on.push.branches: [master] 且无 paths 过滤,合并会触发 publish(Windows runner 构建推 ACR)+ deploy-dev(alembic 迁移 + 容器重启)。

文档新增「关于本 PR 自身的合并边界」章节,写明这不是操作层面无副作用的文档合并,应按一次正式发布处理,选合适时间窗口并单独记录 CI、部署与运行态结果。

这条也是对我的提醒:我不会去合这个 PR,合并时机由你决定。


Generated by Claude Code

@HyxiaoGe

Copy link
Copy Markdown
Owner Author

第三轮复核结论:5263f57 已完整吸收第二轮 6 条意见,当前 PR 为 CLEAN / MERGEABLE,PR container validation 已通过(3m7s)。跨仓 cutover、secrets 重注入、状态迁出 checkout、平台前置清点、未提交资产保护和本 PR 发布边界都已进入 Task/约束/验收正文。

剩余问题已经收敛,但仍有两个执行级断点和三个需要在实施前锁定的契约:

P0-16:Task 2 orchestrator 在 Task 4 之前没有可调用的部署单元

当前顺序是:

  • Task 1:复制两份 deployment workflow,保持 disabled;
  • Task 2:启用顶层 orchestrator,以 DAG 保证 API → UI;
  • Task 4:才创建参数化 _deploy-app.yml reusable workflow。

这里缺少 Task 2 的实际调用路径。普通、disabled 的 workflow 不能直接作为同一 DAG 中带 needs 的 job 被 orchestrator 调用;如果用 workflow_dispatch 触发子 workflow,也无法天然形成同一 run 内可证明的 API → UI 依赖链。

建议在 Task 1 就生成两份逻辑原样、尚未参数化合并的 app-specific reusable workflow:

  • _deploy-api.yml,仅暴露 workflow_call;
  • _deploy-ui.yml,仅暴露 workflow_call。

Task 2 顶层 orchestrator 通过 job-level uses + needs 调用二者,形成真实 DAG;Task 4 再把两份合并为参数化 _deploy-app.yml。这样仍满足“搬迁与重写分离”,因为 Task 1 只改变调用外壳,不合并或优化部署逻辑。

同时补齐新仓 workflow_dispatch 回滚契约:

  • 目标应用:api | ui | both;
  • API/UI 各自的 rollback SHA,不能假设两应用相同;
  • changes job 在手动回滚时不得按路径判定后跳过;
  • 单应用与双应用回滚的顺序、失败中止和最终台账更新规则。

P0-17:部署 flock 尚未真正覆盖旧仓,disable 前也缺少 drain

当前两个旧仓 workflow 中没有任何 deployment flock 调用,而 Task 0 又声明“不改动旧仓任何配置”。仅在宿主机放置锁文件与获取脚本不会产生互斥,旧 workflow 会直接绕过它。

两种方案必须选一种并写清:

  1. 在 cutover 前通过独立 PR 让旧 API/UI 的 Linux deploy job 也持有同一把宿主机锁,锁覆盖完整 docker/systemd 变更区间;或
  2. 不宣称锁覆盖三仓,改为严格 drain:冻结 merge/dispatch → 查询三个仓 queued/in-progress run → 等待或安全取消至 0 → disable 旧 workflow → 再次确认无在途 run → enable 新仓。

GitHub disable 只阻止后续触发,不会替代对 queued/in-progress run 的查询、等待或取消。Task 2 runbook 需要把 drain 作为显式门禁;不能只写“冻结”和“disable”。

官方说明:

P1-18:新仓 branch protection 需要 bootstrap 顺序

当前两个旧仓 master 都要求名为 PR container validation 的 required check。Task 0 第 3 步直接复制 branch protection,但新仓此时尚未产生 required gate;Task 4 又计划重建 required checks。

请明确:

  1. Task 0 只复制非 check 类保护,或暂时使用受控 bootstrap 规则;
  2. Task 1 明确恒定 gate 的精确 display name;
  3. gate 在新仓成功运行一次后,再把它设为 required;
  4. Task 4 只在 job 名确实变化时迁移 required context,并验证旧 context 已移除。

GitHub 要求 required check 最近 7 天内在目标仓成功运行过:
https://docs.github.com/en/pull-requests/how-tos/merge-and-close-pull-requests/troubleshooting-required-status-checks

P1-19:changes 与 required gate 的行为契约需要具体化

既然不使用 event-level paths:,Task 1 应规定:

  • changes 使用 checkout 后的完整 Git diff,不依赖 GitHub 300-file event 过滤;
  • 分别定义 PR、push、首次 push、merge commit 与 workflow_dispatch 的 base/head;
  • required gate 使用 if: always();
  • gate 必须验证“按 changes 结果应运行的 app job 成功”,而不是只要 app job 为 skipped 就无条件成功;
  • API 未变化、UI 变化时,UI job 不能因 needs: deploy-api 的 skipped 状态被级联跳过。

P1-20:per-app 发布台账需要定义权威存储与原子更新语义

Task 4 仍只写“新增 per-app 发布台账/manifest”,尚未定义位置和故障语义。请至少明确:

  • 权威来源是运行容器镜像身份、宿主机状态文件,还是外部 deployment record;
  • 成功发布后何时原子更新,失败/自动回滚时如何恢复;
  • 手动回滚后 last deployed SHA 如何变化;
  • 宿主机丢失时如何重建;
  • 禁止把部署时变化的 manifest 直接 commit 回 master,避免递归触发发布。

可以继续把当前运行容器的 immutable image ref + image ID 作为事实来源,台账只作可恢复投影;如果使用宿主机文件,应放在 checkout 外并在同一把部署锁内原子替换。

处理 P0-16 与 P0-17 后,Task 2 才真正具备可执行的 API → UI cutover 链路。P1-18~P1-20 可以在 plan 中固定契约,具体脚本留到对应 Task 实现。

5 条意见全部受理,写入 Task、约束、验收与回退表。文档 258 增至 303 行。

主要变更:

- orchestrator 调用路径:实测两边 workflow 均不暴露 workflow_call,
  普通 workflow 无法被 job-level uses 加 needs 调用,原顺序下
  Task 2 的 DAG 无对象可调。Task 1 新增产出 _deploy-api.yml 与
  _deploy-ui.yml 两份逻辑原样、仅暴露 workflow_call 的外壳,
  只改调用形式不动部署逻辑,Task 4 再合并为参数化版本。
- 跨仓互斥:实测两个旧仓 workflow 的 flock 调用数均为 0,而计划
  声明不改动旧仓,故宿主机放锁文件不产生互斥。约束中锁的范围
  收窄为新仓与宿主机操作,跨仓互斥改由 drain 门禁承担。新增
  disable 不等于停止一条。
- Task 2 runbook 第 2 步改为显式 drain:查询三仓 queued 与
  in-progress run,等待或安全取消至归零并二次确认,每次
  enable disable 切换前重跑,三仓不得同时 enabled。锁的两个
  方案中选择严格 drain,理由与可推翻性写入正文。
- branch protection 分两步 bootstrap:两旧仓 required check 同名
  PR container validation,新仓尚未产生该 check 且 GitHub 要求
  近 7 天内成功运行过,直接复制会使 PR 永久 Pending。Task 0 只
  复制非 check 类保护,gate 成功运行一次后再设 required。
- changes 与 gate 行为契约具体化:完整 Git diff 不依赖 300-file
  过滤,定义五种触发情形的 base head,gate 用 always 并验证应
  运行的 job 成功而非 skipped 即放行,UI job 不得因 needs 的
  skipped 被级联跳过。验收增加两个反例用例。
- per-app 台账语义表:权威来源为运行容器 immutable image ref 加
  image ID,台账仅为可恢复投影,存于 checkout 树外,锁内原子
  替换,定义三种恢复路径,禁止把部署时变化的 manifest commit
  回 master 以免递归触发发布。

Co-Authored-By: Claude <noreply@anthropic.com>

Copy link
Copy Markdown
Owner Author

5 条全部受理,已推送 3593131。文档 258 → 303 行。两个 P0 都用实测确认了 —— 都是真断点。

P0-16 orchestrator 无可调用对象 — 成立

实测两边 workflow 均不暴露 workflow_call(grep workflow_call 零命中)。原顺序下 Task 2 的 DAG 确实无对象可调。

Task 1 新增第 5 步:产出 _deploy-api.yml / _deploy-ui.yml 两份逻辑原样、仅暴露 workflow_call 的外壳。这只改调用形式、不合并也不优化部署逻辑,所以"搬迁与重写分离"仍然成立;Task 4 再合并为参数化 _deploy-app.yml。本 Task 内两份保持不被任何已启用 workflow 调用。

回滚契约也补了(第 7 步):目标应用 api | ui | both、API/UI 各自独立的 rollback SHA、手动回滚时 changes 不得跳过目标应用、单/双应用回滚的顺序与失败中止规则。

P0-17 flock 没覆盖旧仓 — 成立,我的约束是空的

实测两个旧仓 workflow 的 flock 调用数均为 0。而我自己写了"Task 0 不改动旧仓任何配置" —— 那么在宿主机放锁文件根本不产生互斥,旧 workflow 直接绕过。这条约束等于没写。

两个方案我选了方案 2(严格 drain),理由写进了正文:方案 1 要在 cutover 前夕改旧仓的部署 job,而旧仓正是失败时的唯一回退路径,动它会削弱兜底。所以:

  • flock 的范围诚实收窄为「新仓 orchestrator + 宿主机手工操作」,不再宣称覆盖三仓
  • 跨仓互斥改由 drain 门禁承担
  • 新增一条约束:disable 不等于停止 —— 只阻止后续触发,不影响在途 run

runbook 第 2 步改为显式 drain:查询三仓 queued / in_progress → 等待或安全取消 → 归零并二次确认。每次 enable/disable 切换之间都要重跑,三仓不得在任一时刻同时 enabled。

这个选择是可推翻的 —— 如果你要双保险,方案 1 可以作为独立前置 PR 追加,我在正文里也标了。

P1-18 branch protection bootstrap — 成立

实测两个旧仓的 required check 同名 PR container validation,新仓尚未产生过。按你给的链接,GitHub 要求 required check 近 7 天内在目标仓成功运行过,直接复制会让新仓 PR 永久 Pending。

Task 0 第 3 步改为只复制非 check 类保护;Task 1 确定 gate 的精确 display name 并在成功运行一次后设 required;Task 4 仅在 job 名确实变化时迁移 context,并验证旧 context 已移除。

P1-19 changes / gate 契约 — 成立

原计划只写了结构没定语义。Task 1 新增第 6 步,五条逐一写死。其中两条你点出的陷阱我加了专门的反例验收:

  • 构造「API 未变、UI 变」的 PR,确认 UI job 未被级联跳过 —— 用 always() + 显式结果判定,不用裸 needs
  • 构造「应运行的 app job 失败」,确认 gate 失败而非放行

P1-20 台账语义 — 成立

原文只有"新增 per-app 发布台账"几个字。已补一张语义表,采纳你的建议以运行态为准:

项 约定
权威来源 运行容器的 immutable image ref + image ID
台账定位 可恢复投影,丢失可从运行态重建
存储位置 checkout 树之外
更新时机 发布验证通过后,同一把 flock 内原子替换
禁止项 不得把部署时变化的 manifest commit 回 master(会递归触发发布)

失败/自动回滚、手动回滚、宿主机丢失三种恢复路径也分别定义了。


风险表同步加了 5 行。三轮共 20 条意见现已全部落到 Task、约束、验收与回退表里。


Generated by Claude Code

不做什么章节声称 app/ 与 src/ 下不产生 diff,但路径清单 B 类要求
修改 fusion-ui/src/scripts/buildAndDeployWorkflow.test.ts,该文件
位于 src/ 之下,两处自相矛盾。

改为限定业务模块不产生 diff,并显式列出该测试文件为唯一例外。
API 侧 5 个同类测试位于 test/ 与 app/ 平级,不涉及此例外。

Co-Authored-By: Claude <noreply@anthropic.com>

Copy link
Copy Markdown
Owner Author

CI 失败说明:PR container validation on 557006a

结论:这不是本 PR 引入的失败,是一个既有的时序敏感测试在负载下被打穿。 本 PR 不修它(会不当扩大范围),下面给出根因与提议补丁。

失败内容

FAIL: test_fresh_terminal_grace_allows_late_first_write_and_finalize_to_win
(test.services.agent.test_trajectory_reconciliation.TrajectoryReconciliationTests)

  File "test/services/agent/test_trajectory_reconciliation.py", line 277
    self.assertEqual(meta.trajectory_status, "complete")
AssertionError: 'degraded' != 'complete'

Ran 2905 tests in 224.222s
FAILED (failures=1, skipped=1)

为什么不是本 PR 的

  1. 本次 push 的完整 diff 是 1 行 Markdown:

    docs/superpowers/plans/2026-08-31-monorepo-merge.md | 2 +-
    1 file changed, 1 insertion(+), 1 deletion(-)
    

    仅修正「不做什么」章节与路径清单 B 类的一处措辞矛盾,不触及任何 Python 代码。

  2. 同一 check 在紧邻的上一个 commit 3593131 上通过(10:16:12 → 10:19:30),而 3593131 → 557006a 之间只有上述那一行 Markdown。

  3. 本分支此前三次同类纯文档提交(a5ad5b5、5263f57、3593131)的 PR container validation 全部通过。

根因

app/services/agent/trajectory_recorder.py:25 定义:

TRAJECTORY_WAIT_TIMEOUT_SECONDS = 0.25

finalize 路径(L397)以此为墙钟预算等待 worker ack:

acknowledged = handshake.acknowledgement.wait(timeout=TRAJECTORY_WAIT_TIMEOUT_SECONDS)
if not acknowledged:
    self._mark_degraded("recorder_timeout")

失败的测试构造 TrajectoryRecorder + ThreadPoolExecutor(max_workers=1),asyncio.run 完成 record_chunk + finalize(0) 后断言 trajectory_status == "complete" —— 该断言隐含要求 worker 在 0.25s 内完成。本次 run 跑 2905 个测试耗时 224s,runner 负载下这个预算会被打穿,latch 置为 degraded,断言失败。

这不是"环境抖动",是测试对生产超时常量的真实依赖。

提议补丁(不在本 PR 实施)

仓库内已有既定做法可循:兄弟文件 test/services/agent/test_trajectory_recorder.py 在 3 处(L1063 / L1154 / L1326)用 TRAJECTORY_WAIT_TIMEOUT_SECONDS * 3 作为测试侧等待,并在 L1615 有一条契约测试锁定该常量为 0.25。

而 test_trajectory_reconciliation.py 既未导入该常量,也未做任何补偿。建议对齐兄弟文件的约定 —— 该文件 L7 已 from unittest.mock import patch、L298 已在用,改动很小:

# test/services/agent/test_trajectory_reconciliation.py
# test_fresh_terminal_grace_allows_late_first_write_and_finalize_to_win

with patch(
    "app.services.agent.trajectory_recorder.TRAJECTORY_WAIT_TIMEOUT_SECONDS",
    TRAJECTORY_WAIT_TIMEOUT_SECONDS * 3,
):
    asyncio.run(finish_late_recorder())
executor.shutdown(wait=True)

这样测试验证的仍是「迟到写入 + finalize 能赢过 reconciliation」这个真实语义,而不是 runner 当时的调度速度。不建议放宽或删除断言 —— degraded vs complete 的区分正是该测试要守的东西。

同文件中若有其他测试同样隐含 0.25s 依赖,建议一并排查(本次只观测到这一个失败)。

处理

  • 本 PR 为纯文档变更,不在此处修复该测试,避免把一个 plan 文档 PR 扩大到 trajectory 模块
  • 已按流程重跑一次该 job 以确认为间歇性失败;若重跑通过,本 PR 即可继续 review
  • 若重跑仍失败,我会再回来复核是否有我尚未识别的关联

需要的话我可以另开一个 PR 单独修这个 flaky 测试。


Generated by Claude Code

Claude and others added 2 commits August 31, 2026 10:36
原文把 storage/files 直接写成用户上传文件持久化并当作事实,但存储
后端有 local minio oss 三种,由宿主机 .env 的 STORAGE_BACKEND 决定,
不在仓库内,本计划无法确认生产实际取值。

改为条件式表述,并补充两侧依据:local 时 local_storage.py 的
upload 直接写原始字节、download 直接读回,是原件唯一副本,且
models.py 有两处 storage_key 非空列与 storage_backend storage_key
唯一约束硬引用,丢文件会留下指向空对象的 DB 行;minio oss 时对象
存于远端,本地目录重要性大幅下降。

同时指出 deploy.yml L1428 对挂载的断言是无条件的,挂载存在不能
证明后端为 local;L1036 至 L1042 存在从容器内 tar 抢救文件的兼容
路径,说明该数据曾只存在于容器内并出过问题。

Task 0 第 6 步增加 STORAGE_BACKEND 实际取值的判定,结果决定
Task 2 中该项迁移的分量;Task 2 的 2.1 相应改为按判定结果执行。

Co-Authored-By: Claude <noreply@anthropic.com>
原文称需修正 7 份跨仓 plan 的 ../fusion-ui/ 相对路径,把「提到
fusion-ui 的 plan」与「含 ../fusion-ui/ 相对路径的 plan」混为一谈。
实测含该模式的仅 2 份,其中一份是本计划自身,真实存量为 1 份。

同时补充 Task 5 的分诊要求。实测两套记录体系互不索引:台账按
领域加 commit SHA 追踪,71 处 SHA 引用,而 54 份 plan 中仅 4 份
被台账点名;checkbox 追踪已基本废弃,25 份有 box 但 0 勾选、
10 份无 box、仅 9 份全勾。单看一份 plan 无法判断死活,这正是
AGENTS.md 第 11 条要求先读台账再查 git log 的原因。

Task 5 改为迁移时须标注已完成 进行中 已废弃或按状态分目录,
否则等于把索引缺口原样搬进新仓。

Co-Authored-By: Claude <noreply@anthropic.com>
HyxiaoGe pushed a commit that referenced this pull request Aug 31, 2026
回应 PR #84 第一轮评审的两个 P1。

P1 之一:补删 docs/superpowers/plans/2026-08-31-run-skills-mvp.md。
原先以「台账无完成条目」为由保留,该判据错误。核实 master 历史,
64049e5(PR #76 引入 Run 级 Skills 运行时)已逐项实现该计划:
app/ai/skills/registry.py、verified-research/1.0.0 skill、Run
capability 路由、Trajectory API 与 skills 详情端点、agent loop
wiring、previous run skill release 及配套测试;3ba19f9(PR #77)
与 22f8625(PR #79)为后续修正。保留它会恰好留下唯一一份
「已完成却显示未开始、且仍强制调用已弃用插件」的文档,与本 PR
目标相反。docs/superpowers/plans 至此为空,同步移除其 gitignore
白名单。

同时在执行台账补上 Run 级 Skills 运行时的已完成记录。台账缺这条
正是上述错误判据的成因。

P1 之二:确立与插件无关的稳定落位目录 docs/implementation-plans,
并将全部发现入口改为同时覆盖该目录与 docs/superpowers/specs:
AGENTS.md 第 11 条、执行台账开头说明与检查清单第 3 条、
fusion-next-step skill。gitignore 增加对应白名单。

此前仅把发现入口收窄到 specs,会使 PR #83 的 monorepo 实施计划
合入后落在无人扫描的目录中。#83 需配套把文档移入新目录并修正
其对已删文件的引用,两者合并后需在最终树上重跑残留引用检查。

Co-Authored-By: Claude <noreply@anthropic.com>
Claude and others added 2 commits August 31, 2026 11:02
回应 PR #84 评审的第二个 P1:#84 把发现入口收窄后,本计划若仍落在
docs/superpowers/plans 会落在无人扫描的目录,且其对已删文件的完整
路径引用会立即断链。

- 文件迁至 docs/implementation-plans/2026-08-31-monorepo-merge.md,
  该目录由 #84 确立为与已弃用插件无关的稳定落位,并已纳入全部发现
  入口。本分支不改 gitignore,其白名单随 #84 提供,因此本 PR 需在
  #84 之后合并。
- 依据章节:对 2026-06-28-agent-run-continuation.md 的引用改为标注
  该文件已由 #84 清理、原文存于 git 历史,并说明结论不受影响。
- 路径清单 C 类:含 ../fusion-ui/ 的唯一存量文件已随 #84 删除,本项
  在新树上归零,只需对两个保留目录复查一次。
- Task 5 第 2 步重写:fusion-api 侧文档结构已由 #84 简化,本步改为
  迁移 implementation-plans 与 specs,并指出 fusion-ui 侧尚未做过
  同一轮清理、需先按同样口径核查再决定删除或迁移;同时要求 specs
  脱离 superpowers 这一废弃插件名,且落位与发现入口必须一一对应、
  在合并后的最终树上验证。

Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Claude <noreply@anthropic.com>
@HyxiaoGe
HyxiaoGe merged commit 658a077 into master Aug 31, 2026
1 check passed
@HyxiaoGe
HyxiaoGe deleted the claude/requirement-assessment-qkkonb branch August 31, 2026 11:36
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant