Skip to content

Enforce strict type checking across Python and TypeScript#270

Merged
IanMayo merged 20 commits intomainfrom
claude/strict-type-checking-WoO58
Feb 27, 2026
Merged

Enforce strict type checking across Python and TypeScript#270
IanMayo merged 20 commits intomainfrom
claude/strict-type-checking-WoO58

Conversation

@IanMayo
Copy link
Copy Markdown
Member

@IanMayo IanMayo commented Feb 18, 2026

Summary

Implements strict type safety across the codebase by adding pyright for Python static type checking, promoting ESLint's no-explicit-any rule to error across all TypeScript packages, and replacing ~208 existing Any/any violations with concrete types. Type checking is now a CI gate that blocks merges on violations.

Key Changes

Configuration & Tooling

  • Added pyrightconfig.json at repo root with standard mode type checking for all Python packages
  • Updated ruff.toml to include ANN (annotation presence) and TC (type checking) rule sets
  • Added pyright>=1.1.0 to pyproject.toml dev dependencies
  • Updated ESLint configs across all TypeScript packages to enforce @typescript-eslint/no-explicit-any: error:
    • apps/vscode/.eslintrc.json
    • apps/loader/.eslintrc.cjs
    • shared/components/.eslintrc.cjs
  • Added strict: true to apps/web-shell/tsconfig.node.json
  • Added typecheck script to apps/web-shell/package.json

CI Integration

  • Added typecheck task to Taskfile.yml that runs uv run pyright and pnpm -r typecheck
  • Updated .github/workflows/ci.yml to run type checking between lint and test steps

Type Safety Fixes

  • Replaced any with concrete types in test files:

    • apps/vscode/tests/__mocks__/vscode.ts: Added MockUri, MockCommand, MockThemeIcon interfaces
    • apps/vscode/tests/unit/labelInterval.test.ts, setTrackColor.test.ts, symbolInterval.test.ts: Replaced any with TestTrackFeature interface
    • shared/components/src/MapView/__tests__/temporal-utils.test.ts: Replaced any with TestFeatureInput interface
    • shared/components/src/MapView/__tests__/selection.test.tsx: Typed mock props instead of using any
    • apps/vscode/tests/unit/openPlotsService.test.ts: Added MockWorkspaceState interface
    • apps/vscode/tests/unit/generateReferencePoints.test.ts: Added GoldenFile interface
    • apps/web-shell/src/mocks/calcService.ts: Removed any type assertions
    • shared/components/src/MapView/MapView.tsx: Removed eslint-disable comment for any usage
    • shared/components/src/MapView/__fixtures__/exerciseAlpha.ts: Removed eslint-disable comment
  • Added type annotations to Python functions:

    • services/cli/debrief_cli/tools.py: Added -> None return type to tools() function
    • services/cli/debrief_cli/output.py: Added -> None return type to __init__() method
  • Updated apps/web-shell/src/services/toolService.ts: Replaced as any cast with as unknown as ToolExecuteFn and added ToolExecuteFn type definition

  • Updated shared/schemas/scripts/generate.py: Added post-processing to replace dict[str, Any] with dict[str, object] in generated Pydantic boilerplate

Constitutional & Documentation

  • Updated CONSTITUTION.md with Article XV mandating strict type safety with 6 specific mandates
  • Updated .specify/memory/constitution.md to sync Article XV
  • Updated CLAUDE.md to document pyright as an active technology
  • Added comprehensive specification documents in specs/098-strict-type-checking/:
    • spec.md: Feature specification with user stories and acceptance criteria
    • plan.md: Implementation plan with technical context
    • research.md: Research decisions (pyright selection, TypeScript state)
    • quickstart.md: Developer workflow guide

https://claude.ai/code/session_0126Hrb5x1dQKCZ2UdkJsjSj

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Feb 18, 2026

🚀 Preview Deployments

Code Server (Full VS Code Extension)

🖥️ Open Code Server

Browser-based VS Code with the Debrief extension and sample data pre-installed.

Web Shell (Standalone App)

📱 Open Web Shell

Use this for Playwright testing and demos - runs outside Storybook.

Storybook (Component Library)

📚 Open Storybook

Browse all components, stories, and documentation.


All Links
Environment Code Server Web Shell Storybook
This PR Open IDE Open App Open Storybook
Main branch Open App Open Storybook

Updated on commit 93c9a1c

Specify strict type safety across Python and TypeScript domains:
- Feature spec with 5 user stories covering local dev, CI, constitution,
  codebase remediation, and cross-language schema consistency
- Add Article XV to CONSTITUTION.md mandating strict types, prohibiting
  Any/any, and requiring CI enforcement
- Quality checklist passes all validation items

https://claude.ai/code/session_0126Hrb5x1dQKCZ2UdkJsjSj
Address the pattern where tool parameters use generic
Record<string, unknown> instead of per-tool typed interfaces
(~24 occurrences across the codebase). Generic dictionaries
defeat static analysis and are treated as equivalent to `any`.

https://claude.ai/code/session_0126Hrb5x1dQKCZ2UdkJsjSj
Tool parameters should reference existing concrete type declarations
from the schema/type system, not create bespoke per-tool interfaces.

https://claude.ai/code/session_0126Hrb5x1dQKCZ2UdkJsjSj
Phase 0: research.md — pyright over mypy, ESLint gap analysis, schema
  generator audit, CI pipeline design, ruff rule additions
Phase 1: plan.md, data-model.md, quickstart.md, contracts (pyright,
  ESLint, ruff, CI pipeline)
Phase 2: planning post and LinkedIn summary

https://claude.ai/code/session_0126Hrb5x1dQKCZ2UdkJsjSj
80 tasks across 8 phases:
- Phase 1: Setup (pyright, ruff ANN/TC rules)
- Phase 2: Foundation (ESLint consistency across 8 TS packages)
- Phase 3: Constitution verification (Article XV)
- Phase 4: Developer workflow verification
- Phase 5: Schema generation post-processing
- Phase 6: Codebase remediation (~208 violations across 49 files)
- Phase 7: CI pipeline enforcement
- Phase 8: Polish, evidence collection, media, PR

https://claude.ai/code/session_0126Hrb5x1dQKCZ2UdkJsjSj
- Add pyright 1.1+ to dev dependencies (standard mode, 132 baseline errors)
- Create pyrightconfig.json covering all Python packages
- Add ANN (annotation presence) and TC (type-checking imports) to ruff
- Ignore deprecated ANN101/ANN102 (self/cls for Python 3.11+)
- Ruff ANN baseline: 1063 violations

https://claude.ai/code/session_0126Hrb5x1dQKCZ2UdkJsjSj
- apps/vscode: add no-explicit-any: error
- apps/loader: add no-explicit-any: error
- shared/components: promote no-explicit-any from off to error,
  remove blanket test file override
- apps/web-shell: add strict: true to tsconfig.node.json,
  add typecheck script

https://claude.ai/code/session_0126Hrb5x1dQKCZ2UdkJsjSj
- Add Article XV to .specify/memory/constitution.md cache
- Post-process gen-pydantic output: replace dict[str, Any] with
  dict[str, object] in boilerplate classes (ConfiguredBaseModel, LinkMLMeta)
- Remove unused Any import from generated Python

https://claude.ai/code/session_0126Hrb5x1dQKCZ2UdkJsjSj
- Add task typecheck to Taskfile.yml (uv run pyright + pnpm -r typecheck)
- Add type checking step to ci.yml between lint and test

https://claude.ai/code/session_0126Hrb5x1dQKCZ2UdkJsjSj
…hase 6b

Replace `any` with proper typed interfaces across VS Code tests, shared
components, web-shell services, and session-state tests. All 1177 tests
pass (571 components + 291 vscode + 572 session-state + others).

https://claude.ai/code/session_0126Hrb5x1dQKCZ2UdkJsjSj
… Phase 6a

Python: add return type annotations to CLI commands, replace Any with
object in output.py where safe, add JSON-serializable comments to
legitimate Any fields. Pyright stays at 132 errors (no regressions).

TypeScript: improve toolService.ts type safety with asToolFn wrapper.

https://claude.ai/code/session_0126Hrb5x1dQKCZ2UdkJsjSj
…hase 8

- Fix last 2 no-explicit-any in useTreeState.test.ts (0 remaining)
- Create evidence: test-summary.md, usage-example.md, violation-inventory.md,
  pyright-output.txt, eslint-output.txt
- Create media: shipped-post.md, linkedin-shipped.md
- Mark all 80 tasks complete in tasks.md

https://claude.ai/code/session_0126Hrb5x1dQKCZ2UdkJsjSj
@IanMayo IanMayo force-pushed the claude/strict-type-checking-WoO58 branch from f8e3db7 to f60b625 Compare February 27, 2026 10:07
claude and others added 6 commits February 27, 2026 11:27
- Add return type annotations (-> None, -> specific types) to all
  public functions, test methods, and pytest fixtures (ANN201/ANN202)
- Add parameter type annotations to all function arguments including
  pytest fixture parameters (ANN001/ANN002/ANN003)
- Add -> None to all __init__ methods (ANN204)
- Move imports into TYPE_CHECKING blocks where safe (TC003/TC005)
- Keep Callable at runtime in models.py (Pydantic needs it)
- Use ParamSpec/TypeVar for typed decorator wrapper in registry.py
- Replace Any with object/specific types where ANN401 flagged
- Remove unused imports/vars in TS test files (ESLint no-unused-vars)
- All 869 Python tests pass, all TS tests pass, 0 lint errors

https://claude.ai/code/session_0126Hrb5x1dQKCZ2UdkJsjSj
- mcp/server.py: use TYPE_CHECKING imports for conditional MCP SDK
- provenance.py: use Pydantic alias names in LogEntry/WasGeneratedBy constructors
- registry.py: use setattr for dynamic tool attribute on wrapper function
- test_exceptions.py: correct Never→None return type
- test_executor.py: add assert narrowing for Optional fields
- test_models.py: use Pydantic aliases + Optional narrowing + type: ignore for
  intentional validation error tests
- test_buffer_zone_generator.py: explicit sensor_model param, float tuples, Any return
- cli/tools.py: add assert for result.error + type: ignore for recursive coords
- config/core.py: use Pydantic alias lastAccessed
- config/storage.py: Callable[[Config], Config] instead of lowercase callable
- test_decorators.py: getattr for dynamic __tool_spec__ attribute
- symbols.py: guard None line_style before dict.get()
- test_coordinates.py, test_timestamps.py: assert not None before unpacking
- test_client.py: type: ignore for unresolvable debrief_session import
- stac catalog.py, conftest.py, test_catalog.py: use datetime alias for PlotMetadata
- test_coverage.py: type: ignore for intentional bad input test
- test_stac_validation.py: assert stac_validator not None before usage

pyright: 0 errors, 0 warnings | ruff: all checks passed | pytest: 869 passed

https://claude.ai/code/session_0126Hrb5x1dQKCZ2UdkJsjSj
26 findings from static analysis comparing CONSTITUTION.md,
ARCHITECTURE.md, and TOOL-RESULTS.md against actual implementation.
1 blocking, 7 significant, 7 minor, 11 informational.
…acement

- getState.ts: add drawingPaletteIndex to SpatialSlice, styleVersion to
  FeaturesSlice to match updated type definitions
- test_decorators.py: move noqa: B009 comments after == comparison
  (were incorrectly placed before, turning comparisons into comments)

https://claude.ai/code/session_0126Hrb5x1dQKCZ2UdkJsjSj
@IanMayo IanMayo temporarily deployed to debrief-preview-pr-270 February 27, 2026 12:13 Inactive
Promote F-1.5 (provenance) and F-2.2 (kind values) to blocking.
Reclassify F-3.3, F-5.2 as drift. Promote F-2.4, F-2.6, F-5.1.
Defer F-4.1 pending results strategy. Add disposition notes throughout.
@IanMayo IanMayo temporarily deployed to debrief-preview-pr-270 February 27, 2026 12:30 Inactive
@IanMayo IanMayo merged commit dbc1160 into main Feb 27, 2026
12 checks passed
@IanMayo IanMayo deleted the claude/strict-type-checking-WoO58 branch February 27, 2026 12:38
github-actions Bot pushed a commit that referenced this pull request Feb 27, 2026
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.

2 participants