Skip to content

chore: Release v0.32.0#1011

Merged
arockwell merged 14 commits intomainfrom
release/v0.32.0
Mar 7, 2026
Merged

chore: Release v0.32.0#1011
arockwell merged 14 commits intomainfrom
release/v0.32.0

Conversation

@arockwell
Copy link
Owner

Release v0.32.0

arockwell and others added 14 commits March 7, 2026 01:15
…o (Issue #ARCH-24)

Introduce a proper Document domain object (@DataClass) that replaces the
scattered TypedDict projections (DocumentRow, DocumentListItem,
RecentDocumentItem, DeletedDocumentItem, ChildDocumentItem,
SupersedeCandidate) with a single type constructed via factory methods.

Phase 1 — Document dataclass (emdx/models/document.py):
- @DataClass(slots=True) with all 15 document fields
- from_row() / from_partial_row() factories with datetime parsing
- __getitem__ / .get() / keys() / items() dict-compat layer
  so all 158 existing bracket-access sites keep working
- to_dict() with datetime→ISO serialization for JSON output
- 31 unit tests covering construction, parsing, compat, serialization

Phase 1b — SearchHit dataclass (emdx/models/search.py):
- Wraps Document + snippet + rank for search results
- Same dict-compat interface with field fallthrough

Phase 2 — Wire into database layer:
- database/documents.py: all functions return Document instead of
  TypedDict casts. Removed _parse_doc_datetimes() (absorbed into
  Document.from_row())
- database/search.py: returns list[SearchHit] instead of
  list[SearchResult]
- database/__init__.py: SQLiteDatabase methods updated to return
  Document / SearchHit
- commands/context.py: switched from DocumentRow to Document

25 cast() calls eliminated. 2068 tests passing, zero breakage.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…CH-24)

Phase 3 of the data model refactor — migrate bracket access to attribute
access across 10 consumer files and 9 test files.

Converted files:
- commands/core.py (43 sites — display_save_result, view, edit, delete,
  _find_all, _find_recent, _view_review, _print_view_header_*)
- commands/context.py, history.py, tags.py, tasks.py, wiki.py, gist.py,
  briefing.py, trash.py
- ui/activity/activity_data.py

Updated test mocks to return Document objects instead of raw dicts:
- test_commands_core.py, test_commands_tags.py, test_commands_trash.py,
  test_gist.py, test_v028_regressions.py, test_activity_doc_type.py,
  test_activity_view.py, test_task_commands.py, test_view_review.py

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…y (Issue #ARCH-24)

Phase 4 — remove DocumentRow, DocumentListItem, RecentDocumentItem,
DeletedDocumentItem, ChildDocumentItem, SupersedeCandidate, and
SearchResult from database/types.py. All replaced by the Document
dataclass and SearchHit in emdx/models/.

Remaining types in database/types.py are non-document structures:
MostViewedDoc, DatabaseStats, DocumentLinkDetail, WikiArticleTimingDict,
StandingQueryRow, StandingQueryMatch.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…(Issue #ARCH-24)

- Create emdx/models/task.py with Task and TaskLogEntry dataclasses
- Factory methods from_row()/from_partial_row() with datetime parsing
- Dict-compat layer (__getitem__, .get()) for incremental migration
- Wire into models/tasks.py: all functions return Task/TaskLogEntry
- Migrate consumers: commands/tasks.py, ui/task_view.py type annotations
- Fix mypy errors: switch 3 bracket accesses to attribute access
- Remove TaskDict, EpicTaskDict, EpicViewDict, TaskLogEntryDict from types.py
- Update test factories to use Task.from_row()

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…at needed)

Tests mock get_task() with raw dicts, so attribute access like
task.epic_key breaks. Restore bracket access via dict-compat layer
until test mocks are migrated to Task objects.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…e #ARCH-24)

Script-converted 102 mock return values from raw dicts to
Task.from_row()/TaskLogEntry.from_row() so attribute access works
on mock return values. Enables removing dict-compat layer later.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…H-24)

Remove __getitem__/.get()/keys()/items()/values()/__contains__ from
Document, SearchHit, Task, and TaskLogEntry dataclasses. Convert all
~220 bracket access sites across 26 files to attribute access.

Add Category dataclass replacing CategoryDict/CategoryWithStatsDict
TypedDicts. Wire into categories.py, commands, and tests.

Net -217 lines removed. All 2076 tests pass.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…H-24)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…(Issue #ARCH-24)

serve.py used dict(doc)/dict(task) which fails without dict-compat.
core.py had one remaining dict(r) on search results.
Test mocks in test_serve.py, test_commands_core.py, and
test_v028_regressions.py still returned raw dicts instead of
SearchHit/Document/Task objects.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…uplicated SQL (Issue #ARCH-30)

SQLiteDatabase had two modes: global (delegate to canonical functions)
and isolated (self-contained SQL for test databases). The isolated
mode duplicated ~300 lines of SQL that had drifted from the real
implementations (missing filters, FK cleanup, version snapshotting).

Now SQLiteDatabase always delegates to the global functions.
Test isolation is handled by the conftest fixture that swaps the
db_connection singleton. The _conn() staticmethod uses dynamic
import lookup so test fixture swaps are visible at call time.

Rewrote test_sqlite_database.py to use the conftest fixture instead
of creating isolated SQLiteDatabase(db_path) instances.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…RCH-30)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@arockwell arockwell merged commit f4d5e0d into main Mar 7, 2026
5 checks passed
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.

1 participant