Skip to content

Phase 5: clear deps-installed mypy errors (mypy-strict gate) — follow-up to #49 #63

Description

@subindevs

Follow-up to #49 (closed by #62). #49 cleared every error the deps-less
mypy check could see and removed the last [[tool.mypy.overrides]] entry, so
mypy . is now clean under the required lint gate.

But that gate runs mypy without project dependencies — with
ignore_missing_imports, every third-party import (numpy, pillow, anthropic, …)
collapses to Any, hiding all type errors that involve those libraries. #62
added a separate mypy-strict CI job that runs uv run mypy . with the
real packages installed (the check contributors get locally per
CONTRIBUTING.md). It is continue-on-error: true for now.

That job currently reports 236 errors in 22 files — none of them
regressions from #62; they are pre-existing mismatches the deps-less gate could
never see. This issue tracks clearing them so mypy-strict can be flipped to
a required gate
(the open task carried over from #49).

Breakdown by error code

Code Count
union-attr 154
operator 25
arg-type 22
assignment 15
attr-defined 11
list-item 4
return-value 3
typeddict-item 1
index 1

Breakdown by file

File Errors
gently/harness/detection/verifier.py 60
gently/hardware/dispim/claude_client.py 48
gently/analysis/steps.py 16
scripts/auto_label_examples.py 12
gently/organisms/celegans/developmental_tracker.py 12
gently/harness/detection/queue.py 12
gently/app/agent.py 12
gently/core/imaging.py 10
gently/app/tools/focus_tools.py 10
gently/detection.py 9
scripts/projection_explorer.py 8
scripts/watch_devices.py 6
gently/analysis/core.py 6
gently/ui/web/server.py + plots.py 3 + 3
(remaining: watch_position, harness/state, recreate_session_videos, embryo_marker, sam_detection, calibration_tools, analysis/focus) 1–2 each

Candidate clusters (each a single-PR phase, à la #48 Phase 3)

  • Anthropic ContentBlock union narrowing — ~154 errors / 7 files (the big one).
    Almost every union-attr error is the same root cause: reading .text off
    response.content[0] where the SDK types the block as
    TextBlock | ThinkingBlock | ToolUseBlock | … (12-member union). Each call
    site emits ~11 errors. A single shared helper (e.g.
    def _block_text(block) -> str with an isinstance(block, TextBlock) guard,
    or filtering [b for b in content if isinstance(b, TextBlock)]) clears the
    whole cluster. This one has real runtime-bug surface: if a response's
    first block is ever a ToolUseBlock/ThinkingBlock, block.text raises
    AttributeError today. Concentrated in verifier.py (55), claude_client.py
    (44), and auto_label_examples.py / developmental_tracker.py / queue.py /
    agent.py / steps.py (11 each).

  • numpy list vs ndarray in focus-curve code — ~25 errors.
    analysis/core.py, app/tools/focus_tools.py, harness/state.py: locals
    annotated list[float] are reassigned to np.asarray(...) and then
    .min()/.max() / fit_focus_curve(...) are called on them. Fix the
    annotation (or keep them ndarrays). Mostly benign at runtime.

  • numpy scalar operands — ~10 operator errors.
    detection.py, imaging.py: arithmetic on np.clip/np.min returns typed
    as SupportsDunderLT[Any]. Annotation-level; benign.

  • pillow ImageFont.truetype union — embryo_marker.py, recreate_session_videos.py.
    Returns FreeTypeFont | ImageFont; narrow or annotate.

  • bytes vs str in watch scripts — scripts/watch_devices.py (6), watch_position.py (2).
    subprocess output handled as both bytes and strworth checking for a
    real decode bug
    , not just an annotation.

Tasks

  • Land the ContentBlock narrowing fix first (biggest cluster + only one with runtime-bug risk)
  • Work the numpy/pillow/bytes clusters
  • Re-run mypy-strict after each, drive the count to 0
  • Flip mypy-strict from continue-on-error: true to a required gate

🤖 Generated with Claude Code

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    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