feat(LinuxTentacleE2E): Phase 12.L.E.11 — E11.u2-Linux stale lockfile recovery
Summary
Pins the kernel-flock-auto-release contract on Linux: a leftover lockfile (from a tentacle process killed mid-upgrade) MUST NOT block the next dispatch, because the kernel automatically releases flocks when the holding process dies.
Why this is a regression test, not a feature test
Linux already does the right thing here — kernel BSD flock has built-in stale-lock recovery via process-death auto-release. The test isn't validating new functionality; it's pinning the contract so a future polish that "improved" lock detection (e.g. by mirroring Windows' PID-based file-content check) doesn't silently regress kernel-flock semantics.
Without this pin: a regression where someone added file-existence-based blocking would leave production agents stuck with stale lockfiles requiring manual cleanup.
| Platform | Mechanism | Stale-detection |
|---|---|---|
| Windows | .ps1 reads PID from lockfile, checks process liveness | Explicit |
| Linux | Kernel BSD flock | Automatic via kernel auto-release |
Test mechanism
Pre-stage a lockfile with sentinel "99999\n" content (no live holder), then run a normal upgrade. The kernel sees no active holder → grants the lock immediately → upgrade proceeds end-to-end exactly like E1.h-Linux.
Assertions
-
exitCode == 0(SUCCESS path, NOT no-op path) - stdout does NOT contain
"upgrade is already in progress on this host"(regression marker — would surface if .sh's idempotency guard misfired) last-upgrade.json.Status == "SUCCESS"- Service marker swapped to
"2.0.0-test"(Phase B fully completed)
Pair with E11.u1-Linux (PR #220)
| Test | Lockfile | Holder | Expected |
|---|---|---|---|
| E11.u1-Linux | exists | active flock holder | exit 0 no-op (real concurrent dispatch) |
| E11.u2-Linux | exists | none | exit 0 SUCCESS (stale lockfile recovery) |
Together these pin both halves of the lock contract: held flock blocks, unattended file does not.
Fidelity tier
.sh + real systemd + real bash + real LocalReleaseMirror + real Phase A+B end-to-end.
Test plan
-
Linux E2E workflow runs Squid.LinuxTentacleE2ETests(manualworkflow_dispatchafter merge) -
E11u2_StaleLockfile_NoLiveHolder_DispatchProceedsNormally_Linuxpasses within ~5s -
No regression on existing 12 Linux E2E tests