You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Originally scoped as a new separate scripts/check-throwing-stubs.mjs script. Re-scoped per 360 evaluation — the existing scripts/check-throwing-stub-callers.mjs (588 LOC, PR #2412, closing #2410) already implements substantially this gate with stronger discrimination than originally proposed here.
Re-scope decision: Add : never return type as a fourth calibration signal to the existing gate, rather than building a separate script.
Problem (unchanged)
When upstream sync re-introduces a previously-gutted function as an unconditional-throw stub, production code that imports it crashes user-visibly. CI passes because tests mock the stub. See #2408 for the canonical example.
Existing coverage
scripts/check-throwing-stub-callers.mjs classifies a function as a "throwing stub" when:
Fork-attributed throw message: /not available in RemoteClaw fork|\bgutted\b|upstream-compat/i
Leading comment matches /Gutted in RemoteClaw fork/i
Live non-test callers of a classified stub fail CI unless allowlisted.
#2408 would have been caught by this gate (variadic-unknown signature + fork-attributed message both present).
Gap being closed here
A throwing stub without any calibration signal — e.g., a plain function foo(): never { throw new Error("something") } reintroduced by upstream sync — would escape the existing gate. Adding : never return type as a fourth calibration signal closes that gap while preserving the existing typed-helper discrimination (typed error-throw helpers like exitHooksCliWithError(err: unknown): never, throwGatewayAuthResolutionError(reason: string): never are correctly excluded today and must remain excluded).
Solution
Modify scripts/check-throwing-stub-callers.mjs:
Add : never return type detection as a fourth calibration signal (OR'd with the existing three)
scripts/check-throwing-stub-callers.mjs extended: : never return type treated as calibration signal
Typed-param exclusion preserved — current 6-8 : never error-throw helpers (exitHooksCliWithError, throwGatewayAuthResolutionError, throwUnresolvedGatewaySecretInput, throwPathEscapesBoundary, local fail arrow functions in subagent-spawn/attachments, path-policy, etc.) remain unflagged
Unit tests added for the 4-signal interaction: (a) : never + throw + no other signal + typed param → NOT flagged (legitimate helper); (b) : never + throw + no other signal + variadic-unknown → FLAGGED
node scripts/check-throwing-stub-callers.mjs passes on current main (no new violations introduced by the extension)
node scripts/check-throwing-stub-callers.mjs --inventory output reviewed for shape changes
pnpm check passes after merge
Out of scope
New separate script (superseded — use existing gate)
Separate .throwing-stubs-allowlist.txt (superseded — .throwing-stub-callers-allowlist already exists)
Standalone pnpm lint:throwing-stubs script (superseded — existing CI job already wires the gate)
Full 21-entry allowlist seed (irrelevant — the typed-param exclusion means most current : never returns aren't flagged)
Effort
~0.5 day (targeted diff + tests on existing 588 LOC script)
Dependencies
Blocked by: — (re-scope removes dependency on authoring an ADR file; HQ ADR 0005 H7 description will be updated to describe the extension approach)
Tracked under: #2433
Status update (2026-04-20)
Originally scoped as a new separate
scripts/check-throwing-stubs.mjsscript. Re-scoped per 360 evaluation — the existingscripts/check-throwing-stub-callers.mjs(588 LOC, PR #2412, closing #2410) already implements substantially this gate with stronger discrimination than originally proposed here.Re-scope decision: Add
: neverreturn type as a fourth calibration signal to the existing gate, rather than building a separate script.Problem (unchanged)
When upstream sync re-introduces a previously-gutted function as an unconditional-throw stub, production code that imports it crashes user-visibly. CI passes because tests mock the stub. See #2408 for the canonical example.
Existing coverage
scripts/check-throwing-stub-callers.mjsclassifies a function as a "throwing stub" when:throwstatement, AND(...args: unknown[])/(..._args: unknown[])/not available in RemoteClaw fork|\bgutted\b|upstream-compat/i/Gutted in RemoteClaw fork/iLive non-test callers of a classified stub fail CI unless allowlisted.
#2408 would have been caught by this gate (variadic-unknown signature + fork-attributed message both present).
Gap being closed here
A throwing stub without any calibration signal — e.g., a plain
function foo(): never { throw new Error("something") }reintroduced by upstream sync — would escape the existing gate. Adding: neverreturn type as a fourth calibration signal closes that gap while preserving the existing typed-helper discrimination (typed error-throw helpers likeexitHooksCliWithError(err: unknown): never,throwGatewayAuthResolutionError(reason: string): neverare correctly excluded today and must remain excluded).Solution
Modify
scripts/check-throwing-stub-callers.mjs:: neverreturn type detection as a fourth calibration signal (OR'd with the existing three).throwing-stub-callers-allowlistalongside the existing fix(agents): restore resolveAgentRuntimeOrThrow body — regression stub crashed every agent dispatch #2408 entryAcceptance criteria
scripts/check-throwing-stub-callers.mjsextended:: neverreturn type treated as calibration signal: nevererror-throw helpers (exitHooksCliWithError,throwGatewayAuthResolutionError,throwUnresolvedGatewaySecretInput,throwPathEscapesBoundary, localfailarrow functions in subagent-spawn/attachments, path-policy, etc.) remain unflagged: never+ throw + no other signal + typed param → NOT flagged (legitimate helper); (b): never+ throw + no other signal + variadic-unknown → FLAGGEDnode scripts/check-throwing-stub-callers.mjspasses on currentmain(no new violations introduced by the extension)node scripts/check-throwing-stub-callers.mjs --inventoryoutput reviewed for shape changespnpm checkpasses after mergeOut of scope
.throwing-stubs-allowlist.txt(superseded —.throwing-stub-callers-allowlistalready exists)pnpm lint:throwing-stubsscript (superseded — existing CI job already wires the gate): neverreturns aren't flagged)Effort
~0.5 day (targeted diff + tests on existing 588 LOC script)
Dependencies
Blocked by: — (re-scope removes dependency on authoring an ADR file; HQ ADR 0005 H7 description will be updated to describe the extension approach)
Tracked under: #2433
References