#3315 — ork stood in front of CC's worktree provisioning
Registering a WorktreeCreate hook does not extend provisioning. It replaces it.
12things CC does
2ork reimplemented
1real cleanup log line, all-time
0worktree_links writers
The gate, read off the shipped 2.1.226 binary
function UHe(){ // hasWorktreeCreateHook
if(Pp("hooks")) return !1;
let e=Due()?.WorktreeCreate; if(e&&e.length>0) return !0;
if(!$x()){ let o=Kle()?.WorktreeCreate; if(o&&o.length>0) return !0 }
let t=ine()?.WorktreeCreate; if(!t||t.length===0) return !1;
let r=$x(), n=r&&!Xc()?GCe():null;
return t.some((o)=>!(r&&("pluginRoot"in o)&&!n?.has(o.pluginId))) // plugin hooks COUNT
}
single call site:
if(UHe()){ hook branch } else { native branch: sIs + aIs }
never both
No filter on
async. No check that the hook returns a path. Any registered
hook flips it, which is why even the async telemetry forwarder had to be removed: leaving it would
keep CC out of its own path with nothing left to provision.
What ork was replacing
| Capability | CC native | ork |
|---|---|---|
worktree.sparsePaths | yes | duplicate |
| path placement | yes | different path |
worktree.baseRef | yes | no |
.worktreeinclude | yes | no |
settings.local.json propagation | yes | no |
core.hooksPath to main repo | yes | no |
worktree.symlinkDirectories | yes | no |
PR worktrees (pull/N/head) | yes | no |
| resume / reset to fresh base | yes | no |
| realpath containment check | yes | no |
git worktree lock | yes | no |
| branch deleted on cleanup | yes | no |
Meanwhile four ork reference docs instructed operators to set
worktree.baseRef, which could not work for them the entire time.
Removal was broken, not merely absent
CC dispatches WorktreeRemove only for hook-created worktrees └─ and refuses when the directory is non-empty (a real worktree always is) └─ the `git worktree remove` fallback lives in the !hookBased branch └─ so provisioned worktrees leaked measured on the author's machine, 2026-08-09 worktree-events.jsonl ........ 11 lines all-time from a REAL worktree ....... 1 (2026-07-18, rows_updated: 0) from vitest temp dirs ...... 10 writing into the live project log worktree-pending markers ..... 3 uncleaned 2026-08-06 01:37, and two from agents that finished minutes earlier
The cascade that never ran
exit-finalizer: SELECT child_sid FROM worktree_links ...
UPDATE worktree_links SET ...
only INSERT INTO worktree_links in the entire repo:
__tests__/worktree/exit-finalizer.test.ts:53 a test fixture
⇒ the UPDATE always matched zero rows. the one real log line says rows_updated: 0.Verified
✓ validate-counts 219 -> 215, PASSED ✓ build idempotent, second run leaves 0 files dirty ✓ hooks suite 7489 passed ! 6 remaining failures subagent-start/context-gate.test.ts — reads LIVE machine state (asserted on "7 background agents active" from this very session). Untouched by this change; filed separately. ✓ wiring assertions INVERTED, not deleted — re-registering anything on WorktreeCreate now fails the suite.
The schema is deliberately untouched. Editing a shipped migration does not affect databases that
already ran it and would drift fresh installs from existing ones. worktree_links
belongs to #3353, which now has no reader left to weigh.