acstack 0.0.0-stage → 0.47.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (143) hide show
  1. package/.claude-plugin/plugin.json +19 -0
  2. package/LICENSE +21 -0
  3. package/README.md +389 -2
  4. package/THIRD_PARTY_NOTICES +14 -0
  5. package/TROUBLESHOOTING.md +225 -0
  6. package/agents/codex/frontend-verifier.toml +352 -0
  7. package/agents/codex/task-checker.toml +345 -0
  8. package/agents/codex/task-executor.toml +157 -0
  9. package/agents/codex/test-writer.toml +149 -0
  10. package/agents/frontend-verifier.md +351 -0
  11. package/agents/task-checker.md +344 -0
  12. package/agents/task-executor.md +156 -0
  13. package/agents/test-writer.md +148 -0
  14. package/assets/playwriter-bridge/build-launcher.ps1 +32 -0
  15. package/assets/playwriter-bridge/doctor.ps1 +450 -0
  16. package/assets/playwriter-bridge/launcher-src.cs +131 -0
  17. package/assets/playwriter-bridge/opener.js +330 -0
  18. package/assets/playwriter-bridge/opener.ps1 +63 -0
  19. package/assets/playwriter-bridge/register-tasks.ps1 +328 -0
  20. package/assets/playwriter-bridge/relay.ps1 +50 -0
  21. package/assets/playwriter-bridge/stop.ps1 +125 -0
  22. package/assets/playwriter-bridge/sync.ps1 +271 -0
  23. package/assets/playwriter-bridge/tunnel.ps1 +325 -0
  24. package/assets/playwriter-bridge/vm-free-port.sh +166 -0
  25. package/assets/terminal-workspace/client-keybindings.md +87 -0
  26. package/assets/terminal-workspace/config.example.yaml +329 -0
  27. package/assets/terminal-workspace/setup.sh +4317 -0
  28. package/cli/README.md +47 -0
  29. package/cli/bin/acstack.js +3 -0
  30. package/cli/dist/index.js +25984 -0
  31. package/cli/dist/index.js.map +7 -0
  32. package/cli/package.json +59 -0
  33. package/docs/adr/0001-ste-writing-standard.md +16 -0
  34. package/docs/adr/0002-version-gate-not-auto-bump.md +35 -0
  35. package/docs/adr/0003-handoff-ack-command.md +19 -0
  36. package/docs/adr/0004-dev-setup-per-host.md +13 -0
  37. package/docs/adr/0005-two-orchestrators-per-host.md +25 -0
  38. package/docs/adr/0006-document-opener-service.md +89 -0
  39. package/docs/adr/0007-lead-check-reads-the-transcript.md +87 -0
  40. package/docs/adr/0008-cli-audits-skill-interviews.md +37 -0
  41. package/docs/adr/0009-verify-the-write-not-the-writer.md +51 -0
  42. package/docs/adr/0010-promote-dev-to-main-by-fast-forward.md +115 -0
  43. package/docs/adr/0011-node-header-is-the-edge-encoding.md +20 -0
  44. package/docs/adr/0012-node-kind-is-a-closed-set-of-five.md +31 -0
  45. package/docs/adr/0013-the-diagram-renderer-is-pure.md +23 -0
  46. package/docs/adr/0014-reading-a-node-hides-its-generated-diagram.md +29 -0
  47. package/docs/adr/0015-a-node-id-links-to-its-issue-through-an-anchor.md +37 -0
  48. package/docs/adr/0016-the-map-root-carries-no-status-of-its-own.md +21 -0
  49. package/docs/adr/0017-call-impeccable-copy-only-its-questions.md +13 -0
  50. package/docs/adr/index.md +17 -0
  51. package/docs/config-reference.md +572 -0
  52. package/docs/dev-setups.md +164 -0
  53. package/docs/migrate-0.8.md +28 -0
  54. package/docs/playwriter-bridge-windows.md +15 -0
  55. package/docs/terminal-workspace-keys.md +137 -0
  56. package/docs/terminal-workspace.md +1774 -0
  57. package/docs/workflows.md +309 -0
  58. package/hooks/ac-writing-style-reminder.sh +86 -0
  59. package/hooks/context-pressure.sh +583 -0
  60. package/hooks/hooks.json +50 -0
  61. package/hooks/session-start-handoff.sh +165 -0
  62. package/hooks/session-start.sh +214 -0
  63. package/orchestrator/AGENTS.md +532 -0
  64. package/output-styles/ac-writing-style.md +286 -0
  65. package/package.json +50 -4
  66. package/pi/agents/frontend-verifier.md +357 -0
  67. package/pi/agents/task-checker.md +348 -0
  68. package/pi/agents/task-executor.md +160 -0
  69. package/pi/agents/test-writer.md +154 -0
  70. package/pi/extension.ts +723 -0
  71. package/profiles/fullstack-python.yaml +29 -0
  72. package/profiles/node-typescript.yaml +23 -0
  73. package/profiles/python.yaml +24 -0
  74. package/skills/archive/SKILL.md +160 -0
  75. package/skills/bootstrap/SKILL.md +109 -0
  76. package/skills/bridge/HANDOFF.md +93 -0
  77. package/skills/bridge/SKILL-VM.md +292 -0
  78. package/skills/bridge/SKILL-WINDOWS.md +526 -0
  79. package/skills/bridge/SKILL.md +121 -0
  80. package/skills/browser-verify/SKILL.md +229 -0
  81. package/skills/code-review/SKILL.md +44 -0
  82. package/skills/commit/SKILL.md +106 -0
  83. package/skills/compact-and-continue/SKILL.md +241 -0
  84. package/skills/explore/SKILL.md +149 -0
  85. package/skills/grilling/SKILL.md +134 -0
  86. package/skills/handoff/SKILL.md +250 -0
  87. package/skills/handoff/launch-herdr.md +197 -0
  88. package/skills/handoff/launch-without-herdr.md +30 -0
  89. package/skills/handoff/lead-check.md +59 -0
  90. package/skills/handoff/outcomes.md +162 -0
  91. package/skills/handoff/running-agent.md +50 -0
  92. package/skills/handoff/watch.md +115 -0
  93. package/skills/host/SKILL.md +247 -0
  94. package/skills/host/detect-host.sh +297 -0
  95. package/skills/host/herdr.md +79 -0
  96. package/skills/host/install-herdr-block.sh +467 -0
  97. package/skills/host/install-orca.sh +512 -0
  98. package/skills/host/notes.md +97 -0
  99. package/skills/host/orca.md +160 -0
  100. package/skills/host/questions.md +163 -0
  101. package/skills/host/report.md +42 -0
  102. package/skills/implement/SKILL.md +230 -0
  103. package/skills/implement/decision-log.md +62 -0
  104. package/skills/implement/design-pass.md +32 -0
  105. package/skills/implement/relaxed-tdd.md +28 -0
  106. package/skills/map/SKILL.md +250 -0
  107. package/skills/map/frontend.md +227 -0
  108. package/skills/map/trackers/files.md +74 -0
  109. package/skills/map/trackers/github.md +180 -0
  110. package/skills/map/visuals.md +387 -0
  111. package/skills/new-worktree/SKILL.md +155 -0
  112. package/skills/new-worktree/detect-orchestrator.sh +328 -0
  113. package/skills/new-worktree/detect-orchestrator.test.sh +894 -0
  114. package/skills/new-worktree/herdr.md +84 -0
  115. package/skills/new-worktree/orca.md +101 -0
  116. package/skills/pre-commit-review/SKILL.md +242 -0
  117. package/skills/pre-commit-review/auto-fix.md +19 -0
  118. package/skills/pre-commit-review/interactive.md +35 -0
  119. package/skills/quick-fix/SKILL.md +125 -0
  120. package/skills/record-context/SKILL.md +106 -0
  121. package/skills/setup/SKILL.md +250 -0
  122. package/skills/setup/browser.md +123 -0
  123. package/skills/setup/design-review.md +97 -0
  124. package/skills/setup/first-run.md +114 -0
  125. package/skills/setup/report.md +68 -0
  126. package/skills/setup/row-fixes.md +196 -0
  127. package/skills/setup/terminal-workspace.md +153 -0
  128. package/skills/sync/SKILL.md +171 -0
  129. package/skills/teardown-worktree/SKILL.md +245 -0
  130. package/skills/teardown-worktree/detector.md +39 -0
  131. package/skills/teardown-worktree/herdr.md +113 -0
  132. package/skills/teardown-worktree/orca.md +61 -0
  133. package/skills/terminal-workspace/SKILL.md +249 -0
  134. package/skills/terminal-workspace/components.md +36 -0
  135. package/skills/terminal-workspace/config-choices.md +69 -0
  136. package/skills/terminal-workspace/emulator-keys.md +48 -0
  137. package/skills/terminal-workspace/headless-clipboard.md +175 -0
  138. package/skills/terminal-workspace/turn-off-and-update.md +104 -0
  139. package/skills/test-conventions/SKILL.md +59 -0
  140. package/skills/visual-docs/SKILL.md +246 -0
  141. package/skills/writing/SKILL.md +231 -0
  142. package/skills/writing/examples.md +153 -0
  143. package/skills/writing/vocabulary.md +96 -0
@@ -0,0 +1,245 @@
1
+ ---
2
+ name: teardown-worktree
3
+ description: "Retire finished git worktrees – move this session back to the main checkout, move the orchestrator's pane back to the main repo workspace, remove the checkouts, and delete the merged local and remote branches. Scans the whole repo, not just the current worktree. Use whenever the user says \"tear down the worktree\", \"clean up worktrees\", \"remove this worktree\", \"delete the worktree and branch\", \"clean up stale worktrees\", or otherwise wants finished worktrees and their branches gone."
4
+ argument-hint: "[worktree name, or nothing to scan the whole repo]"
5
+ ---
6
+
7
+ # Teardown worktree
8
+
9
+ Retire finished worktrees.
10
+
11
+ Move this session out first. Remove the worktrees next. Delete the branches they were on last.
12
+
13
+ Removing a worktree this session is standing in, or one that still holds a running agent, destroys live work. The order below exists to prevent that, as far as either orchestrator can tell. Follow it.
14
+
15
+ ## When to use
16
+
17
+ Trigger on "tear down the worktree", "clean up worktrees", "remove this worktree", "delete the worktree and branch", "clean up stale worktrees". Also fair game straight after a merge, when the user says the work has shipped.
18
+
19
+ ## Scope
20
+
21
+ One repo per run: the repo that owns the cwd. Resolve its main checkout from anywhere inside it:
22
+
23
+ ```bash
24
+ dirname "$(git rev-parse --git-common-dir)"
25
+ ```
26
+
27
+ Submodules are separate repos with their own worktrees and their own remote.
28
+
29
+ If the repo has submodules carrying worktrees, say so. Offer a second run against each. Never scan them silently.
30
+
31
+ ## 1. Build the plan
32
+
33
+ Remove nothing before the full plan is on screen and the user has approved it. One approval covers the whole run.
34
+
35
+ List every worktree of the repo:
36
+
37
+ ```bash
38
+ git worktree list --porcelain
39
+ ```
40
+
41
+ Skip the main checkout. First settle who hosts this session and who owns each checkout, then classify each remaining worktree on the four checks that follow.
42
+
43
+ ### Which orchestrator hosts this session, and which one owns each checkout
44
+
45
+ Settle both before the four checks. A worktree orchestrator is a tool that opens panes and holds worktrees for you – herdr and Orca are the two this skill knows.
46
+
47
+ Two different facts drive this skill:
48
+
49
+ - The **host** is the orchestrator running this session's terminal. It decides how this session moves itself out in step 2.
50
+ - The **owner** is the orchestrator holding a checkout on disk. It decides which command step 3 runs against that checkout.
51
+
52
+ The rule in one line: the session's host creates a worktree, and the checkout's owner removes it.
53
+
54
+ Host and owner are often the same, and they do not have to be. A herdr pane can open a checkout Orca created. A checkout herdr created can outlive the pane that made it.
55
+
56
+ So read the owner per worktree, and never assume the host owns anything.
57
+
58
+ Neither tool sees the other's sessions. `herdr worktree list` never reports an Orca agent, and Orca's listing never reports a herdr pane. That is why the live-agent check below asks both tools about every candidate, whoever owns it.
59
+
60
+ A script shipped with the sibling `new-worktree` skill answers both questions. Run it rather than working it out by hand:
61
+
62
+ ```bash
63
+ ACSTACK_ROOT=$(cd -- "$(dirname -- "$(readlink -f "$HOME/.claude/acstack/bin/acstack")")/../.." && pwd)
64
+ "$ACSTACK_ROOT/skills/new-worktree/detect-orchestrator.sh" # the host
65
+ "$ACSTACK_ROOT/skills/new-worktree/detect-orchestrator.sh" <path> # one checkout's owner
66
+ ```
67
+
68
+ Read `detector.md` before you run the detector for the first time in a session. It explains the path, the six output lines, and the case where the script does not run.
69
+
70
+ Run the script once with no argument to read `active`. Then run it once per worktree in the plan, passing that worktree's path, and read `owner` from each run.
71
+
72
+ Repeat a non-empty `warning` to the user verbatim, before anything else happens. Then let `active` decide how this session moves itself out in step 2. Let each checkout's `owner` decide how step 3 removes it.
73
+
74
+ The script sometimes does not run at all. Then follow `detector.md`, and treat every worktree as plain git.
75
+
76
+ ### Owner
77
+
78
+ Read `owner` for each worktree, passing that worktree's path to the detector. The owner decides how step 3 removes the checkout:
79
+
80
+ - `herdr` – herdr holds this checkout. Step 3 removes it through herdr.
81
+ - `orca` – Orca holds this checkout. Step 3 removes it through Orca.
82
+ - `none` – plain git holds this checkout. Step 3 removes it with git.
83
+
84
+ Plain git is not a fallback for an Orca-owned checkout. It deletes the directory while Orca still holds a row for it in its sidebar, leaving that row pointing at nothing. That is the same failure the `Never` rule at the end of this file names for herdr.
85
+
86
+ Orca's own listing does not settle ownership either. `orca worktree list` also reports herdr and plain git checkouts when the user turns external visibility on. Trust the detector's `owner`.
87
+
88
+ ### Uncommitted work
89
+
90
+ ```bash
91
+ git -C <path> status --porcelain --ignore-submodules=all
92
+ ```
93
+
94
+ `--ignore-submodules=all` is not optional. Without it, a submodule checked out ahead of its committed pointer reads as uncommitted work. Then every worktree in a repo with submodules looks dirty, and you never remove any of them.
95
+
96
+ Report pointer drift in the plan anyway, from `git -C <path> submodule status`. That way a real pending bump stays visible, and the ignore flag does not hide it.
97
+
98
+ Any output from the status check means skip.
99
+
100
+ Do not remove it. Do not force it. List it at the end with what it holds.
101
+
102
+ ### Merged
103
+
104
+ A branch counts as merged if it reached any integration branch the repo actually has. Check `origin/dev` first, then `origin/main`, using whichever exist:
105
+
106
+ ```bash
107
+ git fetch origin --prune --quiet
108
+ git merge-base --is-ancestor <branch> origin/dev
109
+ git merge-base --is-ancestor <branch> origin/main
110
+ ```
111
+
112
+ A squash merge leaves the branch tip unreachable from either, so the ancestor check alone will call shipped work unmerged. Fall back to the pull request:
113
+
114
+ ```bash
115
+ gh pr list --head <branch> --state merged --json number,mergedAt
116
+ ```
117
+
118
+ Merged by either test counts as merged. Merged by neither means skip. Report it.
119
+
120
+ ### Live agent
121
+
122
+ The worktree this session is standing in is never a candidate, whatever else is true. Step 2 still moves the session out before step 3 removes anything.
123
+
124
+ Beyond that, ask both orchestrators about every candidate, whoever owns it. Neither tool sees the other's sessions, and either one can hold a live agent in a checkout the other owns. One tool's silence is not an answer, so a check you skip is a session you may destroy.
125
+
126
+ Skip a tool only when this host does not have it. Read that from the detector's `declared_herdr` and `declared_orca`. A tool the host lacks holds no sessions.
127
+
128
+ Say in the plan which checks ran and which did not, once per worktree, so nobody reads a missing check as a passed check.
129
+
130
+ Ask herdr the way `herdr.md` step 1 says, and Orca the way `orca.md` step 1 says, whoever owns the checkout.
131
+
132
+ #### When the host has neither tool
133
+
134
+ Nothing holds agent state, so nothing can confirm liveness. Classification then rests on the uncommitted-work and merged checks alone.
135
+
136
+ ### Show it
137
+
138
+ Print one table with six columns: worktree, branch, whether the local branch goes, whether the remote branch goes, blocking panes, and the reason. Then ask once.
139
+
140
+ The blocking panes column names each pane that blocks the removal, pane id first and process name after – `w26:p2 claude` for example. Leave the cell empty when nothing blocks. The user then knows which pane to close.
141
+
142
+ ## 2. Move this session out
143
+
144
+ Do this before removing anything, and only after approval.
145
+
146
+ `EnterWorktree` cannot do this. It rejects the main checkout outright, "is the main working tree, not a linked worktree".
147
+
148
+ So no tool call walks the session cwd back. `ExitWorktree` only unwinds a worktree this session entered with `EnterWorktree`. It is a no-op for a session that launched inside one.
149
+
150
+ The removal itself is what moves the session. Run it from the main checkout against an absolute path.
151
+
152
+ The harness then resets the session cwd to the main checkout on its own. Confirm with `pwd` afterwards.
153
+
154
+ - Entered with `EnterWorktree`: call `ExitWorktree` with `action: "keep"` first. Keep, not remove: step 3 owns the removal, and `remove` refuses on a worktree entered by path.
155
+ - Launched inside the worktree: no call needed.
156
+
157
+ Take the pane with you below. Remove the worktree in step 3. Confirm the new cwd after.
158
+
159
+ That much is the same everywhere. What follows depends on the branch `active` names. This step is the one place `active` still decides anything: how this session moves itself.
160
+
161
+ When `active` is `herdr`, follow `herdr.md` step 2 before you remove anything.
162
+
163
+ When `active` is `orca`, follow `orca.md` step 2. It leaves this session's own checkout in place.
164
+
165
+ ### Host: none
166
+
167
+ There is no pane and no workspace, so the cwd move described above is the whole step. No other tool needs to know where this session went.
168
+
169
+ ## 3. Remove the worktrees
170
+
171
+ Every removal through herdr or plain git passes `--force`. Orca is the exception, and `orca.md` step 3 says why. `--force` is necessary here, not a shortcut.
172
+
173
+ Plain `git worktree remove` refuses on any worktree containing submodules with "working trees containing submodules cannot be moved or removed". That refusal hits every worktree in a repo that has them.
174
+
175
+ Forcing is safe only because step 1 already proved the tree clean. It is never a way past uncommitted changes.
176
+
177
+ The hard rule: never run `worktree remove --force` on a workspace that still holds a pane other than this session's own. Forcing waives herdr's own check, so the pane enumeration is the only guard left.
178
+
179
+ Enumerate the panes again immediately before the call. Refuse the removal while any other pane remains.
180
+
181
+ Take the branch each checkout's `owner` names, not the branch `active` names. Decide per worktree: one checkout in the plan can belong to herdr while the next is plain git.
182
+
183
+ Before each removal, confirm the live-agent checks from step 1 still hold. Both tools, every time, because neither sees the other's sessions. A pane can open between the plan and the removal, so re-read the panes rather than trusting the plan.
184
+
185
+ For a checkout whose `owner` is `herdr`, follow `herdr.md` step 3.
186
+
187
+ For a checkout whose `owner` is `orca`, follow `orca.md` step 3. It never passes `--force`, and never removes an unmerged branch.
188
+
189
+ ### Owner: none
190
+
191
+ Plain git, always – there is no workspace to weigh up:
192
+
193
+ ```bash
194
+ git -C <main-root> worktree remove --force <path>
195
+ git -C <main-root> worktree prune
196
+ ```
197
+
198
+ ## 4. Delete the branches
199
+
200
+ Only for worktrees removed in step 3, and only for branches step 1 proved merged.
201
+
202
+ ```bash
203
+ git -C <main-root> branch -d <branch>
204
+ git -C <main-root> push origin --delete <branch>
205
+ ```
206
+
207
+ Skip the local delete for an Orca-owned checkout. `orca worktree rm` already deleted that branch in step 3, so run the remote delete alone.
208
+
209
+ Use `branch -d`, never `-D`. If `-d` refuses, the merge test was wrong. Stop and report rather than forcing.
210
+
211
+ Skip the remote delete when nobody ever pushed the branch, or when merging the pull request already deleted it. The `git fetch origin --prune` from step 1 keeps a branch GitHub already removed from looking like work to do.
212
+
213
+ ## 5. Report
214
+
215
+ State what went and what stayed:
216
+
217
+ - Worktrees removed, with their branches
218
+ - Worktrees skipped, each with its reason: uncommitted work, an unmerged branch, a live agent or terminal, or the checkout this Orca terminal stands in
219
+ - Which live-agent checks ran against each worktree, and which did not, so nobody reads a missing check as a passed check
220
+ - Anything left for the user to decide
221
+
222
+ ## Never
223
+
224
+ - Remove a worktree this session is standing in. Move out first.
225
+ - Remove a worktree whose herdr workspace reports a `working`, `blocked`, `idle` or `done` agent. `idle` means present and waiting, not absent.
226
+ - Decide on the workspace `agent_status` alone. List the panes and read `herdr pane process-info` for each one before removing.
227
+ - Read the workspace `agent_status` as this session's own verdict. Exclude your own pane by `$HERDR_PANE_ID` instead.
228
+ - Remove a workspace that still holds a pane other than your own.
229
+ - Reach for `EnterWorktree` to get back to the main checkout. It rejects the main working tree.
230
+ - Force past uncommitted changes. Skip and report instead.
231
+ - Reach for `git branch -D` when `-d` refuses.
232
+ - Call a branch unmerged on the ancestor check alone. Check the pull request before deciding.
233
+ - Delete a remote branch with no merged pull request and no ancestor in an integration branch.
234
+ - Remove a worktree with plain git while herdr still holds a workspace for it. That leaves a sidebar row pointing at nothing.
235
+ - Scan a submodule's worktrees without saying so.
236
+ - Hard-code an orchestrator, or branch on an environment variable directly. Run the detector, then use `active` and `owner`.
237
+ - Remove a checkout with the branch `active` names. The owner removes, whoever hosts this session.
238
+ - Read one orchestrator's listing as the whole answer. Ask both before every removal.
239
+ - Swallow the detector's `warning`. Say it to the user before doing anything else.
240
+ - Run a tool the host does not have installed. A missing tool holds no sessions.
241
+ - Remove an Orca-owned checkout with plain git. Use `orca worktree rm` and leave Orca's sidebar in step.
242
+ - Pass `--force` to `orca worktree rm`. It waives the only safety checks left at that point.
243
+ - Call `orca worktree rm` on an unmerged branch. It deletes the branch with the checkout, and nothing asks first.
244
+ - Remove the checkout an Orca terminal is standing in. Orca cannot move that terminal out.
245
+ - Stop an Orca terminal during a teardown. Name it and let the user decide.
@@ -0,0 +1,39 @@
1
+ # Teardown worktree: the detector
2
+
3
+ What `detect-orchestrator.sh` prints, and what to do when it does not run.
4
+
5
+ ## Why the path goes through the CLI symlink
6
+
7
+ The path goes through `~/.claude/acstack/bin/acstack`, the invariant symlink the SessionStart hook maintains. The plugin re-creates that symlink every time an agent session starts. It is the only reliable way to find the plugin's own root.
8
+
9
+ Do not invent a shorter path, and do not reach for `$CLAUDE_PLUGIN_ROOT` – the plugin deliberately does not depend on that variable reaching a fresh subshell.
10
+
11
+ ## The six lines
12
+
13
+ The script always exits 0 and prints exactly six lines:
14
+
15
+ - `declared_herdr` – whether the user has herdr installed on this host, recorded in the ACStack global config under `host.orchestrators.herdr`. One of `true`, `false`, `unset`.
16
+ - `declared_orca` – the same yes-or-no answer for Orca, recorded under `host.orchestrators.orca`. One of `true`, `false`, `unset`. The two are independent: a host can have both installed, one, or neither, so one answer says nothing about the other.
17
+ - `detected` – which orchestrator is actually hosting this session, read from the environment markers an orchestrator injects into the terminals it opens. One of `herdr`, `orca`, `none`.
18
+ - `active` – the branch to run for this session. One of `herdr`, `orca`, `none`.
19
+ - `owner` – which orchestrator owns the checkout the script examined. One of `herdr`, `orca`, `none`.
20
+
21
+ The path settles it: a checkout under `~/orca/workspaces/` belongs to Orca, and a checkout under herdr's worktree root belongs to herdr. herdr's config names that root. Anything else is plain git.
22
+
23
+ - `warning` – one line written for a human, empty when there is nothing to say.
24
+
25
+ Declared means installed. Detected means hosting.
26
+
27
+ Detected wins, so `active` always equals `detected`. This session cannot drive an installed orchestrator that does not host it.
28
+
29
+ A marker for an orchestrator the host never declared earns a warning, not a refusal.
30
+
31
+ ## When the script does not run
32
+
33
+ The script sometimes does not run at all: no output, and a non-zero exit from the invocation itself. Then there is no `active` and no `owner` to read.
34
+
35
+ Do not guess either one. Say so to the user. Then treat every worktree as plain git, the branch that touches nothing an orchestrator holds.
36
+
37
+ A missing or non-executable script looks like this, and a plugin older than the script is the usual cause.
38
+
39
+ This is the same detector `new-worktree` runs, so both skills always give the same answer on the same host.
@@ -0,0 +1,113 @@
1
+ # Teardown worktree: herdr
2
+
3
+ The herdr branches of the teardown. Each section names the `SKILL.md` step it belongs to.
4
+
5
+ ## Step 1 – herdr's answer
6
+
7
+ A herdr workspace holds tabs, and each tab holds panes. One status for the whole workspace therefore says nothing about the other tabs in it. So enumerate the panes before every removable verdict.
8
+
9
+ Start with the cheap hint:
10
+
11
+ ```bash
12
+ herdr worktree list
13
+ herdr workspace list
14
+ ```
15
+
16
+ Treat `working`, `blocked`, `idle` and `done` as a live agent. Skip the worktree, and run no further check on it.
17
+
18
+ `idle` does not mean empty. In herdr it means an agent is present and waiting for input, which is exactly the state a session someone left open sits in. Reading `idle` as nobody home is the quickest way to destroy a running session.
19
+
20
+ `unknown` never makes a worktree removable on its own. It summarises a whole workspace, and a second tab running an agent hides behind that one word.
21
+
22
+ So list every pane of the workspace holding the worktree:
23
+
24
+ ```bash
25
+ herdr pane list --workspace <workspace-id>
26
+ ```
27
+
28
+ The listing covers every tab, not only the focused one. Each entry carries `pane_id`, `tab_id`, `agent`, `agent_status`, `cwd` and `foreground_cwd`.
29
+
30
+ Exclude this session's own pane by identifier, never by status. The own pane is the one whose `pane_id` equals `$HERDR_PANE_ID`. Every other pane still counts, whatever the workspace `agent_status` said.
31
+
32
+ The `w26` teardown skipped this step. It read its own workspace's `done` as its own verdict, removed the workspace, and killed a live session in the second tab.
33
+
34
+ Excluding by `pane_id` keeps every other pane inside the check. The step 3 rules then stop the removal.
35
+
36
+ Then read what actually runs in each remaining pane:
37
+
38
+ ```bash
39
+ herdr pane process-info --pane <pane-id>
40
+ ```
41
+
42
+ Any one of these three makes the worktree a skip:
43
+
44
+ - The pane's `agent_status` is `working`, `blocked`, `idle` or `done`.
45
+ - `foreground_processes` holds an agent, `claude` or `codex` for example.
46
+ - A foreground process has a `cwd` inside the worktree's checkout path.
47
+
48
+ The third case is not an agent. An editor or `gh dash` counts here. Deleting the directory under it still breaks it.
49
+
50
+ Close it deliberately, or leave the worktree alone.
51
+
52
+ One `cwd` never blocks: a path carrying the `(deleted)` marker. That shell sits in a directory somebody already removed, as step 2 describes. It holds nothing.
53
+
54
+ Cross-check the pane count against the tabs, every time:
55
+
56
+ ```bash
57
+ herdr tab list --workspace <workspace-id>
58
+ ```
59
+
60
+ Sum `pane_count` across the tabs. A sum above the number of rows `pane list` returned means the enumeration missed something. Skip the worktree and report it.
61
+
62
+ Name every blocking pane in the plan, so the user can close it deliberately.
63
+
64
+ ## Step 2 – Host: herdr
65
+
66
+ When `active` is `herdr`, move the pane out first, or step 3 deletes the worktree under a pane still sitting in that workspace.
67
+
68
+ The move needs this pane's own identifier, and `active` being `herdr` does not guarantee it. The detector reports `herdr` when either of herdr's two environment markers holds a value, and only one of them names the pane. So if `$HERDR_PANE_ID` is empty, herdr's markers are incomplete – say so and stop, rather than issuing a pane move against a blank target.
69
+
70
+ Find the main repo's workspace in `herdr workspace list`: `worktree.repo_root` is the main checkout and `worktree.is_linked_worktree` is `false`. More than one workspace can match, since any pane opened at the repo root qualifies. Prefer the one whose label is the repo name, and ask when it stays ambiguous.
71
+
72
+ Then:
73
+
74
+ ```bash
75
+ herdr pane move "$HERDR_PANE_ID" --new-tab --workspace <main-workspace-id> --focus
76
+ ```
77
+
78
+ If no such workspace exists because it closed earlier, create one first:
79
+
80
+ ```bash
81
+ herdr workspace create --cwd <main-root> --label <repo-name> --no-focus
82
+ ```
83
+
84
+ The pane's own shell keeps the deleted directory as its cwd, which `herdr pane process-info` reports as `(deleted)`. That is cosmetic, and only visible once the agent exits and hands the prompt back.
85
+
86
+ ## Step 3 – Owner: herdr
87
+
88
+ Which command to use depends on whether herdr still holds a workspace for the worktree. Read `open_workspace_id` from `herdr worktree list`.
89
+
90
+ With a workspace, enumerate its panes first:
91
+
92
+ ```bash
93
+ herdr pane list --workspace <workspace-id>
94
+ ```
95
+
96
+ Exclude the pane whose `pane_id` equals `$HERDR_PANE_ID`. Refuse the removal while any other pane remains. Name those pane ids to the user and move to the next worktree.
97
+
98
+ With the workspace clear, let herdr do it, so the sidebar row goes with the worktree:
99
+
100
+ ```bash
101
+ herdr worktree remove --workspace <workspace-id> --force
102
+ ```
103
+
104
+ Without a workspace, plain git:
105
+
106
+ ```bash
107
+ git -C <main-root> worktree remove --force <path>
108
+ git -C <main-root> worktree prune
109
+ ```
110
+
111
+ The worktree this session just left may still have a workspace. Moving the last pane out closes the workspace, and a pane in a second tab keeps it open.
112
+
113
+ So read `open_workspace_id` from `herdr worktree list` again after step 2. A workspace id still set means the pane enumeration above runs on that workspace too, before you remove anything.
@@ -0,0 +1,61 @@
1
+ # Teardown worktree: Orca
2
+
3
+ The Orca branches of the teardown. Each section names the `SKILL.md` step it belongs to.
4
+
5
+ ## Step 1 – Orca's answer
6
+
7
+ Resolve Orca's executable before you call it. The Linux binary is `orca-ide`, and some installs put it on PATH as plain `orca`. Never hard-code either name.
8
+
9
+ This listing reads state and changes nothing. Step 3 runs the removal separately, and only against a checkout Orca owns.
10
+
11
+ ```bash
12
+ ORCA_BIN="$(command -v orca-ide || command -v orca)"
13
+ "$ORCA_BIN" worktree ps --json
14
+ ```
15
+
16
+ Match each entry to a candidate on `.result.worktrees[].path`. Then read `agents`, `liveTerminalCount`, `hasAttachedPty` and `status` from that entry.
17
+
18
+ Skip the worktree while `agents[]` holds anything, or while `liveTerminalCount` is above zero. Orca does not guard this itself on the command-line path. Someone watched a live check remove a worktree whose agent was mid-tool-call.
19
+
20
+ An empty `agents` with a live terminal count is the common case, not a live agent. `orca worktree create` spawns a shell in every checkout it makes. That one shell holds the count at one.
21
+
22
+ Skip it anyway. Then name the terminals, so the user can decide:
23
+
24
+ ```bash
25
+ "$ORCA_BIN" terminal list --worktree path:<path> --json
26
+ ```
27
+
28
+ Tell them what clears an idle shell: `"$ORCA_BIN" terminal stop --worktree path:<path> --json`. A later run then removes the worktree.
29
+
30
+ This skill never stops a terminal. Only the user knows what a shell was holding, so the call is theirs.
31
+
32
+ ## Step 2 – Host: orca
33
+
34
+ Orca has no command that moves a running terminal into another worktree. The `herdr pane move` step in `herdr.md` has no Orca equivalent, so the cwd move is all this session can do.
35
+
36
+ That is not enough for the checkout this session stands in. The Orca terminal keeps its shell inside that directory, and Orca keeps a row bound to it. Removing it breaks both.
37
+
38
+ So leave that one checkout in place. Name it to the user, and say why it stayed. Suggest they run the teardown again from a different Orca terminal.
39
+
40
+ Every other worktree in the plan goes as normal. This session stands outside them, so nothing has to move.
41
+
42
+ ## Step 3 – Owner: orca
43
+
44
+ Orca holds this checkout, so Orca removes it. Resolve the executable the same way step 1 did:
45
+
46
+ ```bash
47
+ ORCA_BIN="$(command -v orca-ide || command -v orca)"
48
+ "$ORCA_BIN" worktree rm --worktree path:<path> --json
49
+ ```
50
+
51
+ Never pass `--force`. It waives Orca's own safety checks, and those checks are the only ones left at this point.
52
+
53
+ Orca refuses two cases by itself. It refuses a dirty tree, and it refuses a path outside `~/orca/workspaces`.
54
+
55
+ Read either refusal rather than overriding it. Step 1 proved the tree clean, so a dirty-tree refusal means somebody changed the tree since.
56
+
57
+ `orca worktree rm` deletes the local branch itself, and it has no keep-branch flag. So decide keep-or-delete before you call it, using the merge result from step 1.
58
+
59
+ Never call it on an unmerged branch: the branch goes with the checkout, and nothing asks first. Leave the checkout in place instead and report it.
60
+
61
+ Step 4 then skips `git branch -d` for this checkout. Orca already deleted that branch. The remote branch is still step 4's job.