// postMeister

always-on agent email + dispatch system // project plan // saturday build day 2026-05-10

1. vision

postMeister is the always-on concierge layer for the agent ecosystem. one email address, one inbox, one dispatcher. the operator sends a message. postMeister routes it to the right agent, wakes sleeping agents, tracks responses, and ensures nothing falls through the cracks.

by saturday morning, the operator sits down with coffee and a bagel and walks through a fully deployed, tested, verified email stack with live agent routing.

2. system architecture

  OPERATOR (phone/desktop/tablet)
       |
       | email to: dispatch@untitledprojects.io
       v
  +------------------+
  | STALWART         |  EC2 (questboard-ec2)
  | SMTP/IMAP/JMAP   |  port 25/587/993/8080
  | mail.untitled-   |  systemd service
  | projects.io      |  ~100MB RAM
  +--------+---------+
           |
           | IMAP poll (python, 30s)
           v
  +------------------+
  | postMeister      |  EC2 (questboard-ec2)
  | python daemon    |  systemd service
  | always-on        |  ~50MB RAM
  +--------+---------+
           |
     +-----+-----+-----+
     |           |     |
     v           v     v
  localMesh   agents  QB
  (nudge)    (email)  (tickets)

3. components

3a. stalwart mail server

softwareStalwart Mail Server (rust, single binary)
hostquestboard-ec2 (100.83.251.119)
domainmail.untitledprojects.io
ports25 (SMTP), 587 (submission), 993 (IMAPS), 8080 (web admin)
storagelocal disk (/var/lib/stalwart)
TLSLet's Encrypt auto-cert via Stalwart built-in ACME
authDKIM + SPF + DMARC configured via GoDaddy DNS

3b. mailboxes

addresspurpose
dispatch@untitledprojects.iomain operator inbox -- postMeister watches this
goulard@untitledprojects.ioagent-specific (example)
dorlange@untitledprojects.iokeymaster agent
postmeister@untitledprojects.iosystem/admin mailbox
artificer@untitledprojects.iooperator personal (optional)

3c. postMeister daemon

languagepython 3
hostquestboard-ec2
servicesystemd (postmeister.service)
poll interval30 seconds (IMAP IDLE if supported)
dependenciesimaplib, smtplib, requests (for localMesh + QB)

routing logic:

  1. check dispatch@ inbox for new messages
  2. parse subject for @{handle}3120 callsign
  3. if callsign found: forward to that agent's mailbox + nudge via localMesh
  4. if no callsign: check body for keywords, route to best agent, or queue in QB
  5. track delivery: log message ID, recipient, timestamp
  6. if agent doesn't respond within SLA: escalate (re-nudge, then alert operator)

3d. agentStateLoop integration

postMeister is state-aware. it knows which agents are IDLE, PREP, or ACTIVE (via localMesh registry). routing decisions use this:

3e. ecoute2 integration (saturday walkthrough)

operator uses ecoute2 voice widget to talk through the system while testing. agent responds via email AND voice (if ecoute2 is connected to the active agent).

4. DNS configuration

required records on untitledprojects.io (GoDaddy):

typenamevalueTTL
Amail3.149.50.128 (Elastic IP)600
MX@mail.untitledprojects.io (priority 10)600
TXT@v=spf1 ip4:3.149.50.128 -all600
TXT_dmarcv=DMARC1; p=quarantine; rua=mailto:postmeister@untitledprojects.io600
TXTstalwart._domainkey[DKIM public key - generated by Stalwart]600
human gate: DNS

operator must verify GoDaddy DNS access works. goulard3120 has API access via vault (godaddy_personal_api_key) and can set records programmatically. no manual action needed unless API fails.

5. day-by-day execution plan

wednesday 05-07 (today) -- foundation
taskownerstatus
install Stalwart binary on EC2goulard3120pending
configure Stalwart (domain, TLS, admin)goulard3120pending
set DNS records via GoDaddy APIgoulard3120pending
create mailboxes (dispatch, postmeister, test)goulard3120pending
send/receive test (agent to dispatch@)goulard3120pending
open EC2 security group ports (25, 587, 993)goulard3120pending

deliverable: stalwart running, DNS propagated, test email round-trip confirmed.

thursday 05-08 -- postMeister daemon
taskownerstatus
write postMeister daemon (IMAP poll, routing, localMesh nudge)goulard3120 or successorpending
deploy as systemd service on EC2agentpending
agentStateLoop phase 1: state tracking in context.mdagentpending
agentStateLoop phase 2: cron switching prototypeagentpending
integration test: email to dispatch@ triggers agent wakeagentpending

deliverable: postMeister daemon running, routing emails to agents, agents waking on nudge.

friday 05-09 -- polish + dashboard
taskownerstatus
neonForge dashboard page: agent state, mailbox status, SLAsagentpending
mobile-responsive testing (Quartz, Pebble, phone)agentpending
postMeister agent profile docagentpending
ecoute2 integration test for saturdayagentpending
end-to-end dry run: operator sends email from phone, agent respondsagentpending
credential resilience test: simulate stale token, verify no haltagentpending

deliverable: everything staged, tested, ready for operator walkthrough.

saturday 05-10 -- BUILD DAY
taskownerstatus
operator arrives, coffee + bagelartificerpending
walkthrough: stalwart admin panel (desktop)agent + artificerpending
test: send email from phone to dispatch@, watch routingartificerpending
test: send email from desktop, verify agent response <60sartificerpending
test: trigger state transitions (IDLE->PREP->ACTIVE->IDLE)artificerpending
review: neonForge dashboard on mobile (Quartz/Pebble)artificerpending
ecoute2 voice walkthrough of architectureagent + artificerpending
approve/reject: sign off on postMeister v1artificerpending

deliverable: operator-approved, production-ready postMeister system.

6. resource budget

compute

resourceusagecost
questboard-ec2 (t3.small)stalwart + postMeister daemon (24/7)$0 incremental (already running)
EC2 security group changesopen ports 25, 587, 993$0
EC2 diskstalwart data (~500MB initial)$0 (within existing EBS)
picass0 (if needed for ecoute2 voice)1-2 hours saturday$1.00
DNS (GoDaddy)5 records on untitledprojects.io$0 (already own domain)

agent labor

dayagent sessionsestimated API cost
wed (today)1 tunnelTime session (goulard3120)~$2-3
thu1 tunnelTime session~$2-3
fri1 tunnelTime session~$2-3
sat1-2 sessions (tunnelTime + specialist)~$3-5

TOTAL BUDGET

compute (4 days)$1.00 (picass0 only)
agent labor (4 days)$9-14 (API tokens)
infrastructure$0 (all existing)
total$10-15

within pre-authorized $10/30-day spend. picass0 usage may push slightly over -- requesting approval for up to $15 total.

7. human gates (frontloaded)

gate 1: DNS verification (today)

after goulard3120 sets DNS records via API, operator confirms MX record propagation. can verify via: dig MX untitledprojects.io or mxtoolbox.com.

gate 2: security group approval (today)

opening ports 25/587/993 on EC2 security group. pre-authorized per SERVICE-CONTRACT (manage AWS security groups). will lock to tailscale IPs + known mail relay IPs.

gate 3: mailbox naming approval (today)

operator confirms mailbox naming convention: dispatch@, {handle}@, postmeister@, artificer@. if different names wanted, specify now.

gate 4: saturday sign-off

operator walks through all deliverables. approves or requests changes. this is the final gate.

8. risks + mitigations

risklikelihoodmitigation
DNS propagation delaymediumset TTL to 600s. start today, should be fully propagated by thursday.
port 25 blocked by AWSmediumAWS blocks outbound 25 by default on new accounts. we may need to request removal or use port 587 relay. can also use SES as smarthost.
stalwart config complexitylowstalwart has sensible defaults. TOML config. well-documented.
agent session continuitymediumdumpshock/savepoint between sessions. successor agents pick up from project plan.
ecoute2 not readylowfallback: saturday walkthrough via email thread instead of voice.

9. saturday morning checklist

by 9am saturday, the operator should be able to:

10. QB tickets

#titlestatus
#680agentStateLoop: IDLE/PREP/ACTIVE state machinequeued
NEWstalwart email server deployment on EC2to file
NEWpostMeister daemon: IMAP routing + localMesh dispatchto file
NEWneonForge agent state dashboardto file
NEWDNS config: mail.untitledprojects.ioto file

postMeister project plan v1.0 // goulard3120 // 2026-05-07
awaiting operator approval to begin execution.