From e4f0b77ca8047a64f9f4779dfe57d2e7b93d9e0f Mon Sep 17 00:00:00 2001 From: Peter Zhang <18501667167@qq.com> Date: Mon, 8 Jun 2026 16:11:32 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20Git=20Workflow=20=E5=A4=9A=20Session=20?= =?UTF-8?q?=E5=B9=B6=E5=8F=91=E9=9A=94=E7=A6=BB=E6=94=B9=E9=80=A0=20-=20Cl?= =?UTF-8?q?oses=20#124?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 核心变更: - _common.sh: setup_worktree 改为 session-unique detached worktree (origin/main) - 所有 Agent 文档移除 git checkout main / git pull origin main - Feature branch 统一从 origin/main 创建: git fetch origin && git checkout -b origin/main - CLAUDE.md: 新增工作区隔离章节, primary worktree 定义为只读参考区 - 新增 start_generic.sh: Generic session worktree 隔离启动器 Co-Authored-By: Claude Opus 4.7 --- .claude/agents/dev-agent.md | 15 ++++++++------- .claude/agents/qe-agent.md | 18 ++++++------------ CLAUDE.md | 18 +++++++++++++----- agents/DEV_AGENT.md | 6 +++--- agents/QE_AGENT.md | 18 ++++++------------ scripts/_common.sh | 37 ++++++++++++++++++------------------- scripts/start_dev_agent.sh | 6 ++---- scripts/start_generic.sh | 22 ++++++++++++++++++++++ scripts/start_qe_agent.sh | 6 ++---- 9 files changed, 80 insertions(+), 66 deletions(-) create mode 100644 scripts/start_generic.sh diff --git a/.claude/agents/dev-agent.md b/.claude/agents/dev-agent.md index 2a929d4..e05d5cc 100644 --- a/.claude/agents/dev-agent.md +++ b/.claude/agents/dev-agent.md @@ -67,16 +67,17 @@ export GITEA_USER=pzhang_dev_agent_01 # Dev-Agent 账号 - `C:\Users\peterz\projects\document_analyzer\docs\PROJECT_CHARTER.md` - `C:\Users\peterz\projects\document_analyzer\docs\GLOBAL_STATE.md` 2. 确认环境变量已设置(GITEA_USER + ~/.gitea/config.yaml) -3. 用 `/loop 10m` 开启 10 分钟间隔的自动轮询 -4. 轮询内容(多轮递进): +3. 确认当前在独立的 git worktree 中(启动脚本已自动切到 `~/.gitea/worktrees///`),不与其他 agent 共享工作目录。工作区始终基于 origin/main,请勿 checkout main 分支 +4. 用 `/loop 10m` 开启 10 分钟间隔的自动轮询 +5. 轮询内容(多轮递进): a. `--action list --labels product-code` — 先捡带 `product-code` 标签的 Issue b. `--action list` 无过滤,筛选 title 带 `[product]` 前缀的无标签 Issue c. `--action blocked-check` — 检查 blocked Issue,若阻塞已解除则自动移除 blocked 标签 d. 都无则分析无标签、无标识的 Issue,判断是否在 Dev 域内 -5. 有 Issue → 走完整闭环处理(分析 → 开发 → push → PR → CI → merge → 自行验证 → 关闭) +6. 有 Issue → 走完整闭环处理(分析 → 开发 → push → PR → CI → merge → 自行验证 → 关闭) - 关闭 Issue 时自动解除被该 Issue 阻塞的其他 Issue(移除 blocked 标签) -6. 无 Issue → 报告 "main healthy,无待处理 Issue",等待下次轮询 -7. 同时保持对话开放,随时响应用户指令 +7. 无 Issue → 报告 "main healthy,无待处理 Issue",等待下次轮询 +8. 同时保持对话开放,随时响应用户指令 ## 上下文管理 Context window 有限。当 session 持续较长时间时: @@ -117,8 +118,8 @@ python scripts/agent_poller.py --action get --issue N ### 3. 开发 / 修复 ``` -1. git pull origin main -2. git checkout -b dev/issue-N- +1. git fetch origin +2. git checkout -b dev/issue-N- origin/main 3. 修改代码 + 更新 UT 4. python -m pytest -v 5. git commit -m "fix: <描述> - Closes #N" diff --git a/.claude/agents/qe-agent.md b/.claude/agents/qe-agent.md index c075715..9cf248f 100644 --- a/.claude/agents/qe-agent.md +++ b/.claude/agents/qe-agent.md @@ -16,7 +16,7 @@ description: "document_analyzer QE-Agent: 自动化验收测试开发与质量 1. 读取项目章程和全局状态:`docs/PROJECT_CHARTER.md` 和 `docs/GLOBAL_STATE.md` 2. 设好环境变量(见下方"环境要求") -3. 确认当前在独立的 git worktree 中(启动脚本已自动切到 `~/.gitea/worktrees/`),不与其他 agent 共享工作目录 +3. 确认当前在独立的 git worktree 中(启动脚本已自动切到 `~/.gitea/worktrees///`),不与其他 agent 共享工作目录。工作区始终基于 origin/main,请勿 checkout main 分支 4. 用 `/loop 10m` 开启 10 分钟间隔的自动轮询 4. 轮询内容(多轮递进): a. `--action list --labels test-code` — 先捡带 `test-code` 标签的 Issue @@ -112,22 +112,16 @@ python scripts/agent_poller.py --action comment --issue --body "QE-Agent 已 ### Step 3: 实施测试 -#### 3.1 确保代码最新 +#### 3.1 确保代码最新并创建分支 ```bash -git checkout main -git pull origin main -``` - -#### 3.2 创建分支 - -```bash -git checkout -b test/issue- +git fetch origin +git checkout -b test/issue- origin/main ``` 分支命名规则:`test/issue-` 或 `test/issue--<简短描述>` -#### 3.3 编写测试代码 +#### 3.2 编写测试代码 测试代码在 `tests/acceptance/` 目录下。现有结构: @@ -149,7 +143,7 @@ tests/acceptance/ - Layer B 覆盖率测试不需要 LLM API - Layer C QE 审计需要 `deepseek-v4-flash` API -#### 3.4 本地验证 +#### 3.3 本地验证 ```bash # 跑全部验收测试(需要 LLM API) diff --git a/CLAUDE.md b/CLAUDE.md index 12dcebc..9edff9e 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -16,13 +16,21 @@ - Agent 身份通过各自环境变量设置(Dev: `pzhang_dev_agent_01`,QE: `pzhang_qe_agent_01`) - **所有 Gitea API 操作必须通过 `python scripts/agent_poller.py`**,禁止直接 curl 或硬编码 token +## 工作区隔离 + +本项目使用 Git worktree 实现多 Agent 会话隔离,确保多个 Generic/Dev/QE session 并发运行互不干扰: + +- **Primary worktree** (`C:\Users\peterz\projects\document_analyzer\`) 是**只读参考区**。仅用于代码阅读、git log 查询、文档查阅、启动脚本。**不在此目录做任何开发提交**。 +- **Generic session 开发**:使用 `bash scripts/start_generic.sh` 启动,自动在 `~/.gitea/worktrees/pzhangzywl//` 创建隔离工作区。 +- **Agent sessions**:由 `start_dev_agent.sh` / `start_qe_agent.sh` 自动在 `~/.gitea/worktrees///` 创建隔离工作区。 +- 所有 session 的 worktree 以 detached 模式从 `origin/main` 创建,**严禁在任何 worktree 中 checkout main 分支**。 +- Feature branch 直接从 `origin/main` 创建:`git fetch origin && git checkout -b origin/main` + ## 代码同步 -Dev-Agent 和 QE-Agent 持续向 main 提交代码,本地可能落后。Session 启动时必须同步: - -- **启动时**:自动执行 `git pull origin main`,确保本地是最新代码 -- **运行中**:定期 `git fetch origin` 检查 `HEAD..origin/main`,有新提交则 pull -- **有冲突时**:暂停并报告,不自动解决(人工介入) +- Primary worktree:`git fetch origin` 即可(只读,不 pull)。 +- 隔离 worktree:启动脚本自动从最新 `origin/main` 创建,始终是最新代码。 +- Session 运行中需要同步时:`git fetch origin`,新分支从最新 `origin/main` 创建。 ## 上下文管理 diff --git a/agents/DEV_AGENT.md b/agents/DEV_AGENT.md index cd4f868..3f9fcde 100644 --- a/agents/DEV_AGENT.md +++ b/agents/DEV_AGENT.md @@ -65,7 +65,7 @@ export GITEA_USER=pzhang_dev_agent_01 # Dev-Agent 账号 1. 读取项目章程和全局状态:`docs/PROJECT_CHARTER.md` 和 `docs/GLOBAL_STATE.md` 2. 确认环境变量已设置(GITEA_USER + ~/.gitea/config.yaml) -3. 确认当前在独立的 git worktree 中(启动脚本已自动切到 `~/.gitea/worktrees/`),不与其他 agent 共享工作目录 +3. 确认当前在独立的 git worktree 中(启动脚本已自动切到 `~/.gitea/worktrees///`),不与其他 agent 共享工作目录。工作区始终基于 origin/main,请勿 checkout main 分支 4. 用 `/loop 10m` 开启 10 分钟间隔的自动轮询 4. 轮询内容(多轮递进): a. `--action list --labels product-code` — 先捡带 `product-code` 标签的 Issue @@ -156,8 +156,8 @@ python scripts/agent_poller.py --action get --issue N ``` 1. [判定] 是代码级修复还是质量级修复? -2. git pull origin main -3. git checkout -b dev/issue-N- +2. git fetch origin +3. git checkout -b dev/issue-N- origin/main 4. 修改功能代码 + 更新/补充 UT 和接口集成测试 5. python -m pytest -v # 本地全量 UT/集成测试 6. [仅质量级修复] python scripts/run_pipeline.py --input "input/<文档>.docx" diff --git a/agents/QE_AGENT.md b/agents/QE_AGENT.md index 83b8d05..70ed121 100644 --- a/agents/QE_AGENT.md +++ b/agents/QE_AGENT.md @@ -15,7 +15,7 @@ description: QE Agent — 自动化验收测试开发与质量门禁。轮询 Gi 1. 读取项目章程和全局状态:`docs/PROJECT_CHARTER.md` 和 `docs/GLOBAL_STATE.md` 2. 设好环境变量(见下方"环境要求") -3. 确认当前在独立的 git worktree 中(启动脚本已自动切到 `~/.gitea/worktrees/`),不与其他 agent 共享工作目录 +3. 确认当前在独立的 git worktree 中(启动脚本已自动切到 `~/.gitea/worktrees///`),不与其他 agent 共享工作目录。工作区始终基于 origin/main,请勿 checkout main 分支 4. 用 `/loop 10m` 开启 10 分钟间隔的自动轮询 4. 轮询内容(多轮递进): a. `--action list --labels test-code` — 先捡带 `test-code` 标签的 Issue @@ -111,22 +111,16 @@ python scripts/agent_poller.py --action comment --issue --body "QE-Agent 已 ### Step 3: 实施测试 -#### 3.1 确保代码最新 +#### 3.1 确保代码最新并创建分支 ```bash -git checkout main -git pull origin main -``` - -#### 3.2 创建分支 - -```bash -git checkout -b test/issue- +git fetch origin +git checkout -b test/issue- origin/main ``` 分支命名规则:`test/issue-` 或 `test/issue--<简短描述>` -#### 3.3 编写测试代码 +#### 3.2 编写测试代码 测试代码在 `tests/acceptance/` 目录下。现有结构: @@ -148,7 +142,7 @@ tests/acceptance/ - Layer B 覆盖率测试不需要 LLM API - Layer C QE 审计需要 `deepseek-v4-flash` API -#### 3.4 本地验证 +#### 3.3 本地验证 ```bash # 跑全部验收测试(需要 LLM API) diff --git a/scripts/_common.sh b/scripts/_common.sh index a352664..86807b5 100644 --- a/scripts/_common.sh +++ b/scripts/_common.sh @@ -21,37 +21,36 @@ fi # ── Worktree isolation ───────────────────────────────────────────────────────── GITEA_WORKTREE_DIR="${GITEA_WORKTREE_DIR:-$HOME/.gitea/worktrees}" +_WORKTREE_PATH="" setup_worktree() { local user="$1" - local worktree="$GITEA_WORKTREE_DIR/$user" + local ts + ts="$(date +%Y%m%d-%H%M%S)" + local worktree="$GITEA_WORKTREE_DIR/$user/$ts" - # Already inside a worktree we created — reuse it. - if [ -f "$worktree/.gitea-worktree" ]; then - echo "Using existing worktree: $worktree" - PROJECT_DIR="$worktree" - cd "$PROJECT_DIR" - return 0 - fi + # Ensure origin/main is current so worktree starts from latest + git -C "$_MAIN_REPO_DIR" fetch origin main 2>/dev/null || true - local branch="agent/${user}/$(date +%Y%m%d-%H%M%S)" - echo "Creating worktree: $worktree (branch: $branch)" - mkdir -p "$GITEA_WORKTREE_DIR" - git -C "$_MAIN_REPO_DIR" worktree add -b "$branch" "$worktree" origin/main + echo "Creating worktree: $worktree (detached from origin/main)" + mkdir -p "$(dirname "$worktree")" + git -C "$_MAIN_REPO_DIR" worktree add --detach "$worktree" origin/main touch "$worktree/.gitea-worktree" + PROJECT_DIR="$worktree" + _WORKTREE_PATH="$worktree" cd "$PROJECT_DIR" } cleanup_worktree() { - local user="$1" - local worktree="$GITEA_WORKTREE_DIR/$user" - if [ -d "$worktree" ]; then - rm -f "$worktree/.gitea-worktree" - echo "Cleaning up worktree: $worktree" - git -C "$_MAIN_REPO_DIR" worktree remove "$worktree" 2>/dev/null || true - rm -rf "$worktree" 2>/dev/null || true + local worktree="${_WORKTREE_PATH:-}" + if [ -z "$worktree" ] || [ ! -f "$worktree/.gitea-worktree" ]; then + echo "No worktree to clean up (not created by this session)." + return 0 fi + rm -f "$worktree/.gitea-worktree" + echo "Cleaning up worktree: $worktree" + git -C "$_MAIN_REPO_DIR" worktree remove --force "$worktree" 2>/dev/null || true } # ── Validate required environment ────────────────────────────────────────────── diff --git a/scripts/start_dev_agent.sh b/scripts/start_dev_agent.sh index a01ccd2..2087217 100644 --- a/scripts/start_dev_agent.sh +++ b/scripts/start_dev_agent.sh @@ -19,15 +19,13 @@ source "$SCRIPT_DIR/_common.sh" setup_worktree "$GITEA_USER" # Cleanup worktree on exit (optional, comment out to keep for debugging) -trap 'cleanup_worktree "$GITEA_USER"' EXIT +trap 'cleanup_worktree' EXIT banner "Dev" require_token - -AGENT_CONF="$_MAIN_REPO_DIR/.claude/agents/dev-agent.md" launch_agent \ "dev-agent" \ - "$AGENT_CONF" \ + "$PROJECT_DIR/.claude/agents/dev-agent.md" \ "Dev-Agent" \ "执行一次 Issue 巡检(单次任务,不要用 /loop): 1. python scripts/agent_poller.py --action list 列出所有打开的 Issue diff --git a/scripts/start_generic.sh b/scripts/start_generic.sh new file mode 100644 index 0000000..aa384f4 --- /dev/null +++ b/scripts/start_generic.sh @@ -0,0 +1,22 @@ +#!/usr/bin/env bash +# Generic session 启动脚本 — 为人类用户提供 worktree 隔离 +# 用法: bash scripts/start_generic.sh +# GITEA_USER 默认 pzhangzywl(人类用户),可通过环境变量覆盖 + +set -eu + +export GITEA_USER="${GITEA_USER:-pzhangzywl}" + +SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" +source "$SCRIPT_DIR/_common.sh" + +setup_worktree "$GITEA_USER" +trap 'cleanup_worktree' EXIT + +banner "Generic" +require_token + +echo "工作目录: $PROJECT_DIR" +echo "" +cd "$PROJECT_DIR" +claude diff --git a/scripts/start_qe_agent.sh b/scripts/start_qe_agent.sh index a5823bd..5807fec 100644 --- a/scripts/start_qe_agent.sh +++ b/scripts/start_qe_agent.sh @@ -19,15 +19,13 @@ source "$SCRIPT_DIR/_common.sh" setup_worktree "$GITEA_USER" # Cleanup worktree on exit (optional, comment out to keep for debugging) -trap 'cleanup_worktree "$GITEA_USER"' EXIT +trap 'cleanup_worktree' EXIT banner "QE" require_token - -AGENT_CONF="$_MAIN_REPO_DIR/.claude/agents/qe-agent.md" launch_agent \ "qe-agent" \ - "$AGENT_CONF" \ + "$PROJECT_DIR/.claude/agents/qe-agent.md" \ "QE-Agent" \ "执行一次 Issue 巡检(单次任务,不要用 /loop): 1. python scripts/agent_poller.py --action list --labels test-code 检查 test-code Issue