fix(bin): select empty worktree-pool slots and attribute live occupancy (land of upstream #1923) - #66
Conversation
…upied one `treehouse get` hands out the first available slot and takes no slot argument, so the pre-allocation guard could only refuse. One parked slot therefore blockaded every spawn even when later slots were genuinely empty, and the only way through was authorizing the parked slots by hand. The guard now chooses as well as refuses: it names a demonstrably empty slot that is parked at a detached HEAD or the default branch, and fm-spawn acquires that slot by name with `treehouse enter`, which does not reset it. An occupied slot is skipped untouched. The refusal is preserved exactly where it still matters - with no empty slot to steer to, the allocation falls back to `treehouse get`, so every available slot must still be empty or explicitly authorized, and the refusal still names each slot, its evidence and its apparent owner. Liveness attribution no longer calls a worker gone on a stale recorded pid alone. That pid is one process sampled when the slot was accepted, so it stops matching for reasons that say nothing about the task. Stronger bindings are read first and any one of them carries the live verdict: HERDR_PANE_ID in a live process's environment matching the task's recorded herdr_pane_id, GOTMPDIR matching its recorded tasktmp, or a live process whose cwd is inside the slot. Between choosing a slot and the pane's shell arriving in it, fm-spawn holds the slot with one short-lived process of its own, because treehouse reports a slot in-use while any process's cwd is inside it; the abort path releases it. tests/fm-worktree-guard.test.sh cases (s1) through (s4) and the rewritten (o5) pin the skip, the preserved all-occupied refusal, both liveness bindings with a negative control each, and the path-scoped reclaim authority. docs/verification/worktree-allocation.md records the treehouse behavior measured against v2.1.0.
…r evidence, fix label
…aining owner docs
…quires Trunk began requiring --reason-code on every ship and scout spawn after this branch was cut. The pre-existing spawn helper in this suite was updated on trunk, but the pool-lock helper this branch adds was not, so its directed spawn was refused before it could enter a slot. It now passes NL_RULE_CLASSIFICATION, matching the helper beside it.
424a80d to
28db6fc
Compare
Rebased onto the current fork trunkRebased onto Conflict and how it was resolvedOne conflict, in One integration fix the rebase exposedTrunk began requiring Test results, disclosed in full
The reporting was not trusted on absence: the runner produced real |
…cy (land of upstream kunchenguid#1923) (#66) * fix(bin): allocate an empty pool slot instead of blockading on an occupied one `treehouse get` hands out the first available slot and takes no slot argument, so the pre-allocation guard could only refuse. One parked slot therefore blockaded every spawn even when later slots were genuinely empty, and the only way through was authorizing the parked slots by hand. The guard now chooses as well as refuses: it names a demonstrably empty slot that is parked at a detached HEAD or the default branch, and fm-spawn acquires that slot by name with `treehouse enter`, which does not reset it. An occupied slot is skipped untouched. The refusal is preserved exactly where it still matters - with no empty slot to steer to, the allocation falls back to `treehouse get`, so every available slot must still be empty or explicitly authorized, and the refusal still names each slot, its evidence and its apparent owner. Liveness attribution no longer calls a worker gone on a stale recorded pid alone. That pid is one process sampled when the slot was accepted, so it stops matching for reasons that say nothing about the task. Stronger bindings are read first and any one of them carries the live verdict: HERDR_PANE_ID in a live process's environment matching the task's recorded herdr_pane_id, GOTMPDIR matching its recorded tasktmp, or a live process whose cwd is inside the slot. Between choosing a slot and the pane's shell arriving in it, fm-spawn holds the slot with one short-lived process of its own, because treehouse reports a slot in-use while any process's cwd is inside it; the abort path releases it. tests/fm-worktree-guard.test.sh cases (s1) through (s4) and the rewritten (o5) pin the skip, the preserved all-occupied refusal, both liveness bindings with a negative control each, and the path-scoped reclaim authority. docs/verification/worktree-allocation.md records the treehouse behavior measured against v2.1.0. * no-mistakes(review): serialize slot selection cross-home, record enter evidence, fix label * no-mistakes(document): document slot-selecting pool allocation in remaining owner docs * test(pool): give the directed-spawn case the reason code trunk now requires Trunk began requiring --reason-code on every ship and scout spawn after this branch was cut. The pre-existing spawn helper in this suite was updated on trunk, but the pool-lock helper this branch adds was not, so its directed spawn was refused before it could enter a slot. It now passes NL_RULE_CLASSIFICATION, matching the helper beside it.
…cy (land of upstream kunchenguid#1923) (#66) * fix(bin): allocate an empty pool slot instead of blockading on an occupied one `treehouse get` hands out the first available slot and takes no slot argument, so the pre-allocation guard could only refuse. One parked slot therefore blockaded every spawn even when later slots were genuinely empty, and the only way through was authorizing the parked slots by hand. The guard now chooses as well as refuses: it names a demonstrably empty slot that is parked at a detached HEAD or the default branch, and fm-spawn acquires that slot by name with `treehouse enter`, which does not reset it. An occupied slot is skipped untouched. The refusal is preserved exactly where it still matters - with no empty slot to steer to, the allocation falls back to `treehouse get`, so every available slot must still be empty or explicitly authorized, and the refusal still names each slot, its evidence and its apparent owner. Liveness attribution no longer calls a worker gone on a stale recorded pid alone. That pid is one process sampled when the slot was accepted, so it stops matching for reasons that say nothing about the task. Stronger bindings are read first and any one of them carries the live verdict: HERDR_PANE_ID in a live process's environment matching the task's recorded herdr_pane_id, GOTMPDIR matching its recorded tasktmp, or a live process whose cwd is inside the slot. Between choosing a slot and the pane's shell arriving in it, fm-spawn holds the slot with one short-lived process of its own, because treehouse reports a slot in-use while any process's cwd is inside it; the abort path releases it. tests/fm-worktree-guard.test.sh cases (s1) through (s4) and the rewritten (o5) pin the skip, the preserved all-occupied refusal, both liveness bindings with a negative control each, and the path-scoped reclaim authority. docs/verification/worktree-allocation.md records the treehouse behavior measured against v2.1.0. * no-mistakes(review): serialize slot selection cross-home, record enter evidence, fix label * no-mistakes(document): document slot-selecting pool allocation in remaining owner docs * test(pool): give the directed-spawn case the reason code trunk now requires Trunk began requiring --reason-code on every ship and scout spawn after this branch was cut. The pre-existing spawn helper in this suite was updated on trunk, but the pool-lock helper this branch adds was not, so its directed spawn was refused before it could enter a slot. It now passes NL_RULE_CLASSIFICATION, matching the helper beside it.
…cy (land of upstream kunchenguid#1923) (#66) * fix(bin): allocate an empty pool slot instead of blockading on an occupied one `treehouse get` hands out the first available slot and takes no slot argument, so the pre-allocation guard could only refuse. One parked slot therefore blockaded every spawn even when later slots were genuinely empty, and the only way through was authorizing the parked slots by hand. The guard now chooses as well as refuses: it names a demonstrably empty slot that is parked at a detached HEAD or the default branch, and fm-spawn acquires that slot by name with `treehouse enter`, which does not reset it. An occupied slot is skipped untouched. The refusal is preserved exactly where it still matters - with no empty slot to steer to, the allocation falls back to `treehouse get`, so every available slot must still be empty or explicitly authorized, and the refusal still names each slot, its evidence and its apparent owner. Liveness attribution no longer calls a worker gone on a stale recorded pid alone. That pid is one process sampled when the slot was accepted, so it stops matching for reasons that say nothing about the task. Stronger bindings are read first and any one of them carries the live verdict: HERDR_PANE_ID in a live process's environment matching the task's recorded herdr_pane_id, GOTMPDIR matching its recorded tasktmp, or a live process whose cwd is inside the slot. Between choosing a slot and the pane's shell arriving in it, fm-spawn holds the slot with one short-lived process of its own, because treehouse reports a slot in-use while any process's cwd is inside it; the abort path releases it. tests/fm-worktree-guard.test.sh cases (s1) through (s4) and the rewritten (o5) pin the skip, the preserved all-occupied refusal, both liveness bindings with a negative control each, and the path-scoped reclaim authority. docs/verification/worktree-allocation.md records the treehouse behavior measured against v2.1.0. * no-mistakes(review): serialize slot selection cross-home, record enter evidence, fix label * no-mistakes(document): document slot-selecting pool allocation in remaining owner docs * test(pool): give the directed-spawn case the reason code trunk now requires Trunk began requiring --reason-code on every ship and scout spawn after this branch was cut. The pre-existing spawn helper in this suite was updated on trunk, but the pool-lock helper this branch adds was not, so its directed spawn was refused before it could enter a slot. It now passes NL_RULE_CLASSIFICATION, matching the helper beside it.
…cy (land of upstream kunchenguid#1923) (#66) * fix(bin): allocate an empty pool slot instead of blockading on an occupied one `treehouse get` hands out the first available slot and takes no slot argument, so the pre-allocation guard could only refuse. One parked slot therefore blockaded every spawn even when later slots were genuinely empty, and the only way through was authorizing the parked slots by hand. The guard now chooses as well as refuses: it names a demonstrably empty slot that is parked at a detached HEAD or the default branch, and fm-spawn acquires that slot by name with `treehouse enter`, which does not reset it. An occupied slot is skipped untouched. The refusal is preserved exactly where it still matters - with no empty slot to steer to, the allocation falls back to `treehouse get`, so every available slot must still be empty or explicitly authorized, and the refusal still names each slot, its evidence and its apparent owner. Liveness attribution no longer calls a worker gone on a stale recorded pid alone. That pid is one process sampled when the slot was accepted, so it stops matching for reasons that say nothing about the task. Stronger bindings are read first and any one of them carries the live verdict: HERDR_PANE_ID in a live process's environment matching the task's recorded herdr_pane_id, GOTMPDIR matching its recorded tasktmp, or a live process whose cwd is inside the slot. Between choosing a slot and the pane's shell arriving in it, fm-spawn holds the slot with one short-lived process of its own, because treehouse reports a slot in-use while any process's cwd is inside it; the abort path releases it. tests/fm-worktree-guard.test.sh cases (s1) through (s4) and the rewritten (o5) pin the skip, the preserved all-occupied refusal, both liveness bindings with a negative control each, and the path-scoped reclaim authority. docs/verification/worktree-allocation.md records the treehouse behavior measured against v2.1.0. * no-mistakes(review): serialize slot selection cross-home, record enter evidence, fix label * no-mistakes(document): document slot-selecting pool allocation in remaining owner docs * test(pool): give the directed-spawn case the reason code trunk now requires Trunk began requiring --reason-code on every ship and scout spawn after this branch was cut. The pre-existing spawn helper in this suite was updated on trunk, but the pool-lock helper this branch adds was not, so its directed spawn was refused before it could enter a slot. It now passes NL_RULE_CLASSIFICATION, matching the helper beside it.
Lands upstream PR kunchenguid#1923 (pushed head
c9c5aaf4, "fix(bin): select empty worktree-pool slots and attribute live occupancy") onto this fork's trunk so the running fleet actually gets it.Nothing was redesigned and nothing was re-reviewed. The change was already reviewed upstream, the upstream contribution stays open and untouched on the maintainer's schedule, and only that contribution's own changes are carried here.
What it fixes
A spawn was refused when the worktree pool offered a slot that a live worker still occupied, instead of selecting an empty slot. The allocation now picks an empty slot and attributes live occupancy to its apparent owner, so a refusal names a real conflict rather than an artefact of which slot the pool happened to hand out.
What is carried, and how it was cut
The upstream head
c9c5aaf4is a merge of upstream main833a9a2into the lane, so it is not the contribution alone. The lane's own three commits sit directly on this fork's trunk ated376cf:6c5e9b4fix(bin): allocate an empty pool slot instead of blockading on an occupied onedfeb9d8no-mistakes(review): serialize slot selection cross-home, record enter evidence, fix label7425e9bno-mistakes(document): document slot-selecting pool allocation in remaining owner docsThose three were rebased onto the current trunk
c1141a5. The upstream-main merge commit was deliberately left behind, so this branch carries the contribution and nothing else.Evidence
The rebase was clean - no conflicts at any of the three commits. The resulting change-set is identical, file for file, to the contribution's own change-set at its original base:
Eleven files:
AGENTS.md,bin/fm-spawn.sh,bin/fm-worktree-guard.sh,docs/architecture.md,docs/cmux-backend.md,docs/configuration.md,docs/scripts.md,docs/verification/worktree-allocation.md,docs/zellij-backend.md,tests/fm-spawn-worktree-settle.test.sh,tests/fm-worktree-guard.test.sh.Known structural red
PR must be raised via no-mistakesfails on this pull request by construction: it was opened by hand, so its head carries norefs/notes/no-mistakesattestation. That is the expected state for every hand-opened landing here until the pipeline push-step fix lands, and it is not a defect in this change.