Repository navigation
chore(tooling): 引入 opsx-worktree-provision 隔離 OpenSpec apply - #53
Conversation
把 closed-loop-orchestrator Phase A 從 in-place `git switch -c` 改為 建立 git worktree 到 `<repo>/.worktrees/<change-id>/`。main worktree 保持唯讀,每個 active change 有獨立 working directory,apply 結束 worktree 保留供 review。 - 新增 docs/agent-tooling/opsx-worktree-provision.md (canonical 設計留底) - 新增 .claude/skills/opsx-worktree-provision/SKILL.md (七步流程 + manifest) - .gitignore 加 .worktrees/ ignore 與 skill 例外 - closed-loop-orchestrator Phase A 改呼叫 opsx-worktree-provision - apply-and-verify 觸發前提改 manifest.cwd_hint,所有指令走 worktree 絕對路徑 env policy: agent copy (非 symlink、不覆蓋既存、不 log 內容) venv policy: per-service self-bootstrap (worktree 內各服務首次自建) continue-existing: 不自動 pull --rebase (保守政策) follow-up: .codex/worktrees/* 殘留 GC 拆獨立 change;Codex Code mirror Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
📝 WalkthroughWalkthroughThis PR introduces git worktree isolation for OpenSpec's closed-loop automation pipeline. A new ChangesGit Worktree Isolation for OpenSpec Automation
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 5
🧹 Nitpick comments (4)
.claude/skills/closed-loop-orchestrator/SKILL.md (1)
38-40: ⚡ Quick winSpecify a fence language for this command block.
This block triggers MD040; tagging it as
bashkeeps docs lint-clean.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In @.claude/skills/closed-loop-orchestrator/SKILL.md around lines 38 - 40, The fenced code block containing the command "/opsx-worktree-provision <change-id> --branch-plan <new|continue-existing>" needs a language tag to satisfy MD040; edit the triple-backtick block in SKILL.md to use a bash fence (i.e., replace ``` with ```bash) so the snippet is explicitly marked as bash..claude/skills/opsx-worktree-provision/SKILL.md (1)
28-31: ⚡ Quick winAdd language identifiers to fenced code blocks to satisfy markdownlint.
These unlabeled code fences trigger MD040 and can fail doc quality checks. Add
bash/yamlwhere applicable.Also applies to: 37-39, 59-62, 77-84
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In @.claude/skills/opsx-worktree-provision/SKILL.md around lines 28 - 31, The markdown has unlabeled fenced code blocks (e.g. the blocks containing the git commands `git rev-parse --show-toplevel` and `git rev-parse --git-common-dir` and other unlabeled snippets) which trigger MD040; update each triple-backtick fence to include the appropriate language tag (for shell snippets use ```bash or ```sh and for configuration blocks use ```yaml) so all fenced code blocks are labeled (also fix the other unlabeled blocks around the same sections referenced in the comment)..claude/skills/apply-and-verify/SKILL.md (1)
66-78: ⚡ Quick winAdd explicit fence languages for command snippets.
These command fences are missing language tags and currently trip MD040.
Also applies to: 87-89, 95-97
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In @.claude/skills/apply-and-verify/SKILL.md around lines 66 - 78, The fenced command blocks under the headings "# _worker", "# _bim-control", "# bim-review-coordinator", and "# web-viewer-sample" (and the other similar command blocks later in the file) lack language tags and trigger MD040; update each triple-backtick fence to include a shell language tag such as ```sh or ```bash so the runner commands (e.g., cd "<cwd_hint>/... && python -m pytest ..." and npm test) are explicitly marked as shell commands, ensuring consistency across the other command blocks as well.docs/agent-tooling/opsx-worktree-provision.md (1)
184-194: 💤 Low valueConsider adding .env staleness detection for long-running sessions.
Risk:
.env為 main 快照、main 改動不同步 (line 189) is mitigated only by documentation inmanifest.warnings. For long-running apply sessions spanning days, stale environment configuration could cause subtle runtime failures.Consider enhancing the mitigation with an optional check:
- Record timestamps of copied
.envfiles in the manifest- Provide a helper command to detect if main's
.envfiles have been modified since worktree creation- Warn users in long-running sessions to review and potentially recopy
.envThis is optional for the current scope but could improve robustness for extended workflows.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@docs/agent-tooling/opsx-worktree-provision.md` around lines 184 - 194, The mitigation for ".env 為 main 快照、main 改動不同步" only documents the risk in manifest.warnings; add an optional staleness-detection feature by recording the copied .env file's timestamp/hash into the manifest metadata when creating the worktree (e.g., augment manifest with a .env_snapshot timestamp/checksum), implement a helper (CLI) command to compare the recorded .env snapshot against main's current .env (using timestamp or checksum) and return/warn if changed, and surface this warning in long-running apply sessions (e.g., during apply session startup or via an explicit "check-env-staleness" command) so users are prompted to review/recopy .env when differences are detected.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In @.claude/skills/apply-and-verify/SKILL.md:
- Around line 68-74: The test command lines in SKILL.md use `python -m pytest
...` which conflicts with the declared allowed-tools pattern `Bash(pytest*)`;
either replace the invocations `python -m pytest tests/ -x` with plain `pytest
tests/ -x` (e.g., in the three entries referencing _worker, _bim-control,
bim-review-coordinator) so they match `Bash(pytest*)`, or update the tool
allowlist to permit `python -m pytest` invocations; modify whichever is
appropriate so the command strings and the allowlist (`Bash(pytest*)` vs `python
-m pytest`) are consistent.
In @.claude/skills/opsx-worktree-provision/SKILL.md:
- Line 125: 將原本描述 "gh 指令認 branch 不認 cwd,可在任何位置呼叫" 改為明確說明 gh pr create 的條件:指出若在非
Git 工作目錄呼叫,必須加上 --repo <owner/repo>(或指定工作樹路徑)才能成功,否則需在含 .git 的本地倉庫或 worktree
中執行;具體修改目標為該行文字,將「可在任何位置呼叫」改為「可在任何位置呼叫(需搭配 --repo 指定倉庫),或在本地 git 倉庫 / worktree
中直接執行」以避免誤導。
In `@docs/agent-tooling/opsx-worktree-provision.md`:
- Around line 81-90: The reuse branch in the Step 5 flow currently only checks
directory existence (case (T, *, *)); before setting created_new = false, verify
that target_path is a real Git worktree by checking git worktree list
--porcelain for the absolute path or that target_path contains a .git file; if
the check fails (directory is stale/pruned), delete or clean target_path and let
the logic fall through to the creation cases (the same branches that call git
worktree add / git worktree add -b <branch> origin/<branch> / git worktree add
-b <branch> main) so git can create a fresh worktree.
- Around line 157-168: Update the `cleanup_hint` text to include guidance for
force-deleting branches: either replace the existing `git branch -d
codex/openspec/<change-id>` suggestion with `git branch -D
codex/openspec/<change-id>` for unmerged/abandoned worktrees, or (preferred)
show both variants so users can choose: keep `git branch -d
codex/openspec/<change-id>` as the safe option and add `git branch -D
codex/openspec/<change-id>` as the force option, with a short comment indicating
when to use each; update the `cleanup_hint` output code snippet accordingly.
- Around line 73-80: Update the "Branch 是否綁在其他 path" gate logic to explicitly
allow the case where `git worktree list --porcelain` reports the branch bound to
the same `target_path` and treat it as the reuse path (Step 5 case `T,*,*`)
instead of stopping with `branch-bound-elsewhere`; modify the table or add a
clarifying sentence that the check must compare the reported path against
`target_path` and only trigger STOP `branch-bound-elsewhere` when the bound path
differs, otherwise continue to the reuse flow.
---
Nitpick comments:
In @.claude/skills/apply-and-verify/SKILL.md:
- Around line 66-78: The fenced command blocks under the headings "# _worker",
"# _bim-control", "# bim-review-coordinator", and "# web-viewer-sample" (and the
other similar command blocks later in the file) lack language tags and trigger
MD040; update each triple-backtick fence to include a shell language tag such as
```sh or ```bash so the runner commands (e.g., cd "<cwd_hint>/... && python -m
pytest ..." and npm test) are explicitly marked as shell commands, ensuring
consistency across the other command blocks as well.
In @.claude/skills/closed-loop-orchestrator/SKILL.md:
- Around line 38-40: The fenced code block containing the command
"/opsx-worktree-provision <change-id> --branch-plan <new|continue-existing>"
needs a language tag to satisfy MD040; edit the triple-backtick block in
SKILL.md to use a bash fence (i.e., replace ``` with ```bash) so the snippet is
explicitly marked as bash.
In @.claude/skills/opsx-worktree-provision/SKILL.md:
- Around line 28-31: The markdown has unlabeled fenced code blocks (e.g. the
blocks containing the git commands `git rev-parse --show-toplevel` and `git
rev-parse --git-common-dir` and other unlabeled snippets) which trigger MD040;
update each triple-backtick fence to include the appropriate language tag (for
shell snippets use ```bash or ```sh and for configuration blocks use ```yaml) so
all fenced code blocks are labeled (also fix the other unlabeled blocks around
the same sections referenced in the comment).
In `@docs/agent-tooling/opsx-worktree-provision.md`:
- Around line 184-194: The mitigation for ".env 為 main 快照、main 改動不同步" only
documents the risk in manifest.warnings; add an optional staleness-detection
feature by recording the copied .env file's timestamp/hash into the manifest
metadata when creating the worktree (e.g., augment manifest with a .env_snapshot
timestamp/checksum), implement a helper (CLI) command to compare the recorded
.env snapshot against main's current .env (using timestamp or checksum) and
return/warn if changed, and surface this warning in long-running apply sessions
(e.g., during apply session startup or via an explicit "check-env-staleness"
command) so users are prompted to review/recopy .env when differences are
detected.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: e634566c-8554-4852-8808-9be82e723ebd
📒 Files selected for processing (5)
.claude/skills/apply-and-verify/SKILL.md.claude/skills/closed-loop-orchestrator/SKILL.md.claude/skills/opsx-worktree-provision/SKILL.md.gitignoredocs/agent-tooling/opsx-worktree-provision.md
| !`cd "<cwd_hint>/_worker" && python -m pytest tests/ -x` | ||
|
|
||
| # _bim-control | ||
| !`cd _bim-control && python -m pytest tests/ -x` | ||
| !`cd "<cwd_hint>/_bim-control" && python -m pytest tests/ -x` | ||
|
|
||
| # bim-review-coordinator | ||
| !`cd bim-review-coordinator && python -m pytest tests/ -x` | ||
| !`cd "<cwd_hint>/bim-review-coordinator" && python -m pytest tests/ -x` |
There was a problem hiding this comment.
Test commands conflict with the declared tool allowlist.
The doc now uses python -m pytest ..., but allowed-tools only permits Bash(pytest*). That mismatch can make these steps non-executable under policy enforcement.
Suggested doc-aligned fix
-!`cd "<cwd_hint>/_worker" && python -m pytest tests/ -x`
+!`cd "<cwd_hint>/_worker" && pytest tests/ -x`
-!`cd "<cwd_hint>/_bim-control" && python -m pytest tests/ -x`
+!`cd "<cwd_hint>/_bim-control" && pytest tests/ -x`
-!`cd "<cwd_hint>/bim-review-coordinator" && python -m pytest tests/ -x`
+!`cd "<cwd_hint>/bim-review-coordinator" && pytest tests/ -x`🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In @.claude/skills/apply-and-verify/SKILL.md around lines 68 - 74, The test
command lines in SKILL.md use `python -m pytest ...` which conflicts with the
declared allowed-tools pattern `Bash(pytest*)`; either replace the invocations
`python -m pytest tests/ -x` with plain `pytest tests/ -x` (e.g., in the three
entries referencing _worker, _bim-control, bim-review-coordinator) so they match
`Bash(pytest*)`, or update the tool allowlist to permit `python -m pytest`
invocations; modify whichever is appropriate so the command strings and the
allowlist (`Bash(pytest*)` vs `python -m pytest`) are consistent.
| - 所有 git 動作用 `git -C "<cwd_hint>" ...` 或 `cd "<cwd_hint>" && ...` | ||
| - 各服務測試 `cd "<cwd_hint>/<service>" && <test cmd>` | ||
| - 不在 main worktree (`<repo_root>`) 內做任何 edit / commit | ||
| - gh 指令認 branch 不認 cwd,可在任何位置呼叫 |
There was a problem hiding this comment.
🧩 Analysis chain
🌐 Web query:
Does gh pr createrequire being run inside a local git repository (or using--repo)? Please cite GitHub CLI docs.
💡 Result:
No, gh pr create does not strictly require being run inside a local git repository if using the --repo flag to specify the target repository explicitly. The official GitHub CLI manual documents the -R, --repo <[HOST/]OWNER/REPO> flag, which allows selecting another repository, enabling the command to work outside a local git repo as long as required flags like --title, --body, --head, and --base are provided (since features like --fill rely on local git commits and will fail without a repo) [1][2]. A merged pull request specifically enabled gh pr create --repo from outside a local git repository [2]. Without --repo (or a default repo set via gh repo set-default), it requires a local git repo to determine the repository from remotes [3].
Citations:
- 1: https://cli.github.com/manual/gh_pr_create
- 2: Enable
gh pr createfrom outside of a local git repo cli/cli#6527 - 3:
gh pr createnow requires a default remote repository to be set, can't override on a per-PR basis cli/cli#7216
Clarify conditions for gh invocation from arbitrary locations.
"可在任何位置呼叫" (can be called from any location) is misleading without context. gh pr create requires either a local git repository context OR the --repo flag. Calling it from arbitrary directories without --repo will fail. Revise to specify: "可使用 --repo 指令在任何位置呼叫" (can be called from any location using --repo flag) or document the repo/worktree path requirement explicitly.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In @.claude/skills/opsx-worktree-provision/SKILL.md at line 125, 將原本描述 "gh 指令認
branch 不認 cwd,可在任何位置呼叫" 改為明確說明 gh pr create 的條件:指出若在非 Git 工作目錄呼叫,必須加上 --repo
<owner/repo>(或指定工作樹路徑)才能成功,否則需在含 .git 的本地倉庫或 worktree
中執行;具體修改目標為該行文字,將「可在任何位置呼叫」改為「可在任何位置呼叫(需搭配 --repo 指定倉庫),或在本地 git 倉庫 / worktree
中直接執行」以避免誤導。
| ### Step 4:衝突偵測 | ||
|
|
||
| | 偵測 | 指令 | 失敗動作 | | ||
| |---|---|---| | ||
| | Branch 是否綁在其他 path | `git worktree list --porcelain` | STOP `branch-bound-elsewhere`,列出衝突 path | | ||
| | target_path 是否髒 | `git -C <target_path> status --porcelain`(若存在) | STOP `worktree-dirty`,提示上次 apply 未收尾 | | ||
| | main 是否髒 | `git status --porcelain` | STOP `main-dirty`,要求先 stash / commit | | ||
|
|
There was a problem hiding this comment.
🛠️ Refactor suggestion | 🟠 Major | ⚡ Quick win
Clarify the branch-bound-elsewhere gate logic for same-path scenarios.
Step 4's "branch bound elsewhere" check should explicitly handle the case where git worktree list shows the branch is already bound to the same target_path. This scenario should proceed to the reuse case (Step 5 case T,,) rather than triggering a branch-bound-elsewhere STOP.
Consider adding to the table:
| Branch 是否綁在其他 path | `git worktree list --porcelain` | STOP `branch-bound-elsewhere`,列出衝突 path |
+ ↳ 若綁在 target_path 本身,視為可重用,繼續 Step 5📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| ### Step 4:衝突偵測 | |
| | 偵測 | 指令 | 失敗動作 | | |
| |---|---|---| | |
| | Branch 是否綁在其他 path | `git worktree list --porcelain` | STOP `branch-bound-elsewhere`,列出衝突 path | | |
| | target_path 是否髒 | `git -C <target_path> status --porcelain`(若存在) | STOP `worktree-dirty`,提示上次 apply 未收尾 | | |
| | main 是否髒 | `git status --porcelain` | STOP `main-dirty`,要求先 stash / commit | | |
| ### Step 4:衝突偵測 | |
| | 偵測 | 指令 | 失敗動作 | | |
| |---|---|---| | |
| | Branch 是否綁在其他 path | `git worktree list --porcelain` | STOP `branch-bound-elsewhere`,列出衝突 path | | |
| | target_path 是否髒 | `git -C <target_path> status --porcelain`(若存在) | STOP `worktree-dirty`,提示上次 apply 未收尾 | | |
| | main 是否髒 | `git status --porcelain` | STOP `main-dirty`,要求先 stash / commit | | |
| **注:** 若 Branch 綁在 `target_path` 本身,視為可重用情形,繼續執行 Step 5。 |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@docs/agent-tooling/opsx-worktree-provision.md` around lines 73 - 80, Update
the "Branch 是否綁在其他 path" gate logic to explicitly allow the case where `git
worktree list --porcelain` reports the branch bound to the same `target_path`
and treat it as the reuse path (Step 5 case `T,*,*`) instead of stopping with
`branch-bound-elsewhere`; modify the table or add a clarifying sentence that the
check must compare the reported path against `target_path` and only trigger STOP
`branch-bound-elsewhere` when the bound path differs, otherwise continue to the
reuse flow.
| ### Step 5:建立或重用 | ||
|
|
||
| ```txt | ||
| case (target_path 存在?, branch 本地?, branch origin?): | ||
| (T, *, *) → 重用 (created_new = false) | ||
| (F, T, *) → git worktree add <target_path> <branch> | ||
| (F, F, T) → git worktree add <target_path> -b <branch> origin/<branch> | ||
| (F, F, F) → git worktree add <target_path> -b <branch> main | ||
| ``` | ||
|
|
There was a problem hiding this comment.
Validate target_path is a valid worktree before reusing.
Case (T, *, *) only checks directory existence. If target_path is a leftover directory (e.g., worktree pruned via git worktree prune but directory remains), reuse will fail when git operations run.
Before reusing, verify it's a valid worktree:
# Check if target_path appears in git worktree list
git worktree list --porcelain | grep -q "worktree $(cd target_path && pwd)"
# OR check for .git file
test -f <target_path>/.gitIf invalid, remove the directory and fall through to the creation cases.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@docs/agent-tooling/opsx-worktree-provision.md` around lines 81 - 90, The
reuse branch in the Step 5 flow currently only checks directory existence (case
(T, *, *)); before setting created_new = false, verify that target_path is a
real Git worktree by checking git worktree list --porcelain for the absolute
path or that target_path contains a .git file; if the check fails (directory is
stale/pruned), delete or clean target_path and let the logic fall through to the
creation cases (the same branches that call git worktree add / git worktree add
-b <branch> origin/<branch> / git worktree add -b <branch> main) so git can
create a fresh worktree.
| ## 7. apply 結束後 | ||
|
|
||
| - **不自動清**:worktree 保留供 review、後續 iteration、archive 同步。 | ||
| - skill 在 apply 結束時輸出 `cleanup_hint`: | ||
|
|
||
| ```bash | ||
| git worktree remove <worktree_path> | ||
| git branch -d codex/openspec/<change-id> | ||
| ``` | ||
|
|
||
| - 由 `archive-and-closeout` 收尾時再次提示,但仍由使用者人工執行。 | ||
|
|
There was a problem hiding this comment.
Consider git branch -D (force delete) in the cleanup hint.
The cleanup hint uses git branch -d codex/openspec/<change-id>, which performs a safe delete that fails if the branch hasn't been fully merged. Users cleaning up unmerged worktrees (e.g., abandoned changes or pre-merge cleanup) will encounter errors.
Suggest either:
- Default to
git branch -D(force), or - Provide both options with guidance:
git worktree remove <worktree_path> git branch -d codex/openspec/<change-id> # safe: only if merged git branch -D codex/openspec/<change-id> # force: if unmerged or abandoned
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@docs/agent-tooling/opsx-worktree-provision.md` around lines 157 - 168, Update
the `cleanup_hint` text to include guidance for force-deleting branches: either
replace the existing `git branch -d codex/openspec/<change-id>` suggestion with
`git branch -D codex/openspec/<change-id>` for unmerged/abandoned worktrees, or
(preferred) show both variants so users can choose: keep `git branch -d
codex/openspec/<change-id>` as the safe option and add `git branch -D
codex/openspec/<change-id>` as the force option, with a short comment indicating
when to use each; update the `cleanup_hint` output code snippet accordingly.
There was a problem hiding this comment.
Pull request overview
此 PR 將 OpenSpec apply 流程從 main worktree 內切 branch,改為透過 .worktrees/<change-id>/ 建立隔離 worktree,並更新相關 Claude skills 與設計文件。
Changes:
- 新增
opsx-worktree-provision設計文件與 Claude skill。 - 更新 closed-loop / apply-and-verify 流程以使用
manifest.cwd_hint。 - 更新
.gitignore以忽略.worktrees/並追蹤新 skill。
Reviewed changes
Copilot reviewed 4 out of 5 changed files in this pull request and generated 9 comments.
Show a summary per file
| File | Description |
|---|---|
docs/agent-tooling/opsx-worktree-provision.md |
新增 worktree provisioning 的 canonical 設計文件。 |
.gitignore |
允許追蹤新 Claude skill,並忽略 .worktrees/。 |
.claude/skills/opsx-worktree-provision/SKILL.md |
新增 worktree provisioning skill 流程。 |
.claude/skills/closed-loop-orchestrator/SKILL.md |
將 Phase A 改為呼叫 worktree provisioning。 |
.claude/skills/apply-and-verify/SKILL.md |
將測試、diff、push 等步驟導向 cwd_hint worktree。 |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
|
||
| ``` | ||
| !`git diff --check` | ||
| !`git -C "<cwd_hint>" diff --check` |
|
|
||
| ``` | ||
| !`git push -u origin codex/openspec/<change-id>` | ||
| !`git -C "<cwd_hint>" push -u origin codex/openspec/<change-id>` |
| - 已跑過 `gitnexus-blast-radius pre-change`,risk_level 非 CRITICAL | ||
| - 已在 `codex/openspec/<change-id>` branch | ||
| - 已執行 `opsx-worktree-provision`,取得 manifest,`cwd_hint = <repo>/.worktrees/<change-id>/`,HEAD = `codex/openspec/<change-id>` | ||
| - main worktree (`<repo_root>`) 保持唯讀,所有 git/edit/test 動作走 `git -C "<cwd_hint>"` 或 `cd "<cwd_hint>/<service>"` |
|
|
||
| ``` | ||
| !`gitnexus detect-changes --scope staged` | ||
| !`gitnexus detect-changes --scope staged --cwd "<cwd_hint>"` |
|
|
||
| **Gate**: | ||
| - skill 回報任一 `cwd-not-main` / `main-dirty` / `branch-bound-elsewhere` / `worktree-dirty` → STOP | ||
| - 後續所有 Phase 必須用 `manifest.cwd_hint` 作為 `git -C` / `cd` 目標 |
| - **永不覆蓋**:若 worktree 內目標檔已存在,**跳過**並記在 `env_copied` 的 `skipped` 子段。 | ||
| - **永不 log 內容**:只記檔名與大小,不 echo 任何 `.env` 內容。 | ||
| - **永不 commit**:worktree 內 `.gitignore` 已涵蓋;不得 `git add` `.env`。 |
| - 來源不存在 → 跳過。 | ||
| - 目標已存在於 worktree → 加進 `skipped`,**不覆蓋**。 | ||
| - 否則 `cp "<repo_root>/<path>" "<target_path>/<path>"`,加進 `copied`。 |
| | target_path 存在? | local_exists | remote_exists | 動作 | | ||
| |---|---|---|---| | ||
| | ✓ | * | * | 重用,`created_new = false` | | ||
| | ✗ | ✓ | * | `git worktree add <target_path> <branch>` | |
| | target_path 是否髒 | `git -C <target_path> status --porcelain`(若存在) | STOP `worktree-dirty`,提示上次 apply 未收尾 | | ||
| | main 是否髒 | `git status --porcelain` | STOP `main-dirty`,要求先 stash / commit | | ||
|
|
||
| ### Step 5:建立或重用 | ||
|
|
||
| ```txt | ||
| case (target_path 存在?, branch 本地?, branch origin?): | ||
| (T, *, *) → 重用 (created_new = false) | ||
| (F, T, *) → git worktree add <target_path> <branch> | ||
| (F, F, T) → git worktree add <target_path> -b <branch> origin/<branch> | ||
| (F, F, F) → git worktree add <target_path> -b <branch> main |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 7f46ecefb6
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| - 已執行 `opsx-worktree-provision`,取得 manifest,`cwd_hint = <repo>/.worktrees/<change-id>/`,HEAD = `codex/openspec/<change-id>` | ||
| - main worktree (`<repo_root>`) 保持唯讀,所有 git/edit/test 動作走 `git -C "<cwd_hint>"` 或 `cd "<cwd_hint>/<service>"` |
There was a problem hiding this comment.
Run OpenSpec validation from the worktree
When apply-and-verify is invoked after provisioning, the caller can still be in the main worktree while the change artifacts live under manifest.cwd_hint; however Layer 1 still runs openspec validate <change-id> --strict without cd "<cwd_hint>" or an equivalent cwd flag. In that context it validates main's openspec/changes tree instead of the worktree, so a newly created or updated change can fail as missing or, worse, pass against stale main contents while the actual worktree specs are invalid.
Useful? React with 👍 / 👎.
|
|
||
| ``` | ||
| !`git push -u origin codex/openspec/<change-id>` | ||
| !`git -C "<cwd_hint>" push -u origin codex/openspec/<change-id>` |
There was a problem hiding this comment.
Permit the new git -C commands
The skill now tells the agent to run commands that start with git -C, but the frontmatter still only whitelists prefixes such as Bash(git push*) and Bash(git diff*). In Claude Code's allowed-tools matching this means the new worktree-aware push/diff/status/add/commit commands are not covered by the declared permissions, so the apply flow can be blocked exactly when it tries to operate inside cwd_hint; add the appropriate Bash(git -C*) entries or use an allowed cd "<cwd_hint>" && git ... form consistently.
Useful? React with 👍 / 👎.
|
|
||
| | target_path 存在? | local_exists | remote_exists | 動作 | | ||
| |---|---|---|---| | ||
| | ✓ | * | * | 重用,`created_new = false` | |
There was a problem hiding this comment.
Verify the reused worktree branch
When <repo>/.worktrees/<change_id> already exists but is a clean worktree for a different branch or detached HEAD, this rule reuses it solely because the path exists. The manifest then advertises codex/openspec/<id>, so downstream edits and commits can land on the wrong branch; check target_path's current HEAD/branch against the desired branch before reusing it, and stop or recreate if it differs.
Useful? React with 👍 / 👎.
| # ---------------------------- | ||
| # OpenSpec apply worktrees (opsx-worktree-provision) | ||
| # ---------------------------- | ||
| .worktrees/ |
There was a problem hiding this comment.
Ignore copied local .env files
Step 6 copies service .env files into the linked worktree, but this ignore rule only hides the .worktrees/ directory from the main worktree; inside the linked worktree the copied paths such as _worker/.env or _bim-control/.env are still unignored. When those local files exist, the new worktree becomes dirty with untracked secrets and they can be accidentally staged by explicit git add, so add ignore patterns for the copied .env targets before relying on the copy step.
Useful? React with 👍 / 👎.
|
|
||
| **Gate**: | ||
| - skill 回報任一 `cwd-not-main` / `main-dirty` / `branch-bound-elsewhere` / `worktree-dirty` → STOP | ||
| - 後續所有 Phase 必須用 `manifest.cwd_hint` 作為 `git -C` / `cd` 目標 |
There was a problem hiding this comment.
Pass cwd_hint into spec exploration
This gate says every later phase must use manifest.cwd_hint, but Phase B still invokes openspec-explore-twice without passing or changing cwd, and that skill writes openspec/changes/<change-id>/... using relative paths. Under the new design assumption that the agent process stays in the main worktree, starting a new change will create or edit the OpenSpec artifacts in main before apply, making main dirty and bypassing the intended worktree isolation.
Useful? React with 👍 / 👎.
| |---|---|---| | ||
| | main-dirty | `git status --porcelain` 非空 | `main-dirty` | | ||
| | branch-bound-elsewhere | `git worktree list --porcelain` 顯示 branch 在另一 path | `branch-bound-elsewhere` | | ||
| | worktree-dirty | target_path 存在且 `git -C <target_path> status --porcelain` 非空 | `worktree-dirty` | |
There was a problem hiding this comment.
Permit provisioning's git -C status check
The worktree-dirty gate requires git -C <target_path> status --porcelain when a target path already exists, but this skill's allowed tools only cover prefixes like Bash(git status*), not commands that start with git -C. In a reuse/dirty-check scenario the skill can be blocked before it can inspect the existing worktree, so either whitelist Bash(git -C*) here or express the check as an allowed cd <target_path> && git status ... command.
Useful? React with 👍 / 👎.
|
|
||
| | target_path 存在? | local_exists | remote_exists | 動作 | | ||
| |---|---|---|---| | ||
| | ✓ | * | * | 重用,`created_new = false` | |
There was a problem hiding this comment.
Require target_path to be a registered worktree
If <repo>/.worktrees/<change_id> exists as a leftover plain directory rather than a Git worktree, this branch reuses it without checking git worktree list for that exact path. Because the directory is inside the main repo, git -C <target_path> ... can resolve to the parent repository while files under .worktrees/ remain ignored, so downstream edits may not be committed to codex/openspec/<id> at all; only reuse paths that are registered worktrees for the target branch.
Useful? React with 👍 / 👎.
變更摘要
把
closed-loop-orchestratorPhase A 從 in-placegit switch -c改為建立 git worktree 到<repo>/.worktrees/<change-id>/。main worktree 保持唯讀,每個 active change 有獨立 working directory,apply 結束 worktree 保留供 review。修改原因
依 AGENTS.md / CLAUDE.md §Git 與本機 agent 產物:
原本 Phase A 的 in-place 切換把 main 帶離 main,違反「main 保持唯讀」精神,且無法多 change 並行(雖然 S1 假設目前單 agent)。本 PR 把 branch 改成走 worktree,與 AGENTS.md 隔離精神對齊。
主要變更
docs/agent-tooling/opsx-worktree-provision.md(canonical 設計留底).claude/skills/opsx-worktree-provision/SKILL.md(七步流程 + manifest 輸出).worktrees/ignored;!.claude/skills/opsx-worktree-provision/例外 track 新 skillchange-id-resolve後插入opsx-worktree-provision;安全條款新增 Worktree isolation 條目manifest.cwd_hint;focused tests /git push/git diff --check/gitnexus detect-changes全部走<cwd_hint>絕對路徑;Step 6 report 加cleanup_hint設計決策(已在 explore 階段收斂)
<repo>/.worktrees/<change-id>/.env政策continue-existingpullpull --rebase(保守政策)docs/agent-tooling/)完整設計與 Gate / 風險清單見 docs/agent-tooling/opsx-worktree-provision.md。
驗證方式
git check-ignore—.worktrees/test被 ignore;新 skill 與 design doc 未被 ignoregit add --dry-run— 五個檔案都會被 stagegit diff --check— 無 whitespace 問題git worktree add到.worktrees/<id>/跑一輪(避免測試殘留進 PR)npx gitnexus analyze重建索引風險與影響
closed-loop-orchestratorPhase A、apply-and-verify觸發前提/closed-loop-orchestrator或/apply-and-verify會預期 worktree 已建立;舊有「在 main 直接 git switch」流程被取代codex/openspec/*分支若已在 main 工作樹上 checked out,新流程要求先 stash / commit 才能進入 worktree provisioninggit worktree add .worktrees/<test-id> -b codex/openspec/<test-id> main確認 happy path.envcopy 不覆蓋既存,最壞情況是 worktree 缺 env、各服務啟動失敗,使用者可自行 cp.codex/worktrees/*殘留干擾,由 follow-up change 處理(不在本 PR scope)回滾方式
若 merge 後發現問題:
gh pr revert <pr-number>→ 開 revert PR。skill 檔 revert 即可恢復 in-place 切換語意;.worktrees/目錄為本機 agent 產物,不影響 repo 主體。後續建議
.codex/worktrees/*殘留 GC(目前有 16 個 detached HEAD 殘留),拆獨立 change.codex/skills/opsx-worktree-provision/)apply-and-verify結束時自動 remove worktree 的選項(需先設計清理 gate,目前保守為手動)🤖 Generated with Claude Code
Summary by CodeRabbit
Documentation
Chores