Skip to content

fix: nax timeout no longer cancels runners; add nax salvage - #54

Merged
DavidWells merged 10 commits into
masterfrom
fix/nax-timeout-detach
Sep 28, 2026
Merged

DavidWells merged 10 commits into
masterfrom
fix/nax-timeout-detach

Conversation

@DavidWells

@DavidWells DavidWells commented Sep 28, 2026 •

Copy link
Copy Markdown
Contributor

Problem

nax run agent cancelled healthy Netlify runners when its hidden 25-minute --timeout-minutes ran out. It also recorded an empty result and never read the session back. A 4,558-credit run with a finished, recoverable diff looked lost. Details: docs/ai/bugs/nax-timeout-cancels-runner-and-drops-result.md.

Changes

  • A timeout stops the wait, not the runner. The remote runner keeps working. --cancel-on-timeout opts back into cancelling, for cost-capped CI.
  • Session sync on every timeout path. Result text, usage and diff flags reach .nax/ artifacts. raw.timeout.cancelledRunner records what happened.
  • Resume polls instead of resubmitting. nax run --resume watches a timed-out run whose runner was left running, rather than resubmitting it (which would bill twice).
  • Fix: the wait loop uses its own deadline. It used to check the persisted handle's submit-time deadline, so resume-polling any run older than its original timeout ended instantly.
  • --timeout-minutes is visible in run / run agent help.
  • Timeout guidance. nax prints the runner id, the View run link, and the next step (--resume or nax salvage).
  • New nax salvage --runner <id> [--branch] [--session] [--allow-default-branch]. It creates the branch at the session's base commit if it's missing, commits the diff through Netlify, and waits for the commit. It refuses runners that are still running, sessions with no diff, and the default branch.
  • SDK: Session.baseSha is now mapped (base_sha was already recognized but dropped). This needs to ship in the SDK 0.4.0 publish before the published nax can create branches in salvage.
  • Time Limit prompt section. Every Netlify API prompt gets a ## Time Limit section stating the 25-minute agent runner max. It tells the agent to finish well before it and to report partial results if it gets close.
  • Skills and docs are updated to match.
  • Unrelated: a dashboard fix that drops the hardcoded /Users/david path shortening in the prompt modal.

Testing

  • npm test: 1255 pass. tsc: clean. SDK tests: 146 pass.
  • New unit tests cover the three timeout paths (cancel vs. detach, session read after stop), resume reconcile and mid-step resume polling, the salvage refusal and commit flow, CLI routing and help, and the time-limit prompt.
  • Read-only check against the real runner from the bug report: the SDK now returns baseSha and the 2,862-char session result.
  • Not run: a live timeout, or a live nax salvage against a real repo.

Follow-ups

  • There's no nax wait --runner for re-waiting on a single run agent after a timeout. The guidance points to the run link, then nax salvage.

…session result

- timeout keeps remote runner running unless --cancel-on-timeout
- timeout paths read session so result, usage, diff state persist
- wait deadline governs loop, not stale persisted handle deadline
- resume polls a timed-out run whose runner was left running
- --timeout-minutes visible on run/run agent
Creates the branch at the session base SHA when missing, refuses
running runners, diff-less sessions, and the default branch unless
--allow-default-branch.
test(resume): timed-out run left running is polled on resume
…e local wait

Skill no longer advises raising --timeout-minutes past 25.
…ot a running runner

docs(skills): flow example uses a 25-minute wait
@DavidWells
DavidWells merged commit b8626b5 into master Sep 28, 2026
1 of 2 checks passed
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