@@ -455,60 +455,57 @@ describe('the mirror direction: a reader that is never coming back', () => {
455455 expect ( Number ( String ( declared ) . replaceAll ( '_' , '' ) ) ) . toBe ( SHIM_DRAIN_STALL_MS ) ;
456456 } ) ;
457457
458- it ( 'a CLOSED read end ends the child on its own — by an uncaught EPIPE, never by the bound ' , ( ) => {
459- // ⚠️ This case used to read `elapsedMs < STALL_MS` , and its name used to
460- // say "released at once … EPIPE reaches the callback". BOTH were wrong
461- // about this shape, and the trace that settles it is worth more than the
462- // assertion it replaces .
458+ it ( 'a CLOSED read end ends the child on its own, with the status every other reader gets ' , ( ) => {
459+ // ⚠️ THE NUMBER BELOW MOVED FROM 1 TO 2 , and this case is why it could not
460+ // move quietly. It pinned 1 on purpose — 1 was what the CLI DID, never what
461+ // anyone contracted — and #14858 is the card that changed the CLI. ⛔ This
462+ // was not a broken test and the flip is not a regression .
463463 //
464- // What the child ACTUALLY does with its read end destroyed: oclif's
464+ // What the child USED TO DO with its read end destroyed: oclif's
465465 // `displayWarnings()` makes the first stderr write, the pipe is already
466466 // gone, node raises `write EPIPE` as an `error` event on `process.stderr`,
467- // NOTHING IS LISTENING, and the process dies of an uncaught exception —
468- // exit 1, ~1.4 s in. `writeStderr()` is never called, so the bound this
469- // case was named after is never armed, let alone paid. Traced on one box
470- // with a `--import` observer: the shim's own 415-byte write is #175, at
471- // 9250 ms, behind 174 oclif writes that all EPIPE — 7.8 s after the
472- // unobserved child is already dead.
467+ // NOTHING WAS LISTENING, and the process died of an uncaught exception —
468+ // exit 1, 938-1174 ms in, 12 of 12 runs, traced with a `--import` observer
469+ // that installed no listener here and wrapped no write. `writeStderr()` was
470+ // never called at all, so the bound this case was once named after was
471+ // never armed, let alone paid. (An earlier version of this case read
472+ // `elapsedMs < STALL_MS` and was named for that bound; the wall clock went
473+ // because its whole measured term is child cold start, which is elastic,
474+ // and because it stayed green through the very ablation it named.)
473475 //
474- // ⛔ So the wall-clock bound was not merely fragile, it was a PHANTOM: it
475- // could not fail for the reason it named. Ablated on `bin/run-dev.js`,
476- // same box, same probe, with the old bound's verdict in brackets:
476+ // `bin/run-dev.js` now attaches a no-op `error` listener to
477+ // `process.stderr` before `run()`. A failed stderr write stops being fatal,
478+ // the run reaches the CLI's own exit path — oclif's `handle()`, status 2 —
479+ // and the closed reader answers what the drained and never-read readers
480+ // already answered (#14715 pinned 2 for the never-read one). Re-measured
481+ // for that change, one contiguous 2x2 ablation of the shim on one box, the
482+ // listener present/absent against the `write` callback kept/removed:
477483 //
478- // pristine exit 1, 1387-1711 ms [green]
479- // write callback REMOVED, so a closed path
480- // could only finish on the bound — the
481- // regression this case named exit 1, 1517-1633 ms [GREEN]
482- // EPIPE made non-fatal, callback kept exit 2, 8787-8979 ms [green, 1.2 s spare]
483- // both, so the path really pays the bound exit 2, 23601-23712 ms [red]
484+ // listener present, callback kept (as shipped) exit 2, 1237-1312 ms
485+ // listener present, callback removed exit 2, 16271-16294 ms
486+ // listener absent, callback kept (the defect) exit 1, 983-1028 ms
487+ // listener absent, callback removed exit 1, 843-1031 ms
484488 //
485- // The bound moved only on lines 3 and 4, which change the EXIT CODE too;
486- // against its own regression it stayed green. And its whole measured term
487- // is child cold start, which is elastic — 1.4 s here, 8.9 s the moment
488- // anything lets the child run further — judged against 10 s borrowed from
489- // case 4's parent stall, a number with no relationship to this case.
489+ // ⭐ The exit status is still the observation, and it still carries no load
490+ // term. 1 means the child died on its first write and never reached the
491+ // drain; 2 means it got through to `handle()`, which on this run is only
492+ // reachable THROUGH `writeStderr()` — bound paid or not. BOTH rows that
493+ // remove the listener flip it back to 1, so this line pins the fix and not
494+ // the weather.
490495 //
491- // ⭐ The exit status IS the observation the wall clock was standing in for,
492- // and it carries no load term at all. 1 means the child died on its first
493- // write and never reached the drain; 2 means it got through to `handle()`,
494- // which is only reachable THROUGH `writeStderr()` — bound paid or not. Every
495- // ablation above that reaches the drain flips it, including the one the old
496- // assertion could not see.
497- //
498- // ⚠️ 1 is what the CLI DOES, not what anyone contracted: a caller whose
499- // stderr is closed gets 1 where every other reader gets 2, and cannot tell a
500- // failed command from a crashed CLI. Filed as #14858. If that is fixed to
501- // exit 2 this case reds, which is the point — the fixing PR flips the number
502- // here and says why. ⛔ Do not "repair" a red by loosening this to
503- // `not.toBeNull()`; that is the phantom check all over again.
496+ // ⛔ Do not "repair" a red here by loosening to `not.toBeNull()`; that is
497+ // the phantom check the wall clock already was. A red means the child is
498+ // dying on a stderr write again — the listener is gone, or something now
499+ // writes to stderr ahead of where it is attached.
504500 const evidence =
505501 `closed-read-end child ran ${ closedEnd . elapsedMs } ms (harness cap ${ UNREAD_HARD_CAP_MS } ms); ` +
506502 `case 1 measured the same child at ${ unbuilt . elapsedMs } ms on this runner minutes earlier` ;
507503 expect ( closedEnd . signal , `the harness SIGKILLed the child — it was still alive at the ceiling. ${ evidence } ` ) . toBeNull ( ) ;
508504 expect (
509505 closedEnd . code ,
510- `the child did not die on its first stderr write — it reached the shim's drain, so something now ` +
511- `tolerates EPIPE on stderr (see #14858 and the ablation table above this assertion). ${ evidence } ` ,
512- ) . toBe ( 1 ) ;
506+ `the child did not reach the CLI's own exit path — it died on a stderr write, so nothing is making ` +
507+ `EPIPE non-fatal on \`process.stderr\` any more (see #14858 and the ablation table above this ` +
508+ `assertion). ${ evidence } ` ,
509+ ) . toBe ( 2 ) ;
513510 } ) ;
514511} ) ;
0 commit comments