Skip to content

chore(typing): scope unresolved-import per-file, fix a confidence OverflowError, retract three doc claims - #439

Merged
damo-da merged 3 commits into
Jawafdehi:mainfrom
damodaha:chore/typing-review-followup
Aug 7, 2026
Merged

chore(typing): scope unresolved-import per-file, fix a confidence OverflowError, retract three doc claims#439
damo-da merged 3 commits into
Jawafdehi:mainfrom
damodaha:chore/typing-review-followup

Conversation

@damodaha

@damodaha damodaha commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

User description

Follow-up to #428, which had already merged when these came in — hence a new PR
rather than an amend. Five items.

1. unresolved-import is now ON, with four files scoped out in two override
blocks instead of a tree-wide ignore. A tree-wide ignore bought silence about
typos: from cases.serialzers import ... resolves to nothing, is invisible to
both gates, and blows up at import time. Two blocks, not one, because the exit
conditions differ — the optional deps (cloudpathlib, playwright) are permanent;
the django-stubs re-export gaps (django.template.loader.engines,
django.test.testcases.DatabaseOperationForbidden) should be re-checked on every
stubs bump. Deliberately not folded into the tests block, which would turn the
rule off for every test in the tree. Verified per-file with a deliberate-error
probe: the exempt import stays silent, a fresh bad import in the same file is
still reported.

2. OverflowError on an unfloatable confidence. float() on a large enough
int raises OverflowError — an ArithmeticError, so not covered by the
(TypeError, ValueError) guard in case_proposals.job_kind.on_result. JSON
integers are unbounded, and because jobs.queue.finalize swallows what
on_result raises, the result was a DONE job with no proposal and no recorded
reason: the one outcome that module's docstring promises cannot happen. The float
spelling already worked (1e400inf, caught by the range check); both are
parametrized so a fix for one can't regress the other.

3. The ty pre-commit hook now fires on uv.lock, which pins ty itself plus
every dep whose types it reads — a dependency bump changes what the checker is
while touching no .py file.

4. Whole-tree diagnostic totals in pyproject.toml are gone, replaced by the
command that reproduces them plus the two traps in that recipe: -c "overrides=[]"
silently no-ops (TOML arrays don't replace), and a 0 from a forced-on rule is
indistinguishable from a path that was never analysed. Three of those totals were
already wrong. Counts scoped to an include = list stay — they move when someone
edits the list beside them.

5. Three AGENTS.md claims retracted, not deleted, since the same wording is in
#428's body and merged commit message:

  • The get_form override was not a bug. _changeform_view passes change as
    a keyword, so a **kwargs-only override forwards it untouched — verified with a
    spy on ModelAdmin.get_form, change=True under both signatures. The "bugs ty
    found" bullet is now sorted by whether runtime behaviour changed.
  • The one-warning invariant is conditional. Untouched main gives 981 in a
    fresh worktree. Whitenoise warns No directory at: .../staticfiles/ from every
    test that builds a Django handler, and staticfiles/ is a gitignored
    collectstatic artifact. case_events/bus.py cited that invariant as a
    tripwire; it now rests on the orphaned-coroutine argument alone.
  • Block ordinals ("THIRD", "FOURTH") went stale the moment blocks were
    inserted above them; blocks are identified by opening comment now.

Gates: ruff check clean · ty check passes · all 7 pre-commit hooks pass ·
suite 4419 passed / 4 skipped vs 4416 / 4 on untouched main (+3 = the new cases).
Tests verified to bite: reverting only the except-tuple fails exactly the two
10**400 cases.


PR Type

Documentation, Bug fix, Tests


Description

  • Gate unresolved-import per file

  • Catch huge confidence OverflowError

  • Run ty on uv.lock

  • Correct warning/type-debt docs


Diagram Walkthrough

flowchart LR
  A["ty config"] -- "enables" --> B["unresolved-import"]
  B -- "exempts" --> C["four files"]
  D["confidence parsing"] -- "catches" --> E["OverflowError"]
  F["docs"] -- "corrects" --> G["warning baseline"]
Loading

File Walkthrough

Relevant files
Documentation
bus.py
Clarify publish coroutine failure rationale                           

case_events/bus.py

  • Revises coroutine warning comment
  • Emphasizes orphaned publish prevention
  • Removes fragile suite-warning rationale
+7/-3     
AGENTS.md
Update typing and warning guidance                                             

AGENTS.md

  • Corrects warning-count guidance for staticfiles/
  • Documents per-file unresolved-import policy
  • Refines type-debt and gate notes
  • Removes stale ordinal/count claims
+86/-37 
Bug fix
job_kind.py
Handle unfloatable confidence values                                         

case_proposals/job_kind.py

  • Catches OverflowError from float()
  • Records validation failure for huge integers
  • Documents JSON integer edge case
+13/-3   
Tests
test_intent_job.py
Cover confidence overflow rejection paths                               

case_proposals/tests/test_intent_job.py

  • Adds huge integer confidence case
  • Adds inf confidence regression case
  • Verifies silent rejection reasons remain recorded
+32/-1   
Configuration changes
.pre-commit-config.yaml
Trigger ty on lockfile changes                                                     

.pre-commit-config.yaml

  • Adds uv.lock to ty trigger
  • Documents dependency-bump type-check risk
  • Keeps whole-project ty execution
+21/-7   
pyproject.toml
Scope unresolved import exemptions precisely                         

pyproject.toml

  • Removes stale whole-tree diagnostic totals
  • Enables unresolved-import globally
  • Adds optional-dependency import overrides
  • Adds django-stubs re-export gap overrides
+129/-53


🛠️ Relevant configurations:


These are the relevant configurations for this tool:

[config]

custom_model_max_tokens: 200000
git_provider: github
output_relevant_configurations: True
model: openai/cx/gpt-5.5
ENABLE_AUTO_APPROVAL: True
custom_reasoning_model: False
fallback_models: ['openai/cx/gpt-5.4-mini']
is_auto_command: True
publish_output: True
publish_output_progress: True
progress_gif_url: 
progress_gif_width: 48
verbosity_level: 0
use_extra_bad_extensions: False
log_level: DEBUG
use_wiki_settings_file: True
use_repo_settings_file: True
use_global_settings_file: True
extra_config_url: 
disable_auto_feedback: False
ai_timeout: 120
response_language: en-US
repo_context_files: ['AGENTS.md']
repo_context_from_default_branch: True
repo_context_max_lines: 500
max_description_tokens: 500
max_commits_tokens: 500
max_model_tokens: 32000
model_token_count_estimate_factor: 0.3
patch_extension_skip_types: ['.md', '.txt']
allow_dynamic_context: True
max_extra_lines_before_dynamic_context: 10
patch_extra_lines_before: 5
patch_extra_lines_after: 1
cli_mode: False
large_patch_policy: clip
duplicate_prompt_examples: False
seed: -1
temperature: 0.2
ignore_pr_title: ['^\\[Auto\\]', '^Auto', '^Bump ', '^chore\\(deps\\)']
ignore_pr_target_branches: []
ignore_pr_source_branches: []
ignore_pr_labels: []
ignore_pr_authors: []
ignore_repositories: []
ignore_language_framework: []
restricted_mode: False
enable_ai_metadata: False
reasoning_effort: medium
enable_claude_extended_thinking: False
extended_thinking_budget_tokens: 2048
extended_thinking_max_output_tokens: 4096
claude_extended_thinking_models_override: []
extract_issue_from_branch: True
branch_issue_regex: 
enable_custom_labels: False

[pr_description]

publish_labels: False
add_original_user_description: True
generate_ai_title: False
use_bullet_points: True
extra_instructions: 
enable_pr_type: True
final_update_message: True
enable_help_text: False
enable_help_comment: False
enable_pr_diagram: True
publish_description_as_comment: False
publish_description_as_comment_persistent: True
enable_semantic_files_types: True
collapsible_file_list: adaptive
collapsible_file_list_threshold: 6
inline_file_summary: False
use_description_markers: False
enable_large_pr_handling: True
include_generated_by_header: True
max_ai_calls: 4
async_ai_calls: True

Summary by CodeRabbit

  • Bug Fixes

    • Invalid confidence values, including excessively large integers, are now safely rejected and recorded instead of causing processing errors.
    • Expanded validation coverage for non-numeric, NaN, infinite, and out-of-range confidence values.
  • Documentation

    • Updated contributor guidance and project configuration documentation to reflect current diagnostics, warnings, exemptions, and dependency-sensitive checks.
    • Improved pre-commit coverage for Python, project configuration, and lockfile changes.

oopsy added 3 commits August 7, 2026 20:54
Three changes to the ty config, all from review of the gate that landed in
Jawafdehi#428.

`unresolved-import` was off tree-wide. That bought silence about typos and
little else: a misspelled module (`from cases.serialzers import ...`)
resolves to nothing, is invisible to both gates under a tree-wide ignore,
and blows up at import time in whatever environment first exercises that
path. It is now ON, with four named files scoped out in two override blocks
— two genuinely-optional deps absent from `uv sync`'s venv (cloudpathlib,
playwright), and two django-stubs re-export gaps that resolve at runtime
(`django.template.loader.engines`,
`django.test.testcases.DatabaseOperationForbidden`). The blocks are separate
because their exit conditions differ: the stub gaps should be re-checked on
every django-stubs bump, the optional deps are permanent.

Kept separate from the tests block on purpose, even though both stub-gap
files are tests it already matches — that block turns rules off for every
test in the tree, whereas naming two files keeps a misspelled import in any
OTHER test a failure.

The pre-commit ty hook now also fires on `uv.lock`. The lockfile pins ty
itself plus every dep whose types it reads, so a dependency bump changes
what the checker is and what it knows while touching no `.py` file.

Finally, the whole-tree diagnostic totals in the header comment are gone,
replaced by the command that reproduces them and the two traps in that
recipe (`-c "overrides=[]"` silently no-ops; a 0 from a forced-on rule is
indistinguishable from a path that was never analysed). Three of those
totals were already wrong. The counts scoped to an explicit `include` list
stay — they move when someone edits the list beside them.

Verified per-file rather than tree-wide with a deliberate-error probe at two
sites: the exempt import stays silent, a fresh bad import in the same file
is still reported, and the same bad import elsewhere fails the gate.
`float()` on a large enough int raises OverflowError, which is an
ArithmeticError — not a TypeError and not a ValueError, so it was not in the
except tuple guarding the confidence coercion in `on_result`.

A JSON number has no size limit, so `json.loads` parses a few-hundred-digit
integer into an unbounded Python int and the conversion raises. Because
`jobs.queue.finalize` swallows whatever `on_result` raises, the outcome was a
DONE job with no proposal and no recorded reason — the single outcome this
module's docstring promises cannot happen.

The float spelling is a different case and already worked: JSON `1e400`
parses to `float("inf")`, converts fine, and is stopped by the range check
below. Both are now parametrized, so a fix aimed at one cannot regress the
other.

Verified the tests bite: reverting only the except tuple fails exactly the
two `10**400` cases with "int too large to convert to float". The `inf` case
passes either way by design, and the comment beside it says so.
Three things AGENTS.md asserted after Jawafdehi#428 that re-checking disproved. Each
is corrected in place rather than deleted, because the same overstatement is
in Jawafdehi#428's body and in its merged commit message, which cannot be edited.

The `get_form` override was NOT a bug. AGENTS.md said the override silently
dropped Django's `change`; it did not. `_changeform_view` passes `change` as
a keyword, so a `**kwargs`-only override forwards it untouched — verified
with a spy on `ModelAdmin.get_form`, which reports `change=True` for both the
old and the new signature. Spelling the parameter out is a readability and
typing change only. The "bugs ty found" bullet is now sorted by whether
runtime behaviour actually changed, which separates the one real fix
(`case_events.bus`) and the one live-path `None` (`case_scraper`) from the
two annotation-only ones (`_die() -> NoReturn`, `build_convert_payload`).

The one-warning invariant is conditional, not absolute. Untouched `main`
gives 981 warnings in a fresh worktree, not 1. Root cause is not a
regression: whitenoise warns `No directory at: .../staticfiles/` from every
test that builds a Django handler, and `staticfiles/` is a gitignored
`collectstatic` artifact, so a fresh clone does not have one. The count is
low in a working tree because the directory happens to exist. Documented
both where the baseline is described and where the invariant is stated, with
a one-step way to reproduce it. `case_events/bus.py` cited that invariant as
a tripwire for its own care around orphaned coroutines; that comment now
rests on the orphaned-work argument, which stands on its own.

The block ordinals went stale. The list identified override blocks as
"THIRD" and "FOURTH", which stopped being true the moment blocks were
inserted above them. Blocks are now identified by their opening comment.

@claude claude 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.

Claude Code Review

This pull request is from a fork — automated review is disabled. A repository maintainer can comment @claude review to run a one-time review.

@jawafdehi-pr-agent

Copy link
Copy Markdown

PR Reviewer Guide 🔍

Here are some key observations to aid the review process:

⏱️ Estimated effort to review: 2 🔵🔵⚪⚪⚪
🧪 PR contains tests
🔒 No security concerns identified
⚡ No major issues detected

🛠️ Relevant configurations:


These are the relevant configurations for this tool:

[config]

enable_ai_metadata: False
custom_model_max_tokens: 200000
git_provider: github
output_relevant_configurations: True
model: openai/cx/gpt-5.5
ENABLE_AUTO_APPROVAL: True
custom_reasoning_model: False
fallback_models: ['openai/cx/gpt-5.4-mini']
is_auto_command: True
publish_output: True
publish_output_progress: True
progress_gif_url: 
progress_gif_width: 48
verbosity_level: 0
use_extra_bad_extensions: False
log_level: DEBUG
use_wiki_settings_file: True
use_repo_settings_file: True
use_global_settings_file: True
extra_config_url: 
disable_auto_feedback: False
ai_timeout: 120
response_language: en-US
repo_context_files: ['AGENTS.md']
repo_context_from_default_branch: True
repo_context_max_lines: 500
max_description_tokens: 500
max_commits_tokens: 500
max_model_tokens: 32000
model_token_count_estimate_factor: 0.3
patch_extension_skip_types: ['.md', '.txt']
allow_dynamic_context: True
max_extra_lines_before_dynamic_context: 10
patch_extra_lines_before: 5
patch_extra_lines_after: 1
cli_mode: False
large_patch_policy: clip
duplicate_prompt_examples: False
seed: -1
temperature: 0.2
ignore_pr_title: ['^\\[Auto\\]', '^Auto', '^Bump ', '^chore\\(deps\\)']
ignore_pr_target_branches: []
ignore_pr_source_branches: []
ignore_pr_labels: []
ignore_pr_authors: []
ignore_repositories: []
ignore_language_framework: []
restricted_mode: False
reasoning_effort: medium
enable_claude_extended_thinking: False
extended_thinking_budget_tokens: 2048
extended_thinking_max_output_tokens: 4096
claude_extended_thinking_models_override: []
extract_issue_from_branch: True
branch_issue_regex: 
enable_custom_labels: False

[pr_reviewer]

require_ticket_analysis_review: False
require_score_review: False
require_tests_review: True
require_estimate_effort_to_review: True
require_can_be_split_review: False
require_security_review: True
require_estimate_contribution_time_cost: False
require_todo_scan: False
publish_output_no_suggestions: True
persistent_comment: True
extra_instructions: Focus on: logic errors and edge cases; security/authz regressions; missing error handling;
Django/DRF correctness (migrations, N+1 queries, transaction/atomicity, serializer & permission gaps).
Do NOT comment on formatting, import order, or naming — ruff handles those in CI.

num_max_findings: 3
final_update_message: True
enable_review_labels_security: True
enable_review_labels_effort: True
require_all_thresholds_for_incremental_review: False
minimal_commits_for_incremental_review: 0
minimal_minutes_for_incremental_review: 0
enable_intro_text: True
enable_help_text: False

@jawafdehi-pr-agent

Copy link
Copy Markdown

PR Code Suggestions ✨

No code suggestions found for the PR.

@jawafdehi-pr-agent

Copy link
Copy Markdown

PR Agent Walkthrough 🤖

Welcome to the PR Agent, an AI-powered tool for automated pull request analysis, feedback, suggestions and more.

Here is a list of tools you can use to interact with the PR Agent:

ToolDescriptionTrigger Interactively 💎

DESCRIBE

Generates PR description - title, type, summary, code walkthrough and labels
  • Run

REVIEW

Adjustable feedback about the PR, possible issues, security concerns, review effort and more
  • Run

IMPROVE

Code suggestions for improving the PR
  • Run

UPDATE CHANGELOG

Automatically updates the changelog
  • Run

HELP DOCS

Answers a question regarding this repository, or a given one, based on given documentation path
  • Run

ADD DOCS

Generates documentation to methods/functions/classes that changed in the PR
  • Run

ASK

Answering free-text questions about the PR

[*]

GENERATE CUSTOM LABELS

Generates custom labels for the PR, based on specific guidelines defined by the user

[*]

(1) Note that each tool can be triggered automatically when a new PR is opened, or called manually by commenting on a PR.

(2) Tools marked with [*] require additional parameters to be passed. For example, to invoke the /ask tool, you need to comment on a PR: /ask "<question content>". See the relevant documentation for each tool for more details.

@jawafdehi-pr-agent

Copy link
Copy Markdown

Auto-approved PR

@coderabbitai

coderabbitai Bot commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

The pull request updates ty configuration, documentation, and pre-commit triggers. It also handles oversized confidence values as rejected inputs and adds regression tests for confidence validation.

Changes

Type diagnostics workflow

Layer / File(s) Summary
Diagnostic configuration and validation
.pre-commit-config.yaml, pyproject.toml, AGENTS.md
The ty hook now checks uv.lock. unresolved-import is enabled with targeted exemptions. Documentation removes stale diagnostic totals and records current warning and type-debt rules.
Workflow rationale updates
AGENTS.md, case_events/bus.py
Guidance and comments now describe dependency-sensitive diagnostics, current type findings, and coroutine cleanup without fixed warning-count claims.

Confidence validation

Layer / File(s) Summary
Confidence overflow handling and regression coverage
case_proposals/job_kind.py, case_proposals/tests/test_intent_job.py
Confidence parsing catches OverflowError. Tests cover invalid numeric values and verify that oversized confidence values are recorded as rejected results.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Possibly related PRs

Suggested reviewers: damo-da, jawafdehi-pr-agent

Poem

I’m a rabbit with tests in my tray,
Overflow hops safely away.
ty checks lockfiles at night,
Exemptions stay scoped and right,
While rejected values record their stay.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main changes to typing configuration, confidence overflow handling, and documentation claims.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

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 `@case_proposals/job_kind.py`:
- Around line 252-266: In the confidence parsing flow, assign
result.get("confidence") to a raw value and guard it to the accepted numeric
input types before calling float(), preserving the existing absent/invalid
handling path. Keep OverflowError in the exception handling around conversion so
oversized JSON integers still produce the documented failure outcome.
🪄 Autofix

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: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 461e61fe-fadd-4016-a12b-61bb64a4c7da

📥 Commits

Reviewing files that changed from the base of the PR and between 0be1fda and a77ad5d.

📒 Files selected for processing (6)
  • .pre-commit-config.yaml
  • AGENTS.md
  • case_events/bus.py
  • case_proposals/job_kind.py
  • case_proposals/tests/test_intent_job.py
  • pyproject.toml

Comment on lines +252 to +266
# `except` immediately below is what handles "absent", "not a number" and
# "too big to be a float", in one place. Narrowing first would just
# duplicate that branch.
#
# OverflowError is in the tuple because a JSON number is not bounded by
# what a float can hold. `json.loads` parses a few-hundred-digit integer
# into an unbounded Python int, and `float()` on that raises OverflowError — an
# ArithmeticError, so NOT covered by TypeError/ValueError. Without it a
# runaway integer escapes this handler, and because `jobs.queue.finalize`
# swallows whatever `on_result` raises, the result is a DONE job with no
# proposal and no recorded reason: the one outcome this module's docstring
# promises cannot happen. (A JSON `1e400` is different — it parses to
# float `inf`, converts fine, and is then caught by the range check below.)
confidence = float(result.get("confidence")) # ty: ignore[invalid-argument-type]
except (TypeError, ValueError):
except (TypeError, ValueError, OverflowError):

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

if rg -n 'float\(result\.get\("confidence"\)\)|ty: ignore\[invalid-argument-type\]' case_proposals/job_kind.py; then
  echo "Un-narrowed confidence conversion remains." >&2
  exit 1
fi

rg -n -C 3 'raw_confidence|float\(raw_confidence\)' case_proposals/job_kind.py

Repository: Jawafdehi/JawafdehiAPI

Length of output: 297


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "## file stats"
wc -l case_proposals/job_kind.py

echo
echo "## relevant lines 220-290"
sed -n '220,290p' case_proposals/job_kind.py

echo
echo "## nearby helper definitions"
rg -n -C 4 'def _validation_failure|jobs\.queue\.finalize|result\.get\("confidence"\)' case_proposals/job_kind.py

Repository: Jawafdehi/JawafdehiAPI

Length of output: 5969


Narrow the external confidence value before conversion.

result.get("confidence") is type-unnarrowed from the model output. Add a guard for accepted input types before float(raw_confidence), then keep OverflowError handling for oversized JSON integers.

🤖 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 `@case_proposals/job_kind.py` around lines 252 - 266, In the confidence parsing
flow, assign result.get("confidence") to a raw value and guard it to the
accepted numeric input types before calling float(), preserving the existing
absent/invalid handling path. Keep OverflowError in the exception handling
around conversion so oversized JSON integers still produce the documented
failure outcome.

Source: Coding guidelines

@damo-da
damo-da merged commit 3b37efa into Jawafdehi:main Aug 7, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants