diff --git a/docs/ai-context/git-workflow.md b/docs/ai-context/git-workflow.md index 13754ef..a0d1d71 100644 --- a/docs/ai-context/git-workflow.md +++ b/docs/ai-context/git-workflow.md @@ -77,7 +77,10 @@ PR 别攒太大(建议每 3~5 个 commit 或几百行内就开一次),否 ## PR 创建(炼境托管项目) -本项目由炼境管理,MCP 已注入且 `.claude/liangjing.json` 含 `project_id`。 +本项目由炼境管理,MCP 已注入且 `.claude/liangjing.json` 含 `project_id` 和 `group_id` +(`group_id` 用于定位本项目对应的 MCP 服务器 `lian-jing-{group_id}`)。 +注意:该文件在注入时生成快照——项目移入新产品组时炼境会自动刷新;若发现 `group_id` +缺失或过期,在炼境重新执行「注入 MCP」(或调 MCP 工具 `inject_mcp`)即可回填。 **推送分支后,通过炼境 MCP 创建 PR,禁止用 curl + git credential fill 提取 token:** diff --git a/src-tauri/resources/onboarding/git-workflow.md.tmpl b/src-tauri/resources/onboarding/git-workflow.md.tmpl index 13754ef..a0d1d71 100644 --- a/src-tauri/resources/onboarding/git-workflow.md.tmpl +++ b/src-tauri/resources/onboarding/git-workflow.md.tmpl @@ -77,7 +77,10 @@ PR 别攒太大(建议每 3~5 个 commit 或几百行内就开一次),否 ## PR 创建(炼境托管项目) -本项目由炼境管理,MCP 已注入且 `.claude/liangjing.json` 含 `project_id`。 +本项目由炼境管理,MCP 已注入且 `.claude/liangjing.json` 含 `project_id` 和 `group_id` +(`group_id` 用于定位本项目对应的 MCP 服务器 `lian-jing-{group_id}`)。 +注意:该文件在注入时生成快照——项目移入新产品组时炼境会自动刷新;若发现 `group_id` +缺失或过期,在炼境重新执行「注入 MCP」(或调 MCP 工具 `inject_mcp`)即可回填。 **推送分支后,通过炼境 MCP 创建 PR,禁止用 curl + git credential fill 提取 token:** diff --git a/src-tauri/src/mcp_inject.rs b/src-tauri/src/mcp_inject.rs index 7662910..72e61c3 100644 --- a/src-tauri/src/mcp_inject.rs +++ b/src-tauri/src/mcp_inject.rs @@ -47,18 +47,25 @@ fn liangjing_path(project_id: &str) -> Result { Ok(project_root(project_id)?.join(".claude").join("liangjing.json")) } -/// 写炼境上下文文件,供子项目 Claude 会话直接读取 project_id / group_id +/// 写炼境上下文文件,供子项目 Claude 会话直接读取 project_id / group_id。 +/// 合并写入:保留文件中已有的其他字段,只更新炼境管理的三个字段(重注入可回填缺失的 group_id) fn write_liangjing_context(project_id: &str, group_id: &str, port: u16) -> Result<(), String> { let path = liangjing_path(project_id)?; if let Some(parent) = path.parent() { std::fs::create_dir_all(parent) .map_err(|e| format!("创建 .claude 目录失败: {}", e))?; } - let ctx = json!({ - "project_id": project_id, - "group_id": group_id, - "mcp_port": port - }); + let mut ctx = match std::fs::read_to_string(&path) { + Ok(s) => serde_json::from_str::(&s) + .ok() + .filter(|v| v.is_object()) + .unwrap_or_else(|| json!({})), + Err(_) => json!({}), + }; + let obj = ctx.as_object_mut().expect("ctx 必为 JSON 对象"); + obj.insert("project_id".into(), json!(project_id)); + obj.insert("group_id".into(), json!(group_id)); + obj.insert("mcp_port".into(), json!(port)); let content = serde_json::to_string_pretty(&ctx).map_err(|e| e.to_string())?; std::fs::write(&path, content) .map_err(|e| format!("写入 liangjing.json 失败: {}", e))