Skip to content

claude-code-chat-browser: MessageDict discriminated union — role-specific TypedDicts for mypy strict #117

Description

@clean6378-max-it

Calendar Day

Thursday, July 9, 2026 (PR 1 of 3)

Planned Effort

5 story points (Medium) — sprint item #5

Companion PRs: Thursday PR 2 (dispatch simplify #6) stacks on this; PR 3 (session decorator #7) is independent.

Problem

models/session.py MessageDict (lines 29–52) is a single flat TypedDict: role: RoleLiteral required plus 22 NotRequired fields spanning all five roles. mypy cannot distinguish roles, so msg["thinking"] on a user message type-checks yet is absent at runtime.

Already done and not this issue:

MessageDict remains a flat, monotonically-widening union — the type-safety gap is unresolved.

Goal

One merged PR that splits MessageDict into role-specific TypedDicts unioned on role, updates consumers to narrow on the discriminant, and preserves serialized JSON shapes for API/export parity.

Scope

Touch points

  • models/session.py — introduce:
    • BaseMessageDict (common fields: uuid, timestamp, type, …)
    • UserMessageDict, AssistantMessageDict, SystemMessageDict, ResultMessageDict, ProgressMessageDict
    • MessageDict = Union[...] discriminated on role
  • Consumer narrowing in:
    • utils/jsonl_parser.py
    • utils/tool_dispatch.py
    • api/sessions.py
    • utils/md_exporter.py, utils/json_exporter.py
  • Type-level regression test — mypy rejects role-inappropriate field access (e.g. thinking on user message).

Out of scope

Acceptance Criteria

  • MessageDict refactored into role-specific TypedDicts + Union on role.
  • mypy strict rejects role-inappropriate access (type-level regression test).
  • All listed consumers narrow on the discriminant.
  • [tool.mypy] strict = true passes with no new ignores.
  • Runtime behavior unchanged; tests/test_real_session_fixtures.py and export tests pass.
  • Full pytest, mypy --strict, and ruff pass.
  • PR approved by at least 1 reviewer.

Verification

cd C:\Users\Jasen\CppAliance\claude-code-chat-browser
.\.venv\Scripts\Activate.ps1
mypy -p models -p utils -p api
pytest tests/test_jsonl_parser.py tests/test_real_session_fixtures.py tests/test_api_routes.py -q
pytest -q
ruff check .

Metadata

Metadata

Labels

No labels
No labels

Type

No type

Fields

No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions