Hiro development journal

Making reading state durable and self-sent mail mandatory

Published Machine-readable JSON

Executive summary

The Gmail productivity rules were refined again: Important remains the normal outer gate, while email sent from the owner to the owner is an explicit exception that must always become exactly one task or reading item.

Unread is now an intake condition rather than a retention condition. Important-and-Unread conversations are captured into the reading list, but later Gmail read-state changes no longer remove them.

The reading interface now uses explicit Mark read and Mark unread actions. A captured item retains its source, summary, tags, and audit history while its Hiro reading status changes.

Hiro reconciled historical self-sent mail from the last thirty days. An aggregate exclusivity check found sixty-three self-sent sources: fifty-three linked to tasks, ten linked to reading items, zero linked to both, and zero linked to neither.

The complete live background scan remained bounded and resilient. It reviewed 146 newly eligible conversation versions and continued past seven isolated classification failures.

Work completed

Eligibility model

Completed
  • Replaced the single Important-only search with a server-built Gmail scope representing Important OR owner-to-owner self-sent mail, followed by the user date and spam and trash constraints.
  • Resolved the mailbox owner address through the Gmail profile and detected self-sent messages only when Gmail marks the message Sent and the owner address appears in both From and To.
  • Each fetched conversation now records Important, Important-and-Unread, self-sent, and overall processing eligibility as separate machine facts.
  • Non-important mail remains excluded unless it satisfies the exact self-sent exception.

Mandatory self-sent classification

Completed
  • Added self_sent to the structured local-Qwen input and instructed the model that self-sent mail may never be ignored.
  • Added a deterministic fallback: if bounded and individual model attempts cannot decide, a self-sent conversation with links becomes reading and one without links becomes a task.
  • Removed the former requirement that reading mail contain an external article URL because the email conversation itself is the reading object.
  • Added historical reconciliation for self-sent conversations already recorded as ignored. Explicitly deleted task or reading records remain respected and are not recreated.
  • Important-and-Unread synchronization skips a self-sent source already represented by a task, preserving exactly-one semantics.

Durable reading state

Completed
  • Stopped background jobs from removing captured reading items merely because Gmail later loses the Unread label.
  • Important-and-Unread remains the intake feed for ordinary reading capture.
  • Reading items link back to their Gmail conversation and keep their existing status during subsequent synchronization.
  • Renamed the reading completion state to Read and added Mark read and Mark unread controls in the task-page interface.

Live reconciliation and runtime

Completed
  • Restarted Hiro with the revised query, record metadata, background phases, and reading controls.
  • Validated the combined Gmail query with read-only Gmail count requests before starting reconciliation.
  • Ran one complete server-owned background job. The primary phase reviewed 146 conversation versions; historical self-sent reconciliation added thirty-four tasks and eight reading items beyond outcomes already created in the primary phase.
  • The captured Important-and-Unread phase ensured forty intake items and reported one tagging fallback after bounded retries.
  • Verified the private remote page serves the self-sent explanation plus Mark read and Mark unread controls.

Decisions and reasoning

Validation and evidence

CheckStatusResult
Focused automated regression suite passed Twenty-one tests passed, covering self-sent detection, mandatory non-ignore behavior, historical ignored-source conversion, Important-or-self query construction, persistent reading state, Important-and-Unread intake, Read and Unread UI syntax, removal learning, reconciliation, bounded Qwen batches, dates, tags, persistence, jobs, and API behavior.
Read-only Gmail query validation passed Important, self-sent, and combined thirty-day Gmail queries all returned bounded result metadata without changing mailbox state.
Complete live background job passed with isolated errors The job reviewed 146 newly eligible conversation versions in thirteen safe retrieval batches. It analyzed 139, created eighty-seven task outcomes and five reading outcomes in the primary phase, ignored forty-seven eligible non-self conversations, and reported seven isolated failures without stopping.
Historical self-sent reconciliation passed The reconciliation phase created thirty-four tasks and eight reading items with zero self-sent classification failures.
Self-sent exclusivity audit passed Sixty-three self-sent source records were active: fifty-three had a task, ten had a reading item, zero had both, and zero had neither.
Reading intake state passed Important-and-Unread synchronization ensured forty captured intake conversations. The full reading list contained fifty-three items after adding self-sent reading outcomes, all in Review before owner action.
Private remote interface passed The private remote task page returned status 200 and contained the self-sent rule, Mark read, and Mark unread controls.
Task-page JavaScript syntax passed The embedded task-page script parsed successfully after the reading-state and status-reporting changes.
Public journal unit tests passed npm run test:hiro passed the timestamped-entry unit tests.
Public journal production build passed npm run build generated and validated 54 journal pages, then completed the TypeScript and Vite production build.

Current state

Next steps