fix(ci): green the gates the ai_chat/ChatGateway commits reddened - #81
Merged
Conversation
The three ChatGateway commits (8b790ea, cac3118, 20663a6) landed on main without a full run-ci, reddening LINT, FMT, TYPECHECK and NO-CHEAT. This fixes each at its source. LINT (ruff 0.15.21, the pinned version) - ai_chat/__init__.py: RUF022 __all__ sorted. - search/document_processor.py: SIM102 nested if collapsed. FMT - ruff format over ai_chat/gateway.py + core/function_result.py. TYPECHECK (mypy --strict; the config puts tests in scope on purpose: "a new untyped test fails the gate") - tests/unit/ai_chat/test_gateway.py shipped fully unannotated: 44 no-untyped-def + 19 no-untyped-call. Annotated throughout. - FunctionResult.response widened to `str | dict[str, Any]`, so 37 call sites doing `.response.lower()` stopped type-checking. Added `assert isinstance(<r>.response, str)` next to the existing `assert isinstance(<r>, FunctionResult)` — a real assertion that narrows the union, not a cast. - FunctionResult.hold: `bool` subclasses `int`, so excluding bools from the back-compat int-swap left `str | bool`. Handle bool explicitly; the remaining type is `str | None`. hold(120) still means hold(timeout=120). - ChatGateway.visible_messages / last_activity accept None and non-dict items by design (`for msg in messages or []`, `if not isinstance(msg, dict): continue`) and are tested for it, but were typed `list[dict[str, Any]]`. Widened to match the real, documented contract. Free to change: ChatGateway is new surface no port has implemented yet. NO-CHEAT - Three origin tests asserted nothing ("does not raise"), so they passed regardless of the code. Each now pairs the allowed case with the refusal that proves it is an exemption and not open-by-default: localhost vs an unlisted origin, a listed origin vs a lookalike domain, absent vs present-but-unlisted. Verified: LINT clean, FMT clean, NO-CHEAT clean, mypy clean over every file CI reports, 5940 unit tests pass. The 6 remaining mcp_gateway failures are pre-existing (they fail identically on unmodified main) and env-dependent — CI passes them. Not addressed here (deliberately): GEN-FRESH and DRIFT/SEMVER-DIFF are coordinated-pin artifacts. PORTING_SDK_REF is set to wave6/ctor-dunder-fold, so CI builds against that branch; the matching regen is PR #78's half of the wave, not this branch's.
…pecs CI resolves porting-sdk via PORTING_SDK_REF, currently wave6/ctor-dunder-fold, so GEN-FRESH regenerates from THAT branch's specs and compares. The committed files were generated from main's specs, so six reproduced differently and the gate failed. Regenerated with the pinned ref's specs; `--check` is now clean. Note these are NEWER than the same files on the wave6 branch itself: the swaig specs gained `| str` on several action fields after that branch last regenerated (e.g. `consolidate: bool` -> `bool | str`, `wait: bool` -> `bool | str`). So this is the output current wave6 specs actually produce, which is what CI checks against. Full unit suite still 5940 passed; the 6 mcp_gateway failures are pre-existing and env-dependent (they fail identically on unmodified main).
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.
Coordinated-With: porting-sdk@wave6/ctor-dunder-fold
What this is
The three ChatGateway commits (
8b790ea,cac3118,20663a6) landed onmainwithout a full
run-ci, reddening four gates. This fixes each at its source.It does not touch the gates that are wave6 coordination artifacts — see
"Not in scope" below.
Fixed
LINT —
RUF022(__all__unsorted inai_chat/__init__.py) andSIM102(nested
ifinsearch/document_processor.py).FMT —
ruff formatoverai_chat/gateway.pyandcore/function_result.py.Applied with the pinned
ruff==0.15.21; a newer ruff reformats 19 filesinstead of 2, which is exactly what the pin in
requirements-dev.txtexists toprevent.
TYPECHECK — two root causes, not 105 problems:
tests/unit/ai_chat/test_gateway.pyshipped fully unannotated (44no-untyped-def+ 19no-untyped-call). The mypy config putstestsinscope deliberately — "a new untyped test fails the gate" — so it is annotated
throughout.
FunctionResult.responsewidened tostr | dict[str, Any], so 37 sites doing.response.lower()stopped type-checking. Each getsassert isinstance(<r>.response, str)beside the existingassert isinstance(<r>, FunctionResult): a real assertion that narrows theunion and pins the contract, not a
castpapering over it.FunctionResult.hold:boolsubclassesint, so excluding bools from theback-compat int-swap left
str | bool. Handled explicitly.hold(120)stillmeans
hold(timeout=120)— the existing back-compat shim is untouched.ChatGateway.visible_messages/last_activityacceptNoneand non-dictitems by design (
for msg in messages or [],if not isinstance(msg, dict): continue) and are tested for it, but weretyped
list[dict[str, Any]]. Widened to match the real contract. Free tochange:
ChatGatewayis new surface no port has implemented yet.NO-CHEAT — three origin tests asserted nothing at all, so they passed
regardless of whether the code worked. Each now pairs the allowed case with the
refusal that proves it is a deliberate exemption and not open-by-default:
localhost vs an unlisted origin, a listed origin vs a lookalike domain, and
absent vs present-but-unlisted.
Verification
LINT,FMT,NO-CHEATpass; 29 other gates pass.mypyclean over all 8 files CI reports.mcp_gatewayfailures are pre-existing — verified bystashing this branch's changes and running them on unmodified
main, wherethey fail identically. They are environment-dependent and CI passes them.
Not in scope (deliberately)
GEN-FRESH,DRIFT,SEMVER-DIFFand DOC-AUDIT's unresolvedrouterarecoordinated-pin artifacts, not defects in this code.
PORTING_SDK_REFisset to
wave6/ctor-dunder-fold, so CI builds against that branch — which wascut before the ChatGateway commits and therefore has no
ChatGatewayin itsoracle. Regenerating the oracle standalone is not possible: doing it on top of
wave6 produces an 877+/544- diff whose deletions are wave6-only surface that
maindoes not have.That half is already PR #78's ("wave6: the reference half of the coordinated
pass"), which regenerates those exact generated files and whose
testjobs passon 3.10-3.13. Those gates resolve when the wave lands with
main's commitsabsorbed.
Worth noting separately:
mypyis unpinned (mypy>=1.8) inrequirements-dev.txtwhileruffis pinned exact. It happened to resolve to2.3.0 both locally and in CI, but that is luck — same local-vs-CI drift class
the ruff pin was added to stop.
🤖 Generated with Claude Code
https://claude.ai/code/session_015dYktt85Ltj3oK9gG5VBww