Skip to content

test(k8s-compat): size the docker smoke watchdog for a wedge, not a stopwatch - #715

Merged
blove merged 1 commit into
mainfrom
blove/fix-docker-smoke-watchdog
Sep 17, 2026
Merged

blove merged 1 commit into
mainfrom
blove/fix-docker-smoke-watchdog

Conversation

@blove

@blove blove commented Sep 17, 2026

Copy link
Copy Markdown
Contributor

Refs #535. Addresses one specific manifestation of that issue's ownership flake and leaves the rest of its investigation track alone.

The manifestation this fixes

A different failure mode from the expected undefined to be defined signature already recorded on #535:

Error: Smoke script exceeded its ten-second watchdog after 58 fake commands

I hit this twice locally during an unrelated full-suite run, on removes a renamed owned app but preserves its same-name replacement and allows runs/wait to use its longer command budget. Both pass 94/94 in isolation.

Root cause

The run watchdog was 15s. The slowest scenario's own run window measures 9,719ms on an idle machine, so the margin was about 1.5x.

Every simulated docker/curl call is a symlink to a Node script with a #!node shebang, so each one boots a fresh Node process. A run's wall-clock cost therefore tracks how contended process creation is on the host, not how much work the script did. When the whole repository suite runs, that contention is real and 1.5x is not enough.

Worth noting for the issue's record: pure CPU spin does not reproduce this. Ten busy arithmetic loops left the test passing. Only process-spawn contention reproduces it, which is consistent with the September 15 reassessment that ruled out real Docker resource contention.

Deterministic reproduction

One scenario, ten concurrent node -e "" spawn loops, nothing else varied:

Watchdog Run duration Outcome
15s 15,397ms failed, watchdog fired
60s 15,224ms passed

The duration is essentially identical. Only the budget decided the outcome.

The change

  • Watchdog 15s to 60s. It exists to SIGKILL a wedged script, so it needs to clear any legitimate run while still bounding a hang. 60s is roughly 6x the idle worst case. The constant feeds only setTimeout, the failure message, and elapsedMs assertions, so it cannot alter any scenario's behavior.
  • A headroom guard, declared last so it reads what the scenarios actually measured rather than a number written down once. It fails if the slowest observed run exceeds half the budget, so this margin cannot erode silently again. It fails on the old constant and passes on the new one.
  • Truthful failure message. It said "ten-second" while the constant had been 15s since Harden Kubernetes compatibility infrastructure #523. That misdirected my own diagnosis for a while, and the original report quotes the same wrong number.

Deliberately not touched

The 2,000ms ROUTINE_FAKE_COMMAND_TIMEOUT_MS is the mechanism behind the other signature, the one #535 reproduced by delaying a listing 2,100ms. That issue records "no deadline was changed" as a deliberate choice and #669 added diagnostics instead, so I left it and its INTENTIONAL twin alone. This PR changes one budget.

The sibling runSupervisor watchdog is 5s against a 1,961ms worst case, about 2.5x. Thinner than ideal but far better than 1.5x, and I have no failure evidence for it, so it is unchanged.

Verification

tsc -p test/k8s-compat/tsconfig.json and scoped Biome both clean. Test-only change under test/, so check-changesets.mjs reports no changeset needed, and it confirms that.

Full-file local runs are not trustworthy evidence right now: this machine sat at a 15-minute load average above 25 from concurrent work, and under that I saw two other tests in this file fail and then pass in isolation, which is the same load-sensitivity family and not something this constant can cause. CI is the honest arbiter for the full file.

🤖 Generated with Claude Code

…topwatch

The docker smoke run watchdog was 15s while the slowest scenario's own run
window measures about 10s on an idle machine, leaving roughly 1.5x headroom.
Every simulated `docker`/`curl` call in these scenarios boots a fresh Node
process, so a run's wall-clock cost tracks how contended process creation is
on the host rather than how much work the script did. A full repository suite
spawning processes on every core erases that margin, and the watchdog fires on
runs that are healthy but merely slow.

Reproduced deterministically by running one scenario under ten concurrent
process-spawn loops: it failed at 15,397ms with the old budget and passes at
15,224ms with the new one, the duration being essentially unchanged.

Raises the watchdog to 60s so it still bounds a genuinely hung script while
clearing any legitimate run, and adds a guard that asserts the slowest run the
file actually observed stays within half the budget, so the margin cannot
erode silently again. The failure message also said "ten-second" while the
constant had been 15s since #523, which misdirected diagnosis; it now reports
the real budget.

Refs #535

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@vercel

vercel Bot commented Sep 17, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
b4-run Ready Ready Preview Sep 17, 2026 8:46pm UTC

Request Review

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Automated approval: this PR received an intelligent (AI) code review. See the review comments on this PR.

@blove
blove merged commit 3ccff5c into main Sep 17, 2026
31 of 32 checks passed
@blove
blove deleted the blove/fix-docker-smoke-watchdog branch September 17, 2026 21:42
blove added a commit that referenced this pull request Sep 17, 2026
None of the three touches this page: verify registry error codes,
body-less middleware reject status, and a k8s smoke watchdog. Only the
generated SEO manifest conflicted, resolved by regenerating per the
procedure #712 added to AGENTS.md.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

This branch was successfully deployed

1 active and 1 inactive deployments
vercel-preview — e7b2ca8f Deployed Sep 17, 2026 by blove via vercel-native #2013
Preview — e7b2ca8f Deployed Sep 17, 2026 by vercel[bot]
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.

1 participant