feat(onboard/parity): onboard_project 编排本体与接入报告,处置独立审查(P8d) #39

Merged
lanrtop merged 3 commits from feat/agent-client-parity-p8d into master 2026-10-03 16:39:23 +08:00
Owner

做了什么

P8d:一键接入编排本体 onboard::apply 与报告 onboard::report(MCP / Tauri 投影归 P8e,生产入口 mcp_inject::plan_onboarding / mcp_inject::onboard_project),并处置独立审查的 10 条发现。

  • 编排本体:计划与应用共用同一份演算(项目文件写入序列 + 本机七步 token / shim / claude / codex / dsh / product_group_buff / git_hooks)。onboard_project 依次检查:同一项目已有接入在跑则返回 busy;预检不过返回 failed;未确认返回 refused;然后在接入写锁内重新解析登记、重算计划、核对 digest 与阻断项,不过则 refused。以上分支都零写入。通过后在写锁内按依赖执行写入,释放写锁后再跑 git_hooks(lefthook install)、L1、L0。某步失败只阻断依赖它的步骤,整体记 partial,不自动回滚。
  • 报告:status 为 done / partial / failed / refused / busy,「完成」只按三端可用子集判定。L1 矩阵中,客户端步骤未完成的一端整列 blocked(dep=…)。报告还包含 written_files、repo_changes(限定在项目根,分出 onboard_files 与 other_changes)、HEAD 不变断言、只针对接入文件的建议提交信息,以及 next_actions(commit / Gitea 建仓并注明默认公开 / CI / 飞轮 / 工具链 / lefthook / Codex 信任 / 重启 DSH GUI / Claude trust / 重开会话)。
  • 计划(⑨):单列 root、bypass_permissions(可按项目取消)、codex_trust、next_actions、skipped。选项 skip_targets 允许人对手写同名条目或共享项目键逐项选「跳过」(设计 §4 C1)。
  • 配套:删除登记(UI delete_project 与 MCP unregister_project)持同一把接入写锁,先清理 MCP 配置、再删登记;批量重注入在写锁内取目标快照;一键接入结束后补写一条 mcp_inject 事件,诊断里的注入状态随之更新;apply_onboarding_pack 改为 #[tauri::command(async)]。
  • T1 / T2:project-context.yaml、commands.ts(L1 Cell 增 dep、Cause 增 dependency)、AGENTS.md 架构速查已同步。

自验

  • cargo test(src-tauri):402 passed / 0 failed / 6 ignored,编译 0 warning;pnpm typecheck 通过。
  • onboard::apply 用临时 git 仓库、in-memory 或文件 DB、MemoryCredentialStore,以及假的适配器 / 宿主 / lefthook 执行器 / 定位器 / HTTP。卡片 acceptance ①–⑨ 逐条有用例。审查后新增或加强的用例:
    • 等写锁期间登记被删除、根目录迁移、端口变更 → failed / refused / refused,两个目录都零写入(文件 DB、两条连接)。
    • 同名目录迁到另一个父目录、文件计划完全一致,带回原 digest 仍被拒(root 进了 digest)。
    • 手写 Codex 条目:默认 refused;选跳过后 codex 记 skipped、适配器 0 次调用、手写文件字节不变;身份冲突即使列进 skip_targets 仍 refused。
    • 用户原有的未提交改动不进 onboard_files,也不进 commit 提示;子目录项目不列外层仓库的改动。
    • Codex 替身读写真实 .codex/config.toml:计划里 codex 步是 apply,报告如实记 applied;shim 失败时的 blocked 文案如实。
    • lefthook install 执行时写锁处于空闲状态;本地 lefthook 起不来记 failed 并附启动错误。
    • 删除登记时,清理闭包在写锁内、且先于删登记执行。
  • 变异验证:先 git add 暂存,再用 Edit 注入、跑测试、从暂存区还原,四轮结果:
    • 第 1 轮注入 5 处:7 条预期用例失败。
    • 第 2 轮注入 5 处:6 条失败。
    • 第 3 轮(身份冲突与 needs_human 可跳过):2 条失败。
    • 第 4 轮(被跳过的一端仍调用适配器):1 条失败。

审查处置(独立只读审查 6c69aa2,fix_then_merge,10 条)

# 级别 处置
① 中 已修:写锁内重新解析登记(失效记 failed,根目录或端口变了记 refused);计划 root 进 digest;端口每次重读;删除登记与批量重注入快照改为持锁
② 中 已修:skip_targets,只有 manual_entry / shared_key 可跳过,进 digest,被跳过的一端记 skipped
③ 低 已修:written_files、onboard_files / other_changes,限定项目根;建议提交信息与 commit 提示只针对接入文件
④ 低 已修:补写 mcp_inject 事件(inject_event 纯函数,有单测)
⑤ 低 已修:ClientAdapter::project_config_file,codex 步状态与文案如实;测试替身改为读写真实文件
⑥ 低 已修:保留启动错误;本地存在却起不来记 failed
⑦ 低 部分修:git_hooks 移到写锁外;product_group_buff 有意留在锁内(只写 DB、毫秒级,与删除登记串行)
⑧ 信息 未改代码,登记 known_limits ①:git 只读观测不经 ProcessRunner、无超时,只改 report.rs 会成半迁移
⑨ 信息 采纳为 P8e 指引(async fn + spawn_blocking);修正 project-context.yaml 里「在线程池执行」的不实表述
⑩ 信息 转统筹决定:Codex 未信任 / 非 git / 子目录 / worktree 是否计入 done 或补 next_action

改断言报备:report 单测 head_check 中原断言「只改 a.txt 就给收敛提交信息」,改为「a.txt 不是接入文件 → 不给接入提交信息、计入其他改动;列入本次写入才给」。这是按审查 ③ 有意收窄提交建议的语义。其余断言只做了加强。

没验什么

  • 真实三端端到端:真实三端的 apply 与 L1 都没跑过(真实 claude CLI、Codex、DSH,以及运行中炼境的 MCP 路由)。测试里的客户端一律是替身或「未安装」。这部分要等 P8e 合并、炼境重编译后,由统筹用 [MCP 全局] 实测。卡片保持 🔵。
  • 生产组装无单测:with_onboard_deps、SystemOnboardHost(每次重读端口)、mcp_inject::onboard_project 补写日志这一行,都依赖真实凭据存储、用户目录与连接池。
  • delete_project 生产路径:只测了本体 delete_project_registration 的加锁顺序。真实 remove_project_mcp_locked 里 claude CLI 与 Credential Manager 的清理没跑。
  • reinject_all_mcp 快照持锁:与一键接入真实并发的场景没有测试,只做了代码审阅。
  • 非 Windows 平台:没跑过。lefthook 本地候选的 .cmd 分支只在 Windows 上测过。
  • onboard_files 的归属判定是文件级的:用户对本次写入的非托管块文件(如 .claude/settings.json)另有未提交改动时,这些改动会随该文件一起进入 onboard_files(known_limits ⑪)。
  • 锁内重新解析之后才提交的改根:本次仍写旧根,靠随后 on_project_root_changed 的迁移线程收敛(known_limits ⑥)。

🤖 Generated with Claude Code

## 做了什么 P8d:一键接入编排本体 `onboard::apply` 与报告 `onboard::report`(MCP / Tauri 投影归 P8e,生产入口 `mcp_inject::plan_onboarding` / `mcp_inject::onboard_project`),并处置独立审查的 10 条发现。 - **编排本体**:计划与应用共用同一份演算(项目文件写入序列 + 本机七步 token / shim / claude / codex / dsh / product_group_buff / git_hooks)。`onboard_project` 依次检查:同一项目已有接入在跑则返回 busy;预检不过返回 failed;未确认返回 refused;然后在接入写锁内**重新解析登记**、重算计划、核对 digest 与阻断项,不过则 refused。以上分支都零写入。通过后在写锁内按依赖执行写入,释放写锁后再跑 git_hooks(lefthook install)、L1、L0。某步失败只阻断依赖它的步骤,整体记 partial,不自动回滚。 - **报告**:status 为 done / partial / failed / refused / busy,「完成」只按三端可用子集判定。L1 矩阵中,客户端步骤未完成的一端整列 blocked(dep=…)。报告还包含 `written_files`、`repo_changes`(限定在项目根,分出 `onboard_files` 与 `other_changes`)、HEAD 不变断言、只针对接入文件的建议提交信息,以及 next_actions(commit / Gitea 建仓并注明默认公开 / CI / 飞轮 / 工具链 / lefthook / Codex 信任 / 重启 DSH GUI / Claude trust / 重开会话)。 - **计划(⑨)**:单列 `root`、`bypass_permissions`(可按项目取消)、`codex_trust`、`next_actions`、`skipped`。选项 `skip_targets` 允许人对手写同名条目或共享项目键逐项选「跳过」(设计 §4 C1)。 - **配套**:删除登记(UI delete_project 与 MCP unregister_project)持同一把接入写锁,先清理 MCP 配置、再删登记;批量重注入在写锁内取目标快照;一键接入结束后补写一条 `mcp_inject` 事件,诊断里的注入状态随之更新;`apply_onboarding_pack` 改为 `#[tauri::command(async)]`。 - T1 / T2:`project-context.yaml`、`commands.ts`(L1 Cell 增 dep、Cause 增 dependency)、`AGENTS.md` 架构速查已同步。 ## 自验 - `cargo test`(src-tauri):**402 passed / 0 failed / 6 ignored**,编译 0 warning;`pnpm typecheck` 通过。 - `onboard::apply` 用临时 git 仓库、in-memory 或文件 DB、MemoryCredentialStore,以及假的适配器 / 宿主 / lefthook 执行器 / 定位器 / HTTP。卡片 acceptance ①–⑨ 逐条有用例。审查后新增或加强的用例: - 等写锁期间登记被删除、根目录迁移、端口变更 → failed / refused / refused,两个目录都零写入(文件 DB、两条连接)。 - 同名目录迁到另一个父目录、文件计划完全一致,带回原 digest 仍被拒(root 进了 digest)。 - 手写 Codex 条目:默认 refused;选跳过后 codex 记 skipped、适配器 0 次调用、手写文件字节不变;身份冲突即使列进 skip_targets 仍 refused。 - 用户原有的未提交改动不进 onboard_files,也不进 commit 提示;子目录项目不列外层仓库的改动。 - Codex 替身读写真实 `.codex/config.toml`:计划里 codex 步是 apply,报告如实记 applied;shim 失败时的 blocked 文案如实。 - lefthook install 执行时写锁处于空闲状态;本地 lefthook 起不来记 failed 并附启动错误。 - 删除登记时,清理闭包在写锁内、且先于删登记执行。 - **变异验证**:先 git add 暂存,再用 Edit 注入、跑测试、从暂存区还原,四轮结果: - 第 1 轮注入 5 处:7 条预期用例失败。 - 第 2 轮注入 5 处:6 条失败。 - 第 3 轮(身份冲突与 needs_human 可跳过):2 条失败。 - 第 4 轮(被跳过的一端仍调用适配器):1 条失败。 ## 审查处置(独立只读审查 6c69aa2,fix_then_merge,10 条) | # | 级别 | 处置 | |---|---|---| | ① | 中 | 已修:写锁内重新解析登记(失效记 failed,根目录或端口变了记 refused);计划 root 进 digest;端口每次重读;删除登记与批量重注入快照改为持锁 | | ② | 中 | 已修:`skip_targets`,只有 manual_entry / shared_key 可跳过,进 digest,被跳过的一端记 skipped | | ③ | 低 | 已修:`written_files`、`onboard_files` / `other_changes`,限定项目根;建议提交信息与 commit 提示只针对接入文件 | | ④ | 低 | 已修:补写 mcp_inject 事件(`inject_event` 纯函数,有单测) | | ⑤ | 低 | 已修:`ClientAdapter::project_config_file`,codex 步状态与文案如实;测试替身改为读写真实文件 | | ⑥ | 低 | 已修:保留启动错误;本地存在却起不来记 failed | | ⑦ | 低 | 部分修:git_hooks 移到写锁外;product_group_buff 有意留在锁内(只写 DB、毫秒级,与删除登记串行) | | ⑧ | 信息 | 未改代码,登记 known_limits ①:git 只读观测不经 ProcessRunner、无超时,只改 report.rs 会成半迁移 | | ⑨ | 信息 | 采纳为 P8e 指引(async fn + spawn_blocking);修正 project-context.yaml 里「在线程池执行」的不实表述 | | ⑩ | 信息 | 转统筹决定:Codex 未信任 / 非 git / 子目录 / worktree 是否计入 done 或补 next_action | **改断言报备**:report 单测 head_check 中原断言「只改 a.txt 就给收敛提交信息」,改为「a.txt 不是接入文件 → 不给接入提交信息、计入其他改动;列入本次写入才给」。这是按审查 ③ 有意收窄提交建议的语义。其余断言只做了加强。 ## 没验什么 - **真实三端端到端**:真实三端的 apply 与 L1 都没跑过(真实 claude CLI、Codex、DSH,以及运行中炼境的 MCP 路由)。测试里的客户端一律是替身或「未安装」。这部分要等 P8e 合并、炼境重编译后,由统筹用 [MCP 全局] 实测。卡片保持 🔵。 - **生产组装无单测**:`with_onboard_deps`、`SystemOnboardHost`(每次重读端口)、`mcp_inject::onboard_project` 补写日志这一行,都依赖真实凭据存储、用户目录与连接池。 - **delete_project 生产路径**:只测了本体 `delete_project_registration` 的加锁顺序。真实 `remove_project_mcp_locked` 里 claude CLI 与 Credential Manager 的清理没跑。 - **reinject_all_mcp 快照持锁**:与一键接入真实并发的场景没有测试,只做了代码审阅。 - **非 Windows 平台**:没跑过。lefthook 本地候选的 `.cmd` 分支只在 Windows 上测过。 - **onboard_files 的归属判定是文件级的**:用户对本次写入的非托管块文件(如 `.claude/settings.json`)另有未提交改动时,这些改动会随该文件一起进入 onboard_files(known_limits ⑪)。 - **锁内重新解析之后才提交的改根**:本次仍写旧根,靠随后 `on_project_root_changed` 的迁移线程收敛(known_limits ⑥)。 🤖 Generated with [Claude Code](https://claude.com/claude-code)
lanrtop added 3 commits 2026-10-03 16:32:16 +08:00
- 新增 onboard/apply.rs:计划与应用共用同一份演算(本机七步 token/shim/claude/codex/dsh/
  product_group_buff/git_hooks + 项目文件);apply 依次项目级运行锁(busy)→ 预检(failed)→
  确认(refused)→ 接入写锁内重算计划核对 digest 与阻断项(refused),以上零写入;之后按依赖
  执行 identity、project_files、git_hooks、product_group_buff、token → shim → 三端适配器,
  某步失败只阻断依赖它的步骤(blocked(dep=…)),整体 partial,不自动回滚;随后 L1(未完成的
  客户端一端整列 blocked、不起进程)与 L0
- 新增 onboard/report.rs:status done/partial/failed/refused/busy,「完成」只按三端可用子集;
  repo_changes(git status --porcelain / diff --stat,非 git 为 unavailable)、HEAD 不变断言、
  建议提交信息、next_actions(Gitea 注明默认公开、CI、飞轮、工具链、lefthook、Codex 信任、
  重启 DSH GUI、Claude trust、重开已打开的会话)
- 计划单列 bypass_permissions,可按项目取消(写显式 defaultMode=default 记住选择)
- 下沉:本机七步组装、token_step/outcome_status、控制面判定、lefthook install、独立产品组建组
  移入 onboard(可注入),commands 与 mcp_inject 改为薄包装;生产入口
  mcp_inject::plan_onboarding / onboard_project 供 P8e 投影一行委托
- L1 Cell 增 dep、Cause 增 dependency(commands.ts 同步);project-context.yaml、AGENTS.md 同步
- cargo test 394 passed / 0 failed / 6 ignored;pnpm typecheck 通过;三轮变异验证

Feature-Confirmed: true
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
chore(merge): 合并 master(P4a 标 ✅ 与派 P8d 的蓝图更新)到 P8d
All checks were successful
Push & PR Check / check (push) Successful in 1m5s
6c69aa2ae3
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
fix(onboard/parity): P8d 处置独立审查——锁内重新解析登记并以根目录绑 digest、阻断项可逐项跳过、接入文件与用户改动分开报告等(P8d 审查)
All checks were successful
Push & PR Check / check (push) Successful in 1m9s
Push & PR Check / check (pull_request) Successful in 1m1s
2f2a9f10a3
- ① 接入写锁内重新解析登记:登记消失 failed,根目录或端口变了 refused 并附当前计划;
  计划新增 root 并进 digest;SystemOnboardHost 每次重读端口;删除登记持同一把写锁先清理
  MCP 配置再删登记(delete_project_registration 注入写锁与清理闭包);批量重注入在锁内取快照
- ② OnboardOptions.skip_targets:manual_entry / shared_key 可逐项跳过(进 digest,计划单列
  skipped),跳过的一端记 skipped、不调用适配器;身份冲突、混合文件、needs_human 仍只能中止
- ③ 报告新增 written_files;repo_changes 限定项目根,分出 onboard_files 与 other_changes,
  建议提交信息与 next_action commit 只针对接入文件
- ④ 一键接入补写 mcp_inject 事件(inject_event),诊断注入状态随之更新
- ⑤ ClientAdapter::project_config_file:codex 步本次由 project_files 写入时记 applied,blocked 文案如实
- ⑥ lefthook 保留启动错误,本地存在却起不来记 failed;⑦ git_hooks 移到写锁外
- ⑧⑨⑩ 登记 known_limits / P8e 指引 / 转统筹决定;project-context.yaml 同步(T1)
- cargo test 402 passed / 0 failed / 6 ignored;pnpm typecheck 通过;四轮变异验证

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
lanrtop merged commit d018d44729 into master 2026-10-03 16:39:23 +08:00
Sign in to join this conversation.
No reviewers
No Label
No Milestone
No project
No Assignees
1 Participants
Notifications
Due Date
The due date is invalid or out of range. Please use the format 'yyyy-mm-dd'.

No due date set.

Dependencies

No dependencies set.

Reference: lanrtop/dev-manager-tauri#39
No description provided.