Releases: agentfirstkit/agent-first-mail
Releases · agentfirstkit/agent-first-mail
Release list
v0.11.0
- Settle each review item the moment a person decides it, so closing the window ends the session instead of discarding unsettled work, and re-read the terminal result from the workspace afterwards — a process killed mid-session loses nothing already settled
- Drop the session-level submitted/cancelled/dismissed vocabulary and the Deferred outcome, add Decided for a disposition the agent never proposed, and check the three outcome invariants right after deserialization instead of leaving each writer to remember them
- Move stale-suggestion detection from a whole-session gate to a per-item flag, so one item whose message has moved on no longer refuses to open the rest of the queue
- Open a draft's attachments through one primitive that checks the directory and the file separately, refuses non-regular files before any open, and compares the opened handle's identity with what was checked — a symlink under files/ can no longer be read, hashed and attached while the push plan shows a harmless case-relative path
- Switch review delivery to AFUI's window|link|session and delete afmail's own LAN implementation and discovery, keeping the one-shot fifteen-minute link expiry and review_ready carrying review_url
- Render the real page in doctor, one render per surface, so a frontend called healthy cannot still fail the escaping policy, rendered-markup guard and element contract that only the serving side applied
- Declare the four review hooks a page cannot render without and check them before a window opens, leaving the other twenty-one undeclared because they belong to surfaces that legitimately lack them
- Put the review page's routing, session channel and unload guard on AFUI's page kernel, keeping only what is afmail's: which update ends a turn, flushing dirty editors before a send, and selection clamping
- Stop drawing a second head inside a framed session — the page hides its brand and saving line and sends up only what a frame cannot know, keeping the local-workspace pill
- Bound triage review with no message ids to the current queue newest-first and say in the result whether any were left out, instead of implying every current suggestion is included
- Pin the IMAP push contract with a recording test server, and pin the per-file locale overlay so a frontend overriding one template still gets the rest of the active language pack rather than falling back to English
- Stop quoting values from credential-bearing arguments in error events, and run the local container gates on Apple's container runtime as well as Docker
- Upgrade Agent-First Data to 0.34.0, Agent-First UI to 0.5.0 and Agent-First Slug to 0.7.1
v0.10.0
- Move the human review window onto agent-first-ui: afmail's own TcpListener loop, request parser, urlencoded decoder, Chromium launcher, and profile guard are deleted, and the single action= form path becomes typed routes
- Give each review surface its own ui_kind (triage_review, case_review, notification_review, draft_review) so replacing one frontend cannot silently replace the other three
- Replace Review UI template overrides under workspace templates/ with AFUI frontends at .afui/frontends/afmail/<ui_kind>/, declared against Review UI API version 1, with per-file fallback to the built-in localized pack; content templates stay in the workspace tree
- Report a LAN review plan that lapses unopened as outcome expired instead of dismissed, and record cancel as a completed decision, so a caller can tell 'nobody was there' from 'someone declined to answer'
- Extend afmail doctor to smoke-render the Review UI that would actually serve each surface, reporting a broken or unloadable user frontend as its own issue rather than failing every other check
- Collapse imap.password_secret_env and smtp.password_secret_env into imap.password_secret and smtp.password_secret, which now take the AFDATA source grammar (the value, env:NAME, file:PATH#DOT_PATH, literal:VALUE); stream sources are refused in config and afmail's credential-naming rule still applies to env sources
- Accept the same source grammar for afmail api serve --access-token-secret
- Upgrade agent-first-data to 0.32.1 and agent-first-ui to 0.3.1
v0.9.0
- Compile the entire CLI from a closed-world registry of 106 commands and 140 legal argument shapes, replacing hand-written conflict rules, error-hint tables and raw-argv scanning with shapes the binary can enumerate
- Require arguments to follow their command — there are no global flags before it — and remove -h along with every short flag
- Make --log a repeatable closed enum, so --log a,b becomes --log a --log b
- Replace the suggestion set sub-subcommands with an --action argument whose operands are named flags, so a triage, case or notification suggestion is one flat shape
- Require --confirm on doctor repair as an argument shape rather than rejecting it as a business error
- Make --help list every legal argument combination of that command at once, and --docs render the whole reference
- Derive a message's identity from its raw RFC822 bytes instead of its Message-ID, so byte-identical copies converge on one record and a reused Message-ID no longer collides two unrelated mails
- Refund the --max-new-messages and byte budget spent on cross-mailbox duplicates, and report candidate_count_is_upper_bound from pull --dry-run since recognizing a duplicate needs the body a dry run never fetches
- Abort a push step with the new imap_uidvalidity_changed error before issuing any STORE or MOVE against stale UIDs
- Detect a UIDVALIDITY reset during pull, discard the stale cursor, force a full reconcile, and report uid_validity_reset_count and the affected mailboxes
- Move every remaining location of a multi-location message instead of skipping the whole move when one copy already sits in the target, and persist flag state after each location so a later failure keeps earlier progress
- Reject conflicting per-mailbox archive steps with the new archive_action_conflict error as a preflight, before any notification or case write lands locally
- Allocate a random opaque push id per draft-send lifecycle so re-sending a draft records new sent evidence instead of overwriting the earlier one
- Stop escalating failures that provably preceded any remote call into the manual-reconciliation push_remote_outcome_unknown state
- Support Bcc recipients — kept in the local draft, Review UI, push preview and the sender's private evidence, stripped from SMTP DATA, retained in the SMTP envelope
- Stop re-rendering hand-edited contact and draft files from their structs; a frontmatter edit now moves only the keys whose values changed, preserving comments, key order, quote styles and body, including through contact rename
- Report retryable: false on a partial push --confirm envelope, since exit 3 is never permission to retry a batch; per-item retryable inside failures remains the field that says what to re-queue
- Stop printing "***" from config show for a secret that was never set, which had disagreed with config get and implied a credential was configured
- Install the skill's bundled references/http-api.md alongside SKILL.md, which skill install had been dropping while SKILL.md pointed at it
- Exit 0 on a broken pipe such as --docs | head, matching the AFDATA emitter
- Document exit codes 3 and 4, the cli_invocation_invalid and output_setup_failed defect codes, the byte-exact identity model, and the fact that push ids are opaque
- Relock onto agent-first-data 0.31.0 and agent-first-slug 0.6.2, and cover every declared shape with a synthetic-invocation test that fails when a builder arm reads an argument id its shape cannot supply
v0.8.0
- Add blocking local and LAN review sessions for triage, cases, notifications, and drafts, returning one typed human decision that never authorizes a remote push.
- Render generated Markdown, new scaffolds, and review HTML from one MiniJinja template system over typed render documents, with editable overrides and nine built-in language packs.
- Expose the domain through a typed OpenAPI 3.2 HTTP API with committed, drift-tested contract and JSON Schema artifacts.
- Add afmail demo: a loopback mock IMAP/SMTP server and seeded workspace that exercises the real pull, review, and confirmed push paths.
- Gate the demo, api, and review surfaces behind cargo features, leaving an excluded command discoverable and returning a structured feature_disabled error.
- Send replies before message moves within a push plan, so a reply is never stranded by a move that ran ahead of it.
- Route protocol events with --output-to: finite commands split result from diagnostics, review and serve commands keep one ordered stream on stdout, and the -V short flag is gone.
- Resolve config domain rules in one document path, fixing a cleared optional field falling back to a non-null default and config add identities failing on a fresh workspace.
- Upgrade to agent-first-data 0.26.2 and agent-first-slug 0.5.0.
v0.7.1
- Restore numeric rendering in generated Markdown: attachment byte sizes and message and attachment counts print as numbers again, not an arbitrary-precision wrapper object, after the afdata dependency enabled that globally.
- Rework config editing to change .afmail/config.json in place through afdata's DocumentFile — validate the whole config before writing, commit atomically, and preserve on-disk key order — replacing the hand-written sparse-diff writer.
- Migrate onto afdata 0.20, which absorbed the retired agent-first-config, adopting its redesigned config, document, version, and help APIs.
- Bump the agent-first-slug dependency to 0.3.0.
v0.7.0
- Adopt afdata protocol v1 end-to-end: commands emit typed, structured command results with flattened error fields via a semantic CLI emitter, replacing serialized output bags
- Add request-idempotency across every state-changing command via a global --request-id key that records and replays outcomes so retries are deduplicated (message dispositions, case lifecycle, draft edits, contact edits/renames, membership, notes, summaries, local deletes, field edits)
- Bind remote effects to reviewed plans: push and purge require a reviewed plan id before any remote effect runs, and case-archive lifecycle finalizes only after a successful push
- Support explicit workspace selection via --workspace with a stable workspace identity, and make onboarding readiness an explicit reported state in afmail status
- Harden untrusted-mail and privacy boundaries: bound IMAP body fetches by default, enforce render boundaries on untrusted content, and redact private startup argv shape and runtime log fields
- Make network failures recoverable by marking IMAP connect and SMTP remote failures retryable with explicit retry phases and reason-required safe recovery
- Add incremental pull with persisted cursors, plus mailbox pull budgeting via --max-new-messages and --max-total-bytes and pre-pull size estimation via --dry-run
- Report workspace storage usage in bytes through afmail status and surface partial command outcomes
- Make draft intent and content states explicit with separate lifecycle states, add a draft list command, and rename draft save to upload
- Add batch operations and message list filters: batch message dispositions, batch case and notification additions requiring ids, require --group for case move, require contact reasons, and add case set-summary
- Redesign the AFUI mail workspace to safely render full case conversations including archived views, load web packs, and show timezone-aware rendered times
- Optimize the render pipeline, reorganize the workspace state directory layout, and order the push queue by persisted enqueue sequence
v0.6.0
- Add notification delete command to remove an empty notification collection, with --allow-notes to permit deletion when user-authored notes are present
- Split message restore into message unspam and message untrash with semantics specific to each disposition, queuing the appropriate remote move when needed
- Replace contact archive/reopen lifecycle with a single contact delete command; remove case reopen in favor of case delete for empty active cases; add case remove to extract one message back to triage
- Collapse the archive top-level subcommand into case — archived case list, show, restore, remove, and move are now available directly under case
- Add case move support for archived cases, enabling reordering within the archive without requiring a full restore-and-re-archive cycle
- Fall back to COPY+EXPUNGE when the IMAP server does not advertise the MOVE capability, requiring UIDPLUS for precise single-message targeting
- Centralize all on-disk workspace directory names into a single layout module, eliminating scattered string literals across the codebase
- Integrate afdata stream file redirection, allowing stdout/stderr to be redirected to a file via CLI args before any output is written
v0.5.0
- Rename the standalone direct-message archive model to notification collections: file reference and notification mail with 'afmail notification create/add' under stable nYYYYMMDDNNN uids and read it via 'afmail notification list/show', leaving the archive command to mean archived cases only
- Require an explicit case category on 'afmail case create --group' with no default and no 'open' catch-all, and nest archived cases under archive/cases// so the category survives archival
- Block attachment fetches on spam-classified messages so an agent cannot be lured into pulling hostile payloads from mail it already flagged as spam
- Queue remote trash for every mailbox a case's messages occupy, including Sent, so already-sent replies move to trash with the rest of the conversation when a case is discarded
- Surface a structured audit_warnings entry when a confirmed push effect's audit record cannot be written, instead of silently dropping the lost record
- Add index.md read views to the spam, trash, and deleted folders, and change the notification message-index default fields from sender to from
- Make identity config setup idempotent, fix push incremental refresh, fix restore push cleanup and reply recipients, surface the contact command in CLI error hints, and upgrade dependencies
v0.4.0
- Add fully localized render-template packs for Traditional Chinese, German, Spanish, French, Japanese, Korean, and Brazilian Portuguese, selected by workspace.language_bcp47
- Move every human-language string out of the Rust code into the per-language template packs, so labels, headings, and disposition titles are translated in the templates and adding a language is just dropping a directory
- Replace the hand-coded config dispatch with agent-first-config dot-path traversal, and add a prune command, imap-archive origin provenance, attachment MIME-type detection, and pending-push counts in status and triage output
- Add archive case trash and restore commands
- Show the full product name in --help headings and generated docs while keeping the short afmail binary name in usage strings
- Resolve mailbox import rules in configured order and parse nonstandard message date headers
- Speed up the pull render cache and report render sub-stage progress
- Harden outbound push safety, support sparse config, and unify identity-config slug validation
- Upgrade the IMAP client and other dependencies
v0.3.0
- Add afmail contact subcommand for managing contact cards with CRUD operations, per-group organisation, email/phone fields, tags, archival, and extracting contacts from message senders; email addresses are globally unique across all contacts
- Materialise sender contact links directly onto message views, refreshed automatically when a contact's emails or name change
- Add identity registry: workspaces define named send personas in config with optional identities/.md footer notes; draft commands accept --identity SLUG and write footers into the draft body for review before push
- Fix skill install to add each installed skill directory to the workspace .gitignore managed block, covering both .codex/ and .claude/ agent paths without duplication
- Fix interrupted-transaction sentinel preservation so retried commands correctly detect and recover from previously-failed transactions
- Roll back newly-created case and archive directories automatically if any step in the create command fails, preventing orphan directories in the workspace
- Validate related-message constraint in archive message create before creating any files, and document in the skill that messages with related_message_ids must be grouped into a case