Skip to content

refactor(sse): extract combo target resolution into combo/targetResolution.ts - #8592

Merged
diegosouzapw merged 11 commits into
diegosouzapw:release/v3.8.49from
MumuTW:refactor/combo-target-resolution
Jul 27, 2026
Merged

diegosouzapw merged 11 commits into
diegosouzapw:release/v3.8.49from
MumuTW:refactor/combo-target-resolution

Conversation

@MumuTW

@MumuTW MumuTW commented Jul 25, 2026 •

Copy link
Copy Markdown
Contributor

PR 2 of ~7 in the #3501 god-file decomposition campaign, shrinking open-sse/services/combo.ts toward the 800-line file-size cap.

What this is

A pure move. No behaviour change. The target-resolution stage of handleComboChat — everything between the dispatch prelude and the attempt loop — moves verbatim into a new leaf, open-sse/services/combo/targetResolution.ts, entry point resolveComboTargetPipeline().

Log message wording, log levels, and the order of side effects and awaits are preserved exactly, quirks included. Nothing was "improved" on the way out.

Line counts

File Before After
open-sse/services/combo.ts 3642 3322 (−320, gate units)
open-sse/services/combo/targetResolution.ts — 669 (new, under the 800 cap)
tests/unit/combo-target-resolution-split.test.ts — 148 (new)

Complexity — the leaf contributes ZERO violations

A pure move must be complexity-neutral. The first pass was not: it landed the region as one 311-line function, which turned inline code inside the (already-violating) handleComboChat into a new separately-counted violating function.

Gate base 4053e2314 first pass this PR
check:complexity 2169 2171 (+2) 2169
check:cognitive-complexity 956 957 (+1) 956

Fixed by splitting resolveComboTargetPipeline along its natural stage boundaries into 14 helpers — wildcard expansion; weighted sticky eviction / eligibility / sticky-key / selection; step-key mapper; context-overflow response; pool-size log; smart-pipeline dispatch and its fall-through logger; strategy ordering; continuity filters; task-aware ordering; prompt-cache enablement, first-target protection and affinity stage. Each stage takes the previous stage's output and returns the next.

Per-file check on the new leaf reports 0 violations across all three rules:

npx eslint --no-config-lookup --config eslint.complexity-ratchets.config.mjs \
  --format json open-sse/services/combo/targetResolution.ts
→ 0 violations   (complexity, max-lines-per-function, sonarjs/cognitive-complexity)

Both gates still print RED against their frozen ceilings (2130 / 951). That is pre-existing base-red owned by #8580, not introduced here — the numbers above are identical to base 4053e2314. Neither complexity baseline was rebaselined.

Sub-blocks extracted

In original order, all verbatim:

  1. Provider-wildcard expansion of the combo and the combos collection (feat: Provider-level Wildcard Support in Combos (Provider-based Combos) #2562)
  2. Sticky-weighted LRU eviction, weighted step-group resolution and eligibility, sticky-pin validation, resolveWeightedTargets — including the isTargetSelectableForWeighted predicate
  3. applyRequestTagRouting
  4. The getKnownContextOverflow 400 early return
  5. The weighted / nested-resolution log.info lines
  6. The smart/pipeline-enabled dispatch through handlePipelineCombo / buildPipelineResponse, with all three fall-through branches
  7. Auto-strategy ordering (resolveAutoStrategyOrder) and, for every other strategy, applyStrategyOrdering
  8. Cache-optimized strategy affinity, session stickiness, eval-score ordering, request-compatibility and context-requirement filters
  9. Task-aware reordering with the feat(combo): task-aware routing strategy #4945 explicit-router pin guard
  10. Prompt-cache affinity with the shouldProtectOriginalFirst protection
  11. The parallel pre-screen (preScreenTargets, priority strategy only)

Sub-blocks deliberately SKIPPED

  • Attempt-loop config — maxRetries, retryDelayMs, fallbackDelayMs, maxSetRetries, setRetryDelayMs (base lines 1096–1100). These are loop configuration, not target resolution, and every one is read downstream by the attempt loop. Left in combo.ts.
  • quotaCutoffResetWindowConfig and comboAttemptOrder, immediately past the region ceiling — same reason: attempt-loop state.

Nothing else in the region was skipped; no sub-block turned out to be un-extractable.

Values that escape the region

Every identifier the region declares was grepped forward from the attempt loop. Five are still read downstream, so they are returned rather than recomputed:

  • orderedTargets — the stage's net product
  • stickyWeightedLimit and getWeightedStepKeyForTarget — the sticky-weighted success write-back
  • the session-stickiness result — .messageHash is read on both the success and failure paths
  • preScreenMap — read per attempt

The three early exits (known-context overflow, pipeline dispatch, auto-strategy unavailableResponse) become an { earlyResponse } result the host returns, following the existing resolveAutoStrategyOrder precedent in the same directory. buildAutoCandidates lives in combo.ts, so it is dependency-injected — the combo/ directory keeps zero back-edges and stays acyclic.

Also removed from combo.ts: 16 imports that went dead with the move (verified per-symbol).

Verification

Command Result
npm run typecheck:core clean
npm run lint clean
npm run check:cycles OK — but its default roots do NOT include open-sse/services, so this proves nothing here; see the cycles note below
node scripts/check/check-file-size.mjs OK — 183 arquivos congelados
npm run check:complexity 2169 (= base; RED vs frozen 2130 is pre-existing per #8580)
npm run check:cognitive-complexity 956 (= base; RED vs frozen 951 is pre-existing per #8580)
node --import tsx/esm --test tests/unit/combo-target-resolution-split.test.ts 5/5 pass
node --import tsx/esm --test tests/unit/combo-routing-engine.test.ts 85/85 pass
node --import tsx/esm --test tests/unit/*combo*.test.ts tests/unit/combo/*.test.ts (157 files) 1157/1157 pass
npm run test:vitest 31 files, 274/274 pass
npm run test:unit (full) 26082 pass / 5 fail

The 5 full-suite failures are pre-existing on base and unrelated to this change. Four are in tests/unit/antigravity-oauth-postexchange-nonblocking.test.ts (OAuth postExchange timeout tests) — verified by running that file on a detached checkout of base 4053e2314, where the same four fail identically. The fifth (db-usageanalytics-split.test.ts) passes in isolation; parallel-run flake.

CI gate fix (check:known-symbols)

First CI run failed Fast Quality Gates:

[combo] 1 estratégia(s) canônica(s) sem branch de despacho em combo.ts:
    ✗ priority

Real, and caused by this PR — though no dispatch was lost. The gate's combo sub-check
scans a hardcoded file list, and the strategy === "priority" latency pre-screen moved
into combo/targetResolution.ts with the rest of the region.

Fix is one entry: register combo/targetResolution.ts in comboDispatchFiles, following
the precedent already in that list (the Block J decomposition added its leaves for exactly
this reason). Gate now reports 20 canonical strategies, all 20 via despacho;
tests/unit/check-known-symbols.test.ts stays green at 35/35.

Base-red: the Unit Tests fast-path (2/4) job

Also red, and not this PR. Two tests in
tests/unit/serial/combo-quota-share-cooldown-wait-timing.test.ts (expected 200 → got 429;
expected 429 → got 403). Reproduced byte-identical on a pristine detached worktree at the
base 4053e2314. Pre-existing.

Baseline changes — read this, it was not forgotten

Exactly one entry was ratcheted: open-sse/services/combo.ts in config/quality/file-size-baseline.json, 3642 → 3322, with a justification note in the file's existing note style. check-file-size.mjs --update was deliberately not used — it sweeps ~74 unrelated files. The diff on that file is 2 insertions, 1 deletion.

No complexity or cognitive-complexity baseline was touched.

⚠️ #8582 ratchets the same combo.ts key to 3341. That is the one and only merge conflict between the two PRs. Whoever rebases second must set it to the combined figure, not simply take the lower of the two. Measured on the actual merged tree: combo.ts merges to 3017 lines by wc -l, which is 3018 gate units — check-file-size counts split("\n").length, one higher than wc -l. 3018 is the number that belongs in the baseline entry.

Incidental formatting

prettier --write on combo.ts also reformatted one pre-existing 103-char line at base line 2927 (computeCompatRejectedTargets(...), inside handleRoundRobinCombo) into 5 lines. It is the only non-move hunk in the diff. That line already failed prettier --check on base, so reverting it would leave the file rejecting the formatter — it is kept deliberately.

Tests

Repo rule #8 — production code changed, so tests ship in the same PR. As a pure move, the existing 157-file tests/unit/*combo* suite is the real regression guard (all green above). tests/unit/combo-target-resolution-split.test.ts adds the new leaf's own direct coverage: the exported entry point, priority-path target ordering, the shape handed back to the attempt loop, the empty-pool case, and the known-context-overflow earlyResponse (400 + context_length_exceeded + zero attempts).

Stacking

Stacked alongside #8582 (refactor/combo-dispatch-prelude), which touches a disjoint region of the same file (pinned-model routing, fusion, pipeline, nested combo-ref execute mode, round-robin delegation; base lines 283–286, 603–667, 727–1094). This PR's first body hunk starts at base line 1102.

git merge-tree --write-tree of the two branches auto-merges open-sse/services/combo.ts cleanly — including the import block, where both PRs delete imports their own region no longer needs. The sole conflict is the file-size-baseline.json key noted above.

On cycles

check:cycles is cited green above, but its default roots are src/shared/components, src/lib/db, src/lib/compliance, open-sse/translator, open-sse/mcp-server — open-sse/services is not among them, so a green run says nothing about this directory. (Caught by an adversarial review of #8582; the same correction applies here.)

Scoped explicitly and compared against a pristine detached worktree at the base commit, open-sse/services carries a large pre-existing cyclic cluster that already contains combo.ts. This PR's leaf imports members of that cluster, so it joins it. That is not a new back-edge: no file under combo/ imports combo.ts — the leaf takes buildAutoCandidates by dependency injection — and no previously-acyclic pair became cyclic. Untangling the cluster belongs with the later phases of #3501.

@diegosouzapw

Copy link
Copy Markdown
Owner

Hi @MumuTW — thanks for this Block K decomposition of combo.ts. The shape is clean: 11 sub-blocks extracted, values that escape the region (orderedTargets, preScreenMap, stickyWeightedLimit, etc.) are returned rather than recomputed, and buildAutoCandidates is dependency-injected so combo/ stays acyclic against combo.ts. Verified body: 1157/1157 combo tests + 274/274 vitest, the 5 full-suite failures reproduce byte-identical on base 4053e2314.

One mandatory pre-merge item: the file-size-baseline.json key for open-sse/services/combo.ts is set to 3322 here, but PR #8582 sets it to 3341. The combined merged tree measures 3018 (wc -l = 3017, gate units = split("\n").length + 1). Whoever rebases second must use 3018, not the lower of the two. The git merge-tree --write-tree of the two branches is otherwise clean.

check:cycles default roots do not include open-sse/services, so the green run cited in the PR body says nothing about this directory — but the body already acknowledges that, and the new leaf takes buildAutoCandidates by dep injection, so no new back-edge is introduced.

Approving as merge-ready (★4). Will hand off to /merge-prs for the rebase dance.

@diegosouzapw
diegosouzapw force-pushed the refactor/combo-target-resolution branch from 789c07c to b41e3ae Compare July 27, 2026 03:02
@MumuTW

MumuTW commented Jul 27, 2026

Copy link
Copy Markdown
Contributor Author

CI fix pushed (c127e3d03)

Root-caused the two reds on the stacked tip:

Unit Tests 2/4 — real regression from the extract (not base-red)

Stacking targetResolution onto the dispatchPrelude tip dropped the #8488 / #8494 capability fail-closed wiring:

  • hard filters emptied the pool → generic 404 no_executable_targets instead of 400 capability_mismatch
  • compatFilterFailOpen was never passed into filterTargetsByRequestCompatibility, so fail-open never re-admitted the pool

Restored:

  • main path: applyContinuityFilters in combo/targetResolution.ts (failOpen + describeCapabilityFilterExhaustion → earlyResponse)
  • round-robin path: matching block in handleRoundRobinCombo

Local: combo-routing-engine 86/86 + combo-target-resolution-split 5/5 green (including the two #8488 cases).

Fast Quality Gates — incomplete stack rebank

check:file-size was red on tip growth the prior rebank missed (plus freezing comboStructure.ts / RequestTimeline.tsx). Rebanked measured tip LOC with a justification note.

Waiting on CI for confirmation.

MumuTW added 9 commits July 27, 2026 12:39
…ude.ts

Pure move, no behaviour change. First of ~7 PRs decomposing the combo.ts
god-file (diegosouzapw#3501).

handleComboChat evaluates a series of dispatch branches before it ever
reaches target resolution or the sequential attempt loop. None of them
iterate targets in priority order or need the failover/retry/credential
gate machinery that follows, so they move to a leaf:

  - context-cache pin routing (Fix diegosouzapw#679), including the
    pinIsDurablyUnhealthy / isPinnedModelDurablyUnhealthy health gate
  - fusion panel dispatch + the diegosouzapw#6455 misconfiguration warn
  - pipeline chaining
  - nested combo-ref execute-mode runtime-unit dispatch

Only the chaos and round-robin hand-offs stay inline (11 and 13 lines);
extracting those would be pure indirection.

open-sse/services/combo.ts 3642 -> 3341 (-301)
open-sse/services/combo/dispatchPrelude.ts: 619 (under the 800 cap)

Each helper keeps the fall-through protocol the inline blocks had: return
a Response to OWN the request, return null to fall through. A flipped
null/Response would silently bypass the whole combo strategy, so the new
tests pin both directions for every branch.

combo.ts re-exports pinIsDurablyUnhealthy so combo-pin-health-gate.test.ts
keeps resolving. The leaf takes handleComboChat as a `runCombo` parameter
instead of importing it, so combo/ keeps zero back-edges into combo.ts.

Complexity-neutral: the first cut added +3 violations (two
max-lines-per-function, one complexity) inside the new leaf, so
evaluatePinnedResponse, orderRuntimeUnits, recordRuntimeUnitStickySuccess
and buildBaseOptions were split out. check:complexity now measures 2169
and check:cognitive-complexity 956 — identical to the pristine base.
…n testing

An adversarial mutation audit of the suite added in the previous commit
found it guarded the fall-through protocol well but asserted almost
nothing about what the helpers do once they OWN the request. 5 of 12
seeded mutations survived. Worst case: deleting the pinned-model
dispatch call outright left all 12 tests green.

Three holes, now closed (8 tests -> 20):

Hole A — the honored-pin path had zero coverage. Both existing pin tests
DROP the pin, so the dispatch, the 200-but-empty quality gate, the
[408, 429, 500, 502, 503, 504] failover list and the catch(pinErr)
branch were unguarded — exactly the logic the 2026-06-21 / 2026-06-22
incident comments call load-bearing. Adds five tests over a seeded
healthy provider connection so the pin is actually honored.

Hole B — orderRuntimeUnits was only ever driven with `priority`, which
is a no-op through it. Four of five strategy branches could be deleted
with nothing failing. Adds round-robin rotation and weighted sticky
ordering tests.

Hole C — recordRuntimeUnitStickySuccess never did anything under test:
both its guards need weighted/round-robin, so an early return changed
nothing. Covered by the new sticky-batch test.

Verified by re-running the mutations rather than assuming: all 7 that
previously survived (delete-pin-dispatch, serve-despite-failed-quality,
never-fail-over-on-transient, rr-counter-not-advanced, rotation-removed,
weighted-sticky-skipped, sticky-recording-no-op) are now killed.

The first sticky-batch test I wrote was itself vacuous — asserting "same
unit twice" holds equally when the recording helper is stubbed out, since
nothing advances the counter either. It now asserts the batch runs out
and rotation resumes on the third dispatch, which is what actually
distinguishes the two.

Also restores API_KEY_SECRET in test.after; it was set at module load and
never put back, inconsistent with the DATA_DIR handling beside it.
The combo sub-check of check:known-symbols asserts every canonical routing
strategy has a real dispatch branch. It scanned a hardcoded file list and
matched only `strategy === "..."`, so the prelude extraction tripped it twice:

  [combo] 2 estratégia(s) canônica(s) sem branch de despacho em combo.ts:
      ✗ fusion
      ✗ pipeline

Both branches are still wired — they just moved to combo/dispatchPrelude.ts and
took the early-return guard form `if (strategy !== "fusion") return null;` that
extracting a branch into a `tryXDispatch()` leaf naturally produces.

Two changes, both extending existing precedent (the list already carries the
Block J leaves for the same reason):

- register combo/dispatchPrelude.ts in comboDispatchFiles
- widen the extractor to `strategy [!=]== "..."` so the inverted guard counts

Loose `==`/`!=` stay rejected, and no `handledNotCanonical` fallout: the gate
now reports 20 canonical strategies, all 20 via despacho.
check:mutation-test-coverage --strict failed once the known-symbols fix let
Fast Quality Gates advance to it:

  ✗ 2 covering unit test(s) across 2 module(s) are missing from
    stryker.conf.json tap.testFiles
      open-sse/services/combo/comboStructure.ts
      open-sse/services/combo/rrState.ts

The new tests/unit/combo-dispatch-prelude.test.ts exercises both modules, and
both are already in stryker's mutate list, so without the registration its
mutant kills would not have counted toward the nightly mutation gate.

Note (unchanged, still out of scope): combo/dispatchPrelude.ts itself is not in
stryker's `mutate` list. Adding it would widen the nightly mutation surface,
which is a separate call from fixing this drift.
…ution.ts

Pure move, no behaviour change. Lifts the target-resolution stage of
handleComboChat — everything between the dispatch prelude and the attempt
loop — into a new leaf, open-sse/services/combo/targetResolution.ts.

Moved verbatim: provider-wildcard expansion, weighted step-group resolution
+ sticky-weighted eligibility, request-tag routing, the known-context-overflow
early return, the smart/pipeline-enabled auto dispatch, auto-strategy
ordering, per-strategy ordering, cache-strategy affinity, session stickiness,
eval scores, request-compatibility + context-requirement filters, task-aware
reordering, prompt-cache affinity, and the priority-strategy pre-screen.

The three early exits become an { earlyResponse } result so the host decides
to return them (same pattern as resolveAutoStrategyOrder). The values the
attempt loop still reads — orderedTargets, stickyWeightedLimit,
getWeightedStepKeyForTarget, the session-stickiness result and preScreenMap —
are returned instead of closed over. Loop config (maxRetries, retryDelayMs,
fallbackDelayMs, maxSetRetries, setRetryDelayMs) stays in combo.ts.

buildAutoCandidates is dependency-injected because it lives in combo.ts, so
the leaf keeps zero back-edges into its host.

combo.ts 3640 -> 3321 lines; new leaf 484 lines (under the 800 cap).
Part of the diegosouzapw#3501 god-file decomposition campaign.
…bo.ts file-size baseline

Follow-up to the target-resolution extraction: the moved region landed as one
311-line function, which converted inline code inside the (already-violating)
handleComboChat into a NEW separately-counted violating function — check:complexity
2169 -> 2171 and check:cognitive-complexity 956 -> 957.

Split resolveComboTargetPipeline along its natural stage boundaries into 14
helpers (wildcard expansion, weighted eviction/eligibility/sticky-key/selection,
step-key mapper, context-overflow response, pool-size log, smart-pipeline dispatch
and its fall-through logger, strategy ordering, continuity filters, task-aware
ordering, prompt-cache enablement/first-target protection/affinity stage). Each
stage takes the previous stage's output and returns the next; still a pure move.

The leaf now contributes ZERO complexity, max-lines-per-function and
cognitive-complexity violations. Both ratchets are back at base 4053e23 values:
check:complexity 2169, check:cognitive-complexity 956. (Both still print RED
against their frozen ceilings 2130/951 — pre-existing base-red per diegosouzapw#8580.)

Also ratchets ONLY the open-sse/services/combo.ts entry in
config/quality/file-size-baseline.json from 3642 to 3322, with a justification
note in the file's existing style. No sweep of unrelated entries.
Rebased onto refactor/combo-dispatch-prelude. Keep both leaves in
check-known-symbols. Regenerate file-size baseline; sync agent skills.
…etResolution extract

Stacking targetResolution onto the dispatchPrelude tip dropped the diegosouzapw#8488/diegosouzapw#8494
compatFilterFailOpen wiring: hard capability filters emptied the pool into a
generic 404 no_executable_targets, and fail-open never re-admitted the pool.

Restore describeCapabilityFilterExhaustion earlyResponse in
applyContinuityFilters and the matching round-robin path, then rebank the
file-size baseline for tip growth the incomplete prior rebank missed.
@MumuTW
MumuTW force-pushed the refactor/combo-target-resolution branch from c127e3d to 4780d8e Compare July 27, 2026 05:23
…ouzapw#8254 type

This branch predates diegosouzapw#8254, which renamed the recordModelLockoutFailure option
`exactCooldownVerified` -> `exactCooldownIsUpstreamReset` and changed combo.ts's
predicate from `lockoutHintVerified` (diegosouzapw#8393's `lockoutHintMs > 0`) to
`lockoutHintMs > mlSettings.baseCooldownMs`. Rebasing onto the current tip brought
the renamed type without updating these two call sites, so typecheck:core failed
with TS2353 at both.

Restores the base expression verbatim rather than re-wiring `lockoutHintVerified`
under the new name. The base predicate is the correct one: selectLockoutCooldownMs
returns the parsed hint ONLY when `lockoutHintMs > baseCooldownMs`, and otherwise
returns 0 or a synthetic baseCooldownMs — so `lockoutHintMs > 0` would mark a
synthetic cooldown as an upstream reset and let it bypass the diegosouzapw#7940 maxCooldownMs
cap, which is the bug diegosouzapw#8254 fixed.
@MumuTW
MumuTW force-pushed the refactor/combo-target-resolution branch from 4780d8e to d7c1e3f Compare July 27, 2026 06:23
check-known-symbols.ts: the combo dispatch file list gained
combo/dispatchPrelude.ts on the release side (diegosouzapw#8582, same extraction series)
while this branch adds combo/targetResolution.ts. Both entries are needed —
each extraction moved a set of `strategy === "..."` dispatch checks out of
combo.ts, and the gate reads all of them to derive the handled-strategy set.

Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com>
@diegosouzapw
diegosouzapw merged commit 0eeb8f4 into diegosouzapw:release/v3.8.49 Jul 27, 2026
5 checks passed
DinonowDev added a commit to DinonowDev/OmniRoute that referenced this pull request Jul 27, 2026
… pools (diegosouzapw#8786)

Strict contextFilterMode excluded every target whose context limit was missing
from the capability catalog, so otherwise-executable combos returned 404
no_executable_targets. Restore unknown-context targets when no known-good
survivor remains, surface context_requirements_exhausted from targetResolution,
and keep the empty-pool payload in pinRecovery after the diegosouzapw#8592 split.
diegosouzapw pushed a commit that referenced this pull request Jul 28, 2026
… pools (#8786) (#8798)

Strict contextFilterMode excluded every target whose context limit was missing
from the capability catalog, so otherwise-executable combos returned 404
no_executable_targets. Restore unknown-context targets when no known-good
survivor remains, surface context_requirements_exhausted from targetResolution,
and keep the empty-pool payload in pinRecovery after the #8592 split.
@diegosouzapw diegosouzapw mentioned this pull request Jul 28, 2026
HouMinXi pushed a commit to HouMinXi/OmniRoute that referenced this pull request Aug 2, 2026
…ution.ts (diegosouzapw#8592)

* refactor(sse): extract combo dispatch prelude into combo/dispatchPrelude.ts

Pure move, no behaviour change. First of ~7 PRs decomposing the combo.ts
god-file (diegosouzapw#3501).

handleComboChat evaluates a series of dispatch branches before it ever
reaches target resolution or the sequential attempt loop. None of them
iterate targets in priority order or need the failover/retry/credential
gate machinery that follows, so they move to a leaf:

  - context-cache pin routing (Fix diegosouzapw#679), including the
    pinIsDurablyUnhealthy / isPinnedModelDurablyUnhealthy health gate
  - fusion panel dispatch + the diegosouzapw#6455 misconfiguration warn
  - pipeline chaining
  - nested combo-ref execute-mode runtime-unit dispatch

Only the chaos and round-robin hand-offs stay inline (11 and 13 lines);
extracting those would be pure indirection.

open-sse/services/combo.ts 3642 -> 3341 (-301)
open-sse/services/combo/dispatchPrelude.ts: 619 (under the 800 cap)

Each helper keeps the fall-through protocol the inline blocks had: return
a Response to OWN the request, return null to fall through. A flipped
null/Response would silently bypass the whole combo strategy, so the new
tests pin both directions for every branch.

combo.ts re-exports pinIsDurablyUnhealthy so combo-pin-health-gate.test.ts
keeps resolving. The leaf takes handleComboChat as a `runCombo` parameter
instead of importing it, so combo/ keeps zero back-edges into combo.ts.

Complexity-neutral: the first cut added +3 violations (two
max-lines-per-function, one complexity) inside the new leaf, so
evaluatePinnedResponse, orderRuntimeUnits, recordRuntimeUnitStickySuccess
and buildBaseOptions were split out. check:complexity now measures 2169
and check:cognitive-complexity 956 — identical to the pristine base.

* test(sse): close the dispatch-prelude coverage holes found by mutation testing

An adversarial mutation audit of the suite added in the previous commit
found it guarded the fall-through protocol well but asserted almost
nothing about what the helpers do once they OWN the request. 5 of 12
seeded mutations survived. Worst case: deleting the pinned-model
dispatch call outright left all 12 tests green.

Three holes, now closed (8 tests -> 20):

Hole A — the honored-pin path had zero coverage. Both existing pin tests
DROP the pin, so the dispatch, the 200-but-empty quality gate, the
[408, 429, 500, 502, 503, 504] failover list and the catch(pinErr)
branch were unguarded — exactly the logic the 2026-06-21 / 2026-06-22
incident comments call load-bearing. Adds five tests over a seeded
healthy provider connection so the pin is actually honored.

Hole B — orderRuntimeUnits was only ever driven with `priority`, which
is a no-op through it. Four of five strategy branches could be deleted
with nothing failing. Adds round-robin rotation and weighted sticky
ordering tests.

Hole C — recordRuntimeUnitStickySuccess never did anything under test:
both its guards need weighted/round-robin, so an early return changed
nothing. Covered by the new sticky-batch test.

Verified by re-running the mutations rather than assuming: all 7 that
previously survived (delete-pin-dispatch, serve-despite-failed-quality,
never-fail-over-on-transient, rr-counter-not-advanced, rotation-removed,
weighted-sticky-skipped, sticky-recording-no-op) are now killed.

The first sticky-batch test I wrote was itself vacuous — asserting "same
unit twice" holds equally when the recording helper is stubbed out, since
nothing advances the counter either. It now asserts the batch runs out
and rotation resumes on the third dispatch, which is what actually
distinguishes the two.

Also restores API_KEY_SECRET in test.after; it was set at module load and
never put back, inconsistent with the DATA_DIR handling beside it.

* fix(ci): teach known-symbols gate the relocated fusion/pipeline dispatch

The combo sub-check of check:known-symbols asserts every canonical routing
strategy has a real dispatch branch. It scanned a hardcoded file list and
matched only `strategy === "..."`, so the prelude extraction tripped it twice:

  [combo] 2 estratégia(s) canônica(s) sem branch de despacho em combo.ts:
      ✗ fusion
      ✗ pipeline

Both branches are still wired — they just moved to combo/dispatchPrelude.ts and
took the early-return guard form `if (strategy !== "fusion") return null;` that
extracting a branch into a `tryXDispatch()` leaf naturally produces.

Two changes, both extending existing precedent (the list already carries the
Block J leaves for the same reason):

- register combo/dispatchPrelude.ts in comboDispatchFiles
- widen the extractor to `strategy [!=]== "..."` so the inverted guard counts

Loose `==`/`!=` stay rejected, and no `handledNotCanonical` fallout: the gate
now reports 20 canonical strategies, all 20 via despacho.

* chore(ci): register combo-dispatch-prelude test in stryker tap.testFiles

check:mutation-test-coverage --strict failed once the known-symbols fix let
Fast Quality Gates advance to it:

  ✗ 2 covering unit test(s) across 2 module(s) are missing from
    stryker.conf.json tap.testFiles
      open-sse/services/combo/comboStructure.ts
      open-sse/services/combo/rrState.ts

The new tests/unit/combo-dispatch-prelude.test.ts exercises both modules, and
both are already in stryker's mutate list, so without the registration its
mutant kills would not have counted toward the nightly mutation gate.

Note (unchanged, still out of scope): combo/dispatchPrelude.ts itself is not in
stryker's `mutate` list. Adding it would widen the nightly mutation surface,
which is a separate call from fixing this drift.

* docs(changelog): add fragment for diegosouzapw#8582 combo dispatch prelude

* refactor(sse): extract combo target resolution into combo/targetResolution.ts

Pure move, no behaviour change. Lifts the target-resolution stage of
handleComboChat — everything between the dispatch prelude and the attempt
loop — into a new leaf, open-sse/services/combo/targetResolution.ts.

Moved verbatim: provider-wildcard expansion, weighted step-group resolution
+ sticky-weighted eligibility, request-tag routing, the known-context-overflow
early return, the smart/pipeline-enabled auto dispatch, auto-strategy
ordering, per-strategy ordering, cache-strategy affinity, session stickiness,
eval scores, request-compatibility + context-requirement filters, task-aware
reordering, prompt-cache affinity, and the priority-strategy pre-screen.

The three early exits become an { earlyResponse } result so the host decides
to return them (same pattern as resolveAutoStrategyOrder). The values the
attempt loop still reads — orderedTargets, stickyWeightedLimit,
getWeightedStepKeyForTarget, the session-stickiness result and preScreenMap —
are returned instead of closed over. Loop config (maxRetries, retryDelayMs,
fallbackDelayMs, maxSetRetries, setRetryDelayMs) stays in combo.ts.

buildAutoCandidates is dependency-injected because it lives in combo.ts, so
the leaf keeps zero back-edges into its host.

combo.ts 3640 -> 3321 lines; new leaf 484 lines (under the 800 cap).
Part of the diegosouzapw#3501 god-file decomposition campaign.

* refactor(sse): split targetResolution into stage helpers, ratchet combo.ts file-size baseline

Follow-up to the target-resolution extraction: the moved region landed as one
311-line function, which converted inline code inside the (already-violating)
handleComboChat into a NEW separately-counted violating function — check:complexity
2169 -> 2171 and check:cognitive-complexity 956 -> 957.

Split resolveComboTargetPipeline along its natural stage boundaries into 14
helpers (wildcard expansion, weighted eviction/eligibility/sticky-key/selection,
step-key mapper, context-overflow response, pool-size log, smart-pipeline dispatch
and its fall-through logger, strategy ordering, continuity filters, task-aware
ordering, prompt-cache enablement/first-target protection/affinity stage). Each
stage takes the previous stage's output and returns the next; still a pure move.

The leaf now contributes ZERO complexity, max-lines-per-function and
cognitive-complexity violations. Both ratchets are back at base d408a20 values:
check:complexity 2169, check:cognitive-complexity 956. (Both still print RED
against their frozen ceilings 2130/951 — pre-existing base-red per diegosouzapw#8580.)

Also ratchets ONLY the open-sse/services/combo.ts entry in
config/quality/file-size-baseline.json from 3642 to 3322, with a justification
note in the file's existing style. No sweep of unrelated entries.

* chore: stack targetResolution on dispatchPrelude tip, rebank + skills

Rebased onto refactor/combo-dispatch-prelude. Keep both leaves in
check-known-symbols. Regenerate file-size baseline; sync agent skills.

* fix(sse): restore diegosouzapw#8494 capability fail-closed after targetResolution extract

Stacking targetResolution onto the dispatchPrelude tip dropped the diegosouzapw#8488/diegosouzapw#8494
compatFilterFailOpen wiring: hard capability filters emptied the pool into a
generic 404 no_executable_targets, and fail-open never re-admitted the pool.

Restore describeCapabilityFilterExhaustion earlyResponse in
applyContinuityFilters and the matching round-robin path, then rebank the
file-size baseline for tip growth the incomplete prior rebank missed.

* fix(sse): realign model-lockout cooldown options with the post-diegosouzapw#8254 type

This branch predates diegosouzapw#8254, which renamed the recordModelLockoutFailure option
`exactCooldownVerified` -> `exactCooldownIsUpstreamReset` and changed combo.ts's
predicate from `lockoutHintVerified` (diegosouzapw#8393's `lockoutHintMs > 0`) to
`lockoutHintMs > mlSettings.baseCooldownMs`. Rebasing onto the current tip brought
the renamed type without updating these two call sites, so typecheck:core failed
with TS2353 at both.

Restores the base expression verbatim rather than re-wiring `lockoutHintVerified`
under the new name. The base predicate is the correct one: selectLockoutCooldownMs
returns the parsed hint ONLY when `lockoutHintMs > baseCooldownMs`, and otherwise
returns 0 or a synthetic baseCooldownMs — so `lockoutHintMs > 0` would mark a
synthetic cooldown as an upstream reset and let it bypass the diegosouzapw#7940 maxCooldownMs
cap, which is the bug diegosouzapw#8254 fixed.

---------

Co-authored-by: MumuTW <johnsxn.us@gmail.com>
Co-authored-by: diegosouzapw <diegosouzapw@users.noreply.github.com>
Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com>
HouMinXi pushed a commit to HouMinXi/OmniRoute that referenced this pull request Aug 2, 2026
… pools (diegosouzapw#8786) (diegosouzapw#8798)

Strict contextFilterMode excluded every target whose context limit was missing
from the capability catalog, so otherwise-executable combos returned 404
no_executable_targets. Restore unknown-context targets when no known-good
survivor remains, surface context_requirements_exhausted from targetResolution,
and keep the empty-pool payload in pinRecovery after the diegosouzapw#8592 split.
@MumuTW
MumuTW deleted the refactor/combo-target-resolution branch August 27, 2026 01:47
muhamadgalihsaputra pushed a commit to niyatna/NiyatnaRoute that referenced this pull request Sep 27, 2026
…ution.ts (diegosouzapw#8592)

* refactor(sse): extract combo dispatch prelude into combo/dispatchPrelude.ts

Pure move, no behaviour change. First of ~7 PRs decomposing the combo.ts
god-file (diegosouzapw#3501).

handleComboChat evaluates a series of dispatch branches before it ever
reaches target resolution or the sequential attempt loop. None of them
iterate targets in priority order or need the failover/retry/credential
gate machinery that follows, so they move to a leaf:

  - context-cache pin routing (Fix diegosouzapw#679), including the
    pinIsDurablyUnhealthy / isPinnedModelDurablyUnhealthy health gate
  - fusion panel dispatch + the diegosouzapw#6455 misconfiguration warn
  - pipeline chaining
  - nested combo-ref execute-mode runtime-unit dispatch

Only the chaos and round-robin hand-offs stay inline (11 and 13 lines);
extracting those would be pure indirection.

open-sse/services/combo.ts 3642 -> 3341 (-301)
open-sse/services/combo/dispatchPrelude.ts: 619 (under the 800 cap)

Each helper keeps the fall-through protocol the inline blocks had: return
a Response to OWN the request, return null to fall through. A flipped
null/Response would silently bypass the whole combo strategy, so the new
tests pin both directions for every branch.

combo.ts re-exports pinIsDurablyUnhealthy so combo-pin-health-gate.test.ts
keeps resolving. The leaf takes handleComboChat as a `runCombo` parameter
instead of importing it, so combo/ keeps zero back-edges into combo.ts.

Complexity-neutral: the first cut added +3 violations (two
max-lines-per-function, one complexity) inside the new leaf, so
evaluatePinnedResponse, orderRuntimeUnits, recordRuntimeUnitStickySuccess
and buildBaseOptions were split out. check:complexity now measures 2169
and check:cognitive-complexity 956 — identical to the pristine base.

* test(sse): close the dispatch-prelude coverage holes found by mutation testing

An adversarial mutation audit of the suite added in the previous commit
found it guarded the fall-through protocol well but asserted almost
nothing about what the helpers do once they OWN the request. 5 of 12
seeded mutations survived. Worst case: deleting the pinned-model
dispatch call outright left all 12 tests green.

Three holes, now closed (8 tests -> 20):

Hole A — the honored-pin path had zero coverage. Both existing pin tests
DROP the pin, so the dispatch, the 200-but-empty quality gate, the
[408, 429, 500, 502, 503, 504] failover list and the catch(pinErr)
branch were unguarded — exactly the logic the 2026-06-21 / 2026-06-22
incident comments call load-bearing. Adds five tests over a seeded
healthy provider connection so the pin is actually honored.

Hole B — orderRuntimeUnits was only ever driven with `priority`, which
is a no-op through it. Four of five strategy branches could be deleted
with nothing failing. Adds round-robin rotation and weighted sticky
ordering tests.

Hole C — recordRuntimeUnitStickySuccess never did anything under test:
both its guards need weighted/round-robin, so an early return changed
nothing. Covered by the new sticky-batch test.

Verified by re-running the mutations rather than assuming: all 7 that
previously survived (delete-pin-dispatch, serve-despite-failed-quality,
never-fail-over-on-transient, rr-counter-not-advanced, rotation-removed,
weighted-sticky-skipped, sticky-recording-no-op) are now killed.

The first sticky-batch test I wrote was itself vacuous — asserting "same
unit twice" holds equally when the recording helper is stubbed out, since
nothing advances the counter either. It now asserts the batch runs out
and rotation resumes on the third dispatch, which is what actually
distinguishes the two.

Also restores API_KEY_SECRET in test.after; it was set at module load and
never put back, inconsistent with the DATA_DIR handling beside it.

* fix(ci): teach known-symbols gate the relocated fusion/pipeline dispatch

The combo sub-check of check:known-symbols asserts every canonical routing
strategy has a real dispatch branch. It scanned a hardcoded file list and
matched only `strategy === "..."`, so the prelude extraction tripped it twice:

  [combo] 2 estratégia(s) canônica(s) sem branch de despacho em combo.ts:
      ✗ fusion
      ✗ pipeline

Both branches are still wired — they just moved to combo/dispatchPrelude.ts and
took the early-return guard form `if (strategy !== "fusion") return null;` that
extracting a branch into a `tryXDispatch()` leaf naturally produces.

Two changes, both extending existing precedent (the list already carries the
Block J leaves for the same reason):

- register combo/dispatchPrelude.ts in comboDispatchFiles
- widen the extractor to `strategy [!=]== "..."` so the inverted guard counts

Loose `==`/`!=` stay rejected, and no `handledNotCanonical` fallout: the gate
now reports 20 canonical strategies, all 20 via despacho.

* chore(ci): register combo-dispatch-prelude test in stryker tap.testFiles

check:mutation-test-coverage --strict failed once the known-symbols fix let
Fast Quality Gates advance to it:

  ✗ 2 covering unit test(s) across 2 module(s) are missing from
    stryker.conf.json tap.testFiles
      open-sse/services/combo/comboStructure.ts
      open-sse/services/combo/rrState.ts

The new tests/unit/combo-dispatch-prelude.test.ts exercises both modules, and
both are already in stryker's mutate list, so without the registration its
mutant kills would not have counted toward the nightly mutation gate.

Note (unchanged, still out of scope): combo/dispatchPrelude.ts itself is not in
stryker's `mutate` list. Adding it would widen the nightly mutation surface,
which is a separate call from fixing this drift.

* docs(changelog): add fragment for diegosouzapw#8582 combo dispatch prelude

* refactor(sse): extract combo target resolution into combo/targetResolution.ts

Pure move, no behaviour change. Lifts the target-resolution stage of
handleComboChat — everything between the dispatch prelude and the attempt
loop — into a new leaf, open-sse/services/combo/targetResolution.ts.

Moved verbatim: provider-wildcard expansion, weighted step-group resolution
+ sticky-weighted eligibility, request-tag routing, the known-context-overflow
early return, the smart/pipeline-enabled auto dispatch, auto-strategy
ordering, per-strategy ordering, cache-strategy affinity, session stickiness,
eval scores, request-compatibility + context-requirement filters, task-aware
reordering, prompt-cache affinity, and the priority-strategy pre-screen.

The three early exits become an { earlyResponse } result so the host decides
to return them (same pattern as resolveAutoStrategyOrder). The values the
attempt loop still reads — orderedTargets, stickyWeightedLimit,
getWeightedStepKeyForTarget, the session-stickiness result and preScreenMap —
are returned instead of closed over. Loop config (maxRetries, retryDelayMs,
fallbackDelayMs, maxSetRetries, setRetryDelayMs) stays in combo.ts.

buildAutoCandidates is dependency-injected because it lives in combo.ts, so
the leaf keeps zero back-edges into its host.

combo.ts 3640 -> 3321 lines; new leaf 484 lines (under the 800 cap).
Part of the diegosouzapw#3501 god-file decomposition campaign.

* refactor(sse): split targetResolution into stage helpers, ratchet combo.ts file-size baseline

Follow-up to the target-resolution extraction: the moved region landed as one
311-line function, which converted inline code inside the (already-violating)
handleComboChat into a NEW separately-counted violating function — check:complexity
2169 -> 2171 and check:cognitive-complexity 956 -> 957.

Split resolveComboTargetPipeline along its natural stage boundaries into 14
helpers (wildcard expansion, weighted eviction/eligibility/sticky-key/selection,
step-key mapper, context-overflow response, pool-size log, smart-pipeline dispatch
and its fall-through logger, strategy ordering, continuity filters, task-aware
ordering, prompt-cache enablement/first-target protection/affinity stage). Each
stage takes the previous stage's output and returns the next; still a pure move.

The leaf now contributes ZERO complexity, max-lines-per-function and
cognitive-complexity violations. Both ratchets are back at base 54b4bf1 values:
check:complexity 2169, check:cognitive-complexity 956. (Both still print RED
against their frozen ceilings 2130/951 — pre-existing base-red per diegosouzapw#8580.)

Also ratchets ONLY the open-sse/services/combo.ts entry in
config/quality/file-size-baseline.json from 3642 to 3322, with a justification
note in the file's existing style. No sweep of unrelated entries.

* chore: stack targetResolution on dispatchPrelude tip, rebank + skills

Rebased onto refactor/combo-dispatch-prelude. Keep both leaves in
check-known-symbols. Regenerate file-size baseline; sync agent skills.

* fix(sse): restore diegosouzapw#8494 capability fail-closed after targetResolution extract

Stacking targetResolution onto the dispatchPrelude tip dropped the diegosouzapw#8488/diegosouzapw#8494
compatFilterFailOpen wiring: hard capability filters emptied the pool into a
generic 404 no_executable_targets, and fail-open never re-admitted the pool.

Restore describeCapabilityFilterExhaustion earlyResponse in
applyContinuityFilters and the matching round-robin path, then rebank the
file-size baseline for tip growth the incomplete prior rebank missed.

* fix(sse): realign model-lockout cooldown options with the post-diegosouzapw#8254 type

This branch predates diegosouzapw#8254, which renamed the recordModelLockoutFailure option
`exactCooldownVerified` -> `exactCooldownIsUpstreamReset` and changed combo.ts's
predicate from `lockoutHintVerified` (diegosouzapw#8393's `lockoutHintMs > 0`) to
`lockoutHintMs > mlSettings.baseCooldownMs`. Rebasing onto the current tip brought
the renamed type without updating these two call sites, so typecheck:core failed
with TS2353 at both.

Restores the base expression verbatim rather than re-wiring `lockoutHintVerified`
under the new name. The base predicate is the correct one: selectLockoutCooldownMs
returns the parsed hint ONLY when `lockoutHintMs > baseCooldownMs`, and otherwise
returns 0 or a synthetic baseCooldownMs — so `lockoutHintMs > 0` would mark a
synthetic cooldown as an upstream reset and let it bypass the diegosouzapw#7940 maxCooldownMs
cap, which is the bug diegosouzapw#8254 fixed.

---------

Co-authored-by: MumuTW <johnsxn.us@gmail.com>
Co-authored-by: diegosouzapw <diegosouzapw@users.noreply.github.com>
Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com>
muhamadgalihsaputra pushed a commit to niyatna/NiyatnaRoute that referenced this pull request Sep 27, 2026
… pools (diegosouzapw#8786) (diegosouzapw#8798)

Strict contextFilterMode excluded every target whose context limit was missing
from the capability catalog, so otherwise-executable combos returned 404
no_executable_targets. Restore unknown-context targets when no known-good
survivor remains, surface context_requirements_exhausted from targetResolution,
and keep the empty-pool payload in pinRecovery after the diegosouzapw#8592 split.
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.

2 participants