Skip to content

Adds Agent Mail - #10276

Open
PascalSenn wants to merge 26 commits into
mainfrom
pse/add-agent-mail-to-nitro
Open

Adds Agent Mail#10276
PascalSenn wants to merge 26 commits into
mainfrom
pse/add-agent-mail-to-nitro

Conversation

@PascalSenn

Copy link
Copy Markdown
Member

No description provided.

Adds the SQLite-backed mail store (workspace, schema, IMailStore/MailStore,
MailActor, MailAgentName) mirroring the tasks foundation exactly: same
connection handling, WAL/foreign_keys pragmas, transaction style, and
PRAGMA user_version init/check. Wires IMailStore into DI next to ITaskStore.

No commands yet (perles-net-mail-epic-90n.1); downstream beads build on
this contract.
… agents)

Implements perles-net-mail-epic-90n.2: the nitro agent mail CLI entry
points that mirror the Commands/Tasks conventions, backed by the
IMailStore foundation from 90n.1. Register the mail command group under
`nitro agent mail` and wire the new result DTOs into the AOT JSON
source-generation context.
…t-mail-epic-90n.3)

Adds nitro agent mail send/reply/broadcast as thin wrappers over
IMailStore.SendMessageAsync/ReplyMessageAsync, with --body/--body-file
mutual exclusion enforced at parse time, first-occurrence recipient
ordering, and a shared MailMessageResult JSON DTO. Registers the new
subcommands under nitro agent mail and extends JsonSourceGenerationContext
for their JSON output, following the pattern already used by init/register/
whoami/agents.
Builds the mail board's model/mode layer against the complete IMailStore
contract with fakes, mirroring how the task board's model was built
against ITaskStore before its commands existed (perles-net-mail-epic-90n.7,
started early per the orchestrator's parallelization ruling).

Adds MailState/MailDataLoader (inbox filter cycling: inbox/unread/archived,
thread loading), MailMode (ITuiMode: list + detail panes, focus toggling,
thread view toggle), MailMessageBadge/MailDetailView (rendering), and
MailKeyMap (a standalone key table for the mail command's own dispatcher).
Read-only: no gesture marks a message read or writes to the store. One
additive ThemeTokens entry (mail.message.unread).

Entry command registration, Commands/Mail/, and Services/Mail/ are out of
scope here (commands lane is building those concurrently; entry wiring is
deferred to .8 per the bead comment).
Implements perles-net-mail-epic-90n.4: list, read, acknowledge, and
archive mail messages for the acting agent, mirroring the Commands/Tasks
conventions established by the earlier mail identity and send beads.
Adds `nitro agent mail threads` (conversation-level rollup with
participants, message count, unread count, last activity) and
`nitro agent mail search <text>` (case-insensitive subject/body search,
reusing the inbox row rendering and DTO). Both include archived
messages and honor --limit/--actor per epic conventions.
Adds `nitro agent mail watch`, a poll loop that reconciles the acting
agent's inbox against a baseline captured at start, once per second via
the injected TimeProvider. Prints newly arrived unread messages, oldest
first, using the same rendering as `read` in human mode and the read
DTO in JSON mode. Never marks anything read. An optional --timeout
exits with an error and a stderr-only message when it elapses with no
new mail; without it, watch waits until cancelled.
SearchAsync only LIKE-matched subject and body, not the sender agent
name, though the bead prose requires sender matching. Extend the LIKE
predicate to also cover m.sender, reusing the existing escaped text
and ESCAPE clause.
SearchMailCommand's description still said "subject and body" only,
but the underlying query has matched sender since 4dd2e12.
…ply) + board entry command

Wires read/unread toggle, archive (behind a confirmation), reply, and
compose into the mail board (u/a/r/c), every write going through the
same IMailStore members the CLI uses. Opening a message in the detail
pane marks it read. Compose and reply build on the Form engine with a
shared discard confirmation on Esc when dirty.

MailMode owns its own overlays (archive confirmation, compose/reply
forms, discard confirmation) rather than adding task-specific fields
to TuiShell; TuiShell gets one small additive raw-key routing check
mirroring the existing SearchMode precedent.

Fixes the case-sensitive actor match in MailRecipientView.FindRecipient
(OrdinalIgnoreCase) per .7's binding follow-up, and adds a real
MailStore-backed test file for the recipient/reply semantics
FakeMailStore cannot independently prove.

Registers 'nitro agent mail board' in MailCommand.

perles-net-mail-epic-90n.8
Adds three representative nitro agent mail flows to the e2e VHS tier
(mail-send, mail-error, mail-board), the seeded mailbox fixture
mail-board-flow runs against, and a Mail_Init_Register_Send_Inbox_Round_Trips
smoke test, so the mail CLI gets the same real-binary/real-PTY coverage the
task CLI already has.
…-agent-unify-814.1)

Adds AgentWorkspace/AgentDatabase under Services/Workspace as the shared
discovery, schema composition, and version-stamping layer for tasks and
mail: one .nitro/agents/ directory, one agents.db, one PRAGMA user_version
(2), one transaction for DDL + stamp. TaskStore and MailStore now resolve
their workspace and connections through AgentDatabase instead of forking
their own OpenAsync/version logic; TaskWorkspace.cs and MailWorkspace.cs
are deleted. The old init commands (agent tasks init, agent mail init)
still exist and now build the unified layout, matching this bead's
boundary. "No task/mail workspace found" collapses into one "No agent
workspace found. Run `nitro agent init` first." message.
Extends TuiShell with a tabbed-hosting constructor that owns an ordered
list of TuiTab instances: each tab keeps its own navigation stack and
KeyDispatcher, so switching tabs preserves nested mode state and routes
keys only to the active tab's key table. A one-row tab strip renders
above the content region whenever more than one tab is hosted, tab
switching uses [ and ], and it stays inert while any shell-level or
mode-level overlay is capturing input. The shell-level task overlay
machinery (editor, lifecycle dialogs, pickers, create form) now gates on
which tab owns it. A DataChangedEvent refreshes every hosted tab's active
mode, not only the active one.

Generalizes the mail-mode raw-key-capturing check from a concrete
MailMode type check to a new IRawKeyCapturingMode interface, and wires
its overlay hints into the footer (previously never shown while a mail
overlay was open). Adds MailMode.UnreadCount, refreshed alongside its
other state, for a hosting tab's unread badge.

The existing single-mode constructor is preserved unchanged for
BoardTaskCommand and BoardMailCommand: it wraps its one mode in a single
TuiTab, so the tab strip never renders and behavior is identical.

Scoped per the orchestrator's early-start narrowing on bd-agent-unify-814.3:
tab mechanics only, hosted with fakes; no TaskDbWatcher rename, no entry-
command wiring.
Console.ReadKey on Linux never populates ConsoleKey.Oem4/Oem6 for '['
and ']' (verified with a pty probe: KEY=None(0) CHAR='['/']'), so the
exact-chord equality check in TabSwitchKeys.Resolve always failed and
tab switching was dead outside chords that also set ConsoleKey. Resolve
now matches on KeyChar with no modifiers, mirroring KeyMap's printable-
char fallback, which still covers the Oem4/Oem6-carrying chords used in
existing tests.
…t init (bd-agent-unify-814.2)

Adds InitAgentCommand under agent init: builds the unified .nitro/agents
workspace (agents.db, tasks.jsonl, selective .gitignore) directly, and
migrates a legacy pre-unification workspace when found: a legacy
.nitro/tasks/tasks.db is attach-copied table by table (tasks,
dependencies, labels, comments, events, config, child_counters), a legacy
or already-committed tasks.jsonl is imported through the existing
sync-import merge semantics, and a legacy .nitro/mail/mail.db is reported
obsolete and left untouched by ruling. Prefix precedence is explicit
--prefix, then migrated config, then the directory name. --force reapplies
schema and prefix in place without touching tasks.jsonl. A failed init
parses any source jsonl before creating anything and deletes a
freshly-created agents.db on any later failure, so the command is
retryable and legacy files are never written to.

agent tasks init and agent mail init are removed, not aliased, along with
their now-unused options. The seven remaining "No task/mail workspace
found" command-level messages (SyncTaskCommand x3, BoardTaskCommand,
WhereTaskCommand, DoctorTaskCommand, BoardMailCommand) collapse to "No
agent workspace found. Run `nitro agent init` first." DoctorTaskCommand
also warns on leftover legacy .nitro/tasks and .nitro/mail directories.

JsonSourceGenerationContext swaps TaskWorkspaceInitResult and
MailWorkspaceInitResult for AgentWorkspaceInitResult, and
CommandLine.Smoke.Tests retargets its init-based smoke tests to the new
command.
Adds AlreadyInitialized_Force_PreservesSeededTaskAndMailRows, which was
claimed as covered by bd-agent-unify-814.2's comment but did not exist.
AgentCommand now carries its own action alongside its subcommands: an
interactive terminal with a resolved agent workspace opens the unified
tabbed TUI (tasks + mail) via the new AgentTuiLauncher, starting on the
tasks tab; a non-interactive terminal, or no workspace found, prints
exactly the guidance a bare group with no action prints today (locked
in, since it already lists init/tasks/mail).

Also, from the .3 review notes now due:
- TuiShell's tabbed ctor throws ArgumentOutOfRangeException for an
  out-of-range tasksTabIndex instead of silently clamping it.
- HandleDataChanged no longer routes an inactive tab's own refresh
  follow-ups through the active tab's mode (a latent cross-tab leak).
- TaskDbWatcher is renamed to SqliteDbWatcher, now shared by both the
  bare-agent launcher and the single-tab board commands.
- TuiShellTabsTests gained a ConsoleKey.None shell-level tab-switch
  case (the Linux Console.ReadKey shape), matching TabSwitchKeysTests.
An invalid NITRO_MAIL_ACTOR (or its NITRO_TASK_ACTOR fallback) no longer
prevents the tabbed agent shell from opening. AgentTuiLauncher catches
the ExitException from MailActor.Resolve and hosts the Mail tab with a
new MailUnavailableMode instead: a static "Mail" label, no unread
polling, and the resolution failure rendered with a hint to set
NITRO_MAIL_ACTOR. The Tasks tab and its actor resolution are unaffected.

Deferred from bd-agent-unify-814.3 (fix item 2) to .4.
Sweeps the e2e VHS tier onto the unified .nitro/agents/agents.db workspace
and the tabbed TUI (bd-agent-unify-814.5): init-flow now drives the unified
`nitro agent init`, mail-send/mail-error init the same way, and one shared
fixture (seed.sql + mail-seed.sql applied to the same agents.db, guarded by
PRAGMA user_version 2 plus a task and a mail query) replaces the old
two-fixture layout. board, board-maximize, detail, and mail-board launch via
bare `nitro agent` so the tab strip renders; board and mail-board each
demonstrate a `[`/`]` tab switch. Adds agent-root-flow, driving bare
`nitro agent` into the tabbed TUI and quitting.

search-flow stays on the single-tab `agent tasks board` entry point: typing
a query while the Mail tab is hosted races a Mail-tab refresh loop that
resets SearchMode's own debounced query and never lets it apply, filed as
bd-agent-unify-814.7 (out of this bead's e2e-only scope; see the
NEEDS-PASCAL comment on bd-agent-unify-814.5).

Fixes the one remaining stale `agent tasks init` spelling in the AOT smoke
job of nitro-cli-e2e.yml.
…unify-814.7)

Every store connection opens without pooling and closes after a single
query. In WAL mode that makes SQLite create, checkpoint, and delete the
-wal and -shm siblings on close even for a plain read, which
SqliteDbWatcher's FileSystemWatcher saw as a data change and re-fired on,
200ms later, forever. In the tabbed nitro agent TUI the Mail tab's own
RefreshRequested read kept retriggering itself on every DataChangedEvent,
racing out SearchMode's debounced query reset on the Tasks tab so a typed
search query never applied.

SqliteDbWatcher now watches only the main database file; its mtime moves
only when a write actually lands, not on a read-triggered
checkpoint-of-nothing. Added regression tests proving read-shaped -wal/-shm
churn alone stays silent while a real write amid that same churn still
fires.

Re-recorded search-flow.tape via bare 'nitro agent' (tab strip on screen)
now that the narrowing search demo passes; fixed two stale .5-era tape
comments (detail-flow.tape's mis-attributed cross-reference, list-flow.tape's
pre-unification db path).
RefreshRequested used to reset the pending debounced query to the
last applied one, discarding a not-yet-applied edit and its timer
whenever an external write (e.g. another agent creating a task while
the user types) triggered a refresh. TickAsync now re-runs the last
applied query for display on a refresh without touching a pending,
not-yet-due edit, so the user's typed text and debounce timer survive.

Bead: bd-n6k
…-g3b)

The watcher previously fired only off the main db file's mtime, which
moves via SQLite's PASSIVE close-time checkpoint. That checkpoint is
silently skipped when another connection holds a read lock (a
concurrent TUI reader or a second nitro process), so a real write can
leave frames appended in -wal with no event, leaving the TUI stale
until a later write checkpoints or the user presses r.

Now also key on -wal size growth: a size increase past its last
observed size fires a change, while a plain read's own create and
delete of -wal (which never grows past that baseline) stays silent,
same as before. The -shm sibling stays fully ignored.

Adds deterministic tests for the growth case, including one shaped
like a cross-process writer whose checkpoint is blocked by a
concurrent reader (main db untouched, -wal grows and stays grown).
…t-unify-814.8)

Moves the agents table and its CRUD out of mail into a shared
IAgentRegistry in the Workspace layer, adds role and implicit columns
with an idempotent v2-to-v3 upgrade path, and re-routes register/whoami/
list from `nitro agent mail` to `nitro agent` directly. IMailStore drops
its agent CRUD and now consumes IAgentRegistry, including for the
auto-register-on-send/reply path.
…-role (bd-agent-unify-814.9)

Sending mail to an unknown recipient no longer hard-fails: SendMessageAsync
implicit-creates the recipient's agent row via a new
IAgentRegistry.EnsureImplicitAsync and reports every still-unregistered
recipient back through MailMessage.Unregistered, so an orchestrator can mail
a worker it is about to spawn. The send command prints a warning line per
unregistered recipient and its JSON output (a new MailSendResult DTO, kept
separate from the shared MailMessageResult so reply and broadcast are
unaffected) carries the unregistered list. Broadcast now excludes implicit
rows from "everyone" and gains --role to target only registered agents with
that role.
…er + send policy (bd-agent-unify-814.10)

.8 moved agent register/whoami/list to the nitro agent root (removing the old
mail register/whoami/agents spellings) and .9 changed mail send/broadcast so
an unregistered recipient now succeeds with a "note: has never registered."
warning instead of a hard error. Re-record via run.sh --update to bring the
mail-send-flow and mail-error-flow tapes, goldens, and gifs back in sync:
mail-send-flow now registers both actors via the root command (one with
--role, to demonstrate the read command's "From: name (role)" header) and
mail-error-flow reshapes its hard-fail scene around an INVALID recipient
name (agent-name normalization rejection), the one remaining error case on
send. Also bumps run.sh's FIXTURE_SCHEMA_VERSION guard from 2 to 3 to match
AgentDatabase.CurrentVersion after .8's role/implicit columns landed; without
it the fixture-prep step fails before any flow can record.

Full ./run.sh (all 16 flows) passes with exit 0 twice.
Copilot AI lite review requested due to automatic review settings August 21, 2026 11:38

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR introduces an agent mail feature to the Nitro CLI and unifies local workspace state under a single agent workspace (.nitro/agents/agents.db). It also adds a tabbed TUI launched by bare nitro agent, hosting both Tasks and Mail, and updates the e2e tapes/tests to cover the new behavior.

Changes:

  • Add mail CLI + TUI (send/reply/inbox/threads/search/board) backed by a unified SQLite schema.
  • Unify initialization/workspace plumbing (nitro agent init) and add an agent registry (register/whoami/list) shared by tasks + mail.
  • Improve TUI refresh behavior (new SQLite watcher semantics + SearchMode refresh/debounce interaction) and expand test coverage + e2e tapes.

Reviewed changes

Copilot reviewed 189 out of 205 changed files in this pull request and generated 10 comments.

Show a summary per file
File Description
src/Nitro/CommandLine/test/e2e/search-flow.tape Update search tape to bare nitro agent
src/Nitro/CommandLine/test/e2e/search-flow.golden.txt Golden updated for tab strip/footer
src/Nitro/CommandLine/test/e2e/README.md Document expanded e2e flow set
src/Nitro/CommandLine/test/e2e/mail-send-flow.tape New live mail send/reply tape
src/Nitro/CommandLine/test/e2e/mail-send-flow.golden.txt Golden for mail send/reply flow
src/Nitro/CommandLine/test/e2e/mail-error-flow.tape New invalid-recipient failure tape
src/Nitro/CommandLine/test/e2e/mail-error-flow.golden.txt Golden for invalid-recipient error
src/Nitro/CommandLine/test/e2e/mail-board-flow.tape New Mail tab TUI tape
src/Nitro/CommandLine/test/e2e/mail-board-flow.golden.txt Golden for Mail tab board
src/Nitro/CommandLine/test/e2e/list-flow.tape Update workspace path reference
src/Nitro/CommandLine/test/e2e/init-flow.tape Switch to nitro agent init
src/Nitro/CommandLine/test/e2e/init-flow.golden.txt Golden for unified init output
src/Nitro/CommandLine/test/e2e/fixtures/seed.sql Seed tasks into unified agents.db
src/Nitro/CommandLine/test/e2e/fixtures/mail-seed.sql New deterministic mail seed fixture
src/Nitro/CommandLine/test/e2e/detail-flow.tape Detail tape updated for tabbed TUI
src/Nitro/CommandLine/test/e2e/detail-flow.golden.txt Golden updated for tab strip
src/Nitro/CommandLine/test/e2e/board-maximize-flow.tape Launch maximize flow via bare nitro agent
src/Nitro/CommandLine/test/e2e/board-maximize-flow.golden.txt Golden updated for tab hints/strip
src/Nitro/CommandLine/test/e2e/board-flow.tape Launch board via bare nitro agent + tab switch
src/Nitro/CommandLine/test/e2e/board-flow.golden.txt Golden updated for tab strip/footer
src/Nitro/CommandLine/test/e2e/agent-root-flow.tape New tape proving bare nitro agent mount/quit
src/Nitro/CommandLine/test/e2e/agent-root-flow.golden.txt Golden for agent-root flow
src/Nitro/CommandLine/test/CommandLine.Tests/Tui/Shell/TuiTabTests.cs New unit tests for tab mode stack
src/Nitro/CommandLine/test/CommandLine.Tests/Tui/Shell/TabSwitchKeysTests.cs New tests for [/] tab switching
src/Nitro/CommandLine/test/CommandLine.Tests/Tui/Search/SearchModeTests.cs Add tests for refresh vs debounce behavior
src/Nitro/CommandLine/test/CommandLine.Tests/Tui/Mail/MailRecipientViewTests.cs New tests for per-recipient read/archive logic
src/Nitro/CommandLine/test/CommandLine.Tests/Tui/Mail/MailMessageBuilder.cs New mail test helper builder
src/Nitro/CommandLine/test/CommandLine.Tests/Tui/Mail/MailMessageBadgeTests.cs New tests for list-row rendering
src/Nitro/CommandLine/test/CommandLine.Tests/Tui/Mail/MailDetailViewTests.cs New tests for detail/thread rendering
src/Nitro/CommandLine/test/CommandLine.Tests/Tui/Mail/MailDataLoaderTests.cs New tests for inbox/thread loading
src/Nitro/CommandLine/test/CommandLine.Tests/Tui/Mail/MailAgesTests.cs New tests for relative/absolute age labels
src/Nitro/CommandLine/test/CommandLine.Tests/Services/Workspace/TestFileSystem.cs New test filesystem helper (agents)
src/Nitro/CommandLine/test/CommandLine.Tests/Services/Mail/TestFileSystem.cs New test filesystem helper (mail)
src/Nitro/CommandLine/test/CommandLine.Tests/Services/Mail/MailAgentNameTests.cs New tests for agent name normalization
src/Nitro/CommandLine/test/CommandLine.Tests/Commands/Tasks/WhereTaskCommandTests.cs Update error message for unified init
src/Nitro/CommandLine/test/CommandLine.Tests/Commands/Tasks/TaskStoreTests.cs TaskStore tests updated for AgentDatabase/workspace
src/Nitro/CommandLine/test/CommandLine.Tests/Commands/Tasks/TasksCommandTestBase.cs Use AgentWorkspace + agent init
src/Nitro/CommandLine/test/CommandLine.Tests/Commands/Tasks/SyncTaskCommandTests.cs Update paths + init behavior expectations
src/Nitro/CommandLine/test/CommandLine.Tests/Commands/Tasks/StatusTaskEpicCommandTests.cs Update unified init guidance
src/Nitro/CommandLine/test/CommandLine.Tests/Commands/Tasks/StatsTaskCommandTests.cs Update unified init guidance
src/Nitro/CommandLine/test/CommandLine.Tests/Commands/Tasks/SetTaskConfigCommandTests.cs Update unified init guidance
src/Nitro/CommandLine/test/CommandLine.Tests/Commands/Tasks/ReadyTaskCommandTests.cs Update unified init guidance
src/Nitro/CommandLine/test/CommandLine.Tests/Commands/Tasks/ListTaskConfigCommandTests.cs Update unified init guidance
src/Nitro/CommandLine/test/CommandLine.Tests/Commands/Tasks/InitTaskCommandTests.cs Remove legacy agent tasks init tests
src/Nitro/CommandLine/test/CommandLine.Tests/Commands/Tasks/GetTaskConfigCommandTests.cs Update unified init guidance
src/Nitro/CommandLine/test/CommandLine.Tests/Commands/Tasks/DoctorTaskCommandTests.cs Add warning coverage for legacy dirs
src/Nitro/CommandLine/test/CommandLine.Tests/Commands/Tasks/CloseEligibleTaskEpicCommandTests.cs Update unified init guidance
src/Nitro/CommandLine/test/CommandLine.Tests/Commands/Tasks/BoardTaskCommandTests.cs Update unified init guidance
src/Nitro/CommandLine/test/CommandLine.Tests/Commands/Tasks/BlockedTaskCommandTests.cs Update unified init guidance
src/Nitro/CommandLine/test/CommandLine.Tests/Commands/Mail/MailCommandTestBase.cs New base for mail command tests
src/Nitro/CommandLine/test/CommandLine.Tests/Commands/Mail/MailActorTests.cs New tests for actor resolution precedence
src/Nitro/CommandLine/test/CommandLine.Tests/Commands/Mail/BoardMailCommandTests.cs Tests for mail board command behavior
src/Nitro/CommandLine/test/CommandLine.Tests/Commands/Agent/WhoamiAgentCommandTests.cs New whoami command tests
src/Nitro/CommandLine/test/CommandLine.Tests/Commands/Agent/AgentCommandTestBase.cs New base for agent registry tests
src/Nitro/CommandLine/test/CommandLine.Tests/CommandExecutionResultExtensions.cs Add assertion helper for bare group guidance
src/Nitro/CommandLine/test/CommandLine.Smoke.Tests/SmokeTests.cs Smoke coverage for mail round-trip
src/Nitro/CommandLine/src/CommandLine/Tui/Theming/ThemeTokens.cs Add theme token for unread mail styling
src/Nitro/CommandLine/src/CommandLine/Tui/Shell/TuiTab.cs New tab abstraction for mode stacks
src/Nitro/CommandLine/src/CommandLine/Tui/Shell/TabSwitchKeys.cs New [/] tab switching resolution
src/Nitro/CommandLine/src/CommandLine/Tui/Shell/IRawKeyCapturingMode.cs New interface for raw-key overlays
src/Nitro/CommandLine/src/CommandLine/Tui/Search/SearchMode.cs Refresh handling adjusted to preserve edits
src/Nitro/CommandLine/src/CommandLine/Tui/Runtime/TaskDbWatcher.cs Remove legacy DB watcher
src/Nitro/CommandLine/src/CommandLine/Tui/Mail/MailViewMode.cs New enum for message vs thread view
src/Nitro/CommandLine/src/CommandLine/Tui/Mail/MailUnavailableMode.cs New mode for invalid actor resolution
src/Nitro/CommandLine/src/CommandLine/Tui/Mail/MailReplyForm.cs New reply form widget
src/Nitro/CommandLine/src/CommandLine/Tui/Mail/MailRecipientView.cs Recipient read/archive helpers
src/Nitro/CommandLine/src/CommandLine/Tui/Mail/MailMessageBadge.cs Render mail list rows (markup)
src/Nitro/CommandLine/src/CommandLine/Tui/Mail/MailListFilter.cs New inbox filter enum
src/Nitro/CommandLine/src/CommandLine/Tui/Mail/MailFocus.cs New focus enum (list/detail)
src/Nitro/CommandLine/src/CommandLine/Tui/Mail/MailDataLoader.cs Data loader translating UI filters to store
src/Nitro/CommandLine/src/CommandLine/Tui/Mail/MailAges.cs Shared age formatting for mail list
src/Nitro/CommandLine/src/CommandLine/Tui/Input/TuiMessage.cs Add mail-related TUI messages
src/Nitro/CommandLine/src/CommandLine/Tui/Board/BoardDataLoader.cs Adjust deferred/blocked column filtering
src/Nitro/CommandLine/src/CommandLine/Services/Workspace/IAgentRegistry.cs New shared agent registry contract
src/Nitro/CommandLine/src/CommandLine/Services/Workspace/AgentWorkspace.cs Define unified .nitro/agents layout
src/Nitro/CommandLine/src/CommandLine/Services/Workspace/AgentRole.cs Normalize agent role values
src/Nitro/CommandLine/src/CommandLine/Services/Workspace/AgentRegistrySchema.cs Schema for agents table
src/Nitro/CommandLine/src/CommandLine/Services/Workspace/AgentRecord.cs Agent record model
src/Nitro/CommandLine/src/CommandLine/Services/Tasks/TaskStoreSchema.cs Remove legacy version constant
src/Nitro/CommandLine/src/CommandLine/Services/Tasks/TaskStore.cs Use AgentDatabase + AgentWorkspace
src/Nitro/CommandLine/src/CommandLine/Services/Results/JsonSourceGenerationContext.cs Add JSON result types for agent/mail
src/Nitro/CommandLine/src/CommandLine/Services/Mail/MailThreadSummary.cs Thread summary model
src/Nitro/CommandLine/src/CommandLine/Services/Mail/MailStoreSchema.cs Mail tables schema
src/Nitro/CommandLine/src/CommandLine/Services/Mail/MailRecipientKinds.cs Recipient kind constants
src/Nitro/CommandLine/src/CommandLine/Services/Mail/MailRecipient.cs Recipient record model
src/Nitro/CommandLine/src/CommandLine/Services/Mail/MailMessageCreation.cs Send parameters model
src/Nitro/CommandLine/src/CommandLine/Services/Mail/MailMessage.cs Mail message model
src/Nitro/CommandLine/src/CommandLine/Services/Mail/MailInboxFilter.cs Inbox query filter model
src/Nitro/CommandLine/src/CommandLine/Services/Mail/MailAgentName.cs Normalize/validate mail agent names
src/Nitro/CommandLine/src/CommandLine/Services/Mail/MailActor.cs Resolve actor identity for mail
src/Nitro/CommandLine/src/CommandLine/Extensions/ServiceCollectionExtensions.cs Register AgentDatabase/registry/mail store
src/Nitro/CommandLine/src/CommandLine/Commands/Tasks/WhereTaskCommand.cs Update unified init error guidance
src/Nitro/CommandLine/src/CommandLine/Commands/Tasks/TasksCommand.cs Remove legacy tasks init subcommand
src/Nitro/CommandLine/src/CommandLine/Commands/Tasks/SetTaskConfigCommand.cs Use AgentWorkspace prefix normalization
src/Nitro/CommandLine/src/CommandLine/Commands/Tasks/Options/TaskPrefixOption.cs Remove legacy tasks init option
src/Nitro/CommandLine/src/CommandLine/Commands/Tasks/Options/ForceReinitializeOption.cs Remove legacy tasks init option
src/Nitro/CommandLine/src/CommandLine/Commands/Tasks/InitTaskCommand.cs Remove legacy agent tasks init command
src/Nitro/CommandLine/src/CommandLine/Commands/Tasks/DoctorTaskCommand.cs Warn on leftover legacy workspace dirs
src/Nitro/CommandLine/src/CommandLine/Commands/Tasks/BoardTaskCommand.cs Use unified workspace + new DB watcher
src/Nitro/CommandLine/src/CommandLine/Commands/Mail/ThreadsMailCommand.cs New threads listing command
src/Nitro/CommandLine/src/CommandLine/Commands/Mail/SendMailCommand.cs New send command
src/Nitro/CommandLine/src/CommandLine/Commands/Mail/SearchMailCommand.cs New search command
src/Nitro/CommandLine/src/CommandLine/Commands/Mail/ReplyMailCommand.cs New reply command
src/Nitro/CommandLine/src/CommandLine/Commands/Mail/Options/MailUnreadOption.cs Add --unread filter option
src/Nitro/CommandLine/src/CommandLine/Commands/Mail/Options/MailTimeoutOption.cs Add --timeout option validation
src/Nitro/CommandLine/src/CommandLine/Commands/Mail/Options/MailThreadOption.cs Add --thread option
src/Nitro/CommandLine/src/CommandLine/Commands/Mail/Options/MailSubjectOption.cs Add required --subject option
src/Nitro/CommandLine/src/CommandLine/Commands/Mail/Options/MailSinceOption.cs Add RFC3339 --since parsing
src/Nitro/CommandLine/src/CommandLine/Commands/Mail/Options/MailSearchTextArgument.cs Add search text argument
src/Nitro/CommandLine/src/CommandLine/Commands/Mail/Options/MailRecipientsArgument.cs Add recipients argument
src/Nitro/CommandLine/src/CommandLine/Commands/Mail/Options/MailMessageIdsArgument.cs Add message-ids argument
src/Nitro/CommandLine/src/CommandLine/Commands/Mail/Options/MailMessageIdArgument.cs Add message-id argument
src/Nitro/CommandLine/src/CommandLine/Commands/Mail/Options/MailLimitOption.cs Add --limit option validation
src/Nitro/CommandLine/src/CommandLine/Commands/Mail/Options/MailFromOption.cs Add --from filter option
src/Nitro/CommandLine/src/CommandLine/Commands/Mail/Options/MailCcOption.cs Add repeatable --cc option
src/Nitro/CommandLine/src/CommandLine/Commands/Mail/Options/MailBodyOption.cs Add --body option
src/Nitro/CommandLine/src/CommandLine/Commands/Mail/Options/MailBodyFileOption.cs Add --body-file option
src/Nitro/CommandLine/src/CommandLine/Commands/Mail/Options/MailAllOption.cs Add --all (include archived) option
src/Nitro/CommandLine/src/CommandLine/Commands/Mail/Options/MailActorOption.cs Add --actor option
src/Nitro/CommandLine/src/CommandLine/Commands/Mail/MailThreadRowResult.cs JSON row type for threads
src/Nitro/CommandLine/src/CommandLine/Commands/Mail/MailThreadRow.cs Human-readable threads row formatting
src/Nitro/CommandLine/src/CommandLine/Commands/Mail/MailSendResult.cs JSON result for send (incl. unregistered)
src/Nitro/CommandLine/src/CommandLine/Commands/Mail/MailMessageResult.cs JSON result for message core fields
src/Nitro/CommandLine/src/CommandLine/Commands/Mail/MailMessageDetailResult.cs JSON result for read output
src/Nitro/CommandLine/src/CommandLine/Commands/Mail/MailInboxRowResult.cs JSON row type for inbox
src/Nitro/CommandLine/src/CommandLine/Commands/Mail/MailInboxRow.cs Human-readable inbox row formatting
src/Nitro/CommandLine/src/CommandLine/Commands/Mail/MailIdsResult.cs JSON result for batch mutations
src/Nitro/CommandLine/src/CommandLine/Commands/Mail/MailCommand.cs Add agent mail command group
src/Nitro/CommandLine/src/CommandLine/Commands/Mail/MailBody.cs Shared body resolution/validation
src/Nitro/CommandLine/src/CommandLine/Commands/Mail/InboxMailCommand.cs New inbox command
src/Nitro/CommandLine/src/CommandLine/Commands/Mail/BroadcastMailCommand.cs New broadcast command
src/Nitro/CommandLine/src/CommandLine/Commands/Mail/BoardMailCommand.cs New interactive mail board entry
src/Nitro/CommandLine/src/CommandLine/Commands/Mail/ArchiveMailCommand.cs New archive command
src/Nitro/CommandLine/src/CommandLine/Commands/Mail/AckMailCommand.cs New ack/mark-read command
src/Nitro/CommandLine/src/CommandLine/Commands/Agent/WhoamiAgentCommand.cs New whoami command
src/Nitro/CommandLine/src/CommandLine/Commands/Agent/RegisterAgentCommand.cs New register command
src/Nitro/CommandLine/src/CommandLine/Commands/Agent/Options/StaleAgentOption.cs Add --stale option
src/Nitro/CommandLine/src/CommandLine/Commands/Agent/Options/RoleAgentOption.cs Add --role option
src/Nitro/CommandLine/src/CommandLine/Commands/Agent/Options/ForceReinitializeAgentOption.cs Add --force for agent init
src/Nitro/CommandLine/src/CommandLine/Commands/Agent/Options/AgentPrefixOption.cs Add --prefix for agent init
src/Nitro/CommandLine/src/CommandLine/Commands/Agent/ListAgentCommand.cs New list command for registry
src/Nitro/CommandLine/src/CommandLine/Commands/Agent/AgentTuiLauncher.cs Build/run tabbed Tasks+Mail TUI
src/Nitro/CommandLine/src/CommandLine/Commands/Agent/AgentCommand.cs Make bare nitro agent launch tabbed TUI
.github/workflows/nitro-cli-e2e.yml CI e2e workflow updated to agent init
src/Nitro/CommandLine/src/CommandLine/Tui/Runtime/SqliteDbWatcher.cs New watcher avoiding -shm read churn
src/Nitro/CommandLine/src/CommandLine/Services/Mail/MailStore.cs Mail store implementation over AgentDatabase
src/Nitro/CommandLine/src/CommandLine/Tui/Mail/MailComposeForm.cs Compose form + send outcome plumbing
src/Nitro/CommandLine/src/CommandLine/Tui/Mail/MailLifecycleActions.cs Mark-read/unread/archive helpers
Suppressed comments (2)

src/Nitro/CommandLine/test/e2e/README.md:59

  • This paragraph says search is an exception that must be launched via agent tasks board and should be reverted later, but search-flow.tape already launches via bare nitro agent and documents the bd-agent-unify-814.7 fix as proven. Please update/remove this “exception/revert” guidance to avoid misleading future updates.
    src/Nitro/CommandLine/src/CommandLine/Services/Workspace/AgentWorkspace.cs:1
  • AgentWorkspace uses IFileSystem, but this file has no using ChilliCream.Nitro.CommandLine.Services; so it won’t compile (IFileSystem is in the Services namespace).

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

| `list` / `show` / `create` / `close-reopen` / `dep-tree` / `error` | `nitro agent tasks <cmd>` over the fixture | the non-interactive task commands |
| `board` | the Tasks tab (bare `nitro agent`) | column/row navigation, and a tab switch to Mail and back |
| `board-maximize` | the Tasks tab's maximize toggle (`z`) | the single-column maximized layout |
| `search` | search mode (`/`) via `agent tasks board`, no tab strip (see below) | live query filtering and opening a result's detail pane |
@@ -0,0 +1,35 @@
Tasks Mail (1)
@@ -0,0 +1,29 @@
namespace ChilliCream.Nitro.CommandLine.Services.Mail;
@@ -0,0 +1,35 @@
namespace ChilliCream.Nitro.CommandLine.Services.Mail;
Comment on lines +1 to +4
using ChilliCream.Nitro.CommandLine.Services.Mail;
using ChilliCream.Nitro.CommandLine.Tui.Theming;

namespace ChilliCream.Nitro.CommandLine.Tui.Mail;
Comment on lines +1 to +7
using ChilliCream.Nitro.CommandLine.Services.Mail;
using ChilliCream.Nitro.CommandLine.Tui.Input;
using ChilliCream.Nitro.CommandLine.Tui.Shell;
using ChilliCream.Nitro.CommandLine.Tui.Theming;
using Spectre.Console.Rendering;

namespace ChilliCream.Nitro.CommandLine.Tui.Mail;
Comment on lines +1 to +2
using ChilliCream.Nitro.CommandLine.Services.Mail;
using ChilliCream.Nitro.CommandLine.Tui.Input;
Comment on lines +1 to +9
using System.Data.Common;
using System.Globalization;
using System.Security.Cryptography;
using System.Text;
using ChilliCream.Nitro.CommandLine.Services.Workspace;
using Dapper;
using Microsoft.Data.Sqlite;

namespace ChilliCream.Nitro.CommandLine.Services.Mail;
Comment on lines +1 to +2
using ChilliCream.Nitro.CommandLine.Services.Mail;
using ChilliCream.Nitro.CommandLine.Tui.Input;
Comment on lines +1 to +3
using ChilliCream.Nitro.CommandLine.Services.Mail;
using ChilliCream.Nitro.CommandLine.Tui.Editing;
using ChilliCream.Nitro.CommandLine.Tui.Input;
@github-actions

Copy link
Copy Markdown
Contributor

🎬 Nitro CLI E2E snapshots changed

These flow recordings differ from main (added, removed, or modified). Expand each for the before/after.

🆕 agent-root: added recording
🔁 board: modified
Before: mainAfter: this PR
recordingrecording
🔁 board-maximize: modified
Before: mainAfter: this PR
recordingrecording
🔁 close-reopen: modified
Before: mainAfter: this PR
recordingrecording
🔁 create: modified
Before: mainAfter: this PR
recordingrecording
🔁 dep-tree: modified
Before: mainAfter: this PR
recordingrecording
🔁 detail: modified
Before: mainAfter: this PR
recordingrecording
🔁 error: modified
Before: mainAfter: this PR
recordingrecording
🔁 help: modified
Before: mainAfter: this PR
recordingrecording
🔁 init: modified
Before: mainAfter: this PR
recordingrecording
🔁 list: modified
Before: mainAfter: this PR
recordingrecording
🆕 mail-board: added recording
🆕 mail-error: added recording
🆕 mail-send: added recording
🔁 search: modified
Before: mainAfter: this PR
recordingrecording
🔁 show: modified
Before: mainAfter: this PR
recordingrecording

Run 32478167500 · full set in the nitro-e2e-snapshots artifact.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants