Skip to content

fix(db,clients): declare the undeclared indexes, type the untyped kwargs (CHOO-1436) - #367

Draft
amaudruz wants to merge 3 commits into
worktree-message-notifyfrom
worktree-housekeeping
Draft

fix(db,clients): declare the undeclared indexes, type the untyped kwargs (CHOO-1436)#367
amaudruz wants to merge 3 commits into
worktree-message-notifyfrom
worktree-housekeeping

Conversation

@amaudruz

@amaudruz amaudruz commented Sep 3, 2026

Copy link
Copy Markdown
Collaborator

Two outstanding items from the Tuwunel-replacement work, neither of them part of a plan step. Stacked on #366.

The four undeclared indexes — afa45e2d

ix_agent_sessions_agent_room, ix_agent_sessions_transport_session_id, ix_agents_parent_agent_id and ix_external_user_claims_user_id were created by migrations and never declared on the models. Autogenerate would have emitted DROP INDEX for all four — so the next person to add a column had a one-keystroke path to quietly dropping four indexes off live tables.

The parity test listed them by name rather than filtering by kind, precisely so this stayed visible rather than becoming permanent. The list goes with them, and the test is back to allowing no drift at all.

The constructor pass-through — 443cfb97

Four ClientBase subclasses forwarded their remaining arguments as **kwargs: Any (**kwargs: object plus a type: ignore on AgentClient). That makes the pass-through invisible to the type checker in both directions: the subclass cannot be told it is missing something, and a caller cannot be told it is passing something that no longer exists.

Which is how a stale device_id= type-checked clean and took all four collaboration bridges down at startup. The credential had moved into session_state, and nothing said so until the process refused to start.

ClientBaseKwargs declares the shape once and the subclasses Unpack it, so both checks come back without eleven parameters restated four times.

Verified by putting the original mistake back. With device_id=record.device_id re-added at the factory call site, mypy reports:

core/switch_core/clients/client_factory.py:69: error: Unexpected keyword argument "device_id" for "ClientBase"  [call-arg]

matrix_transport_for widens to ClientBase[Any], which is what it always was in fact — it reads five base attributes and never the config. ClientBase is invariant in its config type, so the previous annotation only type-checked while nobody was checking.

Testing

2355 pass, ruff and mypy clean.

🤖 Generated with Claude Code

amaudruz and others added 3 commits September 3, 2026 22:43
…O-1436)

`ix_agent_sessions_agent_room`, `ix_agent_sessions_transport_session_id`,
`ix_agents_parent_agent_id` and `ix_external_user_claims_user_id` were created
by migrations and never declared on the models. Autogenerate would have
emitted `DROP INDEX` for all four, so the next person to add a column had a
one-keystroke path to quietly dropping four indexes off live tables.

The parity test listed them by name rather than filtering by kind, precisely
so this stayed visible. The list goes with them, and the test is back to
allowing no drift at all.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…CHOO-1436)

Four `ClientBase` subclasses took their own arguments and forwarded the rest
as `**kwargs: Any` (`**kwargs: object` with a `type: ignore` on `AgentClient`).
That makes the pass-through invisible to the type checker on both sides: the
subclass cannot be told it is missing something, and a caller cannot be told
it is passing something that no longer exists.

Which is how a stale `device_id=` type-checked clean and took all four
collaboration bridges down at startup. The credential had moved into
`session_state`, and nothing said so until the process refused to start.

`ClientBaseKwargs` declares the shape once and the subclasses unpack it, so
both checks come back without eleven parameters restated four times. Verified
by putting the original mistake back: mypy now reports "Unexpected keyword
argument "device_id" for "ClientBase"" at the call site.

`matrix_transport_for` widens to `ClientBase[Any]`, which is what it always
was in fact — it reads five base attributes and never the config. `ClientBase`
is invariant in its config type, so the previous annotation only type-checked
while nobody was checking.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
`list_after_seq` was added for the delivery cursor without noticing that
`list_for_room` already was that query, character for character. Two names for
one behaviour is how they drift.

`list_for_room` keeps the name and gains the paragraph that justified the
second one, including the part worth writing down: a cursor starting at 0 also
skips reconstructed history, which is numbered below zero, because a backfill
is not something to deliver.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
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.

1 participant