@monoes/monomindcli 1.9.17 → 1.10.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 (118) hide show
  1. package/.claude/commands/mastermind/_repeat.md +182 -39
  2. package/.claude/commands/mastermind/architect.md +17 -11
  3. package/.claude/commands/mastermind/brain.md +4 -0
  4. package/.claude/commands/mastermind/build.md +4 -0
  5. package/.claude/commands/mastermind/content.md +4 -0
  6. package/.claude/commands/mastermind/createorg.md +5 -3
  7. package/.claude/commands/mastermind/finance.md +4 -0
  8. package/.claude/commands/mastermind/idea.md +4 -0
  9. package/.claude/commands/mastermind/marketing.md +4 -0
  10. package/.claude/commands/mastermind/master.md +63 -37
  11. package/.claude/commands/mastermind/ops.md +4 -0
  12. package/.claude/commands/mastermind/release.md +4 -0
  13. package/.claude/commands/mastermind/research.md +4 -0
  14. package/.claude/commands/mastermind/review.md +4 -0
  15. package/.claude/commands/mastermind/runorg.md +5 -3
  16. package/.claude/commands/mastermind/sales.md +4 -0
  17. package/.claude/commands/mastermind/techport.md +9 -0
  18. package/.claude/commands/monomind/do.md +5 -1
  19. package/.claude/commands/monomind/idea.md +5 -1
  20. package/.claude/commands/monomind/improve.md +5 -1
  21. package/.claude/commands/monomind/repeat.md +85 -29
  22. package/.claude/commands/monomind/review.md +6 -2
  23. package/.claude/commands/monomind/understand.md +10 -8
  24. package/.claude/helpers/extras-registry.json +235 -235
  25. package/.claude/helpers/graphify-freshen.cjs +13 -1
  26. package/.claude/helpers/hook-handler.cjs +1 -1
  27. package/.claude/helpers/router.cjs +4 -1
  28. package/.claude/skills/mastermind/_protocol.md +28 -21
  29. package/.claude/skills/mastermind/access.md +236 -0
  30. package/.claude/skills/mastermind/activity.md +191 -0
  31. package/.claude/skills/mastermind/adapter-manager.md +259 -0
  32. package/.claude/skills/mastermind/adapters.md +204 -0
  33. package/.claude/skills/mastermind/agent-detail.md +242 -0
  34. package/.claude/skills/mastermind/agents.md +178 -0
  35. package/.claude/skills/mastermind/approval-detail.md +259 -0
  36. package/.claude/skills/mastermind/approve.md +181 -0
  37. package/.claude/skills/mastermind/architect.md +24 -8
  38. package/.claude/skills/mastermind/backup.md +197 -0
  39. package/.claude/skills/mastermind/bootstrap.md +190 -0
  40. package/.claude/skills/mastermind/budgets.md +237 -0
  41. package/.claude/skills/mastermind/companies.md +256 -0
  42. package/.claude/skills/mastermind/costs.md +151 -0
  43. package/.claude/skills/mastermind/createorg.md +23 -5
  44. package/.claude/skills/mastermind/diagnose.md +249 -0
  45. package/.claude/skills/mastermind/env.md +198 -0
  46. package/.claude/skills/mastermind/environments.md +250 -0
  47. package/.claude/skills/mastermind/export.md +324 -0
  48. package/.claude/skills/mastermind/goal-detail.md +255 -0
  49. package/.claude/skills/mastermind/goals.md +149 -0
  50. package/.claude/skills/mastermind/heartbeat.md +164 -0
  51. package/.claude/skills/mastermind/idea.md +250 -122
  52. package/.claude/skills/mastermind/import.md +281 -0
  53. package/.claude/skills/mastermind/inbox.md +214 -0
  54. package/.claude/skills/mastermind/instance-settings.md +315 -0
  55. package/.claude/skills/mastermind/instance.md +231 -0
  56. package/.claude/skills/mastermind/invite-landing.md +227 -0
  57. package/.claude/skills/mastermind/invites.md +254 -0
  58. package/.claude/skills/mastermind/issue-detail.md +291 -0
  59. package/.claude/skills/mastermind/issues.md +235 -0
  60. package/.claude/skills/mastermind/join-queue.md +170 -0
  61. package/.claude/skills/mastermind/liveness.md +392 -0
  62. package/.claude/skills/mastermind/memory.md +321 -0
  63. package/.claude/skills/mastermind/my-issues.md +146 -0
  64. package/.claude/skills/mastermind/new-agent.md +241 -0
  65. package/.claude/skills/mastermind/org-chart.md +207 -0
  66. package/.claude/skills/mastermind/org-settings.md +217 -0
  67. package/.claude/skills/mastermind/plan-to-tasks.md +136 -0
  68. package/.claude/skills/mastermind/plugin-manager.md +241 -0
  69. package/.claude/skills/mastermind/plugin-settings.md +273 -0
  70. package/.claude/skills/mastermind/plugins.md +190 -0
  71. package/.claude/skills/mastermind/profile.md +187 -0
  72. package/.claude/skills/mastermind/project-detail.md +249 -0
  73. package/.claude/skills/mastermind/project-workspace.md +244 -0
  74. package/.claude/skills/mastermind/projects.md +164 -0
  75. package/.claude/skills/mastermind/routine-detail.md +253 -0
  76. package/.claude/skills/mastermind/routines.md +202 -0
  77. package/.claude/skills/mastermind/runorg.md +74 -9
  78. package/.claude/skills/mastermind/search.md +186 -0
  79. package/.claude/skills/mastermind/secrets.md +199 -0
  80. package/.claude/skills/mastermind/skills.md +156 -0
  81. package/.claude/skills/mastermind/tasks.md +149 -0
  82. package/.claude/skills/mastermind/techport.md +5 -5
  83. package/.claude/skills/mastermind/threads.md +259 -0
  84. package/.claude/skills/mastermind/tree-control.md +250 -0
  85. package/.claude/skills/mastermind/wiki.md +314 -0
  86. package/.claude/skills/mastermind/workspace-detail.md +317 -0
  87. package/.claude/skills/mastermind/workspaces.md +261 -0
  88. package/.claude/skills/mastermind/worktree.md +187 -0
  89. package/dist/src/init/executor.js +8 -8
  90. package/dist/src/init/executor.js.map +1 -1
  91. package/dist/src/init/statusline-generator.d.ts.map +1 -1
  92. package/dist/src/init/statusline-generator.js +12 -0
  93. package/dist/src/init/statusline-generator.js.map +1 -1
  94. package/dist/src/ui/.monomind/data/ranked-context.json +1 -1
  95. package/dist/src/ui/.monomind/loops/mastermind-review-1778664132789.json +16 -0
  96. package/dist/src/ui/.monomind/sessions/current.json +5 -5
  97. package/dist/src/ui/.monomind/sessions/session-1776778451399.json +15 -0
  98. package/dist/src/ui/dashboard.html +3030 -181
  99. package/dist/src/ui/data/mastermind-events.jsonl +8 -0
  100. package/dist/src/ui/data/mastermind-sessions.json +1 -0
  101. package/dist/src/ui/server.mjs +738 -0
  102. package/dist/tsconfig.tsbuildinfo +1 -1
  103. package/package.json +2 -2
  104. package/.claude/skills/.monomind/data/ranked-context.json +0 -5
  105. package/.claude/skills/.monomind/sessions/current.json +0 -13
  106. package/.claude/skills/.monomind/sessions/session-1777829336455.json +0 -15
  107. package/.claude/skills/.monomind/sessions/session-1777831614725.json +0 -15
  108. package/.claude/skills/.monomind/sessions/session-1777832095857.json +0 -15
  109. package/.claude/skills/.monomind/sessions/session-1777839814183.json +0 -15
  110. package/.claude/skills/.monomind/sessions/session-1777841847131.json +0 -15
  111. package/.claude/skills/.monomind/sessions/session-1777843309463.json +0 -15
  112. package/.claude/skills/.monomind/sessions/session-1777880867159.json +0 -15
  113. package/.claude/skills/.monomind/sessions/session-1777881884593.json +0 -15
  114. package/.claude/skills/.monomind/sessions/session-1777884090471.json +0 -15
  115. package/.claude/skills/.monomind/sessions/session-1777884808221.json +0 -15
  116. package/.claude/skills/.monomind/sessions/session-1777885672155.json +0 -15
  117. package/.claude/skills/.monomind/sessions/session-1777886852818.json +0 -15
  118. package/.claude/skills/.monomind/sessions/session-1777896532690.json +0 -15
@@ -0,0 +1,181 @@
1
+ ---
2
+ name: mastermind-approve
3
+ description: Mastermind approve — review and action pending approval requests from agents in a running org. Agents can request human approval before proceeding with sensitive actions.
4
+ type: domain-skill
5
+ default_mode: confirm
6
+ ---
7
+
8
+ # Mastermind Approve
9
+
10
+ This skill is invoked by `mastermind:approve` or directly via `/mastermind:approve`.
11
+
12
+ ---
13
+
14
+ ## Inputs
15
+
16
+ - `brain_context`: BRAIN CONTEXT block
17
+ - `org_name`: org to check approvals for
18
+ - `action`: list | approve | reject | inspect
19
+ - `approval_id`: id of the specific approval request (for approve/reject/inspect)
20
+ - `reason`: optional reason for rejection
21
+ - `caller`: command | master
22
+
23
+ ---
24
+
25
+ ## Step 0 — Brain Load (standalone only)
26
+
27
+ If `caller` is not "command", load brain context following _protocol.md Brain Load Procedure with namespace: `ops`.
28
+
29
+ ---
30
+
31
+ ## Step 1 — Load Approvals
32
+
33
+ Approvals are stored in `.monomind/orgs/<org_name>-approvals.json`:
34
+
35
+ ```bash
36
+ orgFile=".monomind/orgs/${org_name}.json"
37
+ approvalsFile=".monomind/orgs/${org_name}-approvals.json"
38
+ [ ! -f "$approvalsFile" ] && echo '{"approvals":[]}' > "$approvalsFile"
39
+ ```
40
+
41
+ ---
42
+
43
+ ## Step 2 — Execute Action
44
+
45
+ ### list (default)
46
+
47
+ Show pending approval requests from agents:
48
+
49
+ ```bash
50
+ jq -r '
51
+ .approvals | map(select(.status == "pending")) |
52
+ if length == 0 then "No pending approvals." else
53
+ .[] | "[\(.id)] \(.agent_id): \(.title)\n Action: \(.action)\n Risk: \(.risk_level // "low")\n Requested: \(.requested_at)"
54
+ end
55
+ ' "$approvalsFile"
56
+ ```
57
+
58
+ Render as:
59
+ ```
60
+ PENDING APPROVALS — org: <org_name>
61
+ ──────────────────────────────────────────────────
62
+ [req-001] content-writer: Publish to external blog
63
+ Action: POST to https://blog.example.com/api/posts
64
+ Risk: medium
65
+ Requested: 2 min ago
66
+
67
+ [req-002] marketer: Send email campaign
68
+ Action: Send to 1,200 subscribers
69
+ Risk: high ← requires explicit approval
70
+ Requested: 5 min ago
71
+ ──────────────────────────────────────────────────
72
+ 2 pending | Type "approve <id>" or "reject <id> <reason>"
73
+ ```
74
+
75
+ ### inspect
76
+
77
+ Show full details of a single approval request:
78
+
79
+ ```bash
80
+ jq --arg id "$approval_id" '.approvals[] | select(.id == $id)' "$approvalsFile"
81
+ ```
82
+
83
+ Print the agent's requested action, context, and any supporting evidence they provided.
84
+
85
+ ### approve
86
+
87
+ Update approval status and notify the waiting agent via memory:
88
+
89
+ ```bash
90
+ tmp="${approvalsFile}.tmp"
91
+ jq --arg id "$approval_id" \
92
+ '.approvals = [.approvals[] | if .id == $id then .status = "approved" | .resolved_at = (now|todate) | .resolved_by = "human" else . end]' \
93
+ "$approvalsFile" > "$tmp" && mv "$tmp" "$approvalsFile"
94
+
95
+ # Notify the agent via memory so it can proceed
96
+ approval=$(jq --arg id "$approval_id" '.approvals[] | select(.id == $id)' "$approvalsFile")
97
+ agent_id=$(echo "$approval" | jq -r '.agent_id')
98
+ memNs="org:${org_name}"
99
+ npx monomind@latest memory store \
100
+ --key "${memNs}:approval:${approval_id}" \
101
+ --namespace "$memNs" \
102
+ --value '{"status":"approved","approval_id":"'"$approval_id"'","ts":"'"$(date -u +%Y-%m-%dT%H:%M:%SZ)"'"}'
103
+
104
+ echo "Approved request $approval_id — agent $agent_id may proceed."
105
+ ```
106
+
107
+ Emit `org:approval:approved` event to dashboard.
108
+
109
+ ### reject
110
+
111
+ ```bash
112
+ tmp="${approvalsFile}.tmp"
113
+ jq --arg id "$approval_id" --arg reason "${reason:-No reason given}" \
114
+ '.approvals = [.approvals[] | if .id == $id then .status = "rejected" | .resolved_at = (now|todate) | .resolved_by = "human" | .rejection_reason = $reason else . end]' \
115
+ "$approvalsFile" > "$tmp" && mv "$tmp" "$approvalsFile"
116
+
117
+ approval=$(jq --arg id "$approval_id" '.approvals[] | select(.id == $id)' "$approvalsFile")
118
+ agent_id=$(echo "$approval" | jq -r '.agent_id')
119
+ memNs="org:${org_name}"
120
+ npx monomind@latest memory store \
121
+ --key "${memNs}:approval:${approval_id}" \
122
+ --namespace "$memNs" \
123
+ --value '{"status":"rejected","approval_id":"'"$approval_id"'","reason":"'"${reason:-No reason given}"'","ts":"'"$(date -u +%Y-%m-%dT%H:%M:%SZ)"'"}'
124
+
125
+ echo "Rejected request $approval_id. Agent $agent_id has been notified."
126
+ ```
127
+
128
+ Emit `org:approval:rejected` event.
129
+
130
+ ---
131
+
132
+ ## How Agents Request Approval
133
+
134
+ Agents that need human approval before a sensitive action should:
135
+
136
+ 1. Write to the approvals file:
137
+ ```bash
138
+ approvalsFile=".monomind/orgs/${orgName}-approvals.json"
139
+ [ ! -f "$approvalsFile" ] && echo '{"approvals":[]}' > "$approvalsFile"
140
+ approval_id="req-$(date +%s)"
141
+ tmp="${approvalsFile}.tmp"
142
+ jq --arg id "$approval_id" \
143
+ --arg agent "$role_id" \
144
+ --arg title "$action_title" \
145
+ --arg action "$action_description" \
146
+ --arg risk "medium" \
147
+ '.approvals += [{"id":$id,"agent_id":$agent,"title":$title,"action":$action,"risk_level":$risk,"status":"pending","requested_at":(now|todate)}]' \
148
+ "$approvalsFile" > "$tmp" && mv "$tmp" "$approvalsFile"
149
+ ```
150
+
151
+ 2. Emit `org:approval:requested` event to dashboard (so the human is notified).
152
+
153
+ 3. Poll memory for the approval decision:
154
+ ```bash
155
+ while true; do
156
+ result=$(npx monomind@latest memory search --query "approval:${approval_id}" --namespace "${memNs}" 2>/dev/null)
157
+ status=$(echo "$result" | jq -r '.[0].value.status // ""' 2>/dev/null)
158
+ [ "$status" = "approved" ] && break
159
+ [ "$status" = "rejected" ] && { echo "Action rejected: $(echo $result | jq -r '.[0].value.reason // ""')"; exit 1; }
160
+ sleep 30
161
+ done
162
+ ```
163
+
164
+ ---
165
+
166
+ ## Step 3 — Return Output
167
+
168
+ ```yaml
169
+ domain: ops
170
+ status: complete
171
+ action: <action>
172
+ org: <org_name>
173
+ approval_id: <approval_id if applicable>
174
+ pending_count: <N>
175
+ ```
176
+
177
+ ---
178
+
179
+ ## Step 4 — Brain Write (standalone only)
180
+
181
+ If `caller` is not "command", follow _protocol.md Brain Write Procedure for domain `ops`.
@@ -65,7 +65,9 @@ If this skill is invoked directly (not by master):
65
65
 
66
66
  1. If `sessionId` was not provided by the caller: generate it by taking the current UTC datetime formatted as `YYYYMMDDTHHmmss` and prefixing with `mm-` (e.g. `mm-20260506T142345`). Then emit `session:start` (if `caller` is `standalone` — skip if `command` or `master`, as the caller emits it). Before executing the curl below, substitute the generated sessionId for `<sessionId>`:
67
67
  ```bash
68
- curl -s -X POST "http://localhost:4242/api/mastermind/event" \
68
+ REPO_ROOT=$(git rev-parse --show-toplevel 2>/dev/null || pwd)
69
+ CTRL_URL=$(jq -r '.url // "http://localhost:4242"' "$REPO_ROOT/.monomind/control.json" 2>/dev/null || echo "http://localhost:4242")
70
+ curl -s -X POST "${CTRL_URL}/api/mastermind/event" \
69
71
  -H "Content-Type: application/json" \
70
72
  -d '{"type":"session:start","session":"<sessionId>","domain":"architect","ts":'"$(date +%s)"'000}' || true
71
73
  ```
@@ -100,7 +102,9 @@ If this skill is invoked directly (not by master):
100
102
  6. Proceed with complexity assessment below
101
103
  7. At end: emit `session:complete` (if `caller` is `standalone`). Before executing the curl below, substitute the resolved sessionId for `<sessionId>`:
102
104
  ```bash
103
- curl -s -X POST "http://localhost:4242/api/mastermind/event" \
105
+ REPO_ROOT=$(git rev-parse --show-toplevel 2>/dev/null || pwd)
106
+ CTRL_URL=$(jq -r '.url // "http://localhost:4242"' "$REPO_ROOT/.monomind/control.json" 2>/dev/null || echo "http://localhost:4242")
107
+ curl -s -X POST "${CTRL_URL}/api/mastermind/event" \
104
108
  -H "Content-Type: application/json" \
105
109
  -d '{"type":"session:complete","session":"<sessionId>","domain":"architect","ts":'"$(date +%s)"'000}' || true
106
110
  ```
@@ -289,7 +293,9 @@ Before spawning, resolve two values:
289
293
  Then emit `agent:spawn` for the manager and spawn it. Before executing the curl below, substitute the resolved sessionId for `<sessionId>`:
290
294
 
291
295
  ```bash
292
- curl -s -X POST "http://localhost:4242/api/mastermind/event" \
296
+ REPO_ROOT=$(git rev-parse --show-toplevel 2>/dev/null || pwd)
297
+ CTRL_URL=$(jq -r '.url // "http://localhost:4242"' "$REPO_ROOT/.monomind/control.json" 2>/dev/null || echo "http://localhost:4242")
298
+ curl -s -X POST "${CTRL_URL}/api/mastermind/event" \
293
299
  -H "Content-Type: application/json" \
294
300
  -d '{"type":"agent:spawn","session":"<sessionId>","domain":"architect","agent":"<manager_agent_type lowercased and hyphenated, e.g. software-architect>","task":"coordinate architecture analysis","ts":'"$(date +%s)"'000}'
295
301
  ```
@@ -437,14 +443,18 @@ The `description` must be the complete briefing, including CONTEXT, BRAIN MEMORY
437
443
 
438
444
  BEFORE spawning each agent, emit agent:spawn to the live dashboard. Before each of the following curl commands executes, `<sessionId>` must already be substituted with the session ID from the CONTEXT header Session field above. When substituting `<stream-description>` and other free-text fields into the JSON payload, strip any double-quotes and backslashes from the value to keep the JSON well-formed:
439
445
  \`\`\`bash
440
- curl -s -X POST "http://localhost:4242/api/mastermind/event" \
446
+ REPO_ROOT=$(git rev-parse --show-toplevel 2>/dev/null || pwd)
447
+ CTRL_URL=$(jq -r '.url // "http://localhost:4242"' "$REPO_ROOT/.monomind/control.json" 2>/dev/null || echo "http://localhost:4242")
448
+ curl -s -X POST "${CTRL_URL}/api/mastermind/event" \
441
449
  -H "Content-Type: application/json" \
442
450
  -d '{"type":"agent:spawn","session":"<sessionId>","domain":"architect","agent":"<subagent_type lowercased and hyphenated, e.g. software-architect>","task":"<stream-description>","ts":'"$(date +%s)"'000}'
443
451
  \`\`\`
444
452
 
445
453
  If handing off artifacts to another domain (e.g. build for refactoring implementation, review for post-restructure check), emit intercom. When substituting `<msg>` and other free-text fields, strip any double-quotes and backslashes from the value to keep the JSON well-formed:
446
454
  \`\`\`bash
447
- curl -s -X POST "http://localhost:4242/api/mastermind/event" \
455
+ REPO_ROOT=$(git rev-parse --show-toplevel 2>/dev/null || pwd)
456
+ CTRL_URL=$(jq -r '.url // "http://localhost:4242"' "$REPO_ROOT/.monomind/control.json" 2>/dev/null || echo "http://localhost:4242")
457
+ curl -s -X POST "${CTRL_URL}/api/mastermind/event" \
448
458
  -H "Content-Type: application/json" \
449
459
  -d '{"type":"intercom","session":"<sessionId>","from":"architect","to":"<domain>","msg":"<msg>","ts":'"$(date +%s)"'000}'
450
460
  \`\`\`
@@ -453,7 +463,9 @@ To track task execution, log progress via \`monotask card comment add "$BOARD_ID
453
463
 
454
464
  BEFORE returning, emit domain:complete to the live dashboard:
455
465
  \`\`\`bash
456
- curl -s -X POST "http://localhost:4242/api/mastermind/event" \
466
+ REPO_ROOT=$(git rev-parse --show-toplevel 2>/dev/null || pwd)
467
+ CTRL_URL=$(jq -r '.url // "http://localhost:4242"' "$REPO_ROOT/.monomind/control.json" 2>/dev/null || echo "http://localhost:4242")
468
+ curl -s -X POST "${CTRL_URL}/api/mastermind/event" \
457
469
  -H "Content-Type: application/json" \
458
470
  -d '{"type":"domain:complete","session":"<sessionId>","domain":"architect","status":"<choose: complete | partial | blocked>","artifacts":[],"decisions":[],"ts":'"$(date +%s)"'000}'
459
471
  \`\`\`
@@ -539,7 +551,9 @@ Before executing the curl blocks below and when constructing the Task() descript
539
551
 
540
552
  1. Emit `agent:spawn` to the dashboard (use the resolved agent slug):
541
553
  ```bash
542
- curl -s -X POST "http://localhost:4242/api/mastermind/event" \
554
+ REPO_ROOT=$(git rev-parse --show-toplevel 2>/dev/null || pwd)
555
+ CTRL_URL=$(jq -r '.url // "http://localhost:4242"' "$REPO_ROOT/.monomind/control.json" 2>/dev/null || echo "http://localhost:4242")
556
+ curl -s -X POST "${CTRL_URL}/api/mastermind/event" \
543
557
  -H "Content-Type: application/json" \
544
558
  -d '{"type":"agent:spawn","session":"<sessionId>","domain":"architect","agent":"<resolved agent slug, e.g. software-architect>","task":"<prompt>","ts":'"$(date +%s)"'000}'
545
559
  ```
@@ -553,7 +567,9 @@ Before executing the curl blocks below and when constructing the Task() descript
553
567
  3. Include current directory structure context (`find . -maxdepth 3 -type d | grep -Ev "(^|/)(node_modules|dist|\.git)(/|$)"`)
554
568
  4. Collect output, then emit `domain:complete`:
555
569
  ```bash
556
- curl -s -X POST "http://localhost:4242/api/mastermind/event" \
570
+ REPO_ROOT=$(git rev-parse --show-toplevel 2>/dev/null || pwd)
571
+ CTRL_URL=$(jq -r '.url // "http://localhost:4242"' "$REPO_ROOT/.monomind/control.json" 2>/dev/null || echo "http://localhost:4242")
572
+ curl -s -X POST "${CTRL_URL}/api/mastermind/event" \
557
573
  -H "Content-Type: application/json" \
558
574
  -d '{"type":"domain:complete","session":"<sessionId>","domain":"architect","status":"complete","artifacts":[],"decisions":[],"ts":'"$(date +%s)"'000}'
559
575
  ```
@@ -0,0 +1,197 @@
1
+ ---
2
+ name: mastermind-backup
3
+ description: Mastermind backup — create, list, and restore compressed org backups. Archives org config, state, goals, routines, approvals, projects, and activity log into a timestamped tarball.
4
+ type: domain-skill
5
+ default_mode: confirm
6
+ ---
7
+
8
+ # Mastermind Backup
9
+
10
+ This skill is invoked by `mastermind:backup` or directly via `/mastermind:backup`.
11
+
12
+ ---
13
+
14
+ ## Inputs
15
+
16
+ - `brain_context`: BRAIN CONTEXT block (injected by command, or loaded below if standalone)
17
+ - `org_name`: org to back up or restore (optional for `list`; required for `create`/`restore`)
18
+ - `action`: create | list | restore | delete
19
+ - `backup_file`: path to backup archive (required for `restore`/`delete`; auto-selected for `restore` if omitted → latest)
20
+ - `backup_dir`: directory to store backups (default: `.monomind/backups`)
21
+ - `include_state`: whether to include runtime state file (default: false — state is ephemeral)
22
+ - `caller`: command | master
23
+
24
+ ---
25
+
26
+ ## Step 0 — Brain Load (standalone only)
27
+
28
+ If `caller` is not "command", load brain context following _protocol.md Brain Load Procedure with namespace: `ops`.
29
+
30
+ ---
31
+
32
+ ## Step 1 — Ensure Backup Directory
33
+
34
+ ```bash
35
+ backupDir="${backup_dir:-.monomind/backups}"
36
+ mkdir -p "$backupDir"
37
+ ```
38
+
39
+ ---
40
+
41
+ ## Step 2 — Execute Action
42
+
43
+ ### create
44
+
45
+ Create a compressed backup of all org data files:
46
+
47
+ ```bash
48
+ [ -z "$org_name" ] && { echo "ERROR: --org required for create."; exit 1; }
49
+ orgFile=".monomind/orgs/${org_name}.json"
50
+ [ ! -f "$orgFile" ] && { echo "ERROR: Org '${org_name}' not found."; exit 1; }
51
+
52
+ timestamp=$(date +%Y%m%d-%H%M%S)
53
+ archiveName="${org_name}-${timestamp}.tar.gz"
54
+ archivePath="${backupDir}/${archiveName}"
55
+
56
+ # Collect files to back up
57
+ filesToBackup=""
58
+ for suffix in "" "-goals" "-routines" "-approvals" "-projects" "-worktrees" "-bootstrap"; do
59
+ f=".monomind/orgs/${org_name}${suffix}.json"
60
+ [ -f "$f" ] && filesToBackup="$filesToBackup $f"
61
+ done
62
+
63
+ # Optionally include runtime state
64
+ if [ "${include_state:-false}" = "true" ]; then
65
+ stateFile=".monomind/orgs/${org_name}-state.json"
66
+ [ -f "$stateFile" ] && filesToBackup="$filesToBackup $stateFile"
67
+ fi
68
+
69
+ # Include recent activity (last 500 lines filtered by org)
70
+ eventsFile="data/mastermind-events.jsonl"
71
+ if [ -f "$eventsFile" ]; then
72
+ tmpEvents=$(mktemp /tmp/backup-events-XXXXXX.jsonl)
73
+ grep "\"org\":\"${org_name}\"" "$eventsFile" | tail -500 > "$tmpEvents" || true
74
+ filesToBackup="$filesToBackup $tmpEvents"
75
+ fi
76
+
77
+ # Create archive
78
+ tar -czf "$archivePath" $filesToBackup 2>/dev/null
79
+ [ -n "$tmpEvents" ] && rm -f "$tmpEvents"
80
+
81
+ if [ -f "$archivePath" ]; then
82
+ sizeKb=$(du -k "$archivePath" | awk '{print $1}')
83
+ echo "Backup created: $archivePath (${sizeKb}KB)"
84
+ echo "Files included: $(echo $filesToBackup | wc -w | tr -d ' ')"
85
+ else
86
+ echo "ERROR: Failed to create backup archive."
87
+ exit 1
88
+ fi
89
+ ```
90
+
91
+ Emit `org:backup:created` event:
92
+
93
+ ```bash
94
+ REPO_ROOT=$(git rev-parse --show-toplevel 2>/dev/null || pwd)
95
+ CTRL_URL=$(jq -r '.url // "http://localhost:4242"' "$REPO_ROOT/.monomind/control.json" 2>/dev/null || echo "http://localhost:4242")
96
+ curl -s -X POST "${CTRL_URL}/api/mastermind/event" \
97
+ -H "Content-Type: application/json" \
98
+ -d "$(jq -cn --arg org "$org_name" --arg file "$archiveName" \
99
+ '{type:"org:backup:created",org:$org,file:$file,ts:(now*1000|floor)}')" || true
100
+ ```
101
+
102
+ ### list
103
+
104
+ Show all available backups:
105
+
106
+ ```bash
107
+ echo "BACKUPS — ${backup_dir:-.monomind/backups}"
108
+ echo "──────────────────────────────────────────────"
109
+ printf "%-45s %-12s %s\n" "FILE" "SIZE" "ORG"
110
+ echo "──────────────────────────────────────────────"
111
+
112
+ found=0
113
+ for f in "${backupDir}"/*.tar.gz; do
114
+ [ -f "$f" ] || continue
115
+ name=$(basename "$f")
116
+ sizeKb=$(du -k "$f" | awk '{print $1}')
117
+ orgPart=$(echo "$name" | sed 's/-[0-9]\{8\}-[0-9]\{6\}\.tar\.gz$//')
118
+ if [ -z "$org_name" ] || [ "$orgPart" = "$org_name" ]; then
119
+ printf "%-45s %-12s %s\n" "$name" "${sizeKb}KB" "$orgPart"
120
+ found=$((found + 1))
121
+ fi
122
+ done
123
+
124
+ [ "$found" -eq 0 ] && echo " No backups found."
125
+ echo ""
126
+ echo "Total: $found backup(s)"
127
+ ```
128
+
129
+ ### restore
130
+
131
+ Restore org data from a backup archive:
132
+
133
+ ```bash
134
+ # Auto-select latest backup if not specified
135
+ if [ -z "$backup_file" ]; then
136
+ if [ -n "$org_name" ]; then
137
+ backup_file=$(ls "${backupDir}/${org_name}-"*.tar.gz 2>/dev/null | sort | tail -1)
138
+ fi
139
+ [ -z "$backup_file" ] && { echo "ERROR: No backup file found. Pass --backup-file <path>."; exit 1; }
140
+ fi
141
+
142
+ [ ! -f "$backup_file" ] && { echo "ERROR: Backup file not found: $backup_file"; exit 1; }
143
+
144
+ echo "Restoring from: $backup_file"
145
+ echo "This will overwrite existing org data. Confirm? (skipped in auto mode)"
146
+
147
+ # Extract to a temp dir first, then copy
148
+ tmpDir=$(mktemp -d /tmp/mastermind-restore-XXXXXX)
149
+ tar -xzf "$backup_file" -C "$tmpDir" 2>/dev/null
150
+
151
+ # Move restored files to correct locations
152
+ find "$tmpDir" -name "*.json" | while read -r f; do
153
+ dest=$(echo "$f" | sed "s|$tmpDir||")
154
+ destDir=$(dirname "$dest")
155
+ mkdir -p "$destDir" 2>/dev/null || true
156
+ cp "$f" "$dest" && echo " Restored: $dest"
157
+ done
158
+
159
+ # Handle events file
160
+ find "$tmpDir" -name "*.jsonl" | while read -r f; do
161
+ dest=$(echo "$f" | sed "s|$tmpDir||")
162
+ mkdir -p "$(dirname "$dest")" 2>/dev/null || true
163
+ cat "$f" >> "$dest" && echo " Appended events from backup"
164
+ done
165
+
166
+ rm -rf "$tmpDir"
167
+ echo "Restore complete."
168
+ ```
169
+
170
+ ### delete
171
+
172
+ Remove a specific backup archive:
173
+
174
+ ```bash
175
+ [ -z "$backup_file" ] && { echo "ERROR: --backup-file required for delete."; exit 1; }
176
+ [ ! -f "$backup_file" ] && { echo "ERROR: File not found: $backup_file"; exit 1; }
177
+ rm "$backup_file"
178
+ echo "Deleted: $backup_file"
179
+ ```
180
+
181
+ ---
182
+
183
+ ## Step 3 — Return Output
184
+
185
+ ```yaml
186
+ domain: ops
187
+ status: complete
188
+ action: <action>
189
+ org: <org_name>
190
+ backup_file: <path if created>
191
+ ```
192
+
193
+ ---
194
+
195
+ ## Step 4 — Brain Write (standalone only)
196
+
197
+ If `caller` is not "command", follow _protocol.md Brain Write Procedure for domain `ops`.
@@ -0,0 +1,190 @@
1
+ ---
2
+ name: mastermind-bootstrap
3
+ description: Mastermind bootstrap — one-time org initialization that primes the CEO/boss agent with org context, goal hierarchy, and a signed invite token. Run after createorg before first runorg.
4
+ type: domain-skill
5
+ default_mode: confirm
6
+ ---
7
+
8
+ # Mastermind Bootstrap
9
+
10
+ This skill is invoked by `mastermind:bootstrap` or directly via `/mastermind:bootstrap`.
11
+
12
+ ---
13
+
14
+ ## Inputs
15
+
16
+ - `brain_context`: BRAIN CONTEXT block (injected by command, or loaded below if standalone)
17
+ - `org_name`: org to bootstrap (required)
18
+ - `action`: init | token | status | reset
19
+ - `boss_role_id`: role ID of the CEO/boss agent (default: auto-detect by `reports_to: null`)
20
+ - `caller`: command | master
21
+
22
+ ---
23
+
24
+ ## Step 0 — Brain Load (standalone only)
25
+
26
+ If `caller` is not "command", load brain context following _protocol.md Brain Load Procedure with namespace: `ops`.
27
+
28
+ ---
29
+
30
+ ## Step 1 — Resolve Org
31
+
32
+ ```bash
33
+ orgFile=".monomind/orgs/${org_name}.json"
34
+ [ ! -f "$orgFile" ] && { echo "ERROR: Org '${org_name}' not found. Run /mastermind:createorg first."; exit 1; }
35
+
36
+ bootstrapFile=".monomind/orgs/${org_name}-bootstrap.json"
37
+ ```
38
+
39
+ ---
40
+
41
+ ## Step 2 — Execute Action
42
+
43
+ ### status (check bootstrap state)
44
+
45
+ ```bash
46
+ if [ -f "$bootstrapFile" ]; then
47
+ echo "BOOTSTRAP STATUS — ${org_name}"
48
+ echo "──────────────────────────────────"
49
+ jq -r '
50
+ " State: \(.state // "unknown")",
51
+ " Boss Role: \(.boss_role_id // "-")",
52
+ " Bootstrapped:\(.bootstrapped_at // "never")",
53
+ " Token: \(if .invite_token then (.invite_token | .[0:8]) + "..." else "none" end)",
54
+ " Token used: \(.token_used // false)"
55
+ ' "$bootstrapFile"
56
+ else
57
+ echo "Not bootstrapped. Run /mastermind:bootstrap --org ${org_name} --action init"
58
+ fi
59
+ ```
60
+
61
+ ### token (generate a fresh invite token)
62
+
63
+ Generate a signed one-time token the boss agent uses to authenticate its first session:
64
+
65
+ ```bash
66
+ token=$(openssl rand -hex 24 2>/dev/null || python3 -c "import secrets; print(secrets.token_hex(24))")
67
+ ts=$(date -u +%Y-%m-%dT%H:%M:%SZ)
68
+
69
+ echo "INVITE TOKEN — ${org_name}"
70
+ echo "──────────────────────────────────"
71
+ echo " Token: $token"
72
+ echo " Valid until first use."
73
+ echo ""
74
+
75
+ # Store token in bootstrap file
76
+ [ ! -f "$bootstrapFile" ] && echo '{}' > "$bootstrapFile"
77
+ tmp="${bootstrapFile}.tmp"
78
+ jq --arg token "$token" --arg ts "$ts" \
79
+ '.invite_token = $token | .token_generated_at = $ts | .token_used = false' \
80
+ "$bootstrapFile" > "$tmp" && mv "$tmp" "$bootstrapFile"
81
+ echo "Token stored. Include in boss agent prompt as: INVITE_TOKEN=${token}"
82
+ ```
83
+
84
+ ### init (full bootstrap)
85
+
86
+ Initialize org bootstrap: detect boss, generate token, write primer context:
87
+
88
+ ```bash
89
+ # Auto-detect boss (role with no reports_to or reports_to: null)
90
+ if [ -z "$boss_role_id" ]; then
91
+ boss_role_id=$(jq -r '.roles[] | select(.reports_to == null or .reports_to == "") | .id' "$orgFile" | head -1)
92
+ fi
93
+ [ -z "$boss_role_id" ] && { echo "ERROR: Could not detect boss role. Pass --boss-role-id <id>."; exit 1; }
94
+
95
+ bossConfig=$(jq --arg id "$boss_role_id" '.roles[] | select(.id == $id)' "$orgFile")
96
+ bossTitle=$(echo "$bossConfig" | jq -r '.title // "CEO"')
97
+ orgGoal=$(jq -r '.goal // "No goal set"' "$orgFile")
98
+ orgTopology=$(jq -r '.topology // "hierarchical"' "$orgFile")
99
+ roleCount=$(jq '.roles | length' "$orgFile")
100
+ governance=$(jq -r '.governance.policy // "auto"' "$orgFile")
101
+
102
+ # Generate invite token
103
+ token=$(openssl rand -hex 24 2>/dev/null || python3 -c "import secrets; print(secrets.token_hex(24))")
104
+ ts=$(date -u +%Y-%m-%dT%H:%M:%SZ)
105
+
106
+ # Write bootstrap record
107
+ cat > "$bootstrapFile" <<EOF
108
+ {
109
+ "org": "${org_name}",
110
+ "state": "initialized",
111
+ "boss_role_id": "${boss_role_id}",
112
+ "boss_title": "${bossTitle}",
113
+ "org_goal": "${orgGoal}",
114
+ "topology": "${orgTopology}",
115
+ "role_count": ${roleCount},
116
+ "governance": "${governance}",
117
+ "invite_token": "${token}",
118
+ "token_used": false,
119
+ "token_generated_at": "${ts}",
120
+ "bootstrapped_at": "${ts}"
121
+ }
122
+ EOF
123
+
124
+ echo "BOOTSTRAP COMPLETE — ${org_name}"
125
+ echo "──────────────────────────────────────────"
126
+ echo " Boss: ${bossTitle} (${boss_role_id})"
127
+ echo " Goal: ${orgGoal}"
128
+ echo " Topology: ${orgTopology}"
129
+ echo " Agents: ${roleCount}"
130
+ echo " Governance: ${governance}"
131
+ echo " Token: ${token}"
132
+ echo ""
133
+ echo "CEO PRIMER (include in boss agent prompt):"
134
+ echo "──────────────────────────────────────────"
135
+ cat <<PRIMER
136
+ ORG: ${org_name}
137
+ ROLE: ${bossTitle}
138
+ GOAL: ${orgGoal}
139
+ GOVERNANCE: ${governance}
140
+ INVITE_TOKEN: ${token}
141
+
142
+ You are the autonomous CEO of org '${org_name}'. Your mission: ${orgGoal}.
143
+ You lead ${roleCount} agents in a ${orgTopology} topology.
144
+ Governance mode: ${governance}. In 'board' or 'strict' mode, pause before high-risk actions and emit approval requests.
145
+ Use your INVITE_TOKEN for your first heartbeat. Token is single-use.
146
+ PRIMER
147
+ ```
148
+
149
+ Emit `org:bootstrap:complete` event:
150
+
151
+ ```bash
152
+ REPO_ROOT=$(git rev-parse --show-toplevel 2>/dev/null || pwd)
153
+ CTRL_URL=$(jq -r '.url // "http://localhost:4242"' "$REPO_ROOT/.monomind/control.json" 2>/dev/null || echo "http://localhost:4242")
154
+ curl -s -X POST "${CTRL_URL}/api/mastermind/event" \
155
+ -H "Content-Type: application/json" \
156
+ -d "$(jq -cn --arg org "$org_name" --arg boss "$boss_role_id" \
157
+ '{type:"org:bootstrap:complete",org:$org,boss:$boss,ts:(now*1000|floor)}')" || true
158
+ ```
159
+
160
+ ### reset
161
+
162
+ Clear bootstrap state (next init will regenerate token):
163
+
164
+ ```bash
165
+ if [ -f "$bootstrapFile" ]; then
166
+ rm "$bootstrapFile"
167
+ echo "Bootstrap state cleared for '${org_name}'. Run --action init to re-bootstrap."
168
+ else
169
+ echo "No bootstrap file found for '${org_name}'."
170
+ fi
171
+ ```
172
+
173
+ ---
174
+
175
+ ## Step 3 — Return Output
176
+
177
+ ```yaml
178
+ domain: ops
179
+ status: complete
180
+ action: <action>
181
+ org: <org_name>
182
+ boss_role_id: <boss_role_id>
183
+ state: initialized | token | reset
184
+ ```
185
+
186
+ ---
187
+
188
+ ## Step 4 — Brain Write (standalone only)
189
+
190
+ If `caller` is not "command", follow _protocol.md Brain Write Procedure for domain `ops`.