chore(stub-debt): resolve 6 fork-stub typing mismatches in agent-runner e2e — baseline 6 → 0#2458
Merged
alexey-pelykh merged 1 commit intomainfrom Apr 22, 2026
Merged
Conversation
…er e2e — baseline 6 → 0 (#2352) Bite B of #2354 umbrella (drive stub-debt baseline to zero). Resolves the 6 `@ts-expect-error -- fork stub typing mismatch` suppressions in src/auto-reply/reply/agent-runner.runreplyagent.e2e.test.ts by properly typing the local `modelFallbackModule` spy host with `vi.fn<ModelFallbackFn>()` instead of `{ runWithModelFallback: vi.fn() } as any`. When the host was `any`, `vi.spyOn` resolved to the untyped overload `(...args: unknown[]) => any` and the callback impls' strictly-typed `{ run }` parameters were contravariantly incompatible — removing `as any` and binding the mock's function signature makes the spies accept the existing callback shapes without suppression. Changes: - `src/auto-reply/reply/agent-runner.runreplyagent.e2e.test.ts`: - Replace `const modelFallbackModule = { runWithModelFallback: vi.fn() } as any;` (with `eslint-disable-next-line @typescript-eslint/no-explicit-any`) with a local `ModelFallbackFn` function type and `vi.fn<ModelFallbackFn>()`. - Delete 6 `// @ts-expect-error -- fork stub typing mismatch` comments. - Formatter (oxfmt) reflows 5/6 `vi.spyOn(...).mockImplementation(...)` chains into multi-line builder-chain style — cosmetic only, no behavior change. Callback bodies (mock return shape, `expect()` assertions) are byte-identical modulo whitespace. - `.stub-debt-baseline`: `6` → `0`. The baseline file and `scripts/check-stub-debt.mjs` gate simplification (Bite C) remain the next step to close #2354 — a separate follow-up PR. Verification: - `node scripts/check-stub-debt.mjs` → `stub-debt check passed: 0 == baseline 0.` (H8 fork-boundary-mock counter unchanged: `132 == baseline 132`). - `pnpm check` (format + tsgo + lint + project-specific lints) → exit 0. - E2E file runtime parity: 37 failed / 5 passed / 42 total — identical to pre-change. The 37 failures are pre-existing (resolveFallbackTransition gutted per Middleware Boundary Principle); not touched by this PR and not run by CI's `pnpm test` (which excludes e2e via test-parallel.mjs). - Adversarial validation (fresh-context subclaude): CLEAN verdict on 7 AC + 9 adversarial checks (no bypass patterns, no stealth normalization, no H8 regression, no formatter side effects, Bite C gate-simplification ready). Refs: #2354, #2457, ADR 0005 H5 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
3 tasks
alexey-pelykh
added a commit
that referenced
this pull request
Apr 22, 2026
… — Bite C (#2354) **Bite C** of the #2354 umbrella (drive stub-debt baseline to zero and remove it). Bites A (#2457, baseline 12 → 6) and B (#2458, baseline 6 → 0) drove the H5 `@ts-expect-error` count to zero across `src/`, `extensions/`, and `ui/`. This PR retires the H5 baseline entirely and flips the gate to zero-tolerance. The H8 fork-boundary-mock counter (`.fork-boundary-mock-baseline = 132`) is untouched — still baselined, still ratchetable. Changes: - `scripts/check-stub-debt.mjs`: inline the H5 counter as a zero-tolerance check (was baseline-gated via `readBaseline`+`reportCounter`). Any `@ts-expect-error` in a gated file fails the script with an inventory and a remediation pointer to Bite A (`as unknown as T` cast pattern, PR #2457) and Bite B (`vi.fn<Fn>()` typed-mock pattern, PR #2458). The H8 branch — `readBaseline` + `reportCounter` for `.fork-boundary-mock-baseline` — is byte-identical to pre-change; inline-for-H5 / helper-for-H8 asymmetry is intentional since the two counters are now fundamentally different patterns. - `.stub-debt-baseline`: DELETED (last value was `0`). - `CLAUDE.md:121`: rewrote the `stub-debt-gate` bullet to reflect zero-tolerance H5 + link to `CONTRIBUTING.md § Fork-boundary mocks` for H8 detail. - `CONTRIBUTING.md:217`: row label for the sync-pr-audit composite summary updated from `H8 stub-debt + fork-boundary-mock baselines` to `H5 stub-debt (strict) + H8 fork-boundary-mock` — also corrects pre-existing mislabel of H5 as H8. Script reference unchanged. - `.github/workflows/sync-pr-audit.yml:116`: same row-label update; script invocation and exit-code variable `H8` intentionally unchanged to minimize churn. Verification: - `node scripts/check-stub-debt.mjs` → `stub-debt check passed: 0 @ts-expect-error suppressions.` + `fork-boundary-mock check passed: 132 == baseline 132.` (exit 0). - Failure-path probe (temp `@ts-expect-error` under `src/`) → script prints inventory, remediation guide, and exits 1. Confirms the zero-tolerance branch. - `pnpm check` (format + tsgo + lint + project-specific lints) → exit 0. - `pnpm test` (full unit+extensions+gateway suite) → 7010 passed / 3 skipped / 7013 total. - Rescan: `git ls-files | xargs grep -l "\.stub-debt-baseline"` → zero hits. No stale references remain. - Adversarial validation (fresh-context subclaude): 5 AC PASS + 13 adversarial checks PASS; 1 MINOR cross-repo finding (HQ ADR 0005 H5 staleness) tracked as post-merge HQ follow-up, does NOT block this PR. Closes #2354 Refs: #2457, #2458, ADR 0005 H5 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
6 tasks
alexey-pelykh
added a commit
that referenced
this pull request
Apr 22, 2026
… — Bite C (#2354) (#2459) **Bite C** of the #2354 umbrella (drive stub-debt baseline to zero and remove it). Bites A (#2457, baseline 12 → 6) and B (#2458, baseline 6 → 0) drove the H5 `@ts-expect-error` count to zero across `src/`, `extensions/`, and `ui/`. This PR retires the H5 baseline entirely and flips the gate to zero-tolerance. The H8 fork-boundary-mock counter (`.fork-boundary-mock-baseline = 132`) is untouched — still baselined, still ratchetable. Changes: - `scripts/check-stub-debt.mjs`: inline the H5 counter as a zero-tolerance check (was baseline-gated via `readBaseline`+`reportCounter`). Any `@ts-expect-error` in a gated file fails the script with an inventory and a remediation pointer to Bite A (`as unknown as T` cast pattern, PR #2457) and Bite B (`vi.fn<Fn>()` typed-mock pattern, PR #2458). The H8 branch — `readBaseline` + `reportCounter` for `.fork-boundary-mock-baseline` — is byte-identical to pre-change; inline-for-H5 / helper-for-H8 asymmetry is intentional since the two counters are now fundamentally different patterns. - `.stub-debt-baseline`: DELETED (last value was `0`). - `CLAUDE.md:121`: rewrote the `stub-debt-gate` bullet to reflect zero-tolerance H5 + link to `CONTRIBUTING.md § Fork-boundary mocks` for H8 detail. - `CONTRIBUTING.md:217`: row label for the sync-pr-audit composite summary updated from `H8 stub-debt + fork-boundary-mock baselines` to `H5 stub-debt (strict) + H8 fork-boundary-mock` — also corrects pre-existing mislabel of H5 as H8. Script reference unchanged. - `.github/workflows/sync-pr-audit.yml:116`: same row-label update; script invocation and exit-code variable `H8` intentionally unchanged to minimize churn. Verification: - `node scripts/check-stub-debt.mjs` → `stub-debt check passed: 0 @ts-expect-error suppressions.` + `fork-boundary-mock check passed: 132 == baseline 132.` (exit 0). - Failure-path probe (temp `@ts-expect-error` under `src/`) → script prints inventory, remediation guide, and exits 1. Confirms the zero-tolerance branch. - `pnpm check` (format + tsgo + lint + project-specific lints) → exit 0. - `pnpm test` (full unit+extensions+gateway suite) → 7010 passed / 3 skipped / 7013 total. - Rescan: `git ls-files | xargs grep -l "\.stub-debt-baseline"` → zero hits. No stale references remain. - Adversarial validation (fresh-context subclaude): 5 AC PASS + 13 adversarial checks PASS; 1 MINOR cross-repo finding (HQ ADR 0005 H5 staleness) tracked as post-merge HQ follow-up, does NOT block this PR. Closes #2354 Refs: #2457, #2458, ADR 0005 H5 Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Bite B of the #2354 umbrella (drive stub-debt baseline to zero and remove it). Resolves the 6 remaining
@ts-expect-error -- fork stub typing mismatchsuppressions insrc/auto-reply/reply/agent-runner.runreplyagent.e2e.test.ts— the gate inventory drops from 6 to 0.Sibling PR #2457 (Bite A, merged
d75ea3da45) took the baseline from 12 to 6. This PR closes the remaining gap. A future follow-up (Bite C) will delete.stub-debt-baselineand simplifyscripts/check-stub-debt.mjsto fail on any@ts-expect-error— that's what closes #2354.Root cause
All 6 suppressions guard
vi.spyOn(modelFallbackModule, "runWithModelFallback").mockImplementation(...)callbacks. The host object was declared as:When the host is
any,vi.spyOn(obj, key)resolves to the untyped overload(...args: unknown[]) => any. Each callback's strictly-typed{ run }/{ provider, model, run }parameter is contravariantly incompatible withunknown[]— TS errors, hence the per-callback@ts-expect-error. Empirically verified: removing one suppression producedTS2345: ... Type 'unknown' is not assignable to type '{ run: ... }'.Fix
Bind the mock's function signature with a local
ModelFallbackFntype sovi.spyOnpicks the typed overload. Theas any+eslint-disable-next-line @typescript-eslint/no-explicit-anygo away, and the 6 callback@ts-expect-errorcomments are no longer needed.Changes
src/auto-reply/reply/agent-runner.runreplyagent.e2e.test.ts:41const modelFallbackModule = { runWithModelFallback: vi.fn() } as any;(+ itseslint-disable) with a localModelFallbackFnfunction type andvi.fn<ModelFallbackFn>()— matches the 5+ existingvi.fn<T>()usages elsewhere in the repo.src/auto-reply/reply/agent-runner.runreplyagent.e2e.test.ts× 6// @ts-expect-error -- fork stub typing mismatchat the 6 previous callsites. Callback bodies unchanged. oxfmt reflowed 5 of 6vi.spyOn(...).mockImplementation(...)chains into multi-line builder-chain style — cosmetic only, no behavior change..stub-debt-baseline6→0.The fork-boundary-mock counter (H8) is unaffected (still
132 == baseline 132).Verification
node scripts/check-stub-debt.mjs→stub-debt check passed: 0 == baseline 0.pnpm tsgo→ exit 0pnpm lint→Found 0 warnings and 0 errors.(3932 files)pnpm format:check→All matched files use the correct format.(5115 files)pnpm check(full: format + tsgo + lint + lint:tmp + lint:no-remoteclaw-ai) → exit 0pnpm vitest run --config vitest.e2e.config.ts src/auto-reply/reply/agent-runner.runreplyagent.e2e.test.ts→ 37 failed / 5 passed / 42 total — IDENTICAL to pre-change. The 37 failures are pre-existing (resolveFallbackTransitiongutted per MBP,agent-runner-execution.ts:225-226); orthogonal to fix(test): resolve 6 fork-stub typing mismatches in agent-runner e2e test #2352 and not run by CI'spnpm test(usesscripts/test-parallel.mjs— unit/extensions/gateway only).@ts-expect-errorremain insrc/,extensions/,ui/).Test plan
node scripts/check-stub-debt.mjspasses at baseline 0pnpm check(format + tsgo + lint + project-specific lints) passes@ts-ignore,@ts-nocheck, oras anyintroduced (grep-verified)build,test,lint,docs,rebrand-gate,zombie-import-gate,stub-debt-gate,throwing-stub-callers-gate,obsolescence-audit-gateContext
d75ea3da45).stub-debt-baseline, simplifyscripts/check-stub-debt.mjs) — separate PR on chore(ci): drive stub debt baseline to zero and remove it #2354Refs: #2354, #2457, ADR 0005 H5
🤖 Generated with Claude Code