Skip to content

chore(tooling): 引入 opsx-worktree-provision 隔離 OpenSpec apply - #53

Merged
monkey1sai merged 1 commit into
mainfrom
worktree-opsx-worktree-provision
May 14, 2026
Merged

monkey1sai merged 1 commit into
mainfrom
worktree-opsx-worktree-provision

Conversation

@monkey1sai

@monkey1sai monkey1sai commented May 14, 2026 •

Copy link
Copy Markdown
Owner

變更摘要

把 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。

修改原因

依 AGENTS.md / CLAUDE.md §Git 與本機 agent 產物:

OpenSpec change 不得直接在 main 上開發;/openspec new <change-id> 前先切到 codex/openspec/<change-id>。

原本 Phase A 的 in-place 切換把 main 帶離 main,違反「main 保持唯讀」精神,且無法多 change 並行(雖然 S1 假設目前單 agent)。本 PR 把 branch 改成走 worktree,與 AGENTS.md 隔離精神對齊。

主要變更

  • tooling: 新增 docs/agent-tooling/opsx-worktree-provision.md(canonical 設計留底)
  • tooling: 新增 .claude/skills/opsx-worktree-provision/SKILL.md(七步流程 + manifest 輸出)
  • gitignore: .worktrees/ ignored;!.claude/skills/opsx-worktree-provision/ 例外 track 新 skill
  • closed-loop-orchestrator: Phase A 在 change-id-resolve 後插入 opsx-worktree-provision;安全條款新增 Worktree isolation 條目
  • apply-and-verify: 觸發前提改 manifest.cwd_hint;focused tests / git push / git diff --check / gitnexus detect-changes 全部走 <cwd_hint> 絕對路徑;Step 6 report 加 cleanup_hint

設計決策(已在 explore 階段收斂)

主題 決策
worktree 根目錄 <repo>/.worktrees/<change-id>/
結束行為 保留 worktree 供 review,不自動清
.env 政策 agent 從 main copy(非 symlink、不覆蓋既存、不 log 內容)
venv 政策 各服務 worktree 內首次 apply 自建(per-service-self-bootstrap)
continue-existing pull 不自動 pull --rebase(保守政策)
是否入 OpenSpec 不(tooling-only,只入 docs/agent-tooling/)
雙 agent 並行 不考慮(單 agent session 假設 S1)

完整設計與 Gate / 風險清單見 docs/agent-tooling/opsx-worktree-provision.md。

驗證方式

  • git check-ignore — .worktrees/test 被 ignore;新 skill 與 design doc 未被 ignore
  • git add --dry-run — 五個檔案都會被 stage
  • git diff --check — 無 whitespace 問題
  • 端到端 happy path — 沒在 PR 前實際 git worktree add 到 .worktrees/<id>/ 跑一輪(避免測試殘留進 PR)
  • GitNexus reindex — 本 PR 只動 skill markdown / gitignore / docs,沒有改任何 function / class / method,依 AGENTS.md 規範不需要 pre-change impact analysis;merge 後可選擇是否跑 npx gitnexus analyze 重建索引

風險與影響

  • risk_level: LOW
  • affected processes: closed-loop-orchestrator Phase A、apply-and-verify 觸發前提
  • 行為差異:
    • 下次 /closed-loop-orchestrator 或 /apply-and-verify 會預期 worktree 已建立;舊有「在 main 直接 git switch」流程被取代
    • 既有 codex/openspec/* 分支若已在 main 工作樹上 checked out,新流程要求先 stash / commit 才能進入 worktree provisioning
  • mitigation:
    • 第一次跑真實 apply 前,先在乾淨 main 上手動試一次 git worktree add .worktrees/<test-id> -b codex/openspec/<test-id> main 確認 happy path
    • .env copy 不覆蓋既存,最壞情況是 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 主體。

後續建議

  • follow-up 1: .codex/worktrees/* 殘留 GC(目前有 16 個 detached HEAD 殘留),拆獨立 change
  • follow-up 2: Codex Code 對應 skill mirror(.codex/skills/opsx-worktree-provision/)
  • follow-up 3: apply-and-verify 結束時自動 remove worktree 的選項(需先設計清理 gate,目前保守為手動)

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Documentation

    • Added skill documentation for Git worktree provisioning and management workflows.
    • Updated orchestration and apply-and-verify specifications to implement worktree-based isolation.
    • Added developer tooling documentation for automated change branch provisioning.
  • Chores

    • Updated project configuration to exclude worktree directories.

Review Change Stack

把 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>
Copilot AI review requested due to automatic review settings May 14, 2026 10:20
@coderabbitai

coderabbitai Bot commented May 14, 2026 •

Copy link
Copy Markdown
Contributor
📝 Walkthrough

Walkthrough

This PR introduces git worktree isolation for OpenSpec's closed-loop automation pipeline. A new opsx-worktree-provision skill provisions isolated worktrees for change branches with safety gates, the orchestrator integrates this step, and apply-and-verify updates all git and test operations to run scoped to the worktree while keeping main read-only.

Changes

Git Worktree Isolation for OpenSpec Automation

Layer / File(s) Summary
Worktree provisioning skill contract
.claude/skills/opsx-worktree-provision/SKILL.md
Defines the complete contract for provisioning isolated git worktrees: input schema, seven-step workflow including worktree validation, origin sync, target resolution, four safety gates (main dirty, branch bound, worktree dirty), and conditional worktree creation. Specifies .env hard-copy rules, manifest YAML output with cwd_hint, base_ref, created_new, and env_copied fields, downstream usage conventions (all git/test under cwd_hint, no main edits), manual cleanup instructions, and explicit security restrictions.
Orchestrator Phase A worktree integration
.claude/skills/closed-loop-orchestrator/SKILL.md
Replaces git switch with worktree-based isolation. Phase A now calls opsx-worktree-provision, consumes the manifest, enforces stop gates for cwd/main cleanliness and worktree state, and mandates all subsequent phases route git/cd operations through manifest.cwd_hint. Changes continue-existing to avoid automatic pull --rebase and forbids edits/commits in main worktree.
Apply-and-verify worktree-scoped execution
.claude/skills/apply-and-verify/SKILL.md
Updates all operations to run inside the provisioned worktree. Adds prerequisite that opsx-worktree-provision obtained cwd_hint. Rewrites focused test layer to execute each service's test command from cwd_hint's service directory. Updates diff hygiene to git -C "<cwd_hint>" diff --check, GitNexus drift to pass --cwd "<cwd_hint>", and git push to git -C "<cwd_hint>" push -u .... Adds PR creation guidance, extends report with worktree_path: <cwd_hint>, adds manual cleanup hints, and updates safety rules against main worktree modifications.
Configuration and design documentation
.gitignore, docs/agent-tooling/opsx-worktree-provision.md
Whitelists opsx-worktree-provision/ skill and ignores .worktrees/ directory. Introduces design spec documenting worktree path/branch naming, provisioning workflow, .env snapshot copying, manifest contract, continue-existing behavior, manual cleanup expectations, and integration into the orchestrator → apply-and-verify → closeout flow with enumerated risks and follow-up items.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

  • monkey1sai/AI-BIM-governance#36: The main PR's worktree-scoped changes build directly on the apply-and-verify and closed-loop-orchestrator skills introduced in PR #36, modifying them to use worktree isolation instead of direct branch switching.

Poem

A worktree springs forth, pristine and new, 🌿
While main sleeps safely, read-only and true,
Gates guard the way—no dirty commits slide,
Each service test runs in its worktree-bound pride! 🐰

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title directly describes the main change: introducing opsx-worktree-provision tooling to isolate OpenSpec apply operations using git worktrees.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch worktree-opsx-worktree-provision

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

🧹 Nitpick comments (4)
.claude/skills/closed-loop-orchestrator/SKILL.md (1)

38-40: ⚡ Quick win

Specify a fence language for this command block.

This block triggers MD040; tagging it as bash keeps 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 win

Add language identifiers to fenced code blocks to satisfy markdownlint.

These unlabeled code fences trigger MD040 and can fail doc quality checks. Add bash/yaml where 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 win

Add 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 value

Consider adding .env staleness detection for long-running sessions.

Risk: .env 為 main 快照、main 改動不同步 (line 189) is mitigated only by documentation in manifest.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 .env files in the manifest
  • Provide a helper command to detect if main's .env files have been modified since worktree creation
  • Warn users in long-running sessions to review and potentially recopy .env

This 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

📥 Commits

Reviewing files that changed from the base of the PR and between e92424b and 7f46ece.

📒 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
  • .gitignore
  • docs/agent-tooling/opsx-worktree-provision.md

Comment on lines +68 to +74
!`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`

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

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,可在任何位置呼叫

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

🧩 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 &lt;[HOST/]OWNER/REPO&gt; 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:


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
中直接執行」以避免誤導。

Comment on lines +73 to +80
### 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 |

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ 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.

Suggested change
### 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.

Comment on lines +81 to +90
### 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
```

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

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>/.git

If 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.

Comment on lines +157 to +168
## 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` 收尾時再次提示,但仍由使用者人工執行。

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

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:

  1. Default to git branch -D (force), or
  2. 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.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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` 目標
Comment on lines +107 to +109
- **永不覆蓋**:若 worktree 內目標檔已存在,**跳過**並記在 `env_copied` 的 `skipped` 子段。
- **永不 log 內容**:只記檔名與大小,不 echo 任何 `.env` 內容。
- **永不 commit**:worktree 內 `.gitignore` 已涵蓋;不得 `git add` `.env`。
Comment on lines +88 to +90
- 來源不存在 → 跳過。
- 目標已存在於 worktree → 加進 `skipped`,**不覆蓋**。
- 否則 `cp "<repo_root>/<path>" "<target_path>/<path>"`,加進 `copied`。
Comment on lines +64 to +67
| target_path 存在? | local_exists | remote_exists | 動作 |
|---|---|---|---|
| ✓ | * | * | 重用,`created_new = false` |
| ✗ | ✓ | * | `git worktree add <target_path> <branch>` |
Comment on lines +78 to +88
| 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

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 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".

Comment on lines +16 to +17
- 已執行 `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>"`

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge 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>`

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge 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` |

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge 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 👍 / 👎.

Comment thread .gitignore
# ----------------------------
# OpenSpec apply worktrees (opsx-worktree-provision)
# ----------------------------
.worktrees/

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge 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` 目標

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge 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` |

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge 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` |

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge 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 👍 / 👎.

@monkey1sai
monkey1sai merged commit cb1259a into main May 14, 2026
5 checks passed
@monkey1sai
monkey1sai deleted the worktree-opsx-worktree-provision branch May 14, 2026 10:30
@monkey1sai
monkey1sai restored the worktree-opsx-worktree-provision branch May 14, 2026 10:30
@monkey1sai
monkey1sai deleted the worktree-opsx-worktree-provision branch May 14, 2026 10:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants