Repository navigation
Conversation
A failure whose every failing test shows a child ended by SIGSEGV, SIGBUS or SIGILL with empty output reruns its files once in the same checkout. A passing rerun passes the gate; every crash is recorded as native_crash with test, signal, pid and the apport report, and status counts the last 7 days. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Bugbot couldn't run - usage limit reachedBugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit. A user or team admin can review and increase usage limits in the Cursor dashboard. (requestId: 2df7cf1f-d1ff-4f52-b961-a96246a13cf1) |
There was a problem hiding this comment.
This is an auto review done by revuto.
Successful native retries produce evidence that acceptance rejects. Native crashes inside suites or subtests also fail to trigger the retry.
| const again = await plan.run(); | ||
| if (again.ok) { | ||
| native.notes.push(`${at} Reran ${plan.what} once in the same checkout: exit 0, so the crash is not the change's.`); | ||
| return again; |
There was a problem hiding this comment.
This is an auto review done by revuto.
[P2] Make recovered runs valid command evidence
The new CLI fixture runs the two-file head command unsuccessfully, then passes only the one-file retry. lib/check.js records both commands, but lib/gate-commands.js:119-122 requires a successful head command and permits only recorded head, proof or host expansions. This retry satisfies neither condition, so check tests reports success while the gate report rejects its evidence and blocks acceptance and reviewer dispatch. Record the retry selection and recovery in an audited receipt, update command validation, and extend the CLI test to check that its successful evidence counts.
| crashes.push({ test, ...crash }); | ||
| mine++; | ||
| } | ||
| if (!mine) every = false; |
There was a problem hiding this comment.
This is an auto review done by revuto.
[P2] Account for aggregate failures from native-crashing descendants
Node's spec reporter includes failed suite and subtest-parent names in testFailure().names, as the existing nested integration cases in test/gates/tests-base.test.js:138-159 verify. Those aggregate parents have no crash error block after their failure header, so this sets every to false even when every failing leaf shows a native crash. Crashes inside describe() or nested subtests therefore never retry. Resolve aggregate parents through their failing descendants, as BaseTests.failingFiles does, while preserving genuine parent or hook failures.
…s are read in the gate The tests gate records its one native crash rerun as receipt.native_rerun, and the command check counts a head that rerun rescued. A suite or parent test that failed only through crashed tests inside it no longer blocks the rerun. Where apport keeps cores, gate commands run with a raised soft core limit; a crashed child's core is copied to the task's private scratch, read with gdb into the evidence and deleted, and the shared copy is emptied. The fixture test asserts its child's output. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Bugbot couldn't run - usage limit reachedBugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit. A user or team admin can review and increase usage limits in the Cursor dashboard. (requestId: 0c69131d-e391-429e-aeb7-edd53ea5215b) |
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Bugbot couldn't run - usage limit reachedBugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit. A user or team admin can review and increase usage limits in the Cursor dashboard. (requestId: 72b17462-3082-495f-b15d-8336e617a9bc) |
There was a problem hiding this comment.
This is an auto review done by revuto.
Revuto completed the review and found no evidence-backed concerns.
…mit prefix Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
# Conflicts: # docs/cli.md # docs/state.md # lib/gate-commands.js # lib/gates/tests.js
Bugbot couldn't run - usage limit reachedBugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit. A user or team admin can review and increase usage limits in the Cursor dashboard. (requestId: 739bc37f-4cba-4feb-beb3-bae725d884d8) |
… over it CodeQL js/redos: repeated optional separators in one pattern backtracked exponentially on a long unclosed output list. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Bugbot couldn't run - usage limit reachedBugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit. A user or team admin can review and increase usage limits in the Cursor dashboard. (requestId: f4fe49be-a888-4b3b-80c6-574f2fc5ac9e) |
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Bugbot couldn't run - usage limit reachedBugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit. A user or team admin can review and increase usage limits in the Cursor dashboard. (requestId: 336cf042-b38d-4c99-8ccb-2de8ba0e50cd) |
|
Review (Tower Crane, clean context) Full review of T460 at revision 5 against its acceptance. Gate results used as supplied: tests (prove, scoped proof fails with the 8 non-test files reverted), clean and CI ok at this sha. Acceptance:
Scope: each file outside the named paths is needed. Blocking findingsNone Blocking count: 0 Follow-ups
|
…ve-node-sigsegvs-in-gates-are-retrie # Conflicts: # test/governor.test.js
Bugbot couldn't run - usage limit reachedBugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit. A user or team admin can review and increase usage limits in the Cursor dashboard. (requestId: 635ca1d5-4779-4989-a4fd-1fea49f0de5c) |
What
The tests gate reruns a failure once when every failing test's error shows a child that ended with
SIGSEGV,SIGBUSorSIGILLand empty output. T264, T412, T416, T426 and T453 each lost a rework round to these Node v26 crashes, which no JavaScript change can cause. Where apport keeps cores, the gate also reads the crashed child's core with gdb.lib/native-crash.js: the parser and the core handling. The parser recognizes two forms. The first is node'schild_processerror object (signal: 'SIGSEGV'with everystdout/stderr/outputit shows empty, pluspid), as in T412. The second is a message that ends where the child's output would follow (exited null (signal SIGSEGV):), as in T453. A suite or parent test that failed only through failing tests inside it is judged by those tests. Spec prints no error under such a parent, and TAP marks itfailureType: 'subtestsFailed'. A parent with an error of its own, such as a failed hook, still blocks the rerun.lib/gates/tests.js: a head, scoped proof, reverted or host-only command whose failing tests all show a native crash reruns only the failing files once in the same checkout, throughgates.tests_proof_cmd {tests}. If the rerun passes, the gate continues as if the first run had passed. If it fails, the first failure stands. The receipt records the rerun asreceipt.native_rerun: {step, files, ok}.lib/gate-commands.js: the evidence command check accepts the rerun's expansion. It also counts a head command the rerun rescued as passed (step: "head",ok: true, and the rerun exited 0). Without this,check testspassed whiletask showrejected its evidence./var/crashreports. On Linux, whencore_patternpipes to apport, each head, proof, reverted, host-only and rerun command runs with its soft core limit raised to the hard limit (treeExecoptioncores; the receipt still records the pinned command). apport writes an unpackaged binary's core to/var/lib/apport/coredump/core.EXE.UID.BOOT.PID.TIME. After each command the gate copies the core whose pid matches a crashed child intonative-cores/under the task scratch (directory 0700, file 0600) and empties the shared copy. A non-root user cannot unlink there. The gate then runsgdb -batch -nx -ex bt [node] -c CORE, records up to 40 frames asnative_crash[].stack, and deletes the copy. If gdb reads no stack,core_errorrecords why and the private copy stays. Other cores written during the command are emptied. Nothing is uploaded.native_crash: [{test, signal, pid, core_file?, stack?, core_error?}]in the evidence and itscheck testsevent.statusprintsnative crashes: N in the last 7 days, last TASK at TIME, and its JSON always hasnative_crashes.docs/state.md#native-crashesand the evidence and receipt paragraphs indocs/state.mdanddocs/cli.md. Changelog:changelog.d/T460.md.Core analysis
No node core has been captured. Checked 2026-10-20 at 21:01 Jerusalem time, at 22:42, on 2026-10-21 at 02:10, at 05:43, and again on 2026-10-21 at 14:30:
/var/crashhas no*node*.crash, and/var/lib/apport/coredumpis empty./var/log/apport.log*(rotations from 2026-10-12 to 2026-10-21) lists 18 node SIGSEGVs, not counting this PR's deliberate fixture crashes: 7 on v26.10.0 and 11 on v26.12.0. The newest, at 2026-10-21 01:39, istower-crane.js worktree list --jsonin a gate worktree running code without this change. Most are tower-crane CLI children in gate worktrees and test fixtures (tower-crane.js claim T1,task show T1,task note T1). Each ran withcore limit 0, and apport loggedexecutable does not belong to a package, ignoring, so no core or report exists for any of them. Between 02:10 and 14:30 every node SIGSEGV apport logged was one of this PR's deliberate fixture crashes (process.kill(process.pid, 'SIGSEGV')).ulimit -c unlimitedshowed that apport 2.34 writes no core into the cwd. It loggedhost pid ... crashed in a container without apport support, so a sandboxed crash keeps nothing. On the host, earlier fixture crashes with limit 512 show apport choosing/var/lib/apport/coredump/core._home_..._bin_node.1000.<boot>.<pid>.<ts>and aborting only on size. That is where the gate now looks.So no stack can be recorded yet, and no Node version is pinned. The next gate crash on the host leaves its stack in
native_crash[].stack. Recording it in a Node issue draft, and pinning a version if it shows a Node or V8 bug, is the follow-up.Verification
test/gates/tests.test.js"a native child crash reruns only the failing file once...": a real fixture childexecs node, which kills itself with SIGSEGV.ulimit -c 1makes apport drop the deliberate core. The fixture writes a fake apport core named with the child's pid, and fakegdbscripts stand in for gdb. The table has five rows:receipt.native_rerunis{step: 'head', files: ['test/crash.test.js'], ok: true}. The core is claimed into a 0700 directory, the shared copy is emptied, gdb gets the gate's node and-c CORE,stackholds its frames, and the copy is deleted.describe, and one-off in a subtest: pass.confirmed_failureand two crashes. gdb fails, socore_erroris recorded and the 0600 copy stays.test/gates.test.js"a one-off native child crash records native_crash...": CLI wiring. It checks the evidence, the audit event,receipt.native_rerun, the two recorded commands (exit 1, then 0),task showreporting the tests gate ok, and thestatustext and JSON.test/native-crash.test.js: the parser variant table has anoutputlist with content beside empty streams, and a long unclosedoutputlist. The old single pattern over that list backtracked exponentially there (CodeQL js/redos Merge is race-free against automation: manual and automatic merges share the task reservation #118). It now splits on commas and checks each item, and the row returns in about 1 ms. The table now also has a spec suite, a spec suite with its own hook failure, a TAPsubtestsFailedparent, a TAPhookFailedparent and a lone failing name. It also covers apportcore_patterndetection and core selection (uid, age, emptied cores), plus the 7-day window.lib/gate-commands.jsat its previous version, the CLI test fails withtests command receipts do not match the pinned command.test/native-crash.test.js test/gate-commands.test.js test/gate-join.test.js test/gates.test.js test/gates/tests-base.test.js test/gates/tests.test.js. All pass exceptgate commands run with gc.autoDetach=false..., which fails the same way at the previous head without this change. The sandbox's git shim sets 42GIT_CONFIG_*variables.npm run check:shared -- --base origin/mainpasses, mutants included.test/fixtures/windows-missing-command.js, which fakes cmd.exe only for the exact commandtower-crane-missing-test-program, missed the prefixed command on a host where apport iscore_pattern. That broke the threetest/escalation.test.jsWindows command-not-found tests. The prefix is nowCORE_LIMITinlib/gates/common.js, and the fixture strips it, since real cmd.exe never gets it. The three tests fail before the fix and pass after it in the sandbox, whosecore_patternis also apport.plannedCommands, the receipt check inlib/gate-commands.jsand both docs keep the native rerun besidereceipt.host_probes.test/escalation.test.js test/native-crash.test.js test/gates/tests.test.js test/gates.test.js test/gate-join.test.js test/gates/tests-base.test.js test/gate-commands.test.js test/host-probes.test.js: 200 of 203 pass. Three fail only in the sandbox: two escalation tests find no temp directory short enough for a broker socket (/tmpis read-only here), andgc.autoDetachsees the sandbox'sGIT_CONFIG_*entries. The host suite passed all three at 311acd9.test/native-crash.test.js test/gates/tests.test.js test/gates.test.js test/gates/tests-base.test.js test/gate-join.test.jsafter merging origin/main: 111 of 112 pass. Onlygc.autoDetachfails, from the sandbox'sGIT_CONFIG_*entries, and it passes when run alone with a clean environment.npm run check:shared -- --base origin/mainpasses.test/governor.test.jsfailed becausekill(suitePid, 0)still answered for an exited, unreaped suite process. main has since fixed the same test (suiteStoppedwithwaitOnRepo), so the merge at 3df5c95 takes main's version and this PR no longer changestest/governor.test.js.test/governor.test.js test/native-crash.test.js test/gates/tests.test.js test/gates.test.js test/gate-join.test.js test/gates/tests-base.test.js test/escalation.test.jspass, except in the sandbox's own environment: withTOWER_CRANE_STATEnaming the read-only project state directory,test/gates/tests.test.jscannot take the worktree lock (EROFS), andgc.autoDetachsees the sandbox'sGIT_CONFIG_*entries. WithTOWER_CRANE_STATEunset, tests.test.js passes 54 of 55, andgc.autoDetachpasses alone once the sandbox'sGIT_CONFIG_*entries are cleared.npm run check:shared -- --base origin/mainpasses.Limits
gcorefails) and apport drops sandboxed crashes. The gdb call and the output parsing are covered by the fake-gdb rows. The first real crash on the host is the first real read.signal:for the object form, so a TAP runner only gets the line form.🤖 Generated with Claude Code
Pre-submit review
one-off,one-off in a describe,one-off in a subtest; CLI wiring in test/gates.test.js "a one-off native child crash..."): pass at this head. A repeating crash fails (rowevery time,confirmed_failure, two crashes): pass. Captured core analyzed or absence stated with date ("Core analysis": /var/crash, /var/lib/apport/coredump and apport.log checked 2026-10-21 14:30 Jerusalem, no node core kept): pass.Note
Medium Risk
Changes tests gate pass/fail and evidence acceptance for real CI runs; core handling is scoped to private scratch but still touches host crash dumps and gdb.
Overview
The tests gate now treats one-off native child crashes (SIGSEGV/SIGBUS/SIGILL with empty output) as infrastructure, not worker failures: when every failing test matches that pattern, it reruns only the failing files once via
gates.tests_proof_cmdbefore any base rerun, and a passing rerun lets the gate continue as if the first run succeeded.A new
lib/native-crash.jsparses spec/TAP andchild_processerror output (including suite/parent cases), optionally raises the core limit under apport, copies matching cores into task scratch, runs gdb for a short backtrace, and recordsnative_crashon evidence and audit events.receipt.native_rerunandlib/gate-commands.jswere updated so rescued head runs still count as valid command receipts.statusadds a rolling 7-day native crash count (native_crashesin JSON).Gate lease planning includes one extra command budget per run;
treeExeccan prefix a POSIX coreulimit, with a Windows test fixture strip for prefixed commands.Reviewed by Cursor Bugbot for commit 3df5c95. Configure here.