dev-manager-tauri/.blueprint/modules/project-dev-variables.md
lanrtop 9aa70eefd9
All checks were successful
Push & PR Check / check (push) Successful in 1m4s
docs(blueprint/dev-variables): 记录 Enterprise 真实分发与取值证据,立卡 V14–V18
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 15:22:45 +09:00

237 lines
24 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
id: project-dev-variables
name: 项目开发变量补给
status: in_progress
progress: 91
---
## 设计决策:人填写、Agent 按项目取值(2026-09-26)
### 背景与目标
开发 Agent 在子项目验收时会反复需要本机专属配置,例如非生产测试账号、沙箱 API Key 或测试端点。用户希望在炼境的项目 UI 填写一次,此后 Agent 能稳定发现并读取,避免把值留在子项目 `.env` 中。首轮只解决 Agent 获取开发变量;子项目进程的 `process.env` 自动注入、CI、生产凭证及部署能力不在范围内。
本模块是已完成的 `project-resource-broker` 的**明确例外**:R1–R11 保持 Gitea/API Key/webhook 常态不泄露、按操作代办;只有用户明确放入“Agent 可读开发变量”的值,才允许经专门工具返回明文。不能将旧的 `get_secret` 禁令改写成通用任意取密接口。
### 方案选择
| 方案 | 收益 | 代价与结论 |
| --- | --- | --- |
| 继续各项目 `.env` | 与现有脚本直接兼容 | 需要重复配置,仍有误提交与 Agent 访问不稳定的问题;保留为回退路径 |
| 炼境保存后由无认证 scoped MCP 返回值 | 最省实现步骤 | scoped URL 仅隔离误操作,不认证调用者;任何能访问本机端口的进程可能取值,否决 |
| **项目级开发变量 + 认证的 scoped MCP 单项读取** | 人填一次、Agent 跨会话复用、仓库无值 | Agent 会看到明文;需要验证 Codex 的认证头与本机凭据供应链,选定 |
### 信任与数据边界
- 仅支持登记在炼境的项目、明确标为开发用途且允许 Agent 读取的标量值。用户在对应项目 UI 填写、修改、撤销;Agent 可登记名称/用途和读取状态,但不能通过 MCP 设置值。非生产、低权限、可重置是使用规则,不能靠变量名称自动判断生产性质。
- SQLite 只保存 `project_id`、规范化变量名、用途、状态所需元数据和随机 `credential_ref`;值保存在现有 Windows Credential Manager adapter。普通列表、readiness、日志、错误与文档不含值。
- 唯一明文出口是 `read_project_dev_variable(project_id, name)`;必须同时验证真实项目绑定、scoped MCP 连接的项目 ID、客户端认证以及记录已由人配置。全局 `/mcp`、未认证请求和跨项目请求必须拒绝。明文进入 Agent 工具结果与会话,因此本方案不声称对 Agent 保密。
- MCP 认证材料不得写入项目仓库、URL 或普通日志。Codex `http_headers_helper` 已用两次独立真实 CLI 会话验证:从 Windows Credential Manager 的随机合成项取得 bearer,真实 initialize 请求均带正确 `Authorization`;失败不得降级成无认证接口。正式打包路径尚未验证。
- 同一 Windows 用户的恶意进程仍可能读取用户可访问的配置或受保护存储;认证只阻断无凭据的本机 HTTP 调用,不提供跨进程强隔离。其他客户端 adapter 未验证前不宣称兼容。
### 系统边界与预计文件
- 数据:`src-tauri/src/db.rs` 增加兼容 migration;新业务模块 `src-tauri/src/commands/dev_variables.rs` 注入数据库连接和 `CredentialStore`,实现登记、保存、读取、撤销的单点边界。
- 认证:`src-tauri/src/mcp_server.rs` / `mcp_tools.rs` 在取值调用前验证项目绑定及 bearer;`src-tauri/src/credential_store.rs` 存储随机认证材料;`src-tauri/src/main.rs` 与 `mcp_inject.rs` 评估最小本机 header helper 和配置注入。旧 MCP 工具继续按原契约可用。
- 人的投影:`src-tauri/src/lib.rs` 注册 Tauri commands,`src/lib/commands.ts` 同步类型与封装;在 `src/components/dashboard/ProjectCard.tsx` 就近入口接入项目级面板,值仅通过显式填写表单提交。
- Agent 投影:`src-tauri/src/mcp_tools.rs` 暴露登记需求、查询非秘密状态、单项取值;不提供批量导出、任意命令、HTTP/SSH/SQL 或部署代理。
- 契约同步:`docs/ai-context/project-context.yaml` 与 `docs/ai-context/agent-button-system.md` 说明例外与信任模型;保留旧设计历史,不将项目通用 API Key 改为 Agent 可读。
### 验证路径
- `[Codex CLI + 合成 MCP]` 用 `http_headers_helper` 提供合成 bearer 后初始化 → 服务端观测认证头;无 header/错误 header → 敏感工具拒绝;未通过则停止实现取值接口。
- `[cargo test]` 用 in-memory SQLite + 模拟 CredentialStore 登记、保存、重启式重建后读取、撤销 → 状态正确,旧值不可再取,列表与错误不含合成值。
- `[真实 scoped MCP]` Agent 在 `p1` 登记 `E2E_PASSWORD`,人通过同一本体保存合成值,Agent 单项读取 → 仅 `p1` 的已认证调用得到该值;`p2`、全局路由和无认证调用失败。
- `human_verify:` 炼境项目 UI 的待填写、已配置、修改和撤销路径可用,默认不显示值;使用者判断是否比重复配置 `.env` 省事。
### 风险与阶段闸门
- **认证材料供应**:helper 与客户端跨会话读取已用随机合成项验证,正式打包版尚未验证;若后续失败必须回到设计,不把 token 写进受 Git 跟踪的 `.codex/config.toml`。
- **明文工具结果**:用户选择开发便利,Agent 可能在会话中持有值;先只用合成数据验证,不读取或迁移真实账号。生产和高权限凭证仍用原有代办/CI/运行时机制。
- **不替代运行时 `.env`**:Agent 读取值不自动设置子进程环境变量;需要时另立任务,不在本迭代暗加 `export_env`。
- **依赖 PR #22**:从已提交的 R11 基线独立分支开发,先核验 PR #22 状态;不得把新改动混入已有 PR 或原 `master` 脏工作区。
## 任务拆解
### ✅ V1 — 认证头 helper 真实客户端可行性
- status: done
- complexity: M
- files: src-tauri/src/main.rs, src-tauri/src/lib.rs, src-tauri/src/credential_store.rs, src-tauri/src/mcp_inject.rs
- depends: project-resource-broker
- acceptance: "agent_verify: [Codex CLI + 合成 MCP] 通过本机 helper 从模拟受保护存储提供 bearer → initialize 请求含正确 Authorization,重启客户端后仍可读取;helper 缺失/失败时连接或取值 fail closed,项目配置文件不含 token。未通过即停止 V2–V7。"
- evidence: `cargo test --locked codex_client_reads_windows_helper_header_across_sessions -- --ignored` 双会话通过;真实 exe helper 的读取/缺失 fail closed 测试通过;config 测试断言无 token。
### ✅ V2 — 敏感 MCP 调用认证与项目绑定
- status: done
- complexity: M
- files: src-tauri/src/mcp_server.rs, src-tauri/src/mcp_tools.rs, src-tauri/src/credential_store.rs
- depends: V1
- acceptance: "[cargo test] 合成 bearer 下 p1 的敏感 tools/call 认证门槛通过;无 header、错误 header、p2 和全局 /mcp 均在 dispatch 前拒绝,现有非敏感 scoped 工具保持可调用;cargo test 全绿。真实取值工具的 HTTP 端到端验收归 V6。"
- evidence: `sensitive_read_requires_matching_project_bearer_on_both_transports` 通过;完整 `cargo test --locked` 通过。
### ✅ V3 — 开发变量元数据与受保护存储本体
- status: done
- complexity: M
- files: src-tauri/src/db.rs, src-tauri/src/commands/dev_variables.rs, src-tauri/src/credential_store.rs
- depends: V2
- acceptance: "[cargo test] in-memory DB + 模拟 CredentialStore 完成登记、保存、覆盖、读取、撤销;模拟写入或删除失败时旧值/引用可恢复,列表序列化和错误不含合成值;旧 schema 经 migrate 后可用。"
- evidence: `dev_variables::tests` 与 `dev_variable_migration_adds_metadata_table_to_existing_database` 通过;数据库重开后仍可读取合成值,删除失败保留旧引用。
### ✅ V4 — Tauri 人用命令与前端契约
- status: done
- complexity: M
- files: src-tauri/src/commands/dev_variables.rs, src-tauri/src/lib.rs, src/lib/commands.ts
- depends: V3
- acceptance: "[Tauri command/cargo test] 以项目 ID 查询待填写/已配置、保存合成值、撤销 → 状态随真实存储变化;常态返回类型无 value,pnpm typecheck exit 0。"
- evidence: `tauri_commands_use_same_state_and_never_return_value_in_list` 通过,`mise exec -- pnpm typecheck` exit 0。
### ✅ V5 — 项目 UI 填写与撤销投影
- status: done
- complexity: M
- files: src/components/dashboard/ProjectCard.tsx, src/components/dashboard/ProjectDevVariablesPanel.tsx, src/lib/commands.ts
- depends: V4
- acceptance: "agent_verify: [Tauri command/cargo test] 填写、覆盖、撤销同一本体状态正确,pnpm typecheck exit 0。human_verify: 在对应项目可见用途与待填写状态,填写/修改/撤销顺手,常态不显示值。"
- human_verify: pending(未启动隔离分支的真实桌面 UI;交人终验时判断交互摩擦)
- evidence: Tauri command 真实函数路径测试与 TypeScript 类型检查通过;填写值从 React Query mutation 缓存中移除。
### ✅ V6 — Agent 登记、状态和单项读取工具
- status: done
- complexity: M
- files: src-tauri/src/mcp_tools.rs, src-tauri/src/commands/dev_variables.rs, src-tauri/src/mcp_server.rs
- depends: V4, V5
- acceptance: "[真实 scoped MCP] p1 Agent 登记 E2E_PASSWORD → UI 待填写;人保存合成值后已认证 Agent 单项读取成功;未认证、p2 和全局路由拒绝;tools/list 无批量导出或任意代理。"
- evidence: `scoped_dev_variable_http_pilot_denies_missing_wrong_cross_and_global_auth` 真实本机 HTTP 测试通过;撤销后读取失败,工具清单无批量出口。
### ✅ V7 — 契约、合成试点与改动边界验收
- status: done
- complexity: M
- files: docs/ai-context/project-context.yaml, docs/ai-context/agent-button-system.md, .blueprint/modules/project-dev-variables.md, src-tauri/src/mcp_server.rs
- depends: V6
- acceptance: "agent_verify: [真实 Codex CLI + 合成数据] 跨会话登记→填写→读取→撤销后再读失败,项目目录无新 .env 或 token;[CLI] cargo test、pnpm typecheck、git diff --check 均 exit 0。human_verify: 不使用真实生产账号、不触发真实 PR/部署/数据库写入,确认日常开发摩擦是否下降。"
- resolved_blocker: 原阻碍为非交互 `exec` 默认 approval=never 拒绝写工具。2026-09-30 用户授权单次 `--approve-for-me`(仅会话 A 登记这一写调用),沿用 R11 先例;未放宽全局策略,读工具无需审批。
- verification: "2026-09-30:新增 ignored 宿主 `mcp_server::tests::isolated_dev_variables_client_pilot`(内存 DB、随机合成账户、临时 scoped MCP,认证走真实 `dev-manager-tauri.exe --lianjing-mcp-header` helper 取 Windows 凭据中的项目 bearer)。自检:helper exit 0;无认证 read_project_test_account → HTTP 403。真实 Codex CLI 0.155.0-alpha.9.2(gpt-5.6-terra)三个独立会话:A 登记 PILOT_LOGIN(environment=local)→ 宿主代人填写;B 新会话 list → configured=true、read → username=pilot-user-12abb974,与宿主生成值一致;宿主代人撤销后 C 新会话 read → 失败「开发变量尚未由用户填写」。finish 后宿主断言:状态全部未配置、目录无 `.env*`、任何文件不含 MCP token 与测试密码、MCP 认证材料已删除、临时目录已清理,test ok。回归:cargo test --locked 227 passed / 5 ignored,pnpm typecheck exit 0,git diff --check 通过。"
- human_verify: "2026-09-30 用户在 dev-variables 构建(真实 DB,已备份)对 Enterprise AGENT_ADMIN 两轮终验:首轮否决两处——修改时空白(→ V12)、撤销无确认框(→ f74fe11,根因 plugin-dialog 异步 confirm,同类 5 处一并修复);次轮通过。日常开发摩擦是否下降待合并后真实任务观察。"
- unverified: "正式打包版 helper 路径;Claude/DeepSeek 等非 Codex 客户端的 bearer helper 取值;B 会话中模型把 list/read 各重复调用 3 次(结果一致,属模型行为,未影响断言);宿主强制终止时 Drop 不保证执行,可能残留合成 Windows 凭据。"
## 设计决策:测试账户一次填写与跨会话复用(2026-09-28)
### 背景
单个开发变量虽已能登记、填写和读取,但测试登录通常同时需要账号与密码。让 Agent 分别登记两个变量、让用户分别填写,仍有重复操作和半配置状态;本迭代把常见测试账户做成一个有语义的需求卡,不扩展到生产凭证或任意表单生成器。
### 方案选择
| 方案 | 取舍 |
| --- | --- |
| 两个独立变量由 UI 猜测配对 | 无迁移,但没有可靠的同一需求身份,保存时可能只写成功一个字段;不选 |
| **在现有开发变量记录上增加 `test_account` 类型,账号/密码作为一份受保护值原子保存** | 复用现有项目边界、Windows Credential Manager 与撤销路径,增加少量非秘密元数据;选定 |
| 新建通用表单/凭证库 | 能支持任意字段,却扩大明文出口与维护面;本轮不做 |
### 系统边界与受影响文件
- `src-tauri/src/db.rs`:旧表兼容迁移,新增类型、目标系统和环境元数据;旧记录保持 `scalar`。
- `src-tauri/src/commands/dev_variables.rs`:需求登记幂等;账号/密码按一份结构化值写入同一受保护引用,读写和撤销沿用项目校验;普通标量 API 不读取或覆盖测试账户记录。
- `src-tauri/src/mcp_tools.rs`、`mcp_server.rs`:项目级登记、状态发现、专用读取;读取遵守现有 bearer 门槛,未认证、跨项目和全局路由拒绝,不增加通用 `get_secret`。
- `src-tauri/src/lib.rs`、`src/lib/commands.ts`、`src/components/dashboard/ProjectDevVariablesPanel.tsx`:一张卡一次填写账号与密码;常态列表仅展示目标系统、环境、用途和配置状态,不回显值。
- `docs/ai-context/project-context.yaml`、`docs/ai-context/agent-button-system.md`:同步外部契约与例外边界。
### 验证路径
- `[cargo test]` 旧 schema 迁移后旧标量仍可读;重复登记同一测试账户只得一张卡,语义冲突拒绝;一次保存后账号与密码同时可读,撤销后同时不可读,列表与错误不含合成值。
- `[真实 scoped MCP]` 合成项目登记→Tauri 本体填写→已认证读取→跨项目、无认证及全局路由拒绝;工具目录没有批量导出或任意代理。
- `human_verify:` 用户在项目面板一次填写账号与密码,后续会话无需重复填写;仅在人主动修改时出现输入框。
### 风险与闸门
- Agent 读取时会得到明文;本能力仅用于用户明确放入的非生产、低权限、可重置测试账户,不承诺对 Agent 保密。
- 真实 Codex 非交互 `exec` 对写工具的客户端限制属于 V7 接入验证,不以错误标注只读或放宽全局策略绕过;业务层合成验收可以独立先做,真实客户端全链路未通过前不宣称日常可用。
- 不自动把值注入子进程环境、不写 `.env`、不接管生产账号、SSH、SQL、HTTP 或部署。
### 拆解建议
按类型与受保护存储 → scoped Agent 投影 → 人用单表单投影 → 合成链路与文档四卡实施;既有 V7 仍单独保持 blocked,直到真实客户端验证通过。
## 任务拆解:测试账户预设
### ✅ V8 — 测试账户类型与原子受保护存储
- status: done
- complexity: M
- files: src-tauri/src/db.rs, src-tauri/src/commands/dev_variables.rs
- depends: V6
- acceptance: "agent_verify: [cargo test] 旧 schema migrate 后旧 scalar 正常;register_test_account(project,name,service,environment,purpose) 重复调用只保留一条且语义冲突拒绝;save_test_account 一次写入合成账号/密码,read_test_account 同时返回,revoke 后同时不可读;列表及错误不含值,写入失败不留下半配置。"
- evidence: `cargo test --locked test_account` 4 项通过;旧表迁移幂等、登记幂等、类型隔离、一次写入/撤销和初次/覆盖失败恢复均由合成数据断言。
### ✅ V9 — Agent 测试账户需求与项目级读取
- status: done
- complexity: M
- files: src-tauri/src/mcp_tools.rs, src-tauri/src/mcp_server.rs
- depends: V8
- acceptance: "agent_verify: [真实 scoped MCP/cargo test] p1 登记一张合成测试账户需求、查询无秘密状态、已认证读取账号与密码;未认证、p2、全局 /mcp 拒绝读取,普通 scalar API 不能读取测试账户;tools/list 不含批量导出或任意代理。"
- evidence: `sensitive_read_requires_matching_project_bearer_on_both_transports` 与扩展后的 `scoped_dev_variable_http_pilot_denies_missing_wrong_cross_and_global_auth` 通过;新明文工具先接入认证门槛再暴露,真实本机 HTTP 拒绝未认证/错误认证/p2/全局调用。
### ✅ V10 — 一张卡填写账号与密码
- status: done
- complexity: M
- files: src-tauri/src/lib.rs, src/lib/commands.ts, src/components/dashboard/ProjectDevVariablesPanel.tsx
- depends: V8
- acceptance: "agent_verify: [Tauri command/cargo test + pnpm typecheck] UI 一次提交调用 save_test_account,状态从待填写到已配置,修改与撤销共用本体;常态 DTO、React Query 缓存与日志不含账号或密码,typecheck exit 0。human_verify: 项目面板一张卡一次填写两个字段,默认不回显值。"
- human_verify: pending(隔离分支真实桌面 UI 尚未由用户终验)
- evidence: `tauri_test_account_command_uses_same_state_without_listing_values` 通过,`mise exec -- pnpm typecheck` exit 0;UI 通过独立调用提交两字段,列表 DTO 只有非秘密元数据和配置状态。
### ✅ V11 — 合成复用验收与契约同步
- status: done
- complexity: M
- files: src-tauri/src/mcp_server.rs, docs/ai-context/project-context.yaml, docs/ai-context/agent-button-system.md
- depends: V9, V10
- acceptance: "agent_verify: [真实 scoped MCP/cargo test] 合成项目登记→同一本体填写→再次查询已配置→读取→撤销后读取失败,并确认目录没有新增 .env 或明文配置;cargo test、pnpm typecheck、git diff --check exit 0。human_verify: 真实桌面 UI 与真实 Agent 客户端跨会话便利性另报未验证,不冒充 V7 完成。"
- human_verify: pending(真实桌面 UI 和真实 Agent 客户端跨会话复用尚未终验;V7 保持 blocked)
- evidence: 真实本机 scoped MCP HTTP 合成链路逐步断言登记、待填写、受保护存储填写、复查已配置、项目 bearer 读取、撤销后拒绝;数据库重开复用测试通过。`cargo test --locked` 227 passed/4 ignored,`mise exec -- pnpm typecheck` 与 `git diff --check` exit 0;未新增 `.env` 或明文配置文件。
## 任务拆解:UI 终验反馈与 agent 可发现性(2026-09-30)
> 来源:用户对 V7 的 human_verify 否决理由——「修改时空白,应像修改配置一样呈现旧值」「撤销无确认框」(后者为 bug,已由 `f74fe11` 修复并加回归测试);以及 agent 侧可发现性缺口:接入包 skill 未提示「需要测试账号时先查炼境」,agent 会继续向人索要。
### ✅ V12 — 修改时显式查看原值(人用投影)
- status: done
- complexity: M
- files: src-tauri/src/commands/dev_variables.rs, src-tauri/src/lib.rs, src/lib/commands.ts, src/components/dashboard/ProjectDevVariablesPanel.tsx, docs/ai-context/project-context.yaml
- depends: V10
- acceptance: "agent_verify: [cargo test] reveal(已配置测试账户) → 账号与密码原值;reveal(标量) → 原值;未配置 → 错误;MCP tools/list 不含任何 reveal 工具。human_verify: 点「修改」→ 账号预填可见、密码预填但默认遮罩,点「显示」可见;保存后生效。"
- verification: "2026-09-30:cargo test reveal_returns_original_value_by_kind_only_for_humans 覆盖测试账户/标量取回、未配置与撤销后报错、MCP tools/list 不含 reveal;全量 cargo test --locked 228 passed / 5 ignored,pnpm typecheck exit 0,vitest 8 passed。"
- human_verify: "2026-09-30 通过:修改预填原账号、密码遮罩可切换显示、撤销弹出确认框且取消不生效。"
- decision: 值仅经本机 Tauri command 在人显式点「修改」时取回,沿用 API Key R2 的显式 reveal 模式;不进 MCP,agent 取值仍只走已认证的 read_project_test_account。密码默认遮罩防截图/旁观泄露。
### ✅ V13 — 接入包 skill 提示 agent 先查炼境测试账户
- status: done
- complexity: S
- files: src-tauri/resources/onboarding/.agents/skills/lian-jing/SKILL.md, src-tauri/src/commands/onboarding.rs
- depends: V9
- acceptance: "agent_verify: [cargo test onboarding] base-onboarding 版本升级后旧版本项目报告 version_mismatch、新模板含测试账户指引。human_verify: 合并并重建后对 Enterprise apply_onboarding_pack,agent 需要登录时先查炼境而非向人索要。"
- verification: "2026-09-30:SKILL.md 新增第 8 步(先 list,已配置单项读取,否则登记并请用户在 UI 填写;禁止对话索要明文、禁止登记生产、禁止写入 Git 跟踪文件、认证被拒如实报告);BASE_ONBOARDING_PACK_VERSION 与模板 capability-packs.json 同步升至 1.5.0(仅升常量时 2 个 onboarding 测试失败,已同步修正);cargo test --locked 全绿。"
- human_verify: pending(分发到 Enterprise 后观察 agent 行为)
- distribution: "2026-09-30:master 6105c3d 重建后对 Enterprise 执行 inject_mcp(托管块新增 http_headers_helper)与 apply_onboarding_pack(SKILL.md、capability-packs.json 1.5.0、git-workflow 托管块 1.6.0→1.7.0;AGENTS.md/lefthook/mise skipped);写入前备份并逐文件比对,Enterprise 44 项既有未提交改动均在托管块外、内容未变。verify_onboarding 13/13 + runtime ready。真实 Codex 新会话在 Enterprise 目录经项目自身配置与 helper:list → AGENT_ADMIN configured,read 成功,username 与用户填写一致。该次为显式指示调用;未提示时 agent 是否自发先查炼境,待真实任务观察。旁证:Codex 仍尝试执行 shell 触发 Windows 沙箱提权 helper 被取消(1223),不影响结果。"
## 后续立卡(2026-09-30,按实测摩擦排序)
### 📋 V14–V16 — 测试账户落地到被 Git 忽略文件
- status: todo
- complexity: M×3
- 设计与卡片草案:`docs/tasks/2026-09-30-dev-variables-materialize.md`(落地本体 / MCP 投影 / Enterprise worktree 试点);开工前需用户确认设计。
- 为什么:agent 读到明文后仍需自行 export 或写 `.env.agent` 才能喂给 `agent-auth.mjs`,明文过一手会话且每个新 worktree 重复。
### 📋 V17 — 非 Codex 客户端的项目认证取值
- status: todo
- complexity: M
- files: src-tauri/src/mcp_inject.rs, docs/ai-context/agent-button-system.md
- depends: V13
- acceptance: "agent_verify: [真实 Claude Code 会话 + 合成账户] 经客户端动态请求头机制携带项目 bearer → read_project_test_account 成功;无认证 → 403。先调研 Claude Code / DeepSeek harness 是否支持动态请求头;不支持则如实记录并在 skill 中保持降级指引,不以静态 token 写入配置绕过。"
- 为什么:用户同时使用 Claude、Codex、DeepSeek;当前仅 Codex 经 helper 验证可读,是跨 agent 准入的最大缺口。
### 📋 V18 — helper 本机路径移出受 Git 跟踪的项目配置
- status: todo
- complexity: M
- files: src-tauri/src/mcp_inject.rs, src-tauri/src/commands/onboarding.rs
- depends: V13
- acceptance: "agent_verify: [cargo test] 注入后项目受跟踪文件不含本机绝对路径;炼境从 debug 换到安装版后无需逐项目重注入即可取值。先设计:候选为稳定 helper 入口(如用户级 shim)或客户端用户级配置,需验证 Codex 项目级配置与用户级配置的合并语义。"
- 为什么:2026-09-30 实测 Enterprise `.codex/config.toml` 受 Git 跟踪,注入写入 `E:\...\target\debug\dev-manager-tauri.exe` 绝对路径——换构建即失效、换机器即错,且会被提交进业务仓库。