Skip to content

Typed accessor methods for raw dict keys #90

Description

@bradjin8

Problem

cppa-cursor-browser has a well-structured models/ layer with 7 frozen @dataclass declarations (Composer, Bubble, Workspace, ExportEntry, CliSessionMeta, WorkspaceLocalComposer, ParseWarning), each with validated from_dict classmethods backed by models/from_dict_validation.py. Type annotations exist on function signatures, [tool.mypy] is configured in pyproject.toml, and CI runs mypy alongside pytest. Despite this typed boundary at the read-from-SQLite edge, the service layer passes data onward as untyped dict[str, Any] through pervasive .get() chains: services/workspace_tabs.py has 79 .get() calls, services/workspace_resolver.py has 31, services/workspace_listing.py has 20, and services/cli_tabs.py has 15 — totalling 149 .get() calls across the service layer alone. API routes add another 39 (api/search.py) and scripts/export.py adds 25. The typed @dataclass models validate data at the read boundary but the validated fields are not carried through the service pipeline — instead, code immediately drops back into raw dict access (e.g., cd.get("fullConversationHeadersOnly"), bubble.get("relevantFiles"), ctx.get("projectLayouts")). When Cursor's weekly schema changes rename a key, the from_dict validator catches it at the model boundary, but the 149+ downstream .get() calls silently return None. The gap is not "no types exist" but "types stop at models/ and don't flow through services/."

Acceptance Criteria

  • Typed accessor methods for top 10 most-accessed raw dict keys in the service layer
  • Accessors log a WARNING when expected key is missing (drift detection)
  • Type annotations that mypy can verify end-to-end from model to service output
  • Existing callers in services/workspace_tabs.py and services/workspace_resolver.py migrated to use typed accessors
  • Tests covering drift detection logging

Implementation Notes

  • Audit the 149 .get() calls in the service layer to identify the top 10 most-accessed keys
  • Pattern: @property methods on the existing model @dataclass classes returning Optional[T] with _logger.warning() on missing keys
  • Brad's PR Extract shared from_dict validation helpers for model classes (#70) #80 (from_dict helpers) and models/from_dict_validation.py provide the validation foundation
  • services/workspace_tabs.py (79 .get() calls, 605 LOC) is the highest-value target

References

  • models/conversation.pyComposer, Bubble, WorkspaceLocalComposer dataclasses with from_dict
  • models/from_dict_validation.py — shared validation helpers
  • services/workspace_tabs.py — 79 .get() calls (primary migration target)
  • services/workspace_resolver.py — 31 .get() calls

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions