@adaptic/maestro 1.1.7 → 1.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (60) hide show
  1. package/.claude/commands/init-maestro.md +502 -260
  2. package/README.md +47 -2
  3. package/bin/maestro.mjs +1 -1
  4. package/docs/guides/agents-observe-setup.md +64 -0
  5. package/docs/guides/ccxray-diagnostics.md +65 -0
  6. package/docs/guides/claude-mem-setup.md +79 -0
  7. package/docs/guides/claude-pace-setup.md +56 -0
  8. package/docs/guides/claudraband-sessions.md +98 -0
  9. package/docs/guides/clawteam-swarm.md +116 -0
  10. package/docs/guides/code-review-graph-setup.md +86 -0
  11. package/docs/guides/email-setup.md +399 -0
  12. package/docs/guides/media-generation-setup.md +349 -0
  13. package/docs/guides/outbound-governance-setup.md +438 -0
  14. package/docs/guides/pdf-generation-setup.md +315 -0
  15. package/docs/guides/poller-daemon-setup.md +550 -0
  16. package/docs/guides/rag-context-setup.md +459 -0
  17. package/docs/guides/self-optimization-pattern.md +82 -0
  18. package/docs/guides/slack-setup.md +350 -0
  19. package/docs/guides/twilio-subaccounts-setup.md +223 -0
  20. package/docs/guides/voice-sms-setup.md +698 -0
  21. package/docs/guides/webhook-relay-setup.md +349 -0
  22. package/docs/guides/whatsapp-setup.md +282 -0
  23. package/docs/runbooks/mac-mini-bootstrap.md +21 -0
  24. package/package.json +2 -1
  25. package/plugins/maestro-skills/plugin.json +16 -0
  26. package/plugins/maestro-skills/skills/agents-observe.md +110 -0
  27. package/plugins/maestro-skills/skills/ccxray-diagnostics.md +91 -0
  28. package/plugins/maestro-skills/skills/claude-pace.md +61 -0
  29. package/plugins/maestro-skills/skills/code-review-graph.md +99 -0
  30. package/scaffold/CLAUDE.md +64 -0
  31. package/scaffold/config/agent.ts.example +2 -1
  32. package/scaffold/config/caller-id-map.yaml +46 -0
  33. package/scaffold/config/known-agents.json +35 -0
  34. package/scripts/daemon/classifier.mjs +264 -50
  35. package/scripts/daemon/dispatcher.mjs +109 -5
  36. package/scripts/daemon/launchd-wrapper-generic.sh +96 -0
  37. package/scripts/daemon/launchd-wrapper-slack-events.sh +37 -0
  38. package/scripts/daemon/launchd-wrapper.sh +91 -0
  39. package/scripts/daemon/lib/session-router.mjs +274 -0
  40. package/scripts/daemon/lib/session-router.test.mjs +295 -0
  41. package/scripts/daemon/prompt-builder.mjs +51 -11
  42. package/scripts/daemon/responder.mjs +234 -19
  43. package/scripts/daemon/session-lock.mjs +194 -0
  44. package/scripts/daemon/sophie-daemon.mjs +16 -2
  45. package/scripts/email-signature.html +20 -4
  46. package/scripts/local-triggers/generate-plists.sh +62 -10
  47. package/scripts/media-generation/README.md +2 -0
  48. package/scripts/pdf-generation/README.md +2 -0
  49. package/scripts/poller/imap-client.mjs +4 -2
  50. package/scripts/poller/slack-poller.mjs +126 -59
  51. package/scripts/poller/trigger.mjs +12 -1
  52. package/scripts/setup/init-agent.sh +91 -1
  53. package/scripts/setup/install-dev-tools.sh +150 -0
  54. package/scripts/spawn-session.sh +21 -6
  55. package/workflows/continuous/backlog-executor.yaml +141 -0
  56. package/workflows/daily/evening-wrap.yaml +41 -1
  57. package/workflows/daily/morning-brief.yaml +17 -0
  58. package/workflows/event-driven/agent-failure-investigation.yaml +137 -0
  59. package/workflows/event-driven/pr-review.yaml +104 -0
  60. package/workflows/weekly/engineering-health.yaml +154 -0
@@ -297,7 +297,7 @@ Do NOT modify these sections (keep them exactly as they are, except for agent na
297
297
  - product-leader: product roadmap, user research, feature delivery, product-market fit, design system
298
298
  - operations-leader: process automation, operational efficiency, fund operations, organisational design, vendor management
299
299
 
300
- ### Sub-agent 4: Update package.json and scripts
300
+ ### Sub-agent 4: Update package.json, scripts, and identity-baked content
301
301
 
302
302
  **Instruction to sub-agent:**
303
303
 
@@ -307,9 +307,57 @@ Do NOT modify these sections (keep them exactly as they are, except for agent na
307
307
  - Variable names like `SOPHIE_AI_DIR` -> `{UPPER_FIRSTNAME}_AI_DIR`
308
308
  - Path references like `/Users/sophie/sophie-ai` -> `/Users/{lowercase-firstname}/{repoSlug}`
309
309
  - LaunchD labels like `ai.adaptic.sophie-` -> `ai.adaptic.{lowercase-firstname}-`
310
+ - Pronouns: if the new agent's gender differs from the scaffolding template, update he/she/him/her/his/hers/himself/herself across system prompts, comments, and documentation. Be surgical — do NOT change pronouns inside generic regex patterns or third-party detection logic.
310
311
 
311
312
  3. **LaunchD plists** in `scripts/local-triggers/plists/` -- Update labels and paths in all `.plist` files.
312
313
 
314
+ 4. **Identity-baked content rewrites (CRITICAL — full overwrites, not grep-replace).** These files contain the agent's outbound identity (name, title, email, phone, signature) and MUST be fully rewritten with the new agent's values. Do not rely on grep-replace alone — read each file, then OVERWRITE it with content that uses these exact values:
315
+
316
+ - `firstName + lastName` (e.g., "Lucas Ferreira")
317
+ - `title` (e.g., "VP, Regulatory & Licensing")
318
+ - `email` (e.g., "lucas@adaptic.ai")
319
+ - `phone` (e.g., "+61 478 964 324" — use the spaced pretty form for human-facing display, the E.164 form for code)
320
+ - `companyName` (e.g., "Adaptic.ai")
321
+ - `companyAddress` (use the company's primary office address — typically Adaptic's DIFC office unless explicitly different)
322
+
323
+ **Files to rewrite:**
324
+
325
+ a. **`scripts/email-signature.html`** — The HTML signature appended to all outbound emails by `send-email.sh` and the Python send scripts. Must contain: name (bold, 14px), title (grey, 13px), Adaptic logo (`https://adaptic.ai/logo.png`), email, phone, company address line, full confidentiality disclaimer footer. Pattern matches the template in `~/maestro/scripts/email-signature.html` — use placeholders {{AGENT_NAME}}, {{AGENT_TITLE}}, {{AGENT_EMAIL}}, {{AGENT_PHONE}}, {{COMPANY_ADDRESS}} and substitute them.
326
+
327
+ b. **`scripts/email-signature-mehran.html`** — Principal's signature block (used by `send-email-as-mehran.py` or equivalent send-as-principal scripts). Update with the principal's values: `principal.fullName`, `principal.title`, `principal.email`. If the principal doesn't have a phone in config/agent.ts, omit the phone line.
328
+
329
+ c. **`scripts/send-email.sh`** — Hardcoded `From:` header and inline signature fallback. Update both. The From header should be in the form `"Lucas Ferreira" <lucas@adaptic.ai>`.
330
+
331
+ d. **`scripts/send-email-threaded.py`** — `USER`, `From` header construction, inline signature, argparse description. All must reflect the new agent.
332
+
333
+ e. **`scripts/send-email-with-attachment.py`** — Same as above.
334
+
335
+ f. **`scripts/pdf-generation/build-document.mjs`** — Default `author` value (used in PDF metadata) and the help text describing the default. Set to the new agent's full name.
336
+
337
+ g. **`scripts/pdf-generation/templates/memo.latex`** — Footer line "Prepared by ... Chief of Staff" — replace with "Prepared by {fullName}, {title}".
338
+
339
+ h. **`scripts/daemon/responder.mjs` `FALLBACK_PREAMBLE`** — System prompt that introduces the agent to Claude. Identity intro line must reference the new agent. Preserve the operational rules.
340
+
341
+ i. **`scripts/daemon/prompt-builder.mjs` `FALLBACK_PREAMBLE`** — Same treatment.
342
+
343
+ j. **`scripts/daemon/classifier.mjs` `SYSTEM_PROMPT`** — Identity intro line. Preserve everything else.
344
+
345
+ k. **`scripts/huddle/huddle-server.mjs` `HUDDLE_SYSTEM_PROMPT`** — Voice agent identity line.
346
+
347
+ l. **`scripts/spawn-session.sh`** — Sub-session bootstrap prompt that names the agent.
348
+
349
+ m. **`scripts/continuous-monitor.sh`** — Channel monitor agent prompt.
350
+
351
+ n. **`scripts/llm_email_dedup.py`, `scripts/comms-monitor.sh`, `scripts/archive-email.sh`, `scripts/poller/gmail-poller.mjs`, `scripts/poller/imap-client.mjs`** — Hardcoded `LUCAS_EMAIL`/`USER`/`gmail_user` constants. Set to the new agent's email.
352
+
353
+ o. **`scripts/{firstname}-inbox-poller.py`** — Rename file from `sophie-inbox-poller.py` (or current scaffolding name) to `{firstname}-inbox-poller.py`. Update internal `LUCAS_EMAIL` constant. Update any plist references to the new filename.
354
+
355
+ p. **`scripts/rag-indexer.py`, `scripts/user-context-search.py`** — Author docstring at the top. Set to the new agent's full name.
356
+
357
+ q. **`scripts/validate-outbound.py`** — Three test/regex references to "Sophie Nguyen" or `lookup_entity("Sophie Nguyen")`. Replace with the new agent's full name. Leave the generic third-party pronoun regex (around line 1007) UNCHANGED — it's a detector, not an identity reference.
358
+
359
+ **Verification step**: After rewrites, run `grep -rn "sophie@adaptic\|Sophie Nguyen\|Chief of Staff" scripts/ docs/business-synthesis/executive-operating-model.md 2>&1` and confirm only intentional peer references remain (Sophie Nguyen as a real Chief of Staff peer, NOT as the agent's own outbound identity). Report any remaining matches you couldn't safely auto-resolve so the main agent can decide.
360
+
313
361
  ### Sub-agent 5: Update agent definitions
314
362
 
315
363
  **Instruction to sub-agent:**
@@ -436,359 +484,556 @@ If yes, run:
436
484
  sudo ./scripts/setup/configure-macos.sh
437
485
  ```
438
486
 
439
- ## Phase 4: Third-Party Service Configuration
487
+ ### Step 4: External SSD configuration (REQUIRED if /Volumes/{name}-SSD is mounted)
440
488
 
441
- Guide the user through setting up external integrations. Present this as a checklistsome steps can be automated, others require manual action.
489
+ The maestro daemon and its launchd-spawned trigger jobs should write all runtime dataClaude Code per-cwd temp dirs, daemon logs, state, outputs, memory, knowledge — to an external SSD when one is available. This keeps the internal disk free for macOS and avoids wear on the system disk.
442
490
 
443
- ### Classification of Setup Steps
491
+ **Two macOS hurdles need to be cleared before the SSD redirect actually works for launchd-spawned processes:**
444
492
 
445
- **Automated (the wizard does it):**
446
- - Twilio WhatsApp sandbox configuration (if TWILIO_ACCOUNT_SID is in .env)
447
- - Cloudflare tunnel creation (via `cloudflared` CLI if installed)
448
- - ElevenLabs voice clone setup (via API if ELEVENLABS_API_KEY is in .env)
449
- - Railway service deployment (via `railway` CLI if installed)
493
+ #### 4a. Enable file ownership on the volume
450
494
 
451
- **Guided (requires human action, wizard walks them through):**
452
- - Slack app creation and token generation
453
- - Gmail app password generation
454
- - Twilio phone number purchase
455
- - Parsec account login (first time only)
495
+ By default, external volumes have Owners disabled, which makes file permissions advisory rather than enforced. The daemon's wrapper writes per-agent log files, and that requires real owners.
456
496
 
457
- ### Step 1: Slack App Setup
497
+ Detect the SSD and enable owners:
498
+
499
+ ```bash
500
+ SSD_VOLUME=""
501
+ for v in /Volumes/*-SSD /Volumes/*SSD* /Volumes/maestro-data; do
502
+ if [ -d "$v" ] && [ "$v" != "/Volumes/Macintosh HD" ]; then SSD_VOLUME="$v"; break; fi
503
+ done
458
504
 
505
+ if [ -n "$SSD_VOLUME" ]; then
506
+ # Tell the user we found an SSD and need sudo to enable owners
507
+ echo "Found external SSD at $SSD_VOLUME — enabling file ownership."
508
+ echo "Please run this in your terminal (it needs sudo):"
509
+ echo " sudo diskutil enableOwnership \"$SSD_VOLUME\""
510
+ echo "Reply 'done' when complete."
511
+ fi
459
512
  ```
460
- Let's set up Slack integration.
461
513
 
462
- IMPORTANT: You can reuse an existing Slack app across multiple agents in the
463
- same workspace. Each agent needs its own bot token and user token, but they
464
- can share the same app configuration.
514
+ Wait for the user to confirm. Then verify:
465
515
 
466
- If you already have a Maestro Slack app configured:
467
- Just paste the bot token (xoxb-...) and user token (xoxp-...) below.
516
+ ```bash
517
+ diskutil info "$SSD_VOLUME" | grep "Owners" | grep -q "Enabled" && echo "OK" || echo "FAIL"
518
+ ```
519
+
520
+ #### 4b. Grant Full Disk Access to bash and node (TCC)
468
521
 
469
- If you need to create a new Slack app:
470
- 1. Go to https://api.slack.com/apps → "Create New App" → "From scratch"
471
- 2. Name it "Maestro - {AgentFirstName}" (or reuse existing "Maestro" app)
472
- 3. Under "OAuth & Permissions", add these BOT scopes:
473
- - chat:write, chat:write.customize
474
- - channels:read, channels:history
475
- - groups:read, groups:history
476
- - im:read, im:history, im:write
477
- - users:read, users:read.email
478
- - reactions:read, reactions:write
479
- - files:read, files:write
480
- 4. Add these USER scopes:
481
- - channels:history, groups:history, im:history
482
- - search:read
483
- 5. Install the app to your workspace
484
- 6. Copy the Bot User OAuth Token (xoxb-...)
485
- 7. Copy the User OAuth Token (xoxp-...)
486
-
487
- For Slack Events API (real-time messages instead of polling):
488
- 8. Under "Event Subscriptions", enable events
489
- 9. Set Request URL to your Cloudflare tunnel URL + /slack/events
490
- 10. Subscribe to bot events: message.channels, message.groups, message.im,
491
- app_mention, reaction_added
492
- 11. Copy the Signing Secret from "Basic Information"
522
+ Even with owners enabled, **macOS TCC blocks launchd-spawned processes from writing to /Volumes/ unless the binary has Full Disk Access**. This is the single most common cause of "Operation not permitted" errors when you run a daemon under launchd that tries to write to an external volume.
523
+
524
+ You cannot grant Full Disk Access programmatically without disabling SIP (which is unsafe). The user must do this via System Settings UI:
525
+
526
+ ```
527
+ 1. Open System Settings → Privacy & Security → Full Disk Access
528
+ 2. Click the + button
529
+ 3. Press Cmd+Shift+G to "Go to Folder", then enter:
530
+ /bin/bash
531
+ Press Enter, select 'bash', click Open
532
+ 4. Click + again, then:
533
+ /usr/bin/node OR ~/.nvm/versions/node/v24.11.1/bin/node
534
+ (whichever node binary the wrapper uses)
535
+ 5. Make sure both toggles are ON
493
536
 
494
- Paste your tokens when ready (or type "skip" to configure later):
495
- Bot token (xoxb-...):
496
- User token (xoxp-...):
497
- Signing secret (optional):
537
+ The toggles take effect immediately. No restart needed.
498
538
  ```
499
539
 
500
- Write the tokens to `.env` using the Edit tool.
540
+ After the user confirms, test that launchd can now write to the SSD:
501
541
 
502
- **Answer to Slack app reusability question:** A single Slack app CAN serve multiple agents in the same workspace. The app defines scopes and event subscriptions; each workspace installation generates unique bot/user tokens. However, if you want separate bot identities (different names/avatars per agent), create one app per agent. The Event Subscriptions URL can only point to one server per app, so if multiple agents need real-time events, either use separate apps or a shared event router.
542
+ ```bash
543
+ cat > /tmp/ssd-tcc-test.plist <<EOF
544
+ <?xml version="1.0" encoding="UTF-8"?>
545
+ <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
546
+ <plist version="1.0">
547
+ <dict>
548
+ <key>Label</key><string>ai.adaptic.ssd-tcc-test</string>
549
+ <key>ProgramArguments</key><array>
550
+ <string>/bin/bash</string><string>-c</string>
551
+ <string>touch "$SSD_VOLUME/.tcc-test" && echo "ok=$?" > /tmp/ssd-tcc-result.log || echo "fail=$?" > /tmp/ssd-tcc-result.log</string>
552
+ </array>
553
+ <key>RunAtLoad</key><true/>
554
+ </dict>
555
+ </plist>
556
+ EOF
557
+ launchctl load /tmp/ssd-tcc-test.plist
558
+ sleep 2
559
+ cat /tmp/ssd-tcc-result.log
560
+ launchctl unload /tmp/ssd-tcc-test.plist
561
+ rm -f "$SSD_VOLUME/.tcc-test"
562
+ ```
563
+
564
+ If you see `ok=0`, TCC is configured correctly and the daemon can use the SSD. If you see `fail=1`, TCC is still blocking — repeat the System Settings step and make sure the toggles are ON.
565
+
566
+ #### 4c. Set up SSD layout and symlinks
503
567
 
504
- ### Step 2: Gmail Setup
568
+ ```bash
569
+ AGENT_NAME="$(grep firstName config/agent.ts | head -1 | sed 's/.*[\x27\"]\([a-zA-Z]*\)[\x27\"].*/\1/' | tr A-Z a-z)"
570
+ SSD_AGENT_ROOT="$SSD_VOLUME/maestro/$AGENT_NAME"
571
+ mkdir -p "$SSD_AGENT_ROOT"/{state,outputs,memory,knowledge,claude-tmp,logs,tmp}
572
+
573
+ # Symlink runtime data dirs from the agent repo to the SSD.
574
+ # IMPORTANT: do NOT symlink logs/ — launchd's StandardErrorPath cannot follow
575
+ # symlinks to external volumes. The daemon's wrapper writes its own log file
576
+ # directly to the SSD via shell redirection (see launchd-wrapper.sh).
577
+ for d in state outputs memory knowledge; do
578
+ if [ -d "$d" ] && [ ! -L "$d" ]; then
579
+ rsync -a "$d/" "$SSD_AGENT_ROOT/$d/"
580
+ rm -rf "$d"
581
+ ln -sfn "$SSD_AGENT_ROOT/$d" "$d"
582
+ fi
583
+ done
505
584
 
585
+ # Create internal-disk logs/ as a real directory (NOT a symlink)
586
+ mkdir -p logs/{daemon,polling,workflows,sessions,audit,security,evolution,huddle,infra,monitor,phone,sms,whatsapp,email,launchd,cloudflared}
506
587
  ```
507
- Let's set up Gmail.
508
588
 
509
- Each agent needs its own Gmail account and app password.
510
- (The poller connects via IMAP — not OAuth — so app passwords are simpler.)
589
+ The wrapper scripts (`scripts/daemon/launchd-wrapper.sh` and `launchd-wrapper-generic.sh`) handle the runtime side: they detect the SSD, set `CLAUDE_CODE_TMPDIR`, and redirect daemon stdout/stderr to a log file on the SSD. They gracefully fall back to internal-disk paths if the SSD isn't writable (e.g. if TCC isn't granted yet).
511
590
 
512
- 1. Log into the agent's Google account ({agent.email})
513
- 2. Enable 2-Factor Authentication if not already enabled
514
- 3. Go to https://myaccount.google.com/apppasswords
515
- 4. Generate an app password for "Mail" on "Mac"
516
- 5. Copy the 16-character password (no spaces)
591
+ #### 4d. Verify
517
592
 
518
- Paste the Gmail app password:
593
+ ```bash
594
+ # Daemon should now be writing to the SSD log file
595
+ launchctl unload ~/Library/LaunchAgents/ai.adaptic.${AGENT_NAME}-daemon.plist
596
+ launchctl load ~/Library/LaunchAgents/ai.adaptic.${AGENT_NAME}-daemon.plist
597
+ sleep 4
598
+ ls -la "$SSD_AGENT_ROOT/logs/daemon/" | tail -5
599
+ ls -la "$SSD_AGENT_ROOT/state/inbox/" | tail -5
519
600
  ```
520
601
 
521
- Write to `.env` as `GMAIL_APP_PASSWORD`.
602
+ You should see the daemon log file growing and inbox directories populating. If you don't, repeat steps 4a–4b (most often it's TCC).
522
603
 
523
- If the agent also monitors the principal's inbox:
524
- ```
525
- Does {principalName} want this agent to monitor their inbox too?
526
- If yes, generate an app password for {principalEmail} using the same steps above.
604
+ ## Phase 4: Autonomous Service Configuration
527
605
 
528
- Paste the secondary Gmail app password (or "skip"):
529
- ```
606
+ This phase sets up all third-party integrations **autonomously**. Use Playwright MCP for web-based setup (Slack API portal, Twilio Console, Google Account, ElevenLabs, Deepgram) and Bash for local scripts. Only ask the user for input when genuinely required (existing credentials, 2FA codes, payment authorisation).
530
607
 
531
- Write to `.env` as `SECONDARY_GMAIL_APP_PASSWORD`.
608
+ **Tooling:**
609
+ - **Playwright MCP** (`mcp__plugin_playwright_playwright__browser_navigate`, `browser_click`, `browser_fill_form`, `browser_snapshot`, etc.) for all web UI interactions
610
+ - **Bash** for local scripts, CLI tools, file writes, service starts
611
+ - If a web UI requires authentication the agent doesn't have, ask the user to log in via `! open <url>` then resume automation once they confirm they're logged in
532
612
 
533
- ### Step 3: Twilio Setup (Optional)
613
+ **Implementation guides**: Each service has a detailed guide in `docs/guides/`. Follow the guide's steps exactly during setup. Reference the guide's troubleshooting section if something fails.
534
614
 
535
- ```
536
- Does this agent need phone/SMS/WhatsApp capabilities? (yes/no)
537
- ```
615
+ ### Step 0: Ask what services this agent needs
538
616
 
539
- If yes:
540
617
  ```
541
- Twilio setup:
542
- 1. Sign up at https://www.twilio.com/ (or use existing account)
543
- 2. From the Console dashboard, copy:
544
- - Account SID (starts with AC...)
545
- - Auth Token
546
- 3. Buy a phone number: Console → Phone Numbers → Buy a Number
547
- - Select a number with SMS + Voice capabilities
548
- - Copy the phone number (E.164 format, e.g., +15551234567)
549
- - Copy the Phone SID (starts with PN...)
618
+ Which services does this agent need? Select all that apply:
550
619
 
551
- Paste your Twilio credentials:
552
- Account SID:
553
- Auth Token:
554
- Phone Number:
555
- Phone SID:
556
- ```
620
+ [1] Slack (messaging, events, typing indicators)
621
+ [2] Gmail (email send/receive via IMAP/SMTP)
622
+ [3] Twilio SMS (inbound/outbound text messaging)
623
+ [4] Twilio WhatsApp (inbound/outbound WhatsApp)
624
+ [5] Voice / Huddle (Deepgram STT + ElevenLabs TTS)
625
+ [6] Cloudflare Tunnels (public webhook URLs — needed if 3/4/5 selected)
626
+ [7] Gemini / Veo (AI image + video generation)
627
+ [8] All of the above
628
+ [9] Minimal (Slack + Gmail only)
557
629
 
558
- Write all to `.env`. Then offer to auto-configure:
559
- ```
560
- Would you like me to configure the Twilio WhatsApp sandbox automatically? (yes/no)
630
+ Which? (comma-separated numbers, or "all" / "minimal")
561
631
  ```
562
632
 
563
- If yes, run: `bash scripts/configure-whatsapp-sandbox.sh`
633
+ Then execute each selected service. For services with existing credentials, ask the user to paste them. For new accounts, drive the web UI via Playwright.
634
+
635
+ ### Step 1: Slack — per `docs/guides/slack-setup.md`
636
+
637
+ **If user has existing tokens:** ask for xoxb- and xoxp- tokens, write to `.env`.
638
+
639
+ **If creating new app — execute via Playwright:**
640
+
641
+ 1. `browser_navigate` to `https://api.slack.com/apps`
642
+ 2. `browser_snapshot` to check auth — if not logged in, ask user: `! open https://api.slack.com/apps` and log in, then resume
643
+ 3. Click "Create New App" → "From scratch"
644
+ 4. `browser_fill_form` with app name "Maestro - {AgentFirstName}", select workspace
645
+ 5. Navigate to OAuth & Permissions
646
+ 6. Add Bot Token Scopes: `chat:write`, `chat:write.customize`, `channels:read`, `channels:history`, `groups:read`, `groups:history`, `im:read`, `im:history`, `im:write`, `users:read`, `users:read.email`, `reactions:read`, `reactions:write`, `files:read`, `files:write`
647
+ 7. Add User Token Scopes: `channels:history`, `groups:history`, `im:history`, `search:read`, `chat:write`
648
+ 8. Click "Install to Workspace" → authorize
649
+ 9. Extract Bot User OAuth Token (xoxb-...) and User OAuth Token (xoxp-...) from the page
650
+ 10. Navigate to Basic Information → extract Signing Secret
651
+ 11. Write `SLACK_BOT_TOKEN`, `SLACK_USER_TOKEN`, `SLACK_SIGNING_SECRET` to `.env`
652
+
653
+ **Verify:**
654
+ ```bash
655
+ source .env && curl -s -H "Authorization: Bearer $SLACK_USER_TOKEN" https://slack.com/api/auth.test | python3 -c "import json,sys; d=json.load(sys.stdin); print('Slack OK: ' + d.get('user','') if d.get('ok') else 'FAIL: ' + d.get('error',''))"
656
+ ```
564
657
 
565
- ### Step 4: Cloudflare Tunnel (Optional)
658
+ ### Step 2: Gmail per `docs/guides/email-setup.md`
566
659
 
660
+ Gmail app passwords require 2FA interaction — ask user:
567
661
  ```
568
- Does this agent need a public URL for webhooks? (yes/no)
569
- (Required for: Slack Events API, Twilio voice callbacks, WhatsApp webhooks)
662
+ Gmail setup: Please generate an app password:
663
+ 1. Go to https://myaccount.google.com/apppasswords (or I can open it for you)
664
+ 2. Generate a password for "Mail" on "Mac"
665
+ 3. Paste the 16-character password here:
570
666
  ```
571
667
 
572
- If yes:
668
+ After receiving the password:
669
+ 1. Write `GMAIL_APP_PASSWORD` to `.env`
670
+ 2. If monitoring principal's inbox, ask for secondary password → `SECONDARY_GMAIL_APP_PASSWORD`
671
+ 3. Install msmtp: `brew install msmtp 2>/dev/null || true`
672
+ 4. Write `~/.msmtprc` per guide § 1.4, set `chmod 600 ~/.msmtprc`
673
+
674
+ **Verify:**
675
+ ```bash
676
+ source .env && python3 -c "import imaplib,os; m=imaplib.IMAP4_SSL('imap.gmail.com'); m.login('${AGENT_EMAIL}', os.environ['GMAIL_APP_PASSWORD']); print('IMAP OK'); m.logout()"
573
677
  ```
574
- Cloudflare tunnel options:
575
678
 
576
- 1. Quick tunnel (free, URL changes on restart):
577
- cloudflared tunnel --url http://localhost:3100
679
+ ### Step 3: Twilio (SMS + WhatsApp) per `docs/guides/voice-sms-setup.md`, `docs/guides/whatsapp-setup.md`
578
680
 
579
- 2. Named tunnel (free, persistent URL recommended):
580
- cloudflared tunnel create {agent-name}
581
- cloudflared tunnel route dns {agent-name} {agent-name}.yourdomain.com
681
+ **If user has credentials:** ask for Account SID, Auth Token, Phone Number → write to `.env`.
582
682
 
583
- 3. Skip (configure manually later)
683
+ **If creating new account — execute via Playwright:**
584
684
 
585
- Which option? (1/2/3)
586
- ```
685
+ 1. `browser_navigate` to `https://www.twilio.com/console`
686
+ 2. `browser_snapshot` — if not logged in, ask user to log in via `! open https://www.twilio.com/login`
687
+ 3. Once authenticated, extract Account SID and Auth Token from Console dashboard
688
+ 4. Navigate to Phone Numbers → Buy a Number → search for SMS+Voice number in preferred country
689
+ 5. **Ask user to confirm the purchase** (payment authorisation)
690
+ 6. After purchase, extract phone number (E.164) and Phone SID
691
+ 7. Write `TWILIO_ACCOUNT_SID`, `TWILIO_AUTH_TOKEN`, `TWILIO_PHONE_NUMBER`, `TWILIO_PHONE_SID` to `.env`
587
692
 
588
- For option 1, run `cloudflared tunnel --url http://localhost:3100` and capture the URL.
589
- For option 2, guide through the DNS setup steps.
693
+ **If SMS selected:** Configure webhook per guide:
694
+ 1. Navigate to Twilio Console Phone Numbers → Active Numbers → select number
695
+ 2. Under Messaging → "A message comes in" → Webhook POST → `{tunnel_url}/sms`
696
+ 3. Enable geo-permissions: navigate to Messaging → Settings → Geo Permissions → enable needed countries
590
697
 
591
- ### Step 5: Voice Integration (Optional)
698
+ **If WhatsApp selected:** Configure sandbox per guide:
699
+ 1. `browser_navigate` to `https://console.twilio.com/us1/develop/sms/try-it-out/whatsapp-learn`
700
+ 2. Under Sandbox Settings → set webhook URL to `{tunnel_url}/whatsapp` POST
701
+ 3. Set Status Callback to `{tunnel_url}/whatsapp/status` POST
702
+ 4. Note and report the sandbox join keyword to the user
703
+ 5. Write `WHATSAPP_MODE=sandbox`, `WHATSAPP_PORT=3002` to `.env`
592
704
 
593
- ```
594
- Does this agent need voice capabilities (phone calls, huddle participation)? (yes/no)
705
+ ### Step 4: Webhook Relay (Railway) — per `docs/guides/webhook-relay-setup.md`
706
+
707
+ **This is the canonical pattern. Do NOT use Cloudflare Tunnels for new agents** — they were a transitional approach. Each agent gets its own Railway-deployed webhook relay. The local Mac mini polls the relay every 5 seconds and never needs an inbound tunnel.
708
+
709
+ The relay handles:
710
+ - `POST /slack/events` — Slack Events API (HMAC verified via SLACK_SIGNING_SECRET)
711
+ - `POST /sms` — Twilio SMS inbound (HMAC verified via TWILIO_AUTH_TOKEN)
712
+ - `POST /whatsapp` — Twilio WhatsApp inbound
713
+ - `POST /whatsapp/status` — Twilio WhatsApp delivery status
714
+ - `GET /events`, `/sms/messages`, `/whatsapp/messages` — drained by Mac mini poller
715
+ - `GET /health` — service status
716
+
717
+ **Source code** is already in the repo at `services/webhook-relay/` (copied from the maestro framework). It's a ~250-line Node 20 HTTP server, no dependencies, deployable straight to Railway.
718
+
719
+ **Prerequisites:**
720
+ - Railway CLI installed: `brew install railway 2>/dev/null || true`
721
+ - User must run `railway login` once (interactive — opens browser)
722
+ - User must have admin rights in the company's Railway workspace (e.g., "Adaptic")
723
+
724
+ **Deploy steps (run from the agent's repo root):**
725
+
726
+ ```bash
727
+ # 1. Create the project in the company's Railway workspace
728
+ cd services/webhook-relay
729
+ railway init --name {firstname-lower}-webhook-relay --workspace {Company}
730
+
731
+ # 2. Add the service and deploy
732
+ railway up --service {firstname-lower}-webhook-relay --detach
733
+
734
+ # 3. Generate a public domain
735
+ railway domain --service {firstname-lower}-webhook-relay
736
+ # Captures: https://{firstname-lower}-webhook-relay-production.up.railway.app
737
+
738
+ # 4. Set env vars (must include the agent's own SLACK_SIGNING_SECRET and TWILIO_AUTH_TOKEN)
739
+ source ../../.env
740
+ railway variables --service {firstname-lower}-webhook-relay \
741
+ --set "SLACK_SIGNING_SECRET=$SLACK_SIGNING_SECRET" \
742
+ --set "TWILIO_AUTH_TOKEN=$TWILIO_AUTH_TOKEN" \
743
+ --set "PUBLIC_HOSTNAME={firstname-lower}-webhook-relay-production.up.railway.app" \
744
+ --set "BUFFER_TTL_MS=600000" \
745
+ --set "MAX_BUFFER_SIZE=1000"
746
+
747
+ # 5. Trigger redeploy so the running container picks up the new env vars
748
+ railway up --service {firstname-lower}-webhook-relay --detach
749
+
750
+ # 6. Wait until /health returns slack_signature: true and twilio_signature: true
751
+ for i in 1 2 3 4 5 6 7 8 9 10 11 12; do
752
+ RESP=$(curl -sf -m 5 https://{firstname-lower}-webhook-relay-production.up.railway.app/health)
753
+ if echo "$RESP" | grep -q '"slack_signature":true' && echo "$RESP" | grep -q '"twilio_signature":true'; then
754
+ echo "Relay live with signature verification"
755
+ break
756
+ fi
757
+ sleep 10
758
+ done
595
759
  ```
596
760
 
597
- If yes:
761
+ **Configure external services to point at the relay:**
762
+
763
+ ```bash
764
+ # Twilio SMS webhook (uses Twilio API directly, no UI)
765
+ RELAY_URL="https://{firstname-lower}-webhook-relay-production.up.railway.app"
766
+ curl -s -u "$TWILIO_ACCOUNT_SID:$TWILIO_AUTH_TOKEN" -X POST \
767
+ "https://api.twilio.com/2010-04-01/Accounts/$TWILIO_ACCOUNT_SID/IncomingPhoneNumbers/$TWILIO_PHONE_SID.json" \
768
+ --data-urlencode "SmsUrl=$RELAY_URL/sms" --data-urlencode "SmsMethod=POST"
598
769
  ```
599
- Voice setup requires:
600
- 1. ElevenLabs API key (for text-to-speech)
601
- → Sign up at https://elevenlabs.io/
602
- → Copy your API key from Profile → API Keys
603
-
604
- 2. Deepgram API key (for speech-to-text)
605
- → Sign up at https://deepgram.com/
606
- → Copy your API key from Console → API Keys
607
770
 
608
- 3. BlackHole virtual audio (for huddle participation)
609
- → This will be installed by the audio setup script
771
+ For **Slack Events Subscription**: use Playwright to update via the App Manifest editor (more reliable than the events page). Navigate to `https://app.slack.com/app-settings/{TEAM_ID}/{APP_ID}/app-manifest`, read the JSON via the CodeMirror instance, add this block to `settings`, and click Save Changes:
610
772
 
611
- Paste API keys:
612
- ElevenLabs API key:
613
- Deepgram API key:
773
+ ```json
774
+ "event_subscriptions": {
775
+ "request_url": "https://{firstname-lower}-webhook-relay-production.up.railway.app/slack/events",
776
+ "bot_events": [
777
+ "app_mention",
778
+ "message.channels",
779
+ "message.groups",
780
+ "message.im",
781
+ "message.mpim"
782
+ ]
783
+ }
614
784
  ```
615
785
 
616
- Write to `.env`. Then run: `bash scripts/huddle/setup-audio.sh`
786
+ After save, navigate to the Event Subscriptions page and check for the yellow "Click here to verify" button — click it. Then **reinstall the app** at `https://api.slack.com/apps/{APP_ID}/install-on-team` so the new event scopes activate.
787
+
788
+ For **Twilio WhatsApp sandbox**: this requires a per-agent Twilio sub-account (see Phase 4 Step 3.5). Cannot share with other agents because the sandbox webhook is account-wide.
617
789
 
618
- ### Step 6: Additional Services (Optional)
790
+ **Update local poll script:**
619
791
 
792
+ ```bash
793
+ # Edit scripts/poll-slack-events.sh and scripts/comms-monitor.sh
794
+ # Set EVENTS_URL to https://{firstname-lower}-webhook-relay-production.up.railway.app/events
620
795
  ```
621
- Any additional services to configure?
622
- 1. OpenAI API key (supplemental model access)
623
- 2. Gemini API key (media generation)
624
- 3. Greptile API key (code search)
625
- 4. Done — skip remaining
626
796
 
627
- Which? (comma-separated numbers, or "done")
797
+ **Install the launchd job that polls the relay every 5 seconds:**
798
+
799
+ ```bash
800
+ cat > scripts/local-triggers/plists/ai.adaptic.{firstname-lower}-poll-relay.plist <<EOF
801
+ <?xml version="1.0" encoding="UTF-8"?>
802
+ <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
803
+ <plist version="1.0">
804
+ <dict>
805
+ <key>Label</key><string>ai.adaptic.{firstname-lower}-poll-relay</string>
806
+ <key>ProgramArguments</key><array>
807
+ <string>/bin/bash</string>
808
+ <string>{REPO_ROOT}/scripts/poll-slack-events.sh</string>
809
+ </array>
810
+ <key>WorkingDirectory</key><string>{REPO_ROOT}</string>
811
+ <key>StartInterval</key><integer>5</integer>
812
+ <key>RunAtLoad</key><true/>
813
+ <key>StandardOutPath</key><string>{REPO_ROOT}/logs/polling/poll-relay-stdout.log</string>
814
+ <key>StandardErrorPath</key><string>{REPO_ROOT}/logs/polling/poll-relay-stderr.log</string>
815
+ </dict>
816
+ </plist>
817
+ EOF
818
+ cp scripts/local-triggers/plists/ai.adaptic.{firstname-lower}-poll-relay.plist ~/Library/LaunchAgents/
819
+ launchctl load ~/Library/LaunchAgents/ai.adaptic.{firstname-lower}-poll-relay.plist
820
+ ```
821
+
822
+ **Add the relay URL block to `.env`:**
823
+
824
+ ```bash
825
+ cat >> .env <<EOF
826
+
827
+ # ─── RAILWAY WEBHOOK RELAY ──────────────────────────────────────────────────
828
+ WEBHOOK_RELAY_URL=https://{firstname-lower}-webhook-relay-production.up.railway.app
829
+ WEBHOOK_RELAY_SLACK_EVENTS=https://{firstname-lower}-webhook-relay-production.up.railway.app/slack/events
830
+ WEBHOOK_RELAY_SMS_INBOUND=https://{firstname-lower}-webhook-relay-production.up.railway.app/sms
831
+ WEBHOOK_RELAY_WHATSAPP_INBOUND=https://{firstname-lower}-webhook-relay-production.up.railway.app/whatsapp
832
+ WEBHOOK_RELAY_POLL_EVENTS=https://{firstname-lower}-webhook-relay-production.up.railway.app/events
833
+ WEBHOOK_RELAY_POLL_SMS=https://{firstname-lower}-webhook-relay-production.up.railway.app/sms/messages
834
+ WEBHOOK_RELAY_POLL_WHATSAPP=https://{firstname-lower}-webhook-relay-production.up.railway.app/whatsapp/messages
835
+ EOF
628
836
  ```
629
837
 
630
- For each, prompt for the API key and write to `.env`.
838
+ **End-to-end test:**
631
839
 
632
- ### Step 7: Service Verification
840
+ 1. Have Lucas (or any user) send a Slack message to a channel where the bot is a member, OR @-mention the bot in a public channel
841
+ 2. Within ~5 seconds, the local Mac mini should fetch the buffered event and write a YAML file to `state/inbox/slack/`
842
+ 3. The inbox processor picks it up and routes it
843
+ 4. Verify `railway logs --service {firstname-lower}-webhook-relay` shows `[slack] buffered ...`
633
844
 
634
- After all services are configured, run verification:
845
+ ### Step 5: Voice / Huddle — per `docs/guides/voice-sms-setup.md` § 5
635
846
 
847
+ **API keys** — if user has them, paste directly. Otherwise, drive signup via Playwright:
848
+
849
+ 1. **ElevenLabs**: `browser_navigate` to `https://elevenlabs.io/` → sign up or log in → navigate to Profile → API Keys → extract key
850
+ 2. **Deepgram**: `browser_navigate` to `https://console.deepgram.com/` → sign up or log in → navigate to API Keys → create and extract key
851
+ 3. Write `ELEVENLABS_API_KEY`, `DEEPGRAM_API_KEY` to `.env`
852
+
853
+ **Local setup:**
636
854
  ```bash
637
- npm run healthcheck
855
+ bash scripts/huddle/setup-audio.sh # Install BlackHole, sox, verify
856
+ cd scripts/huddle && npm install && cd ../.. # Install huddle Node.js deps
857
+ bash scripts/huddle/launch-slack.sh # Launch Slack with CDP
638
858
  ```
639
859
 
640
- Report the results and flag any services that aren't configured.
860
+ ### Step 6: Media Generation per `docs/guides/media-generation-setup.md`
641
861
 
642
- ## Phase 5: Generate Agent README
862
+ 1. If user has Gemini key, paste directly. Otherwise: `browser_navigate` to `https://aistudio.google.com/apikey` → extract or create key
863
+ 2. Write `GEMINI_API_KEY` to `.env`
643
864
 
644
- Generate a comprehensive README.md for this agent's repository. This is NOT the Maestro framework README — it describes THIS specific agent.
865
+ ### Step 7: Additional Keys
645
866
 
646
- **Template structure:**
867
+ Prompt for any remaining optional keys: `OPENAI_API_KEY`, `GREPTILE_API_KEY`. Write to `.env` or skip.
647
868
 
648
- ```markdown
649
- # {repoName}
869
+ ## Phase 5: Subsystem Implementation & Verification
650
870
 
651
- **{fullName}Autonomous {title} for {company}**
871
+ After credentials are configured, this phase **autonomously implements and verifies** every subsystem by following each implementation guide's setup and test steps. This ensures the agent is actually operational not just configured with API keys.
652
872
 
653
- Powered by [@adaptic/maestro](https://github.com/adapticai/maestro)
873
+ **Execution:** Spawn parallel background agents for independent subsystems. Report results as a verification matrix. Do NOT proceed to Phase 6 until all selected subsystems pass (or user explicitly accepts failures).
654
874
 
655
- ---
656
-
657
- ## Who is {firstName}?
875
+ Tell the user:
876
+ ```
877
+ Credentials configured. Now I'll set up and verify each subsystem end-to-end.
878
+ This runs autonomously — I'll report results when complete.
879
+ ```
658
880
 
659
- {firstName} {lastName} is an autonomous AI agent operating as {title} at {company}.
660
- {companyDescription}. {firstName} runs 24/7 on a dedicated Mac mini ({machineName}),
661
- using Claude Code as the reasoning engine and orchestrating 30+ specialist sub-agents.
881
+ ### 5.1 Outbound Governance `docs/guides/outbound-governance-setup.md`
662
882
 
663
- {firstName} reports to {principalFullName} ({principalTitle}) and operates with
664
- {describe autonomy level based on archetype}.
883
+ Verify FIRST all send scripts depend on this.
665
884
 
666
- ## Capabilities
885
+ 1. Verify hooks registered in `.claude/settings.json` (PreToolUse for block-mcp-slack-send and pre-send-audit, PostToolUse for post-action-log, Stop for session-end-log)
886
+ 2. `chmod +x scripts/hooks/*.sh`
887
+ 3. Test dedup: generate key → acquire → verify CLAIMED → cleanup
888
+ 4. Test validate-outbound.py runs without crash
889
+ 5. Test disclosure_assessment.py runs without crash
667
890
 
668
- {Generate 8-12 bullet points based on the archetype and responsibilities.
669
- For executive-operator: comms management, briefs, hiring, strategic execution, etc.
670
- For technical-leader: code review, architecture decisions, engineering health, etc.
671
- For compliance-officer: regulatory tracking, filing management, audit readiness, etc.
672
- Tailor to the specific responsibilities gathered in Phase 1.}
891
+ ### 5.2 Email `docs/guides/email-setup.md`
673
892
 
674
- ## Architecture
893
+ 1. Test IMAP connectivity (if GMAIL_APP_PASSWORD set)
894
+ 2. Verify msmtp config exists: `test -f ~/.msmtprc`
895
+ 3. Verify email signature files: `test -f scripts/email-signature.html`
896
+ 4. `chmod +x scripts/send-email.sh`
675
897
 
676
- Built on the Maestro 5-tier agent architecture:
898
+ ### 5.3 Slack `docs/guides/slack-setup.md`
677
899
 
678
- - **Tier 0**: {firstName} (Executive Cortex) core identity and reasoning
679
- - **Tier 1**: {Generate 4-5 domain controllers relevant to the archetype}
680
- - **Tier 2**: 31 specialist sub-agents
681
- - **Tier 3**: Slack, Gmail, WhatsApp, Browser, Calendar
682
- - **Tier 4**: Decision Log, Risk Register, Knowledge Base
900
+ 1. Test token: `curl -s -H "Authorization: Bearer $SLACK_USER_TOKEN" https://slack.com/api/auth.test`
901
+ 2. Verify slack-send.sh uses xoxp- token (not xoxb-)
902
+ 3. Verify typing indicator exists: `test -f scripts/slack-typing.mjs`
903
+ 4. Verify MCP block hook: `test -f scripts/hooks/block-mcp-slack-send.sh`
683
904
 
684
- ## Powered by Maestro
905
+ ### 5.4 SMS & WhatsApp — `docs/guides/voice-sms-setup.md`, `docs/guides/whatsapp-setup.md`
685
906
 
686
- This repo is an agent instance powered by the [@adaptic/maestro](https://www.npmjs.com/package/@adaptic/maestro) framework.
907
+ 1. Verify `config/caller-id-map.yaml` exists and has principal with `access_level: ceo`
908
+ 2. Start SMS handler, verify health: `curl http://localhost:3001/health`
909
+ 3. Start WhatsApp handler, verify health: `curl http://localhost:3002/health`
910
+ 4. `chmod +x scripts/send-sms.sh scripts/send-whatsapp.sh`
687
911
 
688
- Update framework: npm update @adaptic/maestro && npm run upgrade
689
- Health check: npm run healthcheck
690
- Emergency stop: npm run emergency-stop
912
+ ### 5.5 Voice / Huddle `docs/guides/voice-sms-setup.md` § 5
691
913
 
692
- ## Operating Modes
914
+ 1. `bash scripts/huddle/setup-audio.sh --check`
915
+ 2. Verify huddle deps: `test -d scripts/huddle/node_modules`
916
+ 3. Verify Deepgram + ElevenLabs keys are set
693
917
 
694
- - **Reactive**: Polls Slack/Gmail/Calendar every 60s, classifies and dispatches
695
- - **Scheduled**: {morningBrief time} brief, midday sweep, {eveningWrap time} wrap, weekly cycles
696
- - **Proactive**: Backlog executor every 10 min, parallel agent execution
918
+ ### 5.6 Poller & Daemon `docs/guides/poller-daemon-setup.md`
697
919
 
698
- ## Commands
920
+ 1. Run poller once: `timeout 30 node scripts/poller/index.mjs`
921
+ 2. Verify daemon entry point: `head -5 scripts/daemon/maestro-daemon.mjs`
922
+ 3. Verify plists generated: `ls scripts/local-triggers/plists/*.plist | wc -l`
923
+ 4. Test emergency stop: `touch .emergency-stop` → run trigger → verify blocked → `rm .emergency-stop`
924
+ 5. Verify watchdog: `bash scripts/watchdog/memory-watchdog.sh --check`
699
925
 
700
- | Command | Purpose |
701
- |---------|---------|
702
- | npm run daemon | Start the main orchestrator |
703
- | npm run healthcheck | Verify all subsystems |
704
- | npm run emergency-stop | Halt all operations |
705
- | npm run resume | Resume after emergency stop |
706
- | npm run upgrade | Pull latest Maestro framework |
707
- | claude "/init-maestro" | Reconfigure agent identity |
926
+ ### 5.7 RAG & Context — `docs/guides/rag-context-setup.md`
708
927
 
709
- ## Communication Governance
928
+ 1. Build search index: `python3 scripts/rag-indexer.py --full`
929
+ 2. Verify docs indexed: `python3 scripts/rag-indexer.py --stats`
930
+ 3. Test search: `python3 scripts/user-context-search.py --user unknown --query "adaptic" --max-results 1`
931
+ 4. Run test suite if available: `bash scripts/test-rag-search.sh`
710
932
 
711
- {Generate based on archetype:
712
- - executive-operator: broad autonomy with escalation for legal/financial commitments
713
- - technical-leader: autonomous on technical decisions, escalates on budget/headcount
714
- - compliance-officer: conservative, escalates on submissions and interpretations
715
- - etc.}
933
+ ### 5.8 PDF Generation — `docs/guides/pdf-generation-setup.md`
716
934
 
717
- ---
935
+ 1. `pandoc --version`
936
+ 2. Check XeLaTeX: `xelatex --version 2>/dev/null || ~/Library/TinyTeX/bin/universal-darwin/xelatex --version 2>/dev/null`
937
+ 3. Generate test PDF:
938
+ ```bash
939
+ echo "# Test\nGenerated by init-maestro." > /tmp/init-test.md
940
+ node scripts/pdf-generation/build-document.mjs --input /tmp/init-test.md --template memo --output /tmp/init-test.pdf
941
+ test -f /tmp/init-test.pdf && echo "PDF OK"
942
+ rm -f /tmp/init-test.md /tmp/init-test.pdf
943
+ ```
718
944
 
719
- {fullName} | {title} | {company} Powered by [Maestro](https://github.com/adapticai/maestro)
720
- ```
945
+ ### 5.9 Media Generation`docs/guides/media-generation-setup.md`
721
946
 
722
- Write this README.md to the repo root, populated with all the gathered values.
947
+ 1. Verify Gemini key set
948
+ 2. List specs: `node scripts/media-generation/generate-assets.mjs --list`
949
+ 3. Verify client loads: `node -e "import('./scripts/media-generation/gemini-image-client.mjs').then(() => console.log('OK'))"`
723
950
 
724
- ## Phase 6: Create GitHub Repository
951
+ ### 5.10 Verification Summary
725
952
 
726
- Ask the user whether they want to create a GitHub repo for this agent:
953
+ Print results:
727
954
 
728
955
  ```
729
- Would you like me to create a GitHub repository for this agent? (yes/no)
956
+ ╔══════════════════════════════════════════════════════════════╗
957
+ ║ SUBSYSTEM VERIFICATION RESULTS ║
958
+ ╠══════════════════════════════════════════════════════════════╣
959
+ ║ ║
960
+ ║ Outbound Governance ✅ PASS hooks, dedup, validation ║
961
+ ║ Email (Gmail) ✅ PASS IMAP, SMTP, signatures ║
962
+ ║ Slack ✅ PASS tokens, send, typing ║
963
+ ║ SMS (Twilio) ✅ PASS handler, send, caller-id ║
964
+ ║ WhatsApp ⏭️ SKIP not selected ║
965
+ ║ Voice / Huddle ⏭️ SKIP not selected ║
966
+ ║ Poller & Daemon ✅ PASS poller, plists, watchdog ║
967
+ ║ RAG & Context ✅ PASS index built, search works ║
968
+ ║ PDF Generation ✅ PASS pandoc + xelatex OK ║
969
+ ║ Media Generation ⏭️ SKIP not selected ║
970
+ ║ ║
971
+ ║ Overall: 7/7 selected subsystems PASS ║
972
+ ║ ║
973
+ ║ Guides: docs/guides/ (for detailed testing & troubleshoot) ║
974
+ ╚══════════════════════════════════════════════════════════════╝
730
975
  ```
731
976
 
732
- If yes:
977
+ If any subsystem FAILS: diagnose via the guide's troubleshooting section, attempt one fix, re-run check. If still failing, report failure with specific error and ask user whether to continue or abort.
978
+
979
+ ## Phase 6: Generate Agent README
980
+
981
+ Generate a comprehensive README.md for this agent's repository. This describes THIS specific agent, not the Maestro framework.
982
+
983
+ Include all of the following sections populated with gathered values:
984
+
985
+ 1. **Title and tagline**: `{fullName} — Autonomous {title} for {company}`
986
+ 2. **Who is {firstName}?**: 3-4 sentence description of role, reporting line, autonomy level
987
+ 3. **Capabilities**: 8-12 bullet points based on archetype and responsibilities
988
+ 4. **Architecture**: 5-tier model with role-specific domain controllers
989
+ 5. **Subsystem Status**: Include the Phase 5 verification matrix
990
+ 6. **Operating Modes**: Reactive (polling), Scheduled (triggers), Proactive (backlog)
991
+ 7. **Commands**: npm run daemon, healthcheck, emergency-stop, resume, upgrade
992
+ 8. **Implementation Guides**: Table linking to all 10 guides in `docs/guides/`
993
+ 9. **Communication Governance**: Based on archetype autonomy model
994
+
995
+ Write to repo root as `README.md`.
996
+
997
+ ## Phase 7: Create GitHub Repository
998
+
999
+ Ask the user whether they want to create a GitHub repo:
733
1000
 
734
1001
  ```
735
- Repository setup:
736
- 1. GitHub organization or username? (default: adapticai)
737
- 2. Repository name? (default: {repoName}, e.g., "jacob-ai")
738
- 3. Visibility: private (recommended) or public? (default: private)
1002
+ Would you like me to create a GitHub repository for this agent? (yes/no)
739
1003
  ```
740
1004
 
741
- Then run:
742
- ```bash
743
- gh repo create {org}/{repoName} --private --description "{fullName} — Autonomous {title} for {company} (powered by Maestro)"
744
- ```
1005
+ If yes: ask for org/username (default: adapticai), repo name (default: {repoName}), visibility (default: private). Then:
745
1006
 
746
- After creating the repo, set up git and push:
747
1007
  ```bash
1008
+ gh repo create {org}/{repoName} --private --description "{fullName} — Autonomous {title} for {company} (powered by Maestro)"
748
1009
  git remote add origin https://github.com/{org}/{repoName}.git
749
1010
  git add -A
750
1011
  git commit -m "Initialize {fullName} as {title} — powered by @adaptic/maestro"
751
1012
  git push -u origin main
752
1013
  ```
753
1014
 
754
- If the user declines, skip this step and remind them to set up a repo manually later.
1015
+ ## Phase 8: Final Verification
755
1016
 
756
- ## Phase 7: Final Verification
1017
+ ### Step 1: Grep for stale agent references
757
1018
 
758
- After ALL phases are complete, run these verification steps:
759
-
760
- ### Step 1: Grep for old agent references
761
-
762
- Search critical files for any remaining references to the old agent's first name (case-insensitive). Check:
763
- - CLAUDE.md
764
- - config/agent.ts
765
- - config/environment.yaml
766
- - config/contacts.yaml
767
- - config/priorities.yaml
768
- - package.json
769
- - All files in schedules/triggers/
770
- - All agent.md files in agents/
771
-
772
- Report any stragglers and fix them.
1019
+ Search critical files for old agent name (case-insensitive): CLAUDE.md, config/agent.ts, config/*.yaml, package.json, schedules/triggers/*.md, agents/*/agent.md. Fix any stragglers.
773
1020
 
774
1021
  ### Step 2: Validate config/agent.ts
775
1022
 
776
- Read `config/agent.ts` and verify it has valid TypeScript syntax and all fields are populated with the new values.
1023
+ Read and verify valid TypeScript, all fields populated with new values.
777
1024
 
778
- ### Step 3: Run health check
1025
+ ### Step 3: Health check
779
1026
 
780
1027
  ```bash
781
1028
  npm run healthcheck
782
1029
  ```
783
1030
 
784
- Report the results.
785
-
786
- ### Step 4: Summary
787
-
788
- Print a completion summary:
1031
+ ### Step 4: Completion Summary
789
1032
 
790
1033
  ```
791
- Maestro initialization complete.
1034
+ ═══════════════════════════════════════════════════════════════
1035
+ MAESTRO INITIALIZATION COMPLETE
1036
+ ═══════════════════════════════════════════════════════════════
792
1037
 
793
1038
  Agent: {fullName}, {title}
794
1039
  Archetype: {archetype}
@@ -796,41 +1041,38 @@ Maestro initialization complete.
796
1041
  Principal: {principalName}
797
1042
  Machine: {machineName}
798
1043
 
799
- Files modified:
800
- - config/agent.ts (central identity config)
801
- - CLAUDE.md (operating charter)
802
- - README.md (agent-specific documentation)
803
- - config/environment.yaml, contacts.yaml, priorities.yaml
804
- - package.json
805
- - agents/{agent-slug}/agent.md (+ 30 other agent definitions)
806
- - schedules/triggers/ (13 trigger prompts)
1044
+ Identity (Phase 2): ✅ 8 parallel agents rewrote repo
1045
+ Infrastructure (Phase 3): ✅ {N} launchd triggers installed
1046
+ Services (Phase 4): ✅ {list configured services}
1047
+ Subsystems (Phase 5): {include verification matrix}
1048
+ README (Phase 6): ✅ Agent-specific README generated
1049
+ GitHub (Phase 7): {repo URL or "skipped"}
807
1050
 
808
- Infrastructure:
809
- - {N} launchd triggers installed
810
- - Global Claude Code settings configured
811
- - .env file created {with/without API keys}
1051
+ ─────────────────────────────────────────────────────────
812
1052
 
813
- GitHub: https://github.com/{org}/{repoName} (if created)
1053
+ Next steps:
1054
+ 1. Start the daemon: npm run daemon
1055
+ 2. Monitor logs: tail -f logs/daemon/$(date +%Y-%m-%d)-sessions.jsonl
1056
+ 3. Test a message: Send a Slack DM to {firstName}
814
1057
 
815
- Verify everything:
816
- 1. Review changes: git diff
817
- 2. Check daemons: launchctl list | grep adaptic
818
- 3. Health check: npm run healthcheck
819
- 4. Start daemon: npm run daemon
1058
+ Implementation guides: docs/guides/
1059
+ ═══════════════════════════════════════════════════════════════
820
1060
  ```
821
1061
 
822
- ## Guidelines for the Wizard Conversation
1062
+ ## Guidelines for the Wizard
823
1063
 
824
1064
  - Be warm and professional. This is a setup experience, not an interrogation.
825
- - Offer sensible defaults wherever possible. If the user says "defaults" for any field, use the archetype-appropriate default.
826
- - If the user provides all information upfront (e.g., as arguments to the command), skip the conversational steps and go straight to confirmation.
827
- - Always confirm before executing. The changes are extensive and hard to undo.
828
- - When spawning sub-agents, give each one the COMPLETE set of gathered values so they can work independently.
829
- - Sub-agents MUST run in parallel (use `run_in_background: true`) -- do not run them sequentially.
830
- - After all sub-agents finish, do the verification grep yourself (do not delegate it).
1065
+ - Offer sensible defaults wherever possible.
1066
+ - Always confirm before executing identity changes (Phase 2). Service configuration (Phase 4) and verification (Phase 5) execute autonomously after the user selects services.
1067
+ - Sub-agents MUST run in parallel (`run_in_background: true`).
1068
+ - **Autonomous execution is the default.** Only ask for input when you cannot proceed without it (credentials, 2FA, payment). Everything else web UI navigation, script execution, file writes, verification — you do yourself.
1069
+ - **Use Playwright MCP** for web UIs: Slack API portal, Twilio Console, Google Account, ElevenLabs, Deepgram, Gemini.
1070
+ - **Use Bash** for local operations: scripts, installs, service starts, tests.
1071
+ - If Playwright fails (auth wall, CAPTCHA), fall back to asking user to do that specific step via `! open <url>`, then resume.
831
1072
 
832
1073
  ## Error Handling
833
1074
 
834
- - If a sub-agent fails, report which one failed and what went wrong. Offer to retry just that sub-agent.
835
- - If the user wants to abort mid-wizard, confirm and exit cleanly.
836
- - If config/agent.ts cannot be read, warn that the repo may not be properly set up and suggest running `npx @adaptic/maestro create` first.
1075
+ - If a sub-agent fails, report which one and offer to retry.
1076
+ - If a Phase 5 subsystem verification fails, diagnose using the guide's troubleshooting section, attempt one fix, re-run. If still failing, report with specific error and ask whether to continue.
1077
+ - If user aborts mid-wizard, exit cleanly.
1078
+ - If config/agent.ts unreadable, suggest `npx @adaptic/maestro create` first.