Skip to content

test: identity-guard the serve-debug readiness probe (kill the port-identity flake) - #191

Merged
tina4stack merged 1 commit into
v3from
fix/serve-debug-port-identity
Oct 1, 2026
Merged

tina4stack merged 1 commit into
v3from
fix/serve-debug-port-identity

Conversation

@tina4stack

Copy link
Copy Markdown
Owner

What

'cli_serve_debug_env' flaked when a foreign server held the reused ephemeral port.

Root cause (evidence from a Ruby CI child serve.log; all frameworks share the pattern)

The ephemeral free-port is reused: under load a different, debug-off server (a prior case's child lingering on that port) already holds it, and TINA4_NO_TAKEOVER=true stops our debug-on child evicting it. The old probe hit /__dev directly and trusted the first response — from the foreign server → settled 404 for the debug-true case. A 200/404 on the port proves only that something listens, not that it is our child.

Fix

Each boot plants a per-boot unique readiness route (/ready_<token>) that only our child serves. Readiness waits for a 200 on that (a foreign server 404s it) before polling /__dev; a contended port that never yields our token times out and retries on a fresh port (boot_attempts=5). All assertions unchanged. No mocks — a real child, a real socket.

Parity

tina4-ruby PR #95 (ShutdownProbe Server: banner identity guard), tina4-nodejs #111 (loopBlockWatchdog /fast readiness). Node has no CLI-serve-debug test, so no sibling there.

🤖 Generated with Claude Code

…lake)

test_cli_serve_debug_env flaked when a foreign server held the reused
ephemeral port. _free_port() hands out an ephemeral port; under load a
DIFFERENT debug-off server (a prior case's child lingering on the reused
port) already holds it, and TINA4_NO_TAKEOVER stops our debug-on child
evicting it. The old probe hit /__dev directly and trusted the first
response -- from the FOREIGN server -> settled 404 for the debug-true
case. A 200/404 on the port proves only that SOMETHING listens, not that
it is OUR child.

Fix: each boot plants a per-boot UNIQUE readiness route (/ready_<token>)
that only OUR child serves. Readiness waits for a 200 on THAT (a foreign
server 404s it) before polling /__dev, and a contended port that never
yields our token times out and retries on a FRESH port (boot_attempts=5).
All four assertions unchanged. No mocks: a real child, a real socket.

Parity with tina4-ruby (ShutdownProbe identity guard) and tina4-nodejs
(loopBlockWatchdog /fast readiness).

Verified (py 3.13.11, macOS): 4/4 single, 12/12 under CPU load; gate
proof -- a debug-on server lacking the route 404s /ready_<token> while
serving /__dev=200, so a foreign server is genuinely rejected.

Signed-off-by: Andre van Zuydam <[email protected]>
Co-Authored-By: Claude Opus 4.8 <[email protected]>
Co-Authored-By: Tina4 <[email protected]>
@tina4stack
tina4stack merged commit c149372 into v3 Oct 1, 2026
15 checks passed
@tina4stack
tina4stack deleted the fix/serve-debug-port-identity branch October 1, 2026 20:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants