Skip to content

refactor(models): narrow Any-typed parse boundary with TypedDict unions#72

Merged
wpak-ai merged 5 commits into
masterfrom
refactor/parse-boundary-typeddict
Jun 10, 2026
Merged

refactor(models): narrow Any-typed parse boundary with TypedDict unions#72
wpak-ai merged 5 commits into
masterfrom
refactor/parse-boundary-typeddict

Conversation

@clean6378-max-it

@clean6378-max-it clean6378-max-it commented Jun 9, 2026

Copy link
Copy Markdown
Collaborator

closes #68

Summary

Replaces NotRequired[Any] on MessageDict.tool_result and MessageDict.data with typed unions so mypy strict constrains the JSONL parse boundary without weakening tests or adding # type: ignore.
Rebased onto Monday's ruff/pip-audit CI merge (#70).

Problem

tool_result and data are the highest-risk fields in the Claude Code JSONL format — structurally complex and prone to upstream drift. Any let schema ambiguity flow silently into rendering, export, and search.

Changes

  • models/tool_results.py (new) — per-tool TypedDicts for all 15 _TOOL_RESULT_DISPATCH shapes (Bash, Read, Write, Edit, Glob, Grep, Task variants, TodoWrite, WebFetch, WebSearch, UserInput, Plan), plus ToolResultUnion, ToolNameLiteral, and TypeGuard helpers
  • models/record_data.py (new) — RecordDataUnion for progress data payloads (bash_progress, hook_progress, agent_progress, summary, compact_boundary) with dict[str, object] fallback
  • models/session.pytool_result: ToolResultUnion | None, data: RecordDataUnion; adds ToolUseDict and MessageUsageDict
  • utils/tool_dispatch.py — predicates/builders typed with ToolResultDict; _parse_tool_result accepts ToolResultUnion | None
  • utils/jsonl_parser.pyis_tool_result_dict narrowing at image-extraction site; typed ToolUseDict assembly in _process_assistant
  • utils/md_exporter.py_render_tool_use consumes ToolUseDict with explicit dict[str, object] narrowing
    Unknown upstream shapes use dict[str, object] instead of Any to force explicit narrowing at use sites.

Acceptance criteria

  • tool_result typed with union covering all known tool result shapes from fixtures
  • data typed with union covering known record types
  • Narrowing via TypeGuard / Literal (ToolNameLiteral, is_tool_result_dict)
  • No new # type: ignore in changed production code
  • mypy -p api -p utils -p models passes
  • ruff check . passes (rebased on feat: add ruff and pip-audit CI gates, fix style violations, and add … #70)
  • All existing tests pass (350)

Test plan

mypy -p api -p utils -p models
pytest -q
ruff check .

 tests/test_jsonl_parser.py — all _parse_tool_result parametrized cases green

 tests/test_real_session_fixtures.py — dispatch predicate coverage green

 Full suite green locally after rebase onto #70
Out of scope
Hypothesis fuzz tests (Wednesday #4 — this PR defines the fuzz oracle)
Export partial-failure surfacing (Tuesday PR 2)
Frontend TypeScript types
Dependencies
Depends on: #70 (ruff CI) — rebased
Blocks: Wednesday fuzz testing (#4)

<!-- This is an auto-generated comment: release notes by coderabbit.ai -->
## Summary by CodeRabbit

* **Refactor**
  * Improved structured parsing and runtime validation for progress, tool-result, and tool-use data for more reliable handling.

* **Bug Fixes**
  * Safer handling of malformed or legacy payloads to prevent errors and incorrect fields.
  * Markdown export now skips invalid todo/question entries and maps statuses to display icons.
  * Image extraction and tool-result parsing only run when payloads are recognized as valid.

* **Documentation**
  * Clarified guidance on adding new tool-result renderers.

* **Tests**
  * Updated test docstring to reflect predicate naming.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

Replace NotRequired[Any] on MessageDict.tool_result and data with per-tool and per-record unions, type guards, and dispatch-aligned narrowing so mypy strict constrains schema drift without weakening tests.
@coderabbitai

coderabbitai Bot commented Jun 9, 2026

Copy link
Copy Markdown

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Adds TypedDict unions and TypeGuard predicates for tool results and record data, narrows MessageDict fields to those unions, and updates tool dispatch, JSONL parsing, and markdown rendering to use and validate the new typed contracts.

Changes

Type-narrowing refactor from Any to structured unions

Layer / File(s) Summary
Tool result TypedDict schemas and type guards
models/tool_results.py
Defines TypedDict schemas for many tool-result shapes; exports ToolResultDict, ToolResultUnion, runtime TypeGuard predicates, and ToolNameLiteral.
Record data TypedDict schemas
models/record_data.py
Defines TypedDicts for progress/record data variants and exports RecordDataUnion with a generic dict[str, object] fallback.
Session message type narrowing & exports
models/session.py, models/__init__.py
Adds ToolUseDict, MessageUsageDict, SystemSubtypeLiteral; narrows MessageDict fields to `tool_result: ToolResultUnion
Tool result dispatch with typed predicates
utils/tool_dispatch.py
Updates builders/predicates to accept ToolResultDict, adds defensive normalization for malformed payloads (glob, file_read, web_search, task_retrieval, todo_write), validates inputs with is_tool_result_dict(), and uses a typed predicate→builder registry.
Parser and exporter adoption of typed models
utils/jsonl_parser.py, utils/md_exporter.py
jsonl_parser parses toolUseResult via _parse_tool_result(), gates image extraction on is_tool_result_dict(), normalizes tool_uses and data; md_exporter._render_tool_use accepts ToolUseDict, normalizes input, and guards todos/questions iteration.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Suggested labels

enhancement

Suggested reviewers

  • timon0305
  • jonathanMLDev
  • wpak-ai

"I hopped through types both stout and small,
Replaced wild Any with unions for all.
Guards now check shapes before parse begins,
Exports let callers find each typed bin.
A rabbit cheers the tidy typing thrall! 🐇"

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 12.82% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely summarizes the main refactoring: replacing Any-typed fields in the parse boundary with TypedDict unions for better type safety.
Linked Issues check ✅ Passed The PR fully addresses all coding requirements from issue #68: defines per-tool TypedDicts covering known tool-result shapes, creates RecordDataUnion for data payloads, updates MessageDict fields with typed unions, implements narrowing patterns via TypeGuard functions, and maintains compliance with mypy strict and ruff checks.
Out of Scope Changes check ✅ Passed All changes are directly related to the stated objective of narrowing the JSONL parse boundary. Documentation updates reference the new TypeGuard function names, test docstrings align with the new type model, and utility modules are updated to consume the typed unions, with no unrelated alterations.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch refactor/parse-boundary-typeddict

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
models/__init__.py (1)

3-16: ⚠️ Potential issue | 🔴 Critical | ⚡ Quick win

Fix import sorting to pass ruff check.

The import block is flagged as unsorted by the pipeline. The imports should be in alphabetical order by module name.

📦 Proposed fix
 from models.errors import ErrorResponse
 from models.export import ExportStateDict
 from models.project import ProjectDict, ProjectSessionRowDict, SessionListItemDict
-from models.search import SearchHitDict
 from models.record_data import RecordDataUnion
+from models.search import SearchHitDict
 from models.session import (
     MessageDict,
     QuickSessionInfoDict,
     SessionDict,
     SessionMetadataDict,
     ToolUseDict,
 )
-from models.tool_results import ToolResultUnion
 from models.stats import FilesTouchedDict, SessionStatsDict
+from models.tool_results import ToolResultUnion
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@models/__init__.py` around lines 3 - 16, The import block in
models/__init__.py is unsorted causing Ruff to fail; reorder the import lines
alphabetically by module name so modules appear as: errors (ErrorResponse),
export (ExportStateDict), project (ProjectDict, ProjectSessionRowDict,
SessionListItemDict), record_data (RecordDataUnion), search (SearchHitDict),
session (MessageDict, QuickSessionInfoDict, SessionDict, SessionMetadataDict,
ToolUseDict), stats (FilesTouchedDict, SessionStatsDict), tool_results
(ToolResultUnion); update the file to reflect that alphabetical module ordering
while keeping the same imported symbols.

Source: Pipeline failures

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@models/record_data.py`:
- Line 3: The import line in record_data.py is unsorted and fails ruff; reorder
the imports alphabetically (by module/member name) so the from typing import ...
line lists members in sorted order (e.g., ensure Literal, TypeGuard, TypedDict
are alphabetized) or split into multiple lines per project style so ruff
import-sorting passes; update the import of Literal, TypeGuard, TypedDict
accordingly in the file.

In `@models/tool_results.py`:
- Line 7: The import block in models/tool_results.py is unsorted; reorder the
imported names in the from typing import ... line so they are alphabetically
sorted (e.g., ensure Literal, TypeGuard, TypedDict are in the correct
alphabetical order) to satisfy the ruff sorting rule and rerun the linter; keep
the single from typing import ... statement and do not add or remove imports.

---

Outside diff comments:
In `@models/__init__.py`:
- Around line 3-16: The import block in models/__init__.py is unsorted causing
Ruff to fail; reorder the import lines alphabetically by module name so modules
appear as: errors (ErrorResponse), export (ExportStateDict), project
(ProjectDict, ProjectSessionRowDict, SessionListItemDict), record_data
(RecordDataUnion), search (SearchHitDict), session (MessageDict,
QuickSessionInfoDict, SessionDict, SessionMetadataDict, ToolUseDict), stats
(FilesTouchedDict, SessionStatsDict), tool_results (ToolResultUnion); update the
file to reflect that alphabetical module ordering while keeping the same
imported symbols.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 588107cc-972b-4a26-b183-6be6a98fbc80

📥 Commits

Reviewing files that changed from the base of the PR and between 32e60f4 and 0269b8c.

📒 Files selected for processing (7)
  • models/__init__.py
  • models/record_data.py
  • models/session.py
  • models/tool_results.py
  • utils/jsonl_parser.py
  • utils/md_exporter.py
  • utils/tool_dispatch.py

Comment thread models/record_data.py Outdated
Comment thread models/tool_results.py Outdated
@clean6378-max-it

Copy link
Copy Markdown
Collaborator Author

@CodeRabbit , Can you reeviewe this PR fully?

@coderabbitai

coderabbitai Bot commented Jun 9, 2026

Copy link
Copy Markdown

@clean6378-max-it Sure! I'll kick off a full review of PR #72 right away.

✅ Action performed

Full review finished.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@models/record_data.py`:
- Around line 6-8: The TypedDict BashProgressDataDict is currently total (all
keys required) which makes the TypeGuard is_bash_progress_data unsafe — change
the TypedDict to allow missing keys by declaring it as non-total (e.g., class
BashProgressDataDict(TypedDict, total=False): with the same type:
Literal["bash_progress"] and output: str), and/or mark output as
NotRequired[str]; additionally ensure the TypeGuard function
is_bash_progress_data either checks for the presence of "output" (e.g., "output"
in data) before narrowing or leave the TypedDict non-total so mypy won't assume
output exists after the type guard.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 4b2ee96e-d606-435b-9762-a7866daf186b

📥 Commits

Reviewing files that changed from the base of the PR and between 32e60f4 and 805ef93.

📒 Files selected for processing (7)
  • models/__init__.py
  • models/record_data.py
  • models/session.py
  • models/tool_results.py
  • utils/jsonl_parser.py
  • utils/md_exporter.py
  • utils/tool_dispatch.py

Comment thread models/record_data.py Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
models/record_data.py (1)

46-47: Don’t add extra TypeGuards for progress variants unless code actually narrows on data["type"]

utils/jsonl_parser.py:_process_progress stores data: RecordDataUnion and derives only progress_type = str(data.get("type", "")); there are no consumption sites that branch on data["type"] for hook_progress, agent_progress, or summary. Repo-wide, those discriminator strings only appear in models/record_data.py TypedDict definitions (and compact_boundary is handled as a system subtype, not as record data.type). Also, is_bash_progress_data (models/record_data.py:46-47) is currently unused—add its intended consumption site or remove/defer it.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@models/record_data.py` around lines 46 - 47, The is_bash_progress_data
TypeGuard is currently unused; either remove this TypeGuard from
models/record_data.py or actually use it to narrow progress records where code
branches on data["type"]. If you choose removal, delete the
is_bash_progress_data function and any unused TypedDict-only discriminators; if
you choose to keep it, update utils/jsonl_parser.py::_process_progress to
inspect and branch on data["type"] (e.g., call is_bash_progress_data(data) and
handle the bash_progress shape) so the TypeGuard is consumed and provides real
narrowing.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@models/record_data.py`:
- Around line 46-47: The is_bash_progress_data TypeGuard is currently unused;
either remove this TypeGuard from models/record_data.py or actually use it to
narrow progress records where code branches on data["type"]. If you choose
removal, delete the is_bash_progress_data function and any unused TypedDict-only
discriminators; if you choose to keep it, update
utils/jsonl_parser.py::_process_progress to inspect and branch on data["type"]
(e.g., call is_bash_progress_data(data) and handle the bash_progress shape) so
the TypeGuard is consumed and provides real narrowing.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 6c45113f-de28-44c8-aaac-c296d48c2e10

📥 Commits

Reviewing files that changed from the base of the PR and between 805ef93 and 3bc6b06.

📒 Files selected for processing (1)
  • models/record_data.py

@timon0305 timon0305 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Solid parse-boundary refactor — mypy strict is green, the isinstance-guarded narrowing in the parser/exporter is the right shape, and no # type: ignore crept in. Main thing: the per-tool TypeGuards in tool_results.py are unused and duplicate tool_dispatch.py's predicates (drift risk) — wire them in or drop them. Two minor notes inline.

Comment thread models/tool_results.py
Comment thread models/record_data.py Outdated
Comment thread models/session.py
…view)

Remove duplicate _tool_result_pred_* predicates; dispatch registry uses
TypeGuards from models/tool_results.py as single source of truth. Drop
unused is_bash_progress_data; document ToolNameLiteral | str intent.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
utils/tool_dispatch.py (1)

148-156: ⚡ Quick win

Use .get() for consistency with the defensive pattern.

Line 152 accesses tr["task"] with bracket notation, which will raise KeyError if the key is missing. Although the predicate is_task_retrieval_tool_result guarantees "task" is present, every other builder in this file uses .get() before isinstance checks (see lines 78, 104, 120, 183). Using bracket notation here is inconsistent and fragile if the predicate or dispatch logic changes.

♻️ Recommended fix for consistency
 def _tool_result_build_task_retrieval(
     tr: ToolResultDict, base: dict[str, object]
 ) -> dict[str, object]:
     result = dict(base)
-    task_obj = tr["task"] if isinstance(tr["task"], dict) else {}
+    raw_task = tr.get("task")
+    task_obj = raw_task if isinstance(raw_task, dict) else {}
     result["result_type"] = "task"
     result["retrieval_status"] = tr.get("retrieval_status")
     result["task_id"] = task_obj.get("task_id")
     return result
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@utils/tool_dispatch.py` around lines 148 - 156, The function
_tool_result_build_task_retrieval uses bracket access tr["task"] which can raise
KeyError and is inconsistent with other builders; change it to use
tr.get("task") in the isinstance check and assignment (e.g., task_obj =
tr.get("task") if isinstance(tr.get("task"), dict) else {}) so it follows the
existing defensive pattern and preserves result_type, retrieval_status, and
task_id behavior.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@utils/tool_dispatch.py`:
- Around line 148-156: The function _tool_result_build_task_retrieval uses
bracket access tr["task"] which can raise KeyError and is inconsistent with
other builders; change it to use tr.get("task") in the isinstance check and
assignment (e.g., task_obj = tr.get("task") if isinstance(tr.get("task"), dict)
else {}) so it follows the existing defensive pattern and preserves result_type,
retrieval_status, and task_id behavior.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: e2384d6a-8575-46d5-8c3c-2feb489b014f

📥 Commits

Reviewing files that changed from the base of the PR and between 3bc6b06 and c6a7aad.

📒 Files selected for processing (6)
  • docs/architecture.md
  • models/record_data.py
  • models/session.py
  • models/tool_results.py
  • tests/test_real_session_fixtures.py
  • utils/tool_dispatch.py
✅ Files skipped from review due to trivial changes (3)
  • docs/architecture.md
  • tests/test_real_session_fixtures.py
  • models/record_data.py
🚧 Files skipped from review as they are similar to previous changes (1)
  • models/session.py

@clean6378-max-it

clean6378-max-it commented Jun 10, 2026

Copy link
Copy Markdown
Collaborator Author

Do you think reviewer's concerns are addressed correctly? @CodeRabbit

@coderabbitai

coderabbitai Bot commented Jun 10, 2026

Copy link
Copy Markdown

Tip

For best results, initiate chat on the files or code changes.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Get all reviews on PR `#72`
gh pr view 72 --repo cppalliance/claude-code-chat-browser --json reviews,comments

# Get review comments (inline)
gh api repos/cppalliance/claude-code-chat-browser/pulls/72/comments --paginate | jq '[.[] | {id, path, line, body, user: .user.login, diff_hunk}]'

# Get issue-level comments
gh api repos/cppalliance/claude-code-chat-browser/issues/72/comments --paginate | jq '[.[] | {id, body, user: .user.login}]'

Length of output: 94047



@clean6378-max-it Here's a breakdown of every concern raised and where things stand:


✅ Fully Addressed

Concern Reviewer Status
Unsorted imports in models/record_data.py and models/tool_results.py CodeRabbit ✅ Fixed in commit e72280e
Unsorted module imports in models/__init__.py CodeRabbit ✅ Fixed in commit e72280e
BashProgressDataDict using total=True making TypeGuard unsafe at runtime CodeRabbit ✅ Fixed in commit 3bc6b06 (added total=False)
9 per-tool TypeGuards in models/tool_results.py were dead code, duplicating _tool_result_pred_* predicates in tool_dispatch.py (drift risk) @timon0305 ✅ Resolved — tool_dispatch.py now uses TypeGuards from models/tool_results.py as single source of truth
is_bash_progress_data unused TypeGuard Both CodeRabbit & @timon0305 ✅ Dropped
`ToolNameLiteral strcollapses tostr`, no exhaustiveness checking, needs a clarifying comment @timon0305

⚠️ Still Open

  1. _tool_result_build_task_retrieval uses bracket access tr["task"] (latest CodeRabbit review on commit c6a7aadb, lines 148–156 of utils/tool_dispatch.py): All other builders use .get() defensively — this one is inconsistent and could raise KeyError if the predicate or dispatch logic changes. The fix is a one-liner:

    raw_task = tr.get("task")
    task_obj = raw_task if isinstance(raw_task, dict) else {}
  2. @timon0305's CHANGES_REQUESTED review is still open — they haven't re-reviewed after the wiring commit. You'll want to request a re-review from them once the bracket-access issue above is resolved.

  3. Docstring coverage pre-merge check is failing (12.82% vs. 80% threshold) — this is a warning, not a blocker, but worth noting.

In short: the substantive architectural concerns (dead TypeGuards, unsafe narrowing, import sorting) are properly handled. The one remaining code fix is the nitpick about tr["task"] bracket access, and then getting @timon0305 to re-approve.

@clean6378-max-it

Copy link
Copy Markdown
Collaborator Author

Docstring coverage is enough,

and others are resolved, @CodeRabbit

@coderabbitai

coderabbitai Bot commented Jun 10, 2026

Copy link
Copy Markdown

Tip

For best results, initiate chat on the files or code changes.

@clean6378-max-it Understood — docstring coverage is acceptable for this PR, and good to hear the bracket-access fix is in as well.

At this point the PR looks clean: the architectural concerns (dead TypeGuards, unsafe narrowing, import ordering, total=False on BashProgressDataDict) are all resolved, and the dispatch registry uses models/tool_results.py as the single source of truth.

The only remaining step is getting @timon0305 to re-review and lift their CHANGES_REQUESTED status, since their concerns have been addressed. You may want to request a re-review from them directly on GitHub.


✏️ Learnings added
Learnt from: clean6378-max-it
URL: https://github.com/cppalliance/claude-code-chat-browser/pull/72

Timestamp: 2026-06-10T20:29:22.752Z
Learning: In the cppalliance/claude-code-chat-browser repository, docstring coverage below the 80% CI threshold is acceptable and should not block PR merges. The project maintainer (clean6378-max-it) has explicitly stated that the current docstring coverage (≈12.82%) is sufficient.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.

Comment thread models/tool_results.py
@clean6378-max-it clean6378-max-it requested a review from wpak-ai June 10, 2026 23:24
@wpak-ai wpak-ai merged commit 57462fd into master Jun 10, 2026
11 checks passed
@wpak-ai wpak-ai deleted the refactor/parse-boundary-typeddict branch June 10, 2026 23:30
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.

claude-code-chat-browser: Narrow Any-typed parse boundary in TypedDict models

3 participants