@bobfrankston/rmfmail 1.2.143 → 1.2.145

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/TODO.md CHANGED
@@ -99,13 +99,14 @@ Everything AI-shaped collected here so Bob can think about it on its own terms,
99
99
  |---|---|
100
100
  | **Q103-AI** ❓ | **Rules / extensions engine shape (C39).** Parked 2026-04-23 while Bob experiments with imail. Revisit once imail findings settle. Candidate shapes when it's time: declarative JSONC rules (`if from: foo then move to bar`), TypeScript plugins under `~/.mailx/extensions/`, AI-classified categories (newsletter / priority / action-required), or a hybrid. |
101
101
  | **Q111-AI** ❓ | **Writing assistance.** LanguageTool (API or self-hosted), custom AI via the existing ghost-text path (Ollama / Claude / OpenAI), in-WebView2 native spellcheck only (current), or something else? |
102
- | **Q113-AI** ❓ | **AI-flavored per-message metadata.** The schema shape in Q113 above directly affects where AI-assigned priority / categories / summaries live. If Q113 lands on a separate `message_meta` table the AI tags have a natural home; if it's a JSON column on `messages`, the AI writer mutates the same row. |
102
+ | **Q113-AI** ❓ | **AI-flavored per-message metadata.** The schema shape in Q113 above directly affects where AI-assigned priority / categories / summaries live. If Q113 lands on a separate `message_meta` table the AI tags have a natural home; if it's a JSON column on `messages`, the AI writer mutates the same row. *Update 2026-07-16: C155 answers the cross-app half — categories/signals live ON the message as IMAP keywords with a shared registry; Q113's table-vs-column question now only covers rmfmail-internal rich residue.* |
103
103
 
104
104
  ### AI — Backlog
105
105
 
106
106
  | # | Status | Item |
107
107
  |---|---|---|
108
- | [**C39**](#ext39) ❓ | PARKED | Rules / extensions engine + AI classification. See Q103-AI. |
108
+ | **C155** ❓ | DRAFT | **Annotation registry + imail companion annotator** [M]. Companion app annotates each letter *before* sorting. Two-layer design (2026-07-16 discussion): data plane = IMAP keywords on the message itself (core RFC 3501, portable — Gmail labels / Graph categories are the same concept per provider); vocabulary plane = one shared `annotations.jsonc` registry with MCP-tool-style entries (`description`/`whenToApply` prompt the AI annotator, `sortAction` drives the sorter, `label` feeds UIs). No shared DB needed — IMAP STORE is the concurrency layer; rich residue (dates, summaries) stays out or comes back later as a service-owned sidecar. Design note: `docs/annotation-registry.md`; starter vocabulary: `docs/annotations.jsonc`. Awaiting Bob's think-through — open questions at the end of the design note. Subsumes the cross-app half of Q113/Q113-AI; feeds Q103-AI/C39/P19 (rules engine shape). |
109
+ | [**C39**](#ext39) ❓ | PARKED | Rules / extensions engine + AI classification. See Q103-AI, C155. |
109
110
  | [**P19**](#priority-daily) ❓ | OPEN | Screener — imail rules + AI classifier. Elevated under daily-driver; same classifier question as C39. |
110
111
  | **AI-writing** ❓ | OPEN | Proofread / rewrite / tone-adjust in compose. Currently a Settings toggle that's off; needs the shape from Q111-AI before wiring. |
111
112
  | **AI-extract-contact** | OPEN | Right-click an email → Add contact auto-fills Name / Organization / Phone from the letter body. "In the future" per user 2026-04-23. Depends on a working AI back-end choice from Q111-AI. |
@@ -8181,12 +8181,13 @@ var NativeImapClient = class {
8181
8181
  }
8182
8182
  const allMessages = [];
8183
8183
  let chunkSize = this.fetchChunkSize;
8184
- for (let i = 0; i < uids.length; i += chunkSize) {
8184
+ for (let i = 0; i < uids.length; ) {
8185
8185
  const chunk = uids.slice(i, i + chunkSize);
8186
8186
  const msgs = await this.fetchMessages(chunk.join(","), options);
8187
8187
  allMessages.push(...msgs);
8188
8188
  if (onChunk)
8189
8189
  onChunk(msgs);
8190
+ i += chunk.length;
8190
8191
  if (chunkSize < this.fetchChunkSizeMax)
8191
8192
  chunkSize = Math.min(chunkSize * 4, this.fetchChunkSizeMax);
8192
8193
  }
@@ -8208,7 +8209,7 @@ var NativeImapClient = class {
8208
8209
  const allMessages = [];
8209
8210
  let chunkSize = this.fetchChunkSize;
8210
8211
  let chunkIndex = 0;
8211
- for (let i = 0; i < uids.length; i += chunkSize) {
8212
+ for (let i = 0; i < uids.length; ) {
8212
8213
  const chunk = uids.slice(i, i + chunkSize);
8213
8214
  const msgs = await this.fetchMessages(chunk.join(","), options);
8214
8215
  allMessages.push(...msgs);
@@ -8218,6 +8219,7 @@ var NativeImapClient = class {
8218
8219
  }
8219
8220
  if (onChunk)
8220
8221
  onChunk(msgs);
8222
+ i += chunk.length;
8221
8223
  if (chunkSize < this.fetchChunkSizeMax)
8222
8224
  chunkSize = Math.min(chunkSize * 4, this.fetchChunkSizeMax);
8223
8225
  }