@monoes/monomindcli 1.9.16 → 1.10.0

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 +100 -46
  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 +37 -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 +318 -186
  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 +1 -1
  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,202 @@
1
+ ---
2
+ name: mastermind-routines
3
+ description: Mastermind routines — schedule recurring tasks that trigger agent heartbeats on a cron-like schedule within a running org. Configure concurrency policy and catch-up behavior.
4
+ type: domain-skill
5
+ default_mode: confirm
6
+ ---
7
+
8
+ # Mastermind Routines
9
+
10
+ This skill is invoked by `mastermind:routines` or directly via `/mastermind:routines`.
11
+
12
+ ---
13
+
14
+ ## Inputs
15
+
16
+ - `brain_context`: BRAIN CONTEXT block
17
+ - `org_name`: org to manage routines for
18
+ - `action`: list | add | pause | resume | remove | trigger
19
+ - `routine_id`: slug of the routine (for pause/resume/remove/trigger)
20
+ - `routine_name`: display name (for add)
21
+ - `agent_id`: role id of the agent to trigger
22
+ - `schedule`: cron expression (e.g. "0 9 * * 1-5" = weekdays at 9am)
23
+ - `task_title`: task to create on each trigger
24
+ - `context`: optional context passed to agent on each heartbeat
25
+ - `concurrency`: coalesce_if_active | always_enqueue | skip_if_active (default: coalesce_if_active)
26
+ - `catchup`: skip_missed | enqueue_missed_with_cap (default: skip_missed)
27
+ - `caller`: command | master
28
+
29
+ ---
30
+
31
+ ## Step 0 — Brain Load (standalone only)
32
+
33
+ If `caller` is not "command", load brain context following _protocol.md Brain Load Procedure with namespace: `ops`.
34
+
35
+ ---
36
+
37
+ ## Step 1 — Load Routines
38
+
39
+ Routines are stored in `.monomind/orgs/<org_name>-routines.json`:
40
+
41
+ ```bash
42
+ routinesFile=".monomind/orgs/${org_name}-routines.json"
43
+ [ ! -f "$routinesFile" ] && echo '{"routines":[]}' > "$routinesFile"
44
+ ```
45
+
46
+ ---
47
+
48
+ ## Step 2 — Execute Action
49
+
50
+ ### list (default)
51
+
52
+ Show all routines with their schedule and status:
53
+
54
+ ```bash
55
+ jq -r '
56
+ .routines[] |
57
+ "[\(.id)] \(.name) agent=\(.agent_id) schedule=\"\(.schedule)\" status=\(.status // "active")\n" +
58
+ " task: \(.task_title)\n concurrency: \(.concurrency) catchup: \(.catchup)\n last_run: \(.last_run // "never") next_run: \(.next_run // "unknown")"
59
+ ' "$routinesFile" 2>/dev/null || echo "No routines defined."
60
+ ```
61
+
62
+ Render as:
63
+ ```
64
+ ROUTINES — org: <org_name>
65
+ ──────────────────────────────────────────────────────
66
+ [weekly-report] Weekly Status Report
67
+ Agent: boss | Schedule: 0 9 * * 1 (Mondays 9am)
68
+ Status: active
69
+ Task: "Compile weekly progress report from all agents"
70
+ Concurrency: coalesce_if_active | Catchup: skip_missed
71
+ Last run: 3 days ago | Next run: in 4 days
72
+
73
+ [daily-content] Daily Content Draft
74
+ Agent: content-writer | Schedule: 0 10 * * 1-5 (weekdays 10am)
75
+ Status: active
76
+ Task: "Draft one content piece for the content calendar"
77
+ Concurrency: skip_if_active | Catchup: skip_missed
78
+ Last run: yesterday | Next run: tomorrow 10am
79
+ ```
80
+
81
+ ### add
82
+
83
+ Add a new routine and register a ScheduleWakeup via Claude's native scheduler:
84
+
85
+ ```bash
86
+ routine_id=$(echo "$routine_name" | tr '[:upper:]' '[:lower:]' | sed 's/[^a-z0-9]/-/g' | tr -s '-')
87
+ tmp="${routinesFile}.tmp"
88
+ jq --arg id "$routine_id" \
89
+ --arg name "$routine_name" \
90
+ --arg agent "$agent_id" \
91
+ --arg schedule "$schedule" \
92
+ --arg task "$task_title" \
93
+ --arg context "${context:-}" \
94
+ --arg concurrency "${concurrency:-coalesce_if_active}" \
95
+ --arg catchup "${catchup:-skip_missed}" \
96
+ '.routines += [{
97
+ "id":$id,"name":$name,"agent_id":$agent,"schedule":$schedule,
98
+ "task_title":$task,"context":$context,"concurrency":$concurrency,
99
+ "catchup":$catchup,"status":"active","created_at":(now|todate)
100
+ }]' \
101
+ "$routinesFile" > "$tmp" && mv "$tmp" "$routinesFile"
102
+ echo "Routine added: $routine_id"
103
+ echo "Schedule: $schedule"
104
+ echo ""
105
+ echo "NOTE: To activate this routine, use ScheduleWakeup with:"
106
+ echo " prompt: '/mastermind:routines --action trigger --org $org_name --routine-id $routine_id'"
107
+ echo " delaySeconds: <seconds until next scheduled run>"
108
+ ```
109
+
110
+ After creating, use `ScheduleWakeup` to schedule the first trigger at the appropriate delay based on the cron expression.
111
+
112
+ ### trigger
113
+
114
+ Manually trigger a routine immediately (same as a scheduled run):
115
+
116
+ ```bash
117
+ routine=$(jq --arg id "$routine_id" '.routines[] | select(.id == $id)' "$routinesFile")
118
+ rt_agent=$(echo "$routine" | jq -r '.agent_id')
119
+ rt_task=$(echo "$routine" | jq -r '.task_title')
120
+ rt_context=$(echo "$routine" | jq -r '.context // ""')
121
+ rt_concurrency=$(echo "$routine" | jq -r '.concurrency')
122
+
123
+ # Check concurrency policy
124
+ stateFile=".monomind/orgs/${org_name}-state.json"
125
+ agent_status=$(jq -r --arg a "$rt_agent" '.agents[$a].status // "idle"' "$stateFile" 2>/dev/null)
126
+
127
+ case "$rt_concurrency" in
128
+ skip_if_active)
129
+ [ "$agent_status" = "running" ] && { echo "Skipped: agent $rt_agent is already running (skip_if_active policy)"; exit 0; }
130
+ ;;
131
+ coalesce_if_active)
132
+ # Queue at most one pending run
133
+ ;;
134
+ esac
135
+ ```
136
+
137
+ Then invoke the heartbeat skill logic: create a task card for `rt_task`, trigger the agent heartbeat.
138
+
139
+ Update routine's `last_run` and schedule next wakeup:
140
+
141
+ ```bash
142
+ tmp="${routinesFile}.tmp"
143
+ jq --arg id "$routine_id" --arg ts "$(date -u +%Y-%m-%dT%H:%M:%SZ)" \
144
+ '.routines = [.routines[] | if .id == $id then .last_run = $ts else . end]' \
145
+ "$routinesFile" > "$tmp" && mv "$tmp" "$routinesFile"
146
+ ```
147
+
148
+ ### pause / resume
149
+
150
+ ```bash
151
+ tmp="${routinesFile}.tmp"
152
+ jq --arg id "$routine_id" --arg status "$action" \
153
+ '.routines = [.routines[] | if .id == $id then .status = $status else . end]' \
154
+ "$routinesFile" > "$tmp" && mv "$tmp" "$routinesFile"
155
+ echo "Routine $routine_id set to: $action"
156
+ ```
157
+
158
+ ### remove
159
+
160
+ ```bash
161
+ tmp="${routinesFile}.tmp"
162
+ jq --arg id "$routine_id" '.routines = [.routines[] | select(.id != $id)]' \
163
+ "$routinesFile" > "$tmp" && mv "$tmp" "$routinesFile"
164
+ echo "Routine $routine_id removed."
165
+ ```
166
+
167
+ ---
168
+
169
+ ## Concurrency Policies
170
+
171
+ | Policy | Behavior |
172
+ |--------|----------|
173
+ | `coalesce_if_active` | If a run is already active, keep just one follow-up queued |
174
+ | `always_enqueue` | Queue every trigger, even if routine is already running |
175
+ | `skip_if_active` | Drop new triggers while a run is active |
176
+
177
+ ## Catch-up Policies
178
+
179
+ | Policy | Behavior |
180
+ |--------|----------|
181
+ | `skip_missed` | Ignore windows missed while paused/down |
182
+ | `enqueue_missed_with_cap` | Catch up missed windows in capped batches |
183
+
184
+ ---
185
+
186
+ ## Step 3 — Return Output
187
+
188
+ ```yaml
189
+ domain: ops
190
+ status: complete
191
+ action: <action>
192
+ org: <org_name>
193
+ routine_id: <routine_id if applicable>
194
+ routines_count: <N>
195
+ routines_file: .monomind/orgs/<org_name>-routines.json
196
+ ```
197
+
198
+ ---
199
+
200
+ ## Step 4 — Brain Write (standalone only)
201
+
202
+ If `caller` is not "command", follow _protocol.md Brain Write Procedure for domain `ops`.
@@ -114,14 +114,39 @@ The board and column IDs were written into the org config by `createorg`. If mis
114
114
  [ -z "$todo_col" ] && { echo "ERROR: org config missing todo_col_id — re-run /mastermind:createorg --name ${orgName}."; exit 1; }
115
115
  ```
116
116
 
117
- **Create stop-file directory** (boss agent writes here; must exist before it runs):
117
+ **Create stop-file and state directories:**
118
118
  ```bash
119
119
  mkdir -p .monomind/orgs/.stops
120
120
  ```
121
121
 
122
+ **Initialize org state file** (tracks per-agent status, heartbeat timestamps, token usage):
123
+ ```bash
124
+ stateFile=".monomind/orgs/${orgName}-state.json"
125
+ if [ ! -f "$stateFile" ]; then
126
+ jq -n \
127
+ --arg org "$orgName" \
128
+ --arg runId "$runId" \
129
+ '{org:$org,run_id:$runId,started_at:(now|todate),agents:{}}' \
130
+ > "$stateFile"
131
+ else
132
+ # Update run_id and started_at for this run
133
+ tmp="${stateFile}.tmp"
134
+ jq --arg runId "$runId" \
135
+ '.run_id = $runId | .started_at = (now|todate)' \
136
+ "$stateFile" > "$tmp" && mv "$tmp" "$stateFile"
137
+ fi
138
+ ```
139
+
140
+ **Remove any stale stop file:**
141
+ ```bash
142
+ rm -f "$stopFile"
143
+ ```
144
+
122
145
  **Emit `org:start` to dashboard:**
123
146
  ```bash
124
- curl -s -X POST "http://localhost:4242/api/mastermind/event" \
147
+ REPO_ROOT=$(git rev-parse --show-toplevel 2>/dev/null || pwd)
148
+ CTRL_URL=$(jq -r '.url // "http://localhost:4242"' "$REPO_ROOT/.monomind/control.json" 2>/dev/null || echo "http://localhost:4242")
149
+ curl -s -X POST "${CTRL_URL}/api/mastermind/event" \
125
150
  -H "Content-Type: application/json" \
126
151
  -d "$(jq -cn \
127
152
  --arg session "$sessionId" \
@@ -158,7 +183,7 @@ SHARED INFRASTRUCTURE:
158
183
  - Task board (monotask): board_id=${board_id}
159
184
  Columns: Todo=${todo_col} Doing=${doing_col} Done=${done_col}
160
185
  - Memory namespace: ${memNs} (use: npx monomind@latest memory store/search --namespace ${memNs})
161
- - Dashboard events: POST http://localhost:4242/api/mastermind/event via curl (see below)
186
+ - Dashboard events: POST to mastermind control server via curl see CTRL_URL resolution in DASHBOARD EVENTS section below
162
187
  - Session ID for all events: ${sessionId}
163
188
 
164
189
  TASK BOARD COMMANDS (use these for all task management):
@@ -191,6 +216,42 @@ TASK BOARD COMMANDS (use these for all task management):
191
216
  # Complete a task:
192
217
  monotask card move ${board_id} $CARD_ID ${done_col}
193
218
 
219
+ ORG STATE FILE (update per agent per cycle for dashboard visibility):
220
+ stateFile=".monomind/orgs/${orgName}-state.json"
221
+ # Mark agent as running:
222
+ jq --arg id "<role_id>" --arg ts "$(date -u +%Y-%m-%dT%H:%M:%SZ)" \
223
+ '.agents[$id].status = "running" | .agents[$id].last_heartbeat = $ts' \
224
+ "$stateFile" > "${stateFile}.tmp" && mv "${stateFile}.tmp" "$stateFile"
225
+ # Mark agent as idle after completing:
226
+ jq --arg id "<role_id>" \
227
+ '.agents[$id].status = "idle" | .agents[$id].last_heartbeat_complete = (now|todate)' \
228
+ "$stateFile" > "${stateFile}.tmp" && mv "${stateFile}.tmp" "$stateFile"
229
+ # Add token counts when known:
230
+ jq --arg id "<role_id>" --argjson in <tokens_in> --argjson out <tokens_out> \
231
+ '.agents[$id].tokens_in = ((.agents[$id].tokens_in // 0) + $in) | .agents[$id].tokens_out = ((.agents[$id].tokens_out // 0) + $out)' \
232
+ "$stateFile" > "${stateFile}.tmp" && mv "${stateFile}.tmp" "$stateFile"
233
+
234
+ APPROVAL GATE (when governance.policy is "board" or "strict"):
235
+ Before any external action (sending emails, posting content, making purchases, modifying infrastructure):
236
+ approvalsFile=".monomind/orgs/${orgName}-approvals.json"
237
+ [ ! -f "$approvalsFile" ] && echo '{"approvals":[]}' > "$approvalsFile"
238
+ approval_id="req-$(date +%s)"
239
+ jq --arg id "$approval_id" --arg agent "<role_id>" --arg title "<action summary>" \
240
+ --arg action "<full action description>" --arg risk "medium" \
241
+ '.approvals += [{"id":$id,"agent_id":$agent,"title":$title,"action":$action,"risk_level":$risk,"status":"pending","requested_at":(now|todate)}]' \
242
+ "$approvalsFile" > "${approvalsFile}.tmp" && mv "${approvalsFile}.tmp" "$approvalsFile"
243
+ # Emit approval request event so human sees it in dashboard
244
+ curl -s -X POST "${CTRL_URL}/api/mastermind/event" -H "Content-Type: application/json" \
245
+ -d "$(jq -cn --arg org "${orgName}" --arg id "$approval_id" --arg title "<title>" \
246
+ '{type:"org:approval:requested",org:$org,approval_id:$id,title:$title,ts:(now*1000|floor)}')" || true
247
+ # Poll until approved or rejected (max 30 min):
248
+ for i in $(seq 1 60); do
249
+ status=$(npx monomind@latest memory search --query "approval:${approval_id}" --namespace "${memNs}" 2>/dev/null | jq -r '.[0].value.status // ""' 2>/dev/null)
250
+ [ "$status" = "approved" ] && break
251
+ [ "$status" = "rejected" ] && { echo "Action rejected by governance policy — skip this action"; break; }
252
+ sleep 30
253
+ done
254
+
194
255
  STOP DETECTION (check this FIRST in every loop iteration):
195
256
  ls ${stopFile} 2>/dev/null && echo STOP_REQUESTED
196
257
  If the file exists: emit org:complete event, clean up with "rm -f ${stopFile}", then exit.
@@ -218,7 +279,9 @@ ${orgConfig.roles.filter(r => r.id !== bossRole.id).map(r =>
218
279
  ).join('\n')}
219
280
 
220
281
  DASHBOARD EVENTS — emit via curl (NOT WebFetch — WebFetch does not support POST):
221
- curl -s -X POST http://localhost:4242/api/mastermind/event \
282
+ REPO_ROOT=$(git rev-parse --show-toplevel 2>/dev/null || pwd)
283
+ CTRL_URL=$(jq -r '.url // "http://localhost:4242"' "$REPO_ROOT/.monomind/control.json" 2>/dev/null || echo "http://localhost:4242")
284
+ curl -s -X POST "${CTRL_URL}/api/mastermind/event" \
222
285
  -H "Content-Type: application/json" \
223
286
  -d "$(jq -cn --arg type TYPE --arg session SESSION --arg org ORG '{type:$type,session:$session,org:$org,ts:(now*1000|floor)}')"
224
287
  Payloads:
@@ -238,7 +301,9 @@ START NOW: check for stop signal, assess the board, create initial tasks if none
238
301
  Emit `org:agent:online` for the boss role (team member events are emitted by the boss itself):
239
302
 
240
303
  ```bash
241
- curl -s -X POST "http://localhost:4242/api/mastermind/event" \
304
+ REPO_ROOT=$(git rev-parse --show-toplevel 2>/dev/null || pwd)
305
+ CTRL_URL=$(jq -r '.url // "http://localhost:4242"' "$REPO_ROOT/.monomind/control.json" 2>/dev/null || echo "http://localhost:4242")
306
+ curl -s -X POST "${CTRL_URL}/api/mastermind/event" \
242
307
  -H "Content-Type: application/json" \
243
308
  -d "$(jq -cn \
244
309
  --arg session "$sessionId" \
@@ -272,10 +337,10 @@ ACTIVE ROLES
272
337
 
273
338
  BOARD: <orgName>/org-tasks
274
339
  MEMORY: org:<orgName>
275
- DASHBOARD: http://localhost:4242
340
+ DASHBOARD: see .monomind/control.json for URL (default http://localhost:4242)
276
341
 
277
342
  To stop: click STOP in the dashboard Orgs panel
278
- or run: curl -X POST http://localhost:4242/api/orgs/<orgName>/stop
343
+ or run: CTRL_URL=$(jq -r '.url // "http://localhost:4242"' .monomind/control.json 2>/dev/null || echo "http://localhost:4242"); curl -X POST "${CTRL_URL}/api/orgs/<orgName>/stop"
279
344
  ```
280
345
 
281
346
  ---
@@ -295,8 +360,8 @@ lessons:
295
360
  - what_worked: "Boss agent spawned and org loop started"
296
361
  - what_didnt: ""
297
362
  next_actions:
298
- - "Monitor at http://localhost:4242 — Mastermind Orgs panel"
299
- - "To stop: click STOP in dashboard or POST to /api/orgs/<orgName>/stop"
363
+ - "Monitor in Mastermind Orgs panel (CTRL_URL from .monomind/control.json, default http://localhost:4242)"
364
+ - "To stop: click STOP in dashboard or: CTRL_URL=$(jq -r '.url // \"http://localhost:4242\"' .monomind/control.json); curl -X POST \"${CTRL_URL}/api/orgs/<orgName>/stop\""
300
365
  board_url: "monotask://<orgName>/org-tasks"
301
366
  run_id: "<runId>"
302
367
  ```
@@ -0,0 +1,186 @@
1
+ ---
2
+ name: mastermind-search
3
+ description: Mastermind search — fuzzy cross-org search across tasks, goals, agents, approvals, routines, projects, and activity log. Returns ranked results with org context.
4
+ type: domain-skill
5
+ default_mode: auto
6
+ ---
7
+
8
+ # Mastermind Search
9
+
10
+ This skill is invoked by `mastermind:search` or directly via `/mastermind:search`.
11
+
12
+ ---
13
+
14
+ ## Inputs
15
+
16
+ - `brain_context`: BRAIN CONTEXT block (injected by command, or loaded below if standalone)
17
+ - `query`: search term (required)
18
+ - `org_name`: filter to a specific org (optional — searches all orgs if omitted)
19
+ - `scope`: all | tasks | goals | agents | approvals | routines | projects | activity (default: all)
20
+ - `limit`: max results per category (default: 10)
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 — Resolve Orgs
32
+
33
+ ```bash
34
+ if [ -n "$org_name" ]; then
35
+ orgs="$org_name"
36
+ else
37
+ orgs=$(ls .monomind/orgs/*.json 2>/dev/null | grep -v '\-state\|-goals\|-routines\|-approvals\|-projects\|-worktrees\|-secrets' | xargs -I{} basename {} .json | sort)
38
+ fi
39
+ [ -z "$orgs" ] && { echo "No orgs found. Run /mastermind:createorg first."; exit 0; }
40
+ ```
41
+
42
+ ---
43
+
44
+ ## Step 2 — Search All Scopes
45
+
46
+ ```bash
47
+ query_lower=$(echo "$query" | tr '[:upper:]' '[:lower:]')
48
+ limit="${limit:-10}"
49
+ total_hits=0
50
+
51
+ echo "SEARCH: \"${query}\""
52
+ echo "════════════════════════════════════════════════"
53
+ echo ""
54
+
55
+ for org in $orgs; do
56
+ orgFile=".monomind/orgs/${org}.json"
57
+ [ ! -f "$orgFile" ] && continue
58
+
59
+ org_hits=0
60
+
61
+ # ── Agents ────────────────────────────────────────
62
+ if [ "$scope" = "all" ] || [ "$scope" = "agents" ]; then
63
+ hits=$(jq -r --arg q "$query_lower" \
64
+ '.roles[] | select((.id + " " + .title + " " + (.responsibilities // [] | join(" "))) | ascii_downcase | test($q)) |
65
+ "[AGENT] \(.id): \(.title) type=\(.agent_type)"' \
66
+ "$orgFile" 2>/dev/null | head -"$limit")
67
+ if [ -n "$hits" ]; then
68
+ echo "── $org / agents ──"
69
+ echo "$hits"
70
+ echo ""
71
+ org_hits=$((org_hits + $(echo "$hits" | wc -l)))
72
+ fi
73
+ fi
74
+
75
+ # ── Goals ─────────────────────────────────────────
76
+ goalsFile=".monomind/orgs/${org}-goals.json"
77
+ if [ -f "$goalsFile" ] && { [ "$scope" = "all" ] || [ "$scope" = "goals" ]; }; then
78
+ hits=$(jq -r --arg q "$query_lower" \
79
+ '.goals[] | select((.title + " " + (.description // "") + " " + (.status // "")) | ascii_downcase | test($q)) |
80
+ "[GOAL] [\(.id)] \(.title) status=\(.status // "open")"' \
81
+ "$goalsFile" 2>/dev/null | head -"$limit")
82
+ if [ -n "$hits" ]; then
83
+ echo "── $org / goals ──"
84
+ echo "$hits"
85
+ echo ""
86
+ org_hits=$((org_hits + $(echo "$hits" | wc -l)))
87
+ fi
88
+ fi
89
+
90
+ # ── Routines ──────────────────────────────────────
91
+ routinesFile=".monomind/orgs/${org}-routines.json"
92
+ if [ -f "$routinesFile" ] && { [ "$scope" = "all" ] || [ "$scope" = "routines" ]; }; then
93
+ hits=$(jq -r --arg q "$query_lower" \
94
+ '.routines[] | select((.name + " " + (.description // "") + " " + (.schedule // "")) | ascii_downcase | test($q)) |
95
+ "[ROUTINE] \(.name) schedule=\(.schedule // "-")"' \
96
+ "$routinesFile" 2>/dev/null | head -"$limit")
97
+ if [ -n "$hits" ]; then
98
+ echo "── $org / routines ──"
99
+ echo "$hits"
100
+ echo ""
101
+ org_hits=$((org_hits + $(echo "$hits" | wc -l)))
102
+ fi
103
+ fi
104
+
105
+ # ── Approvals ─────────────────────────────────────
106
+ approvalsFile=".monomind/orgs/${org}-approvals.json"
107
+ if [ -f "$approvalsFile" ] && { [ "$scope" = "all" ] || [ "$scope" = "approvals" ]; }; then
108
+ hits=$(jq -r --arg q "$query_lower" \
109
+ '.approvals[] | select((.title + " " + (.action // "") + " " + (.agent_id // "")) | ascii_downcase | test($q)) |
110
+ "[APPROVAL] [\(.id)] \(.agent_id): \(.title) status=\(.status)"' \
111
+ "$approvalsFile" 2>/dev/null | head -"$limit")
112
+ if [ -n "$hits" ]; then
113
+ echo "── $org / approvals ──"
114
+ echo "$hits"
115
+ echo ""
116
+ org_hits=$((org_hits + $(echo "$hits" | wc -l)))
117
+ fi
118
+ fi
119
+
120
+ # ── Projects ──────────────────────────────────────
121
+ projectsFile=".monomind/orgs/${org}-projects.json"
122
+ if [ -f "$projectsFile" ] && { [ "$scope" = "all" ] || [ "$scope" = "projects" ]; }; then
123
+ hits=$(jq -r --arg q "$query_lower" \
124
+ '.projects[] | select((.name + " " + (.description // "") + " " + (.lead // "")) | ascii_downcase | test($q)) |
125
+ "[PROJECT] \(.name) status=\(.status // "active") lead=\(.lead // "-")"' \
126
+ "$projectsFile" 2>/dev/null | head -"$limit")
127
+ if [ -n "$hits" ]; then
128
+ echo "── $org / projects ──"
129
+ echo "$hits"
130
+ echo ""
131
+ org_hits=$((org_hits + $(echo "$hits" | wc -l)))
132
+ fi
133
+ fi
134
+
135
+ # ── Activity log ──────────────────────────────────
136
+ if [ "$scope" = "all" ] || [ "$scope" = "activity" ]; then
137
+ eventsFile="data/mastermind-events.jsonl"
138
+ if [ -f "$eventsFile" ]; then
139
+ hits=$(grep "\"org\":\"$org\"" "$eventsFile" 2>/dev/null | \
140
+ jq -r --arg q "$query_lower" \
141
+ 'select((tostring | ascii_downcase | test($q))) |
142
+ "[EVENT] \(.type) org=\(.org) \(if .task then "task=\(.task)" elif .role then "role=\(.role)" else "" end)"' \
143
+ 2>/dev/null | tail -"$limit")
144
+ if [ -n "$hits" ]; then
145
+ echo "── $org / activity ──"
146
+ echo "$hits"
147
+ echo ""
148
+ org_hits=$((org_hits + $(echo "$hits" | wc -l)))
149
+ fi
150
+ fi
151
+ fi
152
+
153
+ total_hits=$((total_hits + org_hits))
154
+ done
155
+
156
+ if [ "$total_hits" -eq 0 ]; then
157
+ echo " No results found for \"${query}\""
158
+ echo ""
159
+ echo " Tips:"
160
+ echo " • Try a shorter or more general query"
161
+ echo " • Use --scope to narrow: tasks, goals, agents, approvals, routines, projects, activity"
162
+ echo " • Use --org to limit to a specific org"
163
+ fi
164
+
165
+ echo "════════════════════════════════════════════════"
166
+ echo "Found: ${total_hits} result(s)"
167
+ ```
168
+
169
+ ---
170
+
171
+ ## Step 3 — Return Output
172
+
173
+ ```yaml
174
+ domain: ops
175
+ status: complete
176
+ query: <query>
177
+ scope: <scope>
178
+ orgs_searched: <N>
179
+ total_hits: <N>
180
+ ```
181
+
182
+ ---
183
+
184
+ ## Step 4 — Brain Write (standalone only)
185
+
186
+ If `caller` is not "command", follow _protocol.md Brain Write Procedure for domain `ops`.