Skip to main content

Edita PA Runbook

Edita PA Runbook

TLDR

  • Edita = Alem's AI Personal Assistant. Daemon com.john.edita-loop (LaunchAgent), script ~/system/agents/pa/edita-loop.js. Reports to John, who reports to Alem.
  • Runs email triage every 5 min on [email protected] (Migadu). Classifies ARCHIVE / REPLY_TEMPLATE / ESCALATE, writes drafts, never auto-sends.
  • AUTO_REPLY_ENABLED = false — hardcoded CEO kill switch (order 2026-03-07). Drafts only land in ~/system/intake/drafts/; nothing goes out without a human/John send.
  • Calendar tick and memory-consolidation tick exist in the loop but are stub code ("Faza 3") — not yet active. Only email triage (Faza 1) and the incoming-message handler (Faza 2, event-driven Slack/Telegram) run for real.
  • Check it's alive: launchctl list | grep com.john.edita-loop and cat ~/system/logs/edita-loop-heartbeat.json.
  • Restart: launchctl kickstart -k gui/$(id -u)/com.john.edita-loop.

Identity

Field Value
Name Edita
Role Personal Assistant, ALAI Holding AS
Boss Alem Basic (CEO, [email protected])
Manager John (AI Director)
Primary mailbox [email protected] (Migadu)
System prompt ~/system/agents/pa/edita-system-prompt.md

Language: mirrors the user (Bosnian/English/Norwegian mix OK). Tone: direct, warm, professional, max 3 sentences for routine replies. Edita never says "I can't" — she escalates to John instead.

What Edita does

  • Triages inbound email: ARCHIVE / REPLY_TEMPLATE / ESCALATE
  • Answers Telegram/Slack messages from Alem
  • Creates and updates MC tasks
  • Checks calendar, reminds about meetings (stub — not active yet)
  • Writes draft email replies (never sends automatically)
  • Consolidates memory/session context (stub, delegated to edita-memory-writer.js)
  • Coordinates and escalates — does not deploy, does not build, does not commit code

What Edita does NOT do

  • Send email automatically without passing the Gate 3 kill switch
  • Commit code or deploy services
  • Make business decisions without confirmation
  • Touch financial systems directly

Escalation rules (always → John → Alem)

  • VIP sender (see ~/system/agents/pa/memory/contacts-vip.json)
  • Money/legal keywords: ugovor, faktura, ponuda, legal, NDA, payment
  • New/unknown client contact
  • Classifier confidence < 0.6

Architecture — the loop

Script: ~/system/agents/pa/edita-loop.js (extends daemon-base.js — signal handling, heartbeat, circuit breaker).

masterTick()
  A. emailTriageTick()          — every 5 min   [ACTIVE]
  B. calendarTick()             — every 15 min  [STUB — Faza 3, not active]
  C. memoryConsolidationTick()  — every 30 min  [STUB — Faza 3, delegated to edita-memory-writer.js]
  D. incomingMessageHandler()   — event-driven  [ACTIVE — Slack/Telegram, Faza 2]
  validationTick()              — every 6h, always active (incl. dry-run)

Email triage flow (emailTriageTick):

  1. Pull unclassified mail for [email protected] from ~/system/databases/email-inbox.db.
  2. Classify via Ollama (TRIAGE_MODEL = llama3.1:8b, OLLAMA_HOST default http://localhost:11434).
  3. Write-back classification even in dry-run, so items aren't re-examined every tick.
  4. If reply warranted: build draft, write to ~/system/intake/drafts/draft-<ts>-<subject>.md.
  5. Gate 3 check: autoReplyEnabled = config.auto_reply_enabled || AUTO_REPLY_ENABLED (AUTO_REPLY_ENABLED is hardcoded false in code) — if false, hold and log GATE3_HOLD, notify John. No send happens.

Key config/paths

Const Path
INTAKE_CONFIG ~/system/config/intake-config.json
DRAFTS_DIR ~/system/intake/drafts/
DECISIONS_LOG ~/system/logs/edita-decisions.jsonl
HEARTBEAT_FILE ~/system/logs/edita-loop-heartbeat.json
SYSTEM_PROMPT_FILE ~/system/agents/pa/edita-system-prompt.md
EMAIL_INBOX_DB ~/system/databases/email-inbox.db
VIP_CONTACTS ~/system/agents/pa/memory/contacts-vip.json

Run modes

node ~/system/agents/pa/edita-loop.js               # live (LaunchAgent default)
node ~/system/agents/pa/edita-loop.js --dry-run      # Faza 1: logs decisions only, no drafts sent
node ~/system/agents/pa/edita-loop.js --allow-archive  # next safe step after dry-run: allows ARCHIVE action, still no sends

Operations

# Status
launchctl list | grep com.john.edita-loop
cat ~/system/logs/edita-loop-heartbeat.json

# Restart
launchctl kickstart -k gui/$(id -u)/com.john.edita-loop

# Recent decisions
tail -50 ~/system/logs/edita-decisions.jsonl

# Pending drafts (never auto-sent — review before send)
ls -la ~/system/intake/drafts/

Plist: ~/Library/LaunchAgents/com.john.edita-loop.plist.

Troubleshooting

Edita not triaging new mail

  1. Confirm daemon is running: launchctl list | grep com.john.edita-loop (should show a PID, not -).
  2. Check heartbeat freshness: cat ~/system/logs/edita-loop-heartbeat.json — stale timestamp means the tick loop died silently; kickstart it.
  3. Check Ollama circuit breaker: grep "circuit breaker open" ~/system/logs/edita-loop.log — if tripped, Ollama (localhost:11434) is unreachable; test with curl -s localhost:11434/api/tags.
  4. Confirm [email protected] is actually being scanned — see [[Email System Runbook]] for the account/daemon relationship (separate daemon, email-agent.js, ingests mail into email-inbox.db; Edita reads from that same DB, it does not do its own IMAP fetch).

A draft never turned into a sent email This is expected — AUTO_REPLY_ENABLED = false is a deliberate CEO gate, not a bug. Drafts sit in ~/system/intake/drafts/; John or Alem must review and send manually via the paths in [[Email System Runbook]].

Calendar reminders / auto-memory-consolidation not happening Expected — both are Faza 3 stub code in edita-loop.js (calendarTick, memoryConsolidationTick are no-ops that just log a debug line). Not a regression; they were never activated.

  • [[Email System Runbook]] — the underlying email ingest/audit/send pipeline Edita's triage tick reads from and drafts against.
  • ~/system/agents/pa/edita-memory-writer.js — standalone memory consolidation script (the real implementation behind the Faza 3 stub).