#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

CapabilityCC nativeork
worktree.sparsePathsyesduplicate
path placementyesdifferent path
worktree.baseRefyesno
.worktreeincludeyesno
settings.local.json propagationyesno
core.hooksPath to main repoyesno
worktree.symlinkDirectoriesyesno
PR worktrees (pull/N/head)yesno
resume / reset to fresh baseyesno
realpath containment checkyesno
git worktree lockyesno
branch deleted on cleanupyesno

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.