=== SEQUENTIAL (max_concurrent_lanes: 1) — inert: no slot, no trace, no metric
rc=0
-- semaphore slots:
-- SEM_GATE_SLOT=[] SEM_HELD=[]
-- lock-order.trace:
   (none)
release rc=0
-- semaphore slots:
-- SEM_GATE_SLOT=[] SEM_HELD=[]
=== --dry-run at 3 lanes is not concurrent either
rc=0
-- semaphore slots:
-- SEM_GATE_SLOT=[] SEM_HELD=[]
-- lock-order.trace:
   (none)
=== CONCURRENT (3 lanes) — heavy-test acquired at once, scheduler-side slot attribution
METRIC {"event":"semaphore_acquired","name":"heavy-test","capacity":2,"wait_s":0,"at":"2026-10-18T00:00:00+00:00"}
METRIC {"event":"semaphore_wait_seconds","name":"heavy-test","task_id":"T-7","slot":"3","capacity":2,"wait_s":0,"at":"2026-10-18T00:00:00+00:00"}
rc=0
-- semaphore slots:
   ./heavy-test/1
-- SEM_GATE_SLOT=[1] SEM_HELD=[2 ]
-- lock-order.trace:
   1792281600 <PID> acquire heavy-test 1
=== release
release rc=0
-- semaphore slots:
-- SEM_GATE_SLOT=[] SEM_HELD=[]
-- lock-order.trace:
   1792281600 <PID> release heavy-test 1
=== release again — nothing held, a no-op
release rc=0
-- lock-order.trace:
=== CONCURRENT, inside a lane child — the slot is the lane id
METRIC {"event":"semaphore_acquired","name":"live-qa","capacity":1,"wait_s":0,"at":"2026-10-18T00:00:00+00:00"}
METRIC {"event":"semaphore_wait_seconds","name":"live-qa","task_id":"T-7","slot":"2","capacity":1,"wait_s":0,"at":"2026-10-18T00:00:00+00:00"}
rc=0
-- semaphore slots:
   ./live-qa/1
-- SEM_GATE_SLOT=[1] SEM_HELD=[3 ]
-- lock-order.trace:
   1792281600 <PID> acquire live-qa 1
=== a lock-order refusal: heavy-test (rank 2) while live-qa (rank 3) is held — rc 2, not an expiry
ERR   ! heavy-test semaphore REFUSED — a higher-ranked lock is already held (lib/semaphores.sh lock order); running unguarded rather than deadlocking
METRIC {"event":"semaphore_order_refused","name":"heavy-test","task_id":"T-7","at":"2026-10-18T00:00:00+00:00"}
rc=2
-- semaphore slots:
   ./live-qa/1
-- SEM_GATE_SLOT=[] SEM_HELD=[3 ]
-- lock-order.trace:
   1792281600 <PID> refused heavy-test 
=== releasing live-qa from the slot recorded before the refusal
release rc=0
-- semaphore slots:
-- SEM_GATE_SLOT=[] SEM_HELD=[]
-- lock-order.trace:
   1792281600 <PID> release live-qa 1
=== contention: every heavy-test slot held by a live process, the wait expires (timeout 0)
ERR   x Timed out after 0s waiting for the heavy-test semaphore — returning the task to pending, NOT failing it
METRIC {"event":"semaphore_timeout","name":"heavy-test","wait_s":0,"at":"2026-10-18T00:00:00+00:00"}
METRIC {"event":"semaphore_wait_seconds","name":"heavy-test","task_id":"T-7","slot":"2","capacity":1,"wait_s":0,"outcome":"timeout","at":"2026-10-18T00:00:00+00:00"}
rc=1
-- semaphore slots:
   ./heavy-test/1
-- SEM_GATE_SLOT=[] SEM_HELD=[]
-- lock-order.trace:
   1792281600 <PID> timeout heavy-test 
=== the same expiry with a DEAD holder: timeout 0 reclaims the slot but does not retry
ERR   x Timed out after 0s waiting for the heavy-test semaphore — returning the task to pending, NOT failing it
METRIC {"event":"semaphore_timeout","name":"heavy-test","wait_s":0,"at":"2026-10-18T00:00:00+00:00"}
METRIC {"event":"semaphore_wait_seconds","name":"heavy-test","task_id":"T-7","slot":"2","capacity":1,"wait_s":0,"outcome":"timeout","at":"2026-10-18T00:00:00+00:00"}
rc=1
-- semaphore slots:
-- SEM_GATE_SLOT=[] SEM_HELD=[]
-- lock-order.trace:
   1792281600 <PID> timeout heavy-test 
=== a dead holder with time left: reclaimed on sight, acquired on the next poll
METRIC {"event":"semaphore_acquired","name":"heavy-test","capacity":1,"wait_s":0,"at":"2026-10-18T00:00:00+00:00"}
METRIC {"event":"semaphore_wait_seconds","name":"heavy-test","task_id":"T-7","slot":"2","capacity":1,"wait_s":0,"at":"2026-10-18T00:00:00+00:00"}
rc=0
-- semaphore slots:
   ./heavy-test/1
-- SEM_GATE_SLOT=[1] SEM_HELD=[2 ]
-- lock-order.trace:
   1792281600 <PID> acquire heavy-test 1
-- lock-order.trace:
   1792281600 <PID> release heavy-test 1
=== lane_defer_on_semaphore — a deferred result, exit 13
rc=13
-- result:
   {
     "task_id": "T-7",
     "spec": "harness/stories/STORY-7/tasks/T-7.md#t-7",
     "branch": "factory/task/T-7",
     "lane_path": "<T>/lanes/3",
     "base_sha": "abc1234",
     "head_sha": "<SHA>",
     "outcome": "deferred",
     "reason": "semaphore-timeout:live-qa",
     "at": "2026-10-18T00:00:00+00:00"
   }
