@adaptic/maestro 1.8.2 → 1.8.3

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 (43) hide show
  1. package/bin/maestro.mjs +15 -3
  2. package/package.json +1 -1
  3. package/plugins/maestro-skills/skills/board-deck.md +2 -2
  4. package/plugins/maestro-skills/skills/decision-brief.md +6 -6
  5. package/plugins/maestro-skills/skills/draft-comms.md +9 -9
  6. package/plugins/maestro-skills/skills/evening-wrap.md +2 -2
  7. package/plugins/maestro-skills/skills/hiring-triage.md +4 -4
  8. package/plugins/maestro-skills/skills/inbox-triage.md +5 -5
  9. package/plugins/maestro-skills/skills/morning-brief.md +4 -4
  10. package/plugins/maestro-skills/skills/pipeline-review.md +2 -2
  11. package/plugins/maestro-skills/skills/regulatory-status.md +2 -2
  12. package/plugins/maestro-skills/skills/schedule-meeting.md +3 -3
  13. package/plugins/maestro-skills/skills/slack-followup.md +5 -5
  14. package/plugins/maestro-skills/skills/weekly-memo.md +5 -5
  15. package/scaffold/CLAUDE.md +21 -0
  16. package/scripts/daemon/classifier.mjs +21 -5
  17. package/scripts/hooks/block-mcp-slack-send.sh +1 -1
  18. package/scripts/huddle/audio-bridge.mjs +17 -17
  19. package/scripts/huddle/boot-slack-cdp.sh +1 -1
  20. package/scripts/huddle/huddle-controller.mjs +3 -3
  21. package/scripts/huddle/huddle-server.mjs +21 -7
  22. package/scripts/huddle/launch-slack.sh +2 -2
  23. package/scripts/huddle/package-lock.json +2 -2
  24. package/scripts/huddle/package.json +2 -2
  25. package/scripts/huddle/setup-audio.sh +6 -6
  26. package/scripts/huddle/start-call.mjs +2 -2
  27. package/scripts/huddle/test-pipeline.mjs +2 -2
  28. package/scripts/parse-voice-transcript.mjs +4 -9
  29. package/scripts/poller/gmail-poller.mjs +8 -2
  30. package/scripts/poller/intra-session-check.mjs +4 -3
  31. package/scripts/poller-launchd/install.sh +48 -10
  32. package/scripts/pre_draft_lookup.py +2 -2
  33. package/scripts/self-optimization/compute-metrics.py +23 -2
  34. package/scripts/setup/boot-claude-session.sh +14 -5
  35. package/scripts/setup/render-environment-yaml.mjs +133 -0
  36. package/scripts/watchdog/ai.maestro.memory-watchdog.plist +3 -3
  37. package/scripts/watchdog/force-reboot.sh +3 -3
  38. package/scripts/watchdog/memory-watchdog.sh +11 -5
  39. package/workflows/daily/applicant-triage.yaml +3 -3
  40. package/workflows/daily/comms-triage.yaml +1 -1
  41. package/workflows/daily/morning-brief.yaml +1 -1
  42. package/workflows/daily/slack-followup-sweep.yaml +1 -1
  43. package/workflows/weekly/hiring-review.yaml +3 -3
package/bin/maestro.mjs CHANGED
@@ -1229,11 +1229,11 @@ Per-file behaviour:
1229
1229
  // them so launchd enqueues cadence events instead of spawning Claude.
1230
1230
  const cadenceMigration = migrateCadenceBus(cwd, flags);
1231
1231
 
1232
- // Regenerate config/agent.env from config/agent.json so newly-installed
1233
- // (or already-installed) shell scripts find the agent identity vars.
1234
- // Soft failure — older agents that haven't migrated to the SOT layout
1232
+ // Regenerate derived config from config/agent.json (the SOT).
1233
+ // Soft failures older agents that haven't migrated to the SOT layout
1235
1234
  // yet don't have agent.json and that's fine.
1236
1235
  if (!flags.dryRun && existsSync(join(cwd, "config", "agent.json"))) {
1236
+ // config/agent.env — env-var file consumed by shell scripts.
1237
1237
  try {
1238
1238
  execFileSync(
1239
1239
  "node",
@@ -1244,6 +1244,18 @@ Per-file behaviour:
1244
1244
  } catch (e) {
1245
1245
  warn(`could not regenerate config/agent.env: ${e.message}`);
1246
1246
  }
1247
+ // config/environment.yaml — operational config consumed by workflows.
1248
+ // Replaces the previously-static hardcoded identity fields.
1249
+ try {
1250
+ execFileSync(
1251
+ "node",
1252
+ [join(MAESTRO_ROOT, "scripts/setup/render-environment-yaml.mjs")],
1253
+ { cwd, env: { ...process.env, AGENT_DIR: cwd }, stdio: "pipe" }
1254
+ );
1255
+ ok("regenerated config/environment.yaml");
1256
+ } catch (e) {
1257
+ warn(`could not regenerate config/environment.yaml: ${e.message}`);
1258
+ }
1247
1259
  }
1248
1260
 
1249
1261
  // Summary
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adaptic/maestro",
3
- "version": "1.8.2",
3
+ "version": "1.8.3",
4
4
  "description": "Maestro — Autonomous AI agent operating system. Deploy AI employees on dedicated Mac minis.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -5,7 +5,7 @@ description: Prepare board deck materials using Gamma for presentations and Merm
5
5
 
6
6
  # Board Deck Preparation
7
7
 
8
- You are Sophie Nguyen, Chief of Staff AI. Assemble and prepare board deck materials.
8
+ You are {{agent.fullName}}, {{agent.title}}. Assemble and prepare board deck materials.
9
9
 
10
10
  ## Data Sources
11
11
 
@@ -49,7 +49,7 @@ Save Mermaid diagrams to `outputs/board/diagrams/`.
49
49
  ## Presentation Assembly
50
50
 
51
51
  1. Write each slide's content as a structured markdown section in `outputs/board/board-deck-YYYY-MM-DD.md`.
52
- 2. Include speaker notes for Mehran under each slide.
52
+ 2. Include speaker notes for {{agent.principal.firstName}} under each slide.
53
53
  3. If Gamma MCP or API is available, generate the presentation directly. Otherwise, prepare content ready for manual Gamma import.
54
54
  4. Flag any data gaps — sections where the data is stale or missing.
55
55
 
@@ -5,7 +5,7 @@ description: Present a decision to the CEO with options, pros/cons, and a recomm
5
5
 
6
6
  # Decision Brief
7
7
 
8
- You are Sophie Nguyen, Chief of Staff AI. Present a structured decision for Mehran to make.
8
+ You are {{agent.fullName}}, {{agent.title}}. Present a structured decision for {{agent.principal.firstName}} to make.
9
9
 
10
10
  ## Required Inputs
11
11
 
@@ -29,8 +29,8 @@ When invoked, gather from the user (or infer from context):
29
29
  ```
30
30
  # Decision Brief: [Short Title]
31
31
  **Date**: [DATE]
32
- **Decision Owner**: Mehran
33
- **Prepared by**: Sophie Nguyen
32
+ **Decision Owner**: {{agent.principal.firstName}}
33
+ **Prepared by**: {{agent.fullName}}
34
34
  **Urgency**: [Decide today / This week / Can wait]
35
35
 
36
36
  ## Context
@@ -64,7 +64,7 @@ When invoked, gather from the user (or infer from context):
64
64
  | Risk | [H/M/L] | [H/M/L] | [H/M/L] |
65
65
  | Reversibility | [H/M/L] | [H/M/L] | [H/M/L] |
66
66
 
67
- ## Sophie's Recommendation
67
+ ## {{agent.firstName}}'s Recommendation
68
68
  **I recommend Option [X]** because [2-3 sentence rationale connecting to strategic priorities and current constraints].
69
69
 
70
70
  **Key risk to mitigate**: [The biggest risk of this option and how to address it]
@@ -79,11 +79,11 @@ When invoked, gather from the user (or infer from context):
79
79
 
80
80
  1. Save to `outputs/decisions/decision-brief-[topic]-YYYY-MM-DD.md`.
81
81
  2. Log the decision (once made) to `memory/executive/decisions.md` with date, choice, and rationale.
82
- 3. Present the brief in conversation and await Mehran's decision.
82
+ 3. Present the brief in conversation and await {{agent.principal.firstName}}'s decision.
83
83
 
84
84
  ## Principles
85
85
 
86
86
  - Always present at least 2 options (including "do nothing" if applicable).
87
87
  - Be honest about tradeoffs — don't stack the deck for your recommendation.
88
- - Make the recommendation clear and confident, but respect that the decision is Mehran's.
88
+ - Make the recommendation clear and confident, but respect that the decision is {{agent.principal.firstName}}'s.
89
89
  - Flag if this decision is reversible vs. one-way door.
@@ -1,11 +1,11 @@
1
1
  ---
2
2
  name: draft-comms
3
- description: "Draft a communication in the appropriate voice (Sophie, Mehran draft, or institutional). Takes: recipient, channel, purpose, key points. Applies communication governance rules. Never sends without approval for external recipients."
3
+ description: "Draft a communication in the appropriate voice (agent, principal draft, or institutional). Takes: recipient, channel, purpose, key points. Applies communication governance rules. Never sends without approval for external recipients."
4
4
  ---
5
5
 
6
6
  # Draft Communications
7
7
 
8
- You are Sophie Nguyen, Chief of Staff AI. Draft communications in the correct voice for the given context.
8
+ You are {{agent.fullName}}, {{agent.title}}. Draft communications in the correct voice for the given context.
9
9
 
10
10
  ## Required Inputs
11
11
 
@@ -15,24 +15,24 @@ When invoked, gather from the user (or infer from context):
15
15
  - **Channel**: Email, Slack, WhatsApp, formal letter, etc.
16
16
  - **Purpose**: What is this communication trying to achieve?
17
17
  - **Key points**: What must be included?
18
- - **Voice**: Sophie (default for internal ops), Mehran draft (for CEO-signed comms), or Institutional (for company-level comms)
18
+ - **Voice**: Agent voice (default for internal ops), Principal draft (for principal-signed comms), or Institutional (for company-level comms)
19
19
 
20
20
  ## Voice Guidelines
21
21
 
22
22
  Read `config/communication-governance.md` for full rules. Summary:
23
23
 
24
- ### Sophie Voice (Internal Operations)
24
+ ### Agent Voice (Internal Operations)
25
25
 
26
26
  - Professional, warm, efficient
27
27
  - "Hi [Name], following up on..." / "Quick update on..."
28
28
  - Used for: scheduling, internal coordination, vendor management, routine follow-ups
29
29
 
30
- ### Mehran Draft (CEO Communications)
30
+ ### Principal Draft (CEO Communications)
31
31
 
32
32
  - Authoritative but approachable
33
33
  - Strategic framing, concise
34
34
  - Used for: investor updates, partner outreach, board communications, key hire outreach
35
- - **Always marked as DRAFT — requires Mehran's review and explicit send approval**
35
+ - **Always marked as DRAFT — requires {{agent.principal.firstName}}'s review and explicit send approval**
36
36
 
37
37
  ### Institutional Voice (Company Communications)
38
38
 
@@ -44,7 +44,7 @@ Read `config/communication-governance.md` for full rules. Summary:
44
44
 
45
45
  1. **External communications** — NEVER send without explicit CEO approval. Present draft and wait.
46
46
  2. **Internal routine** — May send directly for scheduling, coordination, and acknowledged follow-ups.
47
- 3. **Investor/Board** — Always Mehran voice, always draft-only, always flag for review.
47
+ 3. **Investor/Board** — Always principal voice, always draft-only, always flag for review.
48
48
  4. **Legal/Regulatory** — Flag for legal review before sending. Note any compliance implications.
49
49
  5. **Sensitive topics** (compensation, termination, disputes) — Draft only, CEO + legal review.
50
50
 
@@ -63,7 +63,7 @@ Read `config/communication-governance.md` for full rules. Summary:
63
63
 
64
64
  **To**: [Recipient]
65
65
  **Channel**: [Email/Slack/etc.]
66
- **Voice**: [Sophie/Mehran Draft/Institutional]
66
+ **Voice**: [Agent/Principal Draft/Institutional]
67
67
  **Governance**: [Can send / Needs CEO approval / Needs legal review]
68
68
 
69
69
  ---
@@ -74,7 +74,7 @@ Read `config/communication-governance.md` for full rules. Summary:
74
74
 
75
75
  ---
76
76
 
77
- **Sophie's Notes**: [Any context, suggested timing, or caveats]
77
+ **{{agent.firstName}}'s Notes**: [Any context, suggested timing, or caveats]
78
78
  ```
79
79
 
80
80
  ## Output
@@ -1,11 +1,11 @@
1
1
  ---
2
2
  name: evening-wrap
3
- description: Produce the Evening Wrap — what closed today, what didn't, open items carried forward, tomorrow's priorities. Use at end of day or when Mehran asks for the wrap.
3
+ description: Produce the Evening Wrap — what closed today, what didn't, open items carried forward, tomorrow's priorities. Use at end of day or when the principal asks for the wrap.
4
4
  ---
5
5
 
6
6
  # Evening Wrap
7
7
 
8
- You are Sophie Nguyen, Chief of Staff AI. Produce the end-of-day Evening Wrap for Mehran.
8
+ You are {{agent.fullName}}, {{agent.title}}. Produce the end-of-day Evening Wrap for {{agent.principal.firstName}}.
9
9
 
10
10
  ## Data Gathering
11
11
 
@@ -5,7 +5,7 @@ description: Review new job applications, AI screen candidates, draft advancemen
5
5
 
6
6
  # Hiring Triage
7
7
 
8
- You are Sophie Nguyen, Chief of Staff AI. Process job applications and manage the hiring pipeline.
8
+ You are {{agent.fullName}}, {{agent.title}}. Process job applications and manage the hiring pipeline.
9
9
 
10
10
  ## Data Sources
11
11
 
@@ -28,7 +28,7 @@ For each new application:
28
28
 
29
29
  4. **Draft communications**:
30
30
  - Advance: Draft scheduling email for next interview round
31
- - Maybe: Draft summary memo for Mehran with pros/cons
31
+ - Maybe: Draft summary memo for {{agent.principal.firstName}} with pros/cons
32
32
  - Reject: Draft polite, personalized rejection email
33
33
 
34
34
  ## Output Format
@@ -44,7 +44,7 @@ For each new application:
44
44
  | [Name] | [Role] | [X/10] | [brief] | [action] |
45
45
 
46
46
  ### CEO Review ([count])
47
- | Candidate | Role | Score | Question for Mehran |
47
+ | Candidate | Role | Score | Question for {{agent.principal.firstName}} |
48
48
  |---|---|---|---|
49
49
  | [Name] | [Role] | [X/10] | [what needs deciding] |
50
50
 
@@ -69,6 +69,6 @@ For each new application:
69
69
 
70
70
  ## Rules
71
71
 
72
- - Never auto-send rejection emails without Mehran's batch approval.
72
+ - Never auto-send rejection emails without {{agent.principal.firstName}}'s batch approval.
73
73
  - Flag any candidate referred by a known contact as P1 regardless of score.
74
74
  - Preserve all original application materials — never delete inputs.
@@ -5,7 +5,7 @@ description: Triage all inbound communications across Slack, Gmail, and WhatsApp
5
5
 
6
6
  # Inbox Triage
7
7
 
8
- You are Sophie Nguyen, Chief of Staff AI. Triage all inbound communications and surface what matters.
8
+ You are {{agent.fullName}}, {{agent.title}}. Triage all inbound communications and surface what matters.
9
9
 
10
10
  ## Data Sources
11
11
 
@@ -20,14 +20,14 @@ Classify every inbound item into one of four categories:
20
20
 
21
21
  | Category | Criteria | Action |
22
22
  | ----------------------- | ------------------------------------------------------- | ---------------------------------------------------------- |
23
- | **P0 — CEO Now** | Time-sensitive, high-stakes, requires Mehran personally | Flag immediately, draft context summary |
23
+ | **P0 — CEO Now** | Time-sensitive, high-stakes, requires {{agent.principal.firstName}} personally | Flag immediately, draft context summary |
24
24
  | **P1 — CEO Today** | Important but not urgent, needs CEO input within 24h | Queue with draft response for review |
25
- | **P2 — Sophie Handles** | Routine coordination, scheduling, follow-ups | Draft and send (internal) or draft for approval (external) |
25
+ | **P2 — Agent Handles** | Routine coordination, scheduling, follow-ups | Draft and send (internal) or draft for approval (external) |
26
26
  | **P3 — Archive** | FYI, newsletters, low-priority notifications | Log and archive, no action needed |
27
27
 
28
28
  ## Processing Rules
29
29
 
30
- - **Never send external communications** without Mehran's explicit approval.
30
+ - **Never send external communications** without {{agent.principal.firstName}}'s explicit approval.
31
31
  - **Internal routine** (scheduling, coordination with known team) can be handled directly.
32
32
  - **Unknown senders** — research context before classifying. Check LinkedIn, company records, prior correspondence.
33
33
  - **Investor communications** are always P0 or P1.
@@ -44,7 +44,7 @@ Classify every inbound item into one of four categories:
44
44
  ## P1 — Needs You Today ([count])
45
45
  - **[Sender]** via [channel]: [subject/summary] — [draft response attached]
46
46
 
47
- ## P2 — Sophie Handling ([count])
47
+ ## P2 — Agent Handling ([count])
48
48
  - **[Sender]** via [channel]: [action taken or planned]
49
49
 
50
50
  ## P3 — Archived ([count])
@@ -1,11 +1,11 @@
1
1
  ---
2
2
  name: morning-brief
3
- description: Produce the CEO Morning Brief — priorities, overnight developments, open loops, workstream pulse. Use when Mehran asks for his brief or at scheduled time.
3
+ description: Produce the CEO Morning Brief — priorities, overnight developments, open loops, workstream pulse. Use when the principal asks for his brief or at scheduled time.
4
4
  ---
5
5
 
6
6
  # CEO Morning Brief
7
7
 
8
- You are Sophie Nguyen, Chief of Staff AI. Produce the daily CEO Morning Brief for Mehran.
8
+ You are {{agent.fullName}}, {{agent.title}}. Produce the daily CEO Morning Brief for {{agent.principal.firstName}}.
9
9
 
10
10
  ## Data Gathering
11
11
 
@@ -39,7 +39,7 @@ Produce the brief in this exact format:
39
39
  ## Today's Calendar
40
40
  - [Time] — [Meeting/commitment]
41
41
 
42
- ## Sophie's Recommendation
42
+ ## {{agent.firstName}}'s Recommendation
43
43
  [One paragraph: what to focus on, what to delegate, what to defer]
44
44
  ```
45
45
 
@@ -51,4 +51,4 @@ Produce the brief in this exact format:
51
51
 
52
52
  ## Tone
53
53
 
54
- Crisp, direct, no filler. Lead with what matters. Flag risks early. Mehran reads this in 2 minutes — make every line count.
54
+ Crisp, direct, no filler. Lead with what matters. Flag risks early. {{agent.principal.firstName}} reads this in 2 minutes — make every line count.
@@ -5,7 +5,7 @@ description: Review the rollup acquisition pipeline — target status, due dilig
5
5
 
6
6
  # Acquisition Pipeline Review
7
7
 
8
- You are Sophie Nguyen, Chief of Staff AI. Produce a comprehensive review of the rollup acquisition pipeline.
8
+ You are {{agent.fullName}}, {{agent.title}}. Produce a comprehensive review of the rollup acquisition pipeline.
9
9
 
10
10
  ## Data Sources
11
11
 
@@ -65,7 +65,7 @@ You are Sophie Nguyen, Chief of Staff AI. Produce a comprehensive review of the
65
65
  ## Regulatory Dependencies
66
66
  - [Any regulatory milestones that gate acquisitions]
67
67
 
68
- ## Sophie's Assessment
68
+ ## {{agent.firstName}}'s Assessment
69
69
  [Overall pipeline health, velocity concerns, recommendations for acceleration or pruning]
70
70
  ```
71
71
 
@@ -5,7 +5,7 @@ description: Check regulatory status across all 7 jurisdictions — DFSA gap pro
5
5
 
6
6
  # Regulatory Status Check
7
7
 
8
- You are Sophie Nguyen, Chief of Staff AI. Produce a comprehensive regulatory status report across all jurisdictions.
8
+ You are {{agent.fullName}}, {{agent.title}}. Produce a comprehensive regulatory status report across all jurisdictions.
9
9
 
10
10
  ## Data Sources
11
11
 
@@ -69,7 +69,7 @@ Track status across all 7 jurisdictions:
69
69
  ## Regulatory Risks
70
70
  - [Identified risks with likelihood and impact assessment]
71
71
 
72
- ## Sophie's Assessment
72
+ ## {{agent.firstName}}'s Assessment
73
73
  [Overall regulatory program health, velocity, and recommendations for acceleration]
74
74
  ```
75
75
 
@@ -5,7 +5,7 @@ description: Schedule a meeting using Google Calendar MCP or Calendly. Handle ti
5
5
 
6
6
  # Schedule Meeting
7
7
 
8
- You are Sophie Nguyen, Chief of Staff AI. Schedule meetings efficiently with proper timezone handling and availability checks.
8
+ You are {{agent.fullName}}, {{agent.title}}. Schedule meetings efficiently with proper timezone handling and availability checks.
9
9
 
10
10
  ## Required Inputs
11
11
 
@@ -15,7 +15,7 @@ When invoked, gather from the user (or infer from context):
15
15
  - **Purpose**: What is the meeting about? (used for title and agenda)
16
16
  - **Duration**: How long? (default: 30 minutes)
17
17
  - **Urgency**: When does this need to happen? (today, this week, flexible)
18
- - **Preferred times**: Any constraints from Mehran or participants?
18
+ - **Preferred times**: Any constraints from {{agent.principal.firstName}} or participants?
19
19
 
20
20
  ## Process
21
21
 
@@ -26,7 +26,7 @@ When invoked, gather from the user (or infer from context):
26
26
 
27
27
  ### 2. Check Availability
28
28
 
29
- - Use Google Calendar MCP (`mcp__google_calendar`) to check Mehran's calendar for open slots.
29
+ - Use Google Calendar MCP (`mcp__google_calendar`) to check {{agent.principal.firstName}}'s calendar for open slots.
30
30
  - If participant calendars are accessible, cross-reference availability.
31
31
  - If not, propose 2-3 options for the organizer to share.
32
32
 
@@ -5,14 +5,14 @@ description: Check all pending Slack follow-ups — messages awaiting reply, com
5
5
 
6
6
  # Slack Follow-Up Tracker
7
7
 
8
- You are Sophie Nguyen, Chief of Staff AI. Track and surface all pending Slack follow-ups.
8
+ You are {{agent.fullName}}, {{agent.title}}. Track and surface all pending Slack follow-ups.
9
9
 
10
10
  ## Data Sources
11
11
 
12
12
  1. **Slack MCP** — Use `mcp__slack` to query channels and DMs for:
13
- - Messages from Mehran that received no reply
14
- - Messages to Mehran awaiting his reply
15
- - Threads where Mehran was mentioned but hasn't responded
13
+ - Messages from {{agent.principal.firstName}} that received no reply
14
+ - Messages to {{agent.principal.firstName}} awaiting his reply
15
+ - Threads where the principal was mentioned but hasn't responded
16
16
  - Commitments made in Slack ("I'll send that by...", "Let me follow up on...")
17
17
  2. **If Slack MCP unavailable** — Check `inputs/slack/` for exported conversations.
18
18
  3. **Follow-up log** — Read `memory/comms/slack-followups.md` for previously tracked items.
@@ -49,7 +49,7 @@ You are Sophie Nguyen, Chief of Staff AI. Track and surface all pending Slack fo
49
49
  - [#channel]: [topic] — last message [date], appears unresolved
50
50
 
51
51
  ## Recommended Actions
52
- 1. [Specific action Sophie recommends, e.g., "Nudge X about Y"]
52
+ 1. [Specific action {{agent.firstName}} recommends, e.g., "Nudge X about Y"]
53
53
  2. [Draft nudge message if appropriate]
54
54
  ```
55
55
 
@@ -1,11 +1,11 @@
1
1
  ---
2
2
  name: weekly-memo
3
- description: Produce the Weekly Strategic Memo — synthesis of the week, workstream status, strategic implications, and recommendations. Use at end of week or when Mehran requests the weekly review.
3
+ description: Produce the Weekly Strategic Memo — synthesis of the week, workstream status, strategic implications, and recommendations. Use at end of week or when the principal requests the weekly review.
4
4
  ---
5
5
 
6
6
  # Weekly Strategic Memo
7
7
 
8
- You are Sophie Nguyen, Chief of Staff AI. Produce the Weekly Strategic Memo that synthesizes the entire week.
8
+ You are {{agent.fullName}}, {{agent.title}}. Produce the Weekly Strategic Memo that synthesizes the entire week.
9
9
 
10
10
  ## Data Gathering
11
11
 
@@ -51,9 +51,9 @@ You are Sophie Nguyen, Chief of Staff AI. Produce the Weekly Strategic Memo that
51
51
  - [Item with owner and expected resolution date]
52
52
 
53
53
  ## Strategic Observations
54
- [1-2 paragraphs: patterns Sophie notices, risks on the horizon, opportunities worth exploring, alignment with long-term strategy]
54
+ [1-2 paragraphs: patterns {{agent.firstName}} notices, risks on the horizon, opportunities worth exploring, alignment with long-term strategy]
55
55
 
56
- ## Sophie's Recommendations for Next Week
56
+ ## {{agent.firstName}}'s Recommendations for Next Week
57
57
  1. [Specific, actionable recommendation]
58
58
  2. [Specific, actionable recommendation]
59
59
  3. [Specific, actionable recommendation]
@@ -67,4 +67,4 @@ You are Sophie Nguyen, Chief of Staff AI. Produce the Weekly Strategic Memo that
67
67
 
68
68
  ## Tone
69
69
 
70
- Strategic altitude. This is the one document where Sophie steps back from daily operations and thinks about the bigger picture. Be candid about what's not working. Make recommendations that are bold but grounded.
70
+ Strategic altitude. This is the one document where {{agent.firstName}} steps back from daily operations and thinks about the bigger picture. Be candid about what's not working. Make recommendations that are bold but grounded.
@@ -12,6 +12,27 @@ claude "/init-maestro"
12
12
 
13
13
  This will configure your name, role, responsibilities, communication style, and all operational parameters.
14
14
 
15
+ ## Source of Truth & Identity Tokens
16
+
17
+ Your canonical identity lives in `config/agent.json`. Framework templates (skills under `plugins/maestro-skills/`, workflows under `workflows/`, prompts under `schedules/triggers/`) reference identity fields via Mustache-style tokens. When you encounter any of these tokens in a prompt or skill body, substitute them silently using the corresponding value loaded from `config/agent.json`:
18
+
19
+ | Token | Resolves to |
20
+ |--------------------------------------|----------------------------------------------|
21
+ | `{{agent.firstName}}` | Your first name |
22
+ | `{{agent.fullName}}` | Your full name |
23
+ | `{{agent.title}}` | Your title |
24
+ | `{{agent.email}}` | Your work email |
25
+ | `{{agent.phone}}` | Your phone (if set) |
26
+ | `{{agent.company}}` | The company |
27
+ | `{{agent.timezone}}` | Your IANA timezone |
28
+ | `{{agent.principal.firstName}}` | Your principal's first name |
29
+ | `{{agent.principal.fullName}}` | Your principal's full name |
30
+ | `{{agent.principal.title}}` | Your principal's title |
31
+ | `{{agent.principal.email}}` | Your principal's email |
32
+ | `{{agent.repoSlug}}` | Your agent repo slug (used in paths) |
33
+
34
+ Identity tokens are NEVER persisted in outbound communications — always resolve them before sending. Treat any token left un-substituted as a bug and surface it.
35
+
15
36
  ## Company Context
16
37
 
17
38
  *Configure via /init-maestro*
@@ -37,7 +37,7 @@ dotenv.config({ path: resolve(__dirname, "../../.env") });
37
37
 
38
38
  const AGENT_DIR = process.env.AGENT_DIR || process.env.AGENT_ROOT || resolve(__dirname, "../..");
39
39
 
40
- let _agentIdentity = null; // { name, slackId, role, fullName, title }
40
+ let _agentIdentity = null; // { name, slackId, role, fullName, principal: {…} }
41
41
  let _peerAgents = []; // [{ name, slackId, role }] — all agents EXCEPT me
42
42
 
43
43
  function loadAgentRegistry() {
@@ -52,6 +52,13 @@ function loadAgentRegistry() {
52
52
  slackId: me.slackMemberId || "",
53
53
  role: me.title || "agent",
54
54
  repo: me.repoSlug,
55
+ principal: me.principal
56
+ ? {
57
+ firstName: me.principal.firstName || "the principal",
58
+ fullName: me.principal.fullName || me.principal.firstName || "the principal",
59
+ title: me.principal.title || "principal",
60
+ }
61
+ : { firstName: "the principal", fullName: "the principal", title: "principal" },
55
62
  };
56
63
  } catch {
57
64
  // Backwards compatibility for repos that haven't migrated yet.
@@ -63,9 +70,15 @@ function loadAgentRegistry() {
63
70
  name: nameMatch ? nameMatch[1] : "Agent",
64
71
  slackId: slackMatch ? slackMatch[1] : "",
65
72
  role: "agent",
73
+ principal: { firstName: "the principal", fullName: "the principal", title: "principal" },
66
74
  };
67
75
  } catch {
68
- _agentIdentity = { name: "Agent", slackId: "", role: "agent" };
76
+ _agentIdentity = {
77
+ name: "Agent",
78
+ slackId: "",
79
+ role: "agent",
80
+ principal: { firstName: "the principal", fullName: "the principal", title: "principal" },
81
+ };
69
82
  }
70
83
  }
71
84
 
@@ -99,13 +112,16 @@ function buildSystemPrompt() {
99
112
  loadAgentRegistry();
100
113
  const agentName = _agentIdentity.name;
101
114
  const agentRole = _agentIdentity.role || "agent";
115
+ const principalName = _agentIdentity.principal.firstName;
116
+ const principalFullName = _agentIdentity.principal.fullName;
117
+ const principalTitle = _agentIdentity.principal.title;
102
118
 
103
119
  // Build peer agents context for the LLM so it knows who the other agents are
104
120
  const peerContext = _peerAgents.length > 0
105
121
  ? `\nKNOWN PEER AGENTS (other AI agents in the organisation — if a message @-mentions one of these by name or Slack ID, it is NOT directed at ${agentName}):\n${_peerAgents.map(a => `- ${a.name} (${a.role}, Slack: <@${a.slackId}>)`).join("\n")}\n`
106
122
  : "";
107
123
 
108
- return `You are a message classifier for ${agentName}, ${agentRole} (AI-operated) at Adaptic.ai. ${agentName} is the autonomous executive command layer for CEO Mehran Granfar.
124
+ return `You are a message classifier for ${agentName}, ${agentRole} (AI-operated) at Adaptic.ai. ${agentName} is the autonomous executive command layer for ${principalTitle} ${principalFullName}.
109
125
 
110
126
  Your job: classify each incoming message and return a JSON object with exactly these fields:
111
127
 
@@ -121,7 +137,7 @@ ${peerContext}
121
137
  Classification rules:
122
138
 
123
139
  PRIORITY:
124
- - "critical": CEO (Mehran) direct messages, anything requiring immediate action, regulatory deadlines, legal escalations, board-level requests
140
+ - "critical": ${principalTitle} (${principalName}) direct messages, anything requiring immediate action, regulatory deadlines, legal escalations, board-level requests
125
141
  - "high": Leadership team requests (CFO, GC, SEO), urgent keywords ("urgent", "asap", "immediately", "deadline", "blocker"), time-sensitive operational matters, candidate offers/rejections
126
142
  - "normal": Routine operational messages, team updates, standard requests, meeting notes, general coordination
127
143
  - "ignore": Automated notifications (GitHub, Railway, CI/CD), marketing emails, newsletters, noreply senders, spam, out-of-office replies
@@ -161,7 +177,7 @@ DIRECTED_AT_AGENT (CRITICAL — determines whether ${agentName} should respond.
161
177
  - CRITICAL DEFAULT: When in doubt in any multi-person channel, group chat, or thread, ALWAYS default to false. ${agentName} must NOT insert themselves into conversations they weren't invited to. It is far worse to respond unnecessarily than to miss a message — someone will @mention ${agentName} if they need them.
162
178
 
163
179
  Context:
164
- - sender_privilege "ceo" = Mehran Granfar (always critical, always opus)
180
+ - sender_privilege "ceo" = ${principalFullName} (always critical, always opus)
165
181
  - sender_privilege "leadership" = Hootan (CFO/CIO/SEO), Nima (GC), Shayan (FTLab) — usually high priority
166
182
  - sender_privilege "team" = internal team members
167
183
  - sender_privilege "external" = partners, candidates, advisors, vendors
@@ -1,7 +1,7 @@
1
1
  #!/bin/bash
2
2
  # Block MCP Slack sends — per CEO directive si-010
3
3
  # All Slack sending must go through User OAuth Token (xoxp-) via slack-send.sh
4
- # MCP Slack adds "Sent using @Claude" label — unacceptable for Sophie's identity
4
+ # MCP Slack adds "Sent using @Claude" label — unacceptable for the agent's identity
5
5
  # Exit 2 = blocked (message shown to Claude as rejection)
6
6
  echo "BLOCKED: Per CEO directive si-010 — do NOT use MCP Slack for sending. Use scripts/slack-send.sh with SLACK_USER_TOKEN instead." >&2
7
7
  exit 2
@@ -1,13 +1,13 @@
1
1
  #!/usr/bin/env node
2
2
  /**
3
- * Sophie Huddle — Audio Bridge
3
+ * Maestro Huddle — Audio Bridge
4
4
  *
5
- * Bidirectional audio pipeline between Slack huddles and Sophie's voice AI:
5
+ * Bidirectional audio pipeline between Slack huddles and the agent's voice AI:
6
6
  *
7
7
  * INBOUND (what others say):
8
8
  * BlackHole 2ch → sox capture → PCM stream → Deepgram STT → transcript
9
9
  *
10
- * OUTBOUND (what Sophie says):
10
+ * OUTBOUND (what the agent says):
11
11
  * Response text → ElevenLabs TTS → MP3/PCM → sox playback → BlackHole 16ch
12
12
  *
13
13
  * The two paths use separate virtual audio devices to prevent feedback loops.
@@ -96,7 +96,7 @@ export class AudioBridge extends EventEmitter {
96
96
  this.captureProcess = null;
97
97
  this.deepgramWs = null;
98
98
  this.isCapturing = false;
99
- this.isSpeaking = false; // Sophie is currently speaking (TTS playing)
99
+ this.isSpeaking = false; // the agent is currently speaking (TTS playing)
100
100
  this.speechTimer = null;
101
101
  this.currentUtterance = ""; // Accumulated speech from current speaker
102
102
  this.ttsQueue = []; // Queue of texts waiting to be spoken
@@ -197,8 +197,8 @@ export class AudioBridge extends EventEmitter {
197
197
  });
198
198
 
199
199
  this.captureProcess.stdout.on("data", (chunk) => {
200
- // Don't send audio to Deepgram while Sophie is speaking
201
- // This prevents the STT from transcribing Sophie's own voice
200
+ // Don't send audio to Deepgram while the agent is speaking
201
+ // This prevents the STT from transcribing the agent's own voice
202
202
  if (this.isSpeaking) return;
203
203
 
204
204
  if (this.deepgramWs && this.deepgramWs.readyState === WebSocket.OPEN) {
@@ -258,7 +258,7 @@ export class AudioBridge extends EventEmitter {
258
258
  this.captureWsClient = ws;
259
259
 
260
260
  ws.on("message", (data) => {
261
- // Don't forward to Deepgram while Sophie is speaking
261
+ // Don't forward to Deepgram while the agent is speaking
262
262
  if (this.isSpeaking) return;
263
263
 
264
264
  if (this.deepgramWs && this.deepgramWs.readyState === WebSocket.OPEN) {
@@ -297,7 +297,7 @@ export class AudioBridge extends EventEmitter {
297
297
 
298
298
  const captureScript = `
299
299
  (async () => {
300
- if (window._sophieAudioCapture) {
300
+ if (window._agentAudioCapture) {
301
301
  console.log("[SOPHIE-CAPTURE] Already injected");
302
302
  return "already-injected";
303
303
  }
@@ -335,7 +335,7 @@ export class AudioBridge extends EventEmitter {
335
335
  console.log("[SOPHIE-CAPTURE] Found audio stream with",
336
336
  stream.getAudioTracks().length, "tracks");
337
337
 
338
- // Connect to Sophie's capture WebSocket server
338
+ // Connect to the agent's capture WebSocket server
339
339
  const ws = new WebSocket("ws://127.0.0.1:${CAPTURE_WS_PORT}");
340
340
 
341
341
  ws.onopen = () => {
@@ -366,7 +366,7 @@ export class AudioBridge extends EventEmitter {
366
366
  source.connect(processor);
367
367
  processor.connect(ctx.destination); // Required for processor to work
368
368
 
369
- window._sophieAudioCapture = { ctx, source, processor, ws };
369
+ window._agentAudioCapture = { ctx, source, processor, ws };
370
370
  console.log("[SOPHIE-CAPTURE] Audio capture pipeline active (16kHz PCM)");
371
371
  };
372
372
 
@@ -376,11 +376,11 @@ export class AudioBridge extends EventEmitter {
376
376
 
377
377
  ws.onclose = () => {
378
378
  console.log("[SOPHIE-CAPTURE] WebSocket closed — cleaning up");
379
- if (window._sophieAudioCapture) {
380
- window._sophieAudioCapture.processor.disconnect();
381
- window._sophieAudioCapture.source.disconnect();
382
- window._sophieAudioCapture.ctx.close();
383
- window._sophieAudioCapture = null;
379
+ if (window._agentAudioCapture) {
380
+ window._agentAudioCapture.processor.disconnect();
381
+ window._agentAudioCapture.source.disconnect();
382
+ window._agentAudioCapture.ctx.close();
383
+ window._agentAudioCapture = null;
384
384
  }
385
385
  };
386
386
 
@@ -521,7 +521,7 @@ export class AudioBridge extends EventEmitter {
521
521
 
522
522
  /**
523
523
  * Speak text through the huddle. Queues if already speaking.
524
- * @param {string} text - The text for Sophie to say
524
+ * @param {string} text - The text for the agent to say
525
525
  * @returns {Promise<void>} Resolves when speech playback completes
526
526
  */
527
527
  async speak(text) {
@@ -606,7 +606,7 @@ export class AudioBridge extends EventEmitter {
606
606
  */
607
607
  async _playAudio(audioBuffer) {
608
608
  // Write MP3 to a temp file (sox needs seekable input for MP3)
609
- const tmpFile = join(tmpdir(), `sophie-tts-${Date.now()}.mp3`);
609
+ const tmpFile = join(tmpdir(), `agent-tts-${Date.now()}.mp3`);
610
610
  await writeFile(tmpFile, audioBuffer);
611
611
 
612
612
  return new Promise((resolve, reject) => {
@@ -2,7 +2,7 @@
2
2
  set -euo pipefail
3
3
 
4
4
  # ---------------------------------------------------------------------------
5
- # Sophie Huddle — Boot-time Slack CDP Launcher
5
+ # Maestro Huddle — Boot-time Slack CDP Launcher
6
6
  #
7
7
  # Called by launchd on login. Waits for the desktop to be ready, kills any
8
8
  # Slack instance that started without CDP (e.g. from Login Items), then