Calendar Day
Thursday, July 9, 2026 (PR 2 of 3)
Planned Effort
3 story points (Medium) — sprint item #6
Depends on: Wednesday PR 2 (adversarial fixtures #4) merged; Thursday PR 1 (MessageDict #5) merged or stacked.
Companion PR: Thursday PR 3 (session decorator #7) — independent.
Problem
_TOOL_RESULT_DISPATCH in utils/tool_dispatch.py (15 entries) is a first-match-wins table where insertion order is load-bearing and deliberately not “specific before generic.” A contributor adding a tool type must understand the whole table plus intentional broad-before-narrow exceptions (is_task_message_tool_result before retrieval/completed/async).
Ordering intent is enforced only positionally (4 ORDERING_INVARIANTS in tests/test_tool_dispatch_ordering.py). Week 1 PR #104 unified the tool-name registry but did not simplify this selection mechanism — it remains the project's most subtle correctness mechanism and fragile extension point.
Goal
One merged PR that refactors dispatch classification so adding a tool type no longer requires reasoning about the entire tuple order, while preserving all existing classification results and passing structural + adversarial tests.
Scope
Approach (pick one or combine)
- Discriminant-based lookup — once
MessageDict carries role/shape discriminant (Thursday PR 1), collapse overlap into direct keying where possible.
- Explicit specificity — if full keying isn't feasible, annotate predicates with priority/score instead of implicit tuple position; document each broad-before-narrow exception.
Touch points
utils/tool_dispatch.py — refactor _TOOL_RESULT_DISPATCH / _parse_tool_result selection.
docs/architecture.md — update “Dispatch table” section with unambiguous selection rule.
- Module docstring — document new rule; preserve comments on intentional broad-before-narrow cases.
Guards (must still pass)
- All 4
ORDERING_INVARIANTS in test_tool_dispatch_ordering.py.
- Adversarial fixtures from
test_tool_dispatch_adversarial.py (Wednesday PR 2).
tests/test_real_session_fixtures.py, tests/test_jsonl_parser.py — no classification change.
Out of scope
Acceptance Criteria
Verification
cd C:\Users\Jasen\CppAliance\claude-code-chat-browser
.\.venv\Scripts\Activate.ps1
pytest tests/test_tool_dispatch_ordering.py tests/test_tool_dispatch_adversarial.py -v
pytest tests/test_real_session_fixtures.py tests/test_jsonl_parser.py tests/test_tool_dispatch_sync.py -q
pytest -q
mypy .
ruff check .
Calendar Day
Thursday, July 9, 2026 (PR 2 of 3)
Planned Effort
3 story points (Medium) — sprint item #6
Depends on: Wednesday PR 2 (adversarial fixtures #4) merged; Thursday PR 1 (MessageDict #5) merged or stacked.
Companion PR: Thursday PR 3 (session decorator #7) — independent.
Problem
_TOOL_RESULT_DISPATCHinutils/tool_dispatch.py(15 entries) is a first-match-wins table where insertion order is load-bearing and deliberately not “specific before generic.” A contributor adding a tool type must understand the whole table plus intentional broad-before-narrow exceptions (is_task_message_tool_resultbefore retrieval/completed/async).Ordering intent is enforced only positionally (4
ORDERING_INVARIANTSintests/test_tool_dispatch_ordering.py). Week 1 PR #104 unified the tool-name registry but did not simplify this selection mechanism — it remains the project's most subtle correctness mechanism and fragile extension point.Goal
One merged PR that refactors dispatch classification so adding a tool type no longer requires reasoning about the entire tuple order, while preserving all existing classification results and passing structural + adversarial tests.
Scope
Approach (pick one or combine)
MessageDictcarries role/shape discriminant (Thursday PR 1), collapse overlap into direct keying where possible.Touch points
utils/tool_dispatch.py— refactor_TOOL_RESULT_DISPATCH/_parse_tool_resultselection.docs/architecture.md— update “Dispatch table” section with unambiguous selection rule.Guards (must still pass)
ORDERING_INVARIANTSintest_tool_dispatch_ordering.py.test_tool_dispatch_adversarial.py(Wednesday PR 2).tests/test_real_session_fixtures.py,tests/test_jsonl_parser.py— no classification change.Out of scope
KNOWN_TOOL_TYPESregistry changes (PR claude-code-chat-browser: Tool dispatch coordination - single authoritative KNOWN_TOOL_TYPES registry #104).Acceptance Criteria
docs/architecture.md“Dispatch table” updated.pytest,mypy --strict, andruffpass.Verification