landWorkspaceTask now holds a per-repo land lease around each landOneRepo call:
a new activeSessionRegistry kind "workspace-repo-land" keyed on the sub-repo
absolute path, registered synchronously before the per-repo try and released in
a finally (on success and failure, only yanking our own taskId+ownerKey entry —
never a foreign/different-kind entry). Two workspace tasks landing the same
sub-repo serialize; the loser throws the retryable WorkspaceRepoLandBusyError,
which reuses the U2 partial-land retry/park machinery (consume a mergeRetry,
backoff re-enqueue up to MAX skipping landed repos, then operator-park). Disjoint
sub-repos never falsely serialize.
The lease is for serialization / clean-room-collision avoidance, not ref
correctness — advanceIntegrationBranchRef's CAS already makes interleaved
update-ref safe. Distinct from the execution-phase "workspace-repo-acquire" lease
(different kind, different lifecycle phase, each ignores the other's entry).
3 new tests (serialize, independence, release-on-failure); oracle (56) + U1/U2
(idempotency) stay green. Gate: build, typecheck, lint, test:gate (649+58).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>