feat(a3): prove wrapModelCall provider routing (LIA-396)#1034
Closed
sliamh11 wants to merge 1 commit into
Closed
Conversation
Proves LangChain's real wrapModelCall middleware contract can route
different chat model providers to different requests within one logical
session: a delegate_to_subagent tool nests a second agent.invoke() inside
the main agent's execute(), both sharing one middleware instance keyed by
request.runtime.context.role.
createProviderRoutingMiddleware is the reusable primitive -- Strategy-
pattern resolveModel/executeOverride seams, no hardcoded role coupling --
exported standalone so A7 (LIA-400) can import it directly for its
cross-provider benchmark matrix.
Per-AC verdict (not a blanket pass): AC1/AC2/AC4/AC5 PASS. AC3 ("both
requests execute within one logical session") is PARTIAL -- call-stack
nesting is proven live (main -> sub -> main trace), but the Claude leg's
live network execution is deferred to A4 (LIA-397, credential proxy)
since ANTHROPIC_API_KEY is absent here. The Ollama/subagent leg is fully
live with zero mocking -- a real local gemma4:e2b call, not a stub.
Forks fresh off origin/main per the established per-slice convention
(A1/PR #1031, A2/PR #1032 both still open).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
sliamh11
added a commit
that referenced
this pull request
Jul 14, 2026
Cherry-picked from a3-provider-override-walking-skeleton (d938a3f), which shares deus-v2/dev's merge-base commit (df9df3f) and applies cleanly. A7 [LIA-400] imports createProviderRoutingMiddleware from this spike directly per A3's own file header comment. A3's own PR (#1034, targeting main) is still open/unmerged and conflicting -- deus-v2/dev roadmap work isn't gated on that landing first. package.json/package-lock.json conflicts resolved by keeping both sides' additive deps (@langchain/mcp-adapters from A5, @langchain/ollama from this commit) and letting npm regenerate the lock incrementally. Also fixes a real test-reliability defect a GPT-backend code-reviewer caught in the cherry-picked test file: the optional live full-Claude smoke test was gated only on ANTHROPIC_API_KEY, but its delegate leg requires local Ollama too -- now gated on both. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
sliamh11
added a commit
that referenced
this pull request
Jul 14, 2026
Also brings in A3's [LIA-396] provider-routing middleware spike, which was cherry-picked into this branch as a prerequisite (A3's own PR #1034 remains open/unmerged, targeting main). 6-chain x 3-provider benchmark; kill-switch criterion 4 recorded NO-PASS-YET (qualified) -- see scripts/spikes/lia400_tool_loop_reliability_benchmark.md. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2 tasks
sliamh11
added a commit
that referenced
this pull request
Jul 17, 2026
… --repo (#1054) ## Summary - `_check_ci_status`/`_query_gh_checks` (ci_status.py) and `_gh_pr_head_branch` (codex_warden_hooks.py) never passed `gh` an explicit `--repo`, relying entirely on `gh`'s cwd-based git-remote resolution. - This silently broke cross-repo gating: a `gh pr merge --repo <other-repo> --admin <n>` command run from a worktree tree whose ambient remote is a *different* repo had its internal CI/PR-view check silently resolve against the wrong repo — confirmed live this session merging a `sliamh11/deus-v2` PR from inside the `sliamh11/Deus` worktree tree, where the gate checked an unrelated same-numbered PR on the wrong repo and produced a false "CI is red" block. - Added `_extract_repo_flag` (command_parse.py) to capture an explicit `-R`/`--repo` value already present in the gated command (global or subcommand-local position, last-occurrence-wins matching gh's own precedence, gh's attached `-Rowner/repo` form included), and threaded it through every gh call site: `_check_ci_status`, `_gh_pr_head_branch`, `_pr_matches_worktree`, `run_admin_merge_gate`, `approve_admin_merge`. - Additive and backward-compatible: argv is byte-identical to today when no `--repo`/`-R` is present in the gated command (verified by dedicated regression tests). ## Test plan - [x] `python3 -m pytest scripts/tests/test_codex_warden_hooks.py -q` → 294 passed (279 pre-existing + 15 new) - [x] Real end-to-end hook invocation (not just unit tests) via `codex_warden_hooks.py run admin-merge-gate`, against live GitHub state: - **Error path, same-repo (control):** `gh pr merge --repo sliamh11/Deus --admin 1053` (real PR with a genuinely failing `ci` check) → correctly denied with `"CI is red ... failing checks: ci"`. - **Cross-repo bug reproduction:** from the same cwd (ambient remote `sliamh11/Deus`), `gh pr merge --repo sliamh11/deus-v2 --admin --squash 14` → correctly denied using deus-v2-*specific* data (10 checks, TrueCourse failing in the unfiltered set) — proven distinct from what the *unscoped* `gh pr checks 14` call from the same cwd resolves to (a completely unrelated `sliamh11/Deus` PR #14, "bump @vitest/coverage-v8", with its own failing `ci`). That mismatch is the exact pre-fix bug. - **Happy/allow path:** real green PR #1034 on `sliamh11/Deus` (0 non-passing required checks, independently confirmed) → `approve_admin_merge` + the real PreToolUse hook invocation both succeed, hook allows (empty output, no `permissionDecision`), one-shot marker consumed as designed. ## Known follow-up (not in scope here) - `_extract_pr_ref` still doesn't recognize gh's attached `-Rowner/repo` short form (only `_extract_repo_flag`, added in this PR, handles it). Low-probability edge case (would only matter if the attached form is combined with a positional PR ref); flagged by code-review as a candidate follow-up, not a regression from this change. - Separately (not touched by this PR): `sliamh11/deus-v2` is a private repo without GitHub Pro, so GitHub's classic branch-protection API returns 403 for it, making `_check_ci_status` classify every deus-v2 PR as `_CI_STATUS_NO_REQUIRED` (fail-closed) regardless of actual CI state. This is an orthogonal billing/plan constraint, surfaced to the user separately — this PR's fix is still correct and necessary (it was actively causing the gate to check a totally wrong, unrelated PR). 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
Owner
Author
|
Superseded — this exact commit (d938a3f) was already cherry-picked onto Deus V2 as commit d054fb4 on sliamh11/deus-v2 main (part of the sequential spike-integration lineage, ahead of A6/A7) before this PR could be migrated. Verified byte-identical file content and confirmed both the AC3-PARTIAL disposition and the live-Ollama hermeticity gate survived. No new port PR needed — closing as duplicate. |
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
wrapModelCallmiddleware contract can route different chat model providers to different requests within one logical session — Claude for a main agent, live local Ollama for a nested subagent.agent.invoke()whosedelegate_to_subagenttool'sexecute()nests a secondagent.invoke(), both sharing onewrapModelCallmiddleware instance disambiguated byrequest.runtime.context.role. Validated live before implementation (see plan).createProviderRoutingMiddlewareis exported as a standalone, parameterized reusable primitive — Strategy-patternresolveModel/executeOverrideseams, zero hardcoded role coupling — so A7 (LIA-400) can import it directly for its cross-provider benchmark matrix.scripts/spikes/lia396_provider_override_walking_skeleton.md:gemma4:e2bcall)main → sub → maintrace); the Claude leg's live network execution is deferred to A4 (LIA-397, credential-proxy), sinceANTHROPIC_API_KEYis absent here — explicitly disclosed, not folded into a blanket PASSorigin/mainper the established per-slice convention (A1/PR spike(a1): LangChain createAgent walking skeleton reusing tool-broker.ts (LIA-394) #1031, A2/PR feat(a2): prove blocking warden enforcement via wrapToolCall (LIA-395) #1032 both still open/unmerged).Test plan
npx vitest run scripts/spikes/lia396_provider_override_walking_skeleton.test.ts— 6/7 passing, 1 correctly skipped (noANTHROPIC_API_KEY)npx tsx scripts/spikes/lia396_provider_override_walking_skeleton.ts— direct demo confirms the livemain → sub → maintrace with a real (non-canned) Ollama answernpm run typecheck— cleannpm teston machines without Ollama/the modelLinear: LIA-396
🤖 Generated with Claude Code