refactor(api,lazarus): separate index tag mutations from Maildir moves #71

Merged
clanker merged 4 commits from pr/clean-maildir-api into main 2026-09-04 07:30:50 +00:00
Member

Overview

Refactors the mutation architecture to separate pure index tag mutations from Maildir filesystem moves across batch, thread, and message operations. Eliminates regex and string-sniffing heuristics in favor of explicit targets.

Changes

1. NED domain service

  • Added _build_target_query in ned/service.py to route explicit queries, threads, messages, and legacy ids sequences without sniffing strings or guessing entity types.
  • Refactored modify_tags to use _build_target_query.
  • Added trash, restore, and archive_local accepting explicit queries, threads, messages, and legacy ids with an optional unmark flag.
  • Retained trash_thread, untrash_thread, archive_thread, and unarchive_thread as non-sniffing compatibility bridges.

2. NED API routes

  • Added batch Maildir move endpoints: POST /api/v1/trash, POST /api/v1/restore, and POST /api/v1/move-archive.
  • Added single thread endpoints: POST /api/v1/threads/{id}/trash, POST /api/v1/threads/{id}/restore, and POST /api/v1/threads/{id}/move-archive.
  • Added single message endpoints: POST /api/v1/messages/{id}/trash, POST /api/v1/messages/{id}/restore, and POST /api/v1/messages/{id}/move-archive with optional thread_id query parameter for cache invalidation.
  • Retained legacy /threads/{id}/archive, /threads/archive, and /threads/trash paths as aliases.

3. NED client library

  • Added explicit thread methods: trash_thread, restore_thread, archive_thread_to_local.
  • Added explicit message methods: trash_message, restore_message, archive_message_to_local.
  • Added explicit batch methods: trash_batch, restore_batch, archive_batch_to_local with unmark flag support.

4. Lazarus desktop client

  • Updated lazarus/actions.py: delete_thread, restore_thread_from_trash, and archive_to_local use batch methods with unmark=True when marked threads exist, and explicit single thread methods otherwise.
  • Updated lazarus/thread.py: archive_message_to_local and delete_message use explicit message methods and verify boolean status.
  • Updated lazarus/search.py and lazarus/thread_model.py: wrapped user search queries in parentheses when joining with AND to prevent Notmuch operator precedence conflicts.

5. Documentation and schema

  • Updated agent.md and docs/api.md with the new endpoint specification and architecture details.
  • Updated ned/openapi.py with canonical route descriptions and path schemas.

6. Test suite

  • Added test_service_maildir_move_actions and test_ned_maildir_move_endpoints in tests/test_ned.py.
  • Updated tests/test_ned_client.py, tests/test_desktop_client.py, and tests/conftest.py.
  • Full test suite passes: 435 tests passing.
## Overview Refactors the mutation architecture to separate pure index tag mutations from Maildir filesystem moves across batch, thread, and message operations. Eliminates regex and string-sniffing heuristics in favor of explicit targets. ## Changes ### 1. NED domain service - Added _build_target_query in ned/service.py to route explicit queries, threads, messages, and legacy ids sequences without sniffing strings or guessing entity types. - Refactored modify_tags to use _build_target_query. - Added trash, restore, and archive_local accepting explicit queries, threads, messages, and legacy ids with an optional unmark flag. - Retained trash_thread, untrash_thread, archive_thread, and unarchive_thread as non-sniffing compatibility bridges. ### 2. NED API routes - Added batch Maildir move endpoints: POST /api/v1/trash, POST /api/v1/restore, and POST /api/v1/move-archive. - Added single thread endpoints: POST /api/v1/threads/{id}/trash, POST /api/v1/threads/{id}/restore, and POST /api/v1/threads/{id}/move-archive. - Added single message endpoints: POST /api/v1/messages/{id}/trash, POST /api/v1/messages/{id}/restore, and POST /api/v1/messages/{id}/move-archive with optional thread_id query parameter for cache invalidation. - Retained legacy /threads/{id}/archive, /threads/archive, and /threads/trash paths as aliases. ### 3. NED client library - Added explicit thread methods: trash_thread, restore_thread, archive_thread_to_local. - Added explicit message methods: trash_message, restore_message, archive_message_to_local. - Added explicit batch methods: trash_batch, restore_batch, archive_batch_to_local with unmark flag support. ### 4. Lazarus desktop client - Updated lazarus/actions.py: delete_thread, restore_thread_from_trash, and archive_to_local use batch methods with unmark=True when marked threads exist, and explicit single thread methods otherwise. - Updated lazarus/thread.py: archive_message_to_local and delete_message use explicit message methods and verify boolean status. - Updated lazarus/search.py and lazarus/thread_model.py: wrapped user search queries in parentheses when joining with AND to prevent Notmuch operator precedence conflicts. ### 5. Documentation and schema - Updated agent.md and docs/api.md with the new endpoint specification and architecture details. - Updated ned/openapi.py with canonical route descriptions and path schemas. ### 6. Test suite - Added test_service_maildir_move_actions and test_ned_maildir_move_endpoints in tests/test_ned.py. - Updated tests/test_ned_client.py, tests/test_desktop_client.py, and tests/conftest.py. - Full test suite passes: 435 tests passing.
Separate mutation operations into pure index tag mutations and Maildir
filesystem moves across batch, thread, and message scopes.

- Eliminate string guessing and sniffing in ned.service by using explicit
  queries, threads, and messages targets in _build_target_query.
- Add Maildir move endpoints: /trash, /restore, and /move-archive for
  batch operations (with optional unmark flag) as well as dedicated
  single thread and single message variants.
- Update NedClient with explicit trash, restore, and archive methods
  for single threads, single messages, and batches.
- Update Lazarus desktop actions in actions.py and thread.py to dispatch
  explicit batch moves with unmark=True when marked threads exist and
  single-entity methods otherwise.
- Wrap user queries in parentheses in SearchModel and ThreadModel to
  prevent precedence bugs when joining with AND.
- Update agent.md, docs/api.md, and ned/openapi.py documentation.
- Add test coverage for new endpoints and client methods.
Prevent batch moves from finding zero files when tag expressions strip
query tags like inbox and marked:

- Collect files matching target queries before modifying tags in
  move_to_trash, move_to_archive, and restore_from_trash.
- Remove premature tag modifications in ned.service trash, restore, and
  archive_local.
- Add fallback stem resolution in _resolve_stale_path ignoring mbsync
  UID annotations so files moving between new and cur with ,U=
  annotations are tracked accurately.
- Skip files already in trash_dir inside plan_trash_moves.
- Pass explicit in-memory marked thread IDs from SearchPanel when
  performing batch operations in desktop client.
- Add regression tests covering UID annotation changes and pre-tag file
  collection.
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
Home/lazarus!71
No description provided.