@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,242 @@
1
+ ---
2
+ name: mastermind-agent-detail
3
+ description: Mastermind agent-detail — deep per-agent inspection: show config, run history, budget usage, heartbeat status, assigned skills, and reset/reconfigure a single agent within an org.
4
+ type: domain-skill
5
+ default_mode: auto
6
+ ---
7
+
8
+ # Mastermind Agent Detail
9
+
10
+ This skill is invoked by `mastermind:agent-detail` or directly via `/mastermind:agent-detail`.
11
+
12
+ ---
13
+
14
+ ## Inputs
15
+
16
+ - `brain_context`: BRAIN CONTEXT block (injected by command, or loaded below if standalone)
17
+ - `org_name`: org the agent belongs to (required)
18
+ - `agent_id`: agent slug/id (required)
19
+ - `action`: show | runs | config | budget | heartbeat | skills | reset
20
+ - `days`: lookback window for run history (default 7)
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 Agent Data
32
+
33
+ ```bash
34
+ orgFile=".monomind/orgs/${org_name}.json"
35
+ [ ! -f "$orgFile" ] && { echo "ERROR: Org '${org_name}' not found."; exit 1; }
36
+
37
+ agentDef=$(jq -r --arg id "$agent_id" '.roles[] | select(.id == $id)' "$orgFile")
38
+ [ -z "$agentDef" ] && { echo "ERROR: Agent '$agent_id' not found in org '$org_name'."; exit 1; }
39
+
40
+ stateFile=".monomind/orgs/${org_name}-state.json"
41
+ agentState="{}"
42
+ [ -f "$stateFile" ] && agentState=$(jq -r --arg id "$agent_id" '.agents[$id] // {}' "$stateFile")
43
+
44
+ activityFile=".monomind/orgs/${org_name}-activity.jsonl"
45
+ days=${days:-7}
46
+ cutoff=$(date -u -v-${days}d +%Y-%m-%dT%H:%M:%SZ 2>/dev/null || date -u -d "${days} days ago" +%Y-%m-%dT%H:%M:%SZ 2>/dev/null || echo "")
47
+ ```
48
+
49
+ ---
50
+
51
+ ## Step 2 — Execute Action
52
+
53
+ ### show (default)
54
+
55
+ ```bash
56
+ echo "AGENT DETAIL — $agent_id @ $org_name"
57
+ echo "────────────────────────────────────────────────────────"
58
+
59
+ echo "$agentDef" | jq -r '
60
+ " ID: \(.id)",
61
+ " Title: \(.title // "-")",
62
+ " Reports to: \(.reports_to // "(top)")",
63
+ " Governance: \(.governance // "inherit")",
64
+ " Model: \(.adapter.model // "default")",
65
+ " Max tokens: \((.adapter.max_tokens // 8192) | tostring)",
66
+ " Heartbeat: \(if (.heartbeat.enabled // false) then "enabled (" + ((.heartbeat.interval // 900) | tostring) + "s)" else "disabled" end)"
67
+ '
68
+
69
+ status=$(echo "$agentState" | jq -r '.status // "unknown"')
70
+ lastRun=$(echo "$agentState" | jq -r '.last_run // "-"')
71
+ totalRuns=$(echo "$agentState" | jq -r '.total_runs // 0')
72
+ tokenUsed=$(echo "$agentState" | jq -r '.tokens_used // 0')
73
+
74
+ echo ""
75
+ echo " Status: $status"
76
+ echo " Last run: $lastRun"
77
+ echo " Total runs: $totalRuns"
78
+ echo " Tokens used: $tokenUsed"
79
+
80
+ # Skills
81
+ skillCount=$(echo "$agentDef" | jq -r '(.skills // []) | length')
82
+ echo ""
83
+ echo " Skills: $skillCount assigned"
84
+ echo "$agentDef" | jq -r '(.skills // [])[] | " · \(.)"'
85
+ ```
86
+
87
+ ### runs
88
+
89
+ ```bash
90
+ echo "RUN HISTORY — $agent_id (last ${days} days)"
91
+ echo "────────────────────────────────────────────────────────"
92
+ printf "%-26s %-10s %-8s %-12s %s\n" "TIMESTAMP" "STATUS" "TOKENS" "DURATION" "TASK"
93
+ echo "────────────────────────────────────────────────────────"
94
+
95
+ found=0
96
+ if [ -f "$activityFile" ]; then
97
+ while IFS= read -r line; do
98
+ agId=$(echo "$line" | jq -r '.agent // ""')
99
+ [ "$agId" != "$agent_id" ] && continue
100
+ ts=$(echo "$line" | jq -r '.ts // ""')
101
+ [ -n "$cutoff" ] && [ "$ts" \< "$cutoff" ] && continue
102
+ st=$(echo "$line" | jq -r '.status // "-"')
103
+ tok=$(echo "$line" | jq -r '.tokens // "-"')
104
+ dur=$(echo "$line" | jq -r '.duration_ms // "-"')
105
+ task=$(echo "$line" | jq -r '.task // "-"' | cut -c1-40)
106
+ printf "%-26s %-10s %-8s %-12s %s\n" "$ts" "$st" "$tok" "${dur}ms" "$task"
107
+ found=$((found + 1))
108
+ done < "$activityFile"
109
+ fi
110
+
111
+ [ "$found" -eq 0 ] && echo " No runs in the last $days days."
112
+
113
+ # 7-day summary bar
114
+ echo ""
115
+ echo "ACTIVITY SUMMARY (last 7 days)"
116
+ for d in 6 5 4 3 2 1 0; do
117
+ dayLabel=$(date -u -v-${d}d +%Y-%m-%d 2>/dev/null || date -u -d "${d} days ago" +%Y-%m-%d 2>/dev/null || echo "?")
118
+ count=0
119
+ if [ -f "$activityFile" ]; then
120
+ count=$(grep "\"agent\":\"${agent_id}\"" "$activityFile" | grep "\"$dayLabel" | wc -l | tr -d ' ')
121
+ fi
122
+ bar=$(printf '%0.s█' $(seq 1 $((count > 10 ? 10 : count))))
123
+ printf " %s %-10s %s\n" "$dayLabel" "$bar" "($count)"
124
+ done
125
+ ```
126
+
127
+ ### config
128
+
129
+ ```bash
130
+ echo "ADAPTER CONFIG — $agent_id"
131
+ echo "────────────────────────────────────────────────────────"
132
+ echo "$agentDef" | jq '.adapter // {"model":"default","max_tokens":8192}'
133
+ echo ""
134
+ echo "RUNTIME CONFIG"
135
+ echo "$agentDef" | jq '.runtimeConfig // {}'
136
+ echo ""
137
+ echo "HEARTBEAT CONFIG"
138
+ echo "$agentDef" | jq '.heartbeat // {"enabled":false}'
139
+ ```
140
+
141
+ ### budget
142
+
143
+ ```bash
144
+ echo "BUDGET — $agent_id @ $org_name"
145
+ echo "────────────────────────────────────────────────────────"
146
+
147
+ orgBudget=$(jq -r '.budget_tokens // 0' "$orgFile")
148
+ agentBudget=$(echo "$agentDef" | jq -r '.budget_tokens // null')
149
+ tokensUsed=$(echo "$agentState" | jq -r '.tokens_used // 0')
150
+
151
+ echo " Org budget: $orgBudget tokens/day"
152
+ [ "$agentBudget" != "null" ] && echo " Agent cap: $agentBudget tokens" || echo " Agent cap: (inherits org)"
153
+ echo " Used today: $tokensUsed tokens"
154
+
155
+ if [ "$orgBudget" -gt 0 ] && [ "$tokensUsed" -gt 0 ]; then
156
+ pct=$((tokensUsed * 100 / orgBudget))
157
+ echo " Utilization: ${pct}%"
158
+ [ "$pct" -ge 80 ] && echo " WARNING: Agent has used ${pct}% of org daily budget."
159
+ fi
160
+
161
+ # Per-day breakdown from activity
162
+ echo ""
163
+ echo "DAILY USAGE (last 7 days)"
164
+ for d in 6 5 4 3 2 1 0; do
165
+ dayLabel=$(date -u -v-${d}d +%Y-%m-%d 2>/dev/null || date -u -d "${d} days ago" +%Y-%m-%d 2>/dev/null || echo "?")
166
+ dayTok=0
167
+ if [ -f "$activityFile" ]; then
168
+ dayTok=$(grep "\"agent\":\"${agent_id}\"" "$activityFile" | grep "\"$dayLabel" | \
169
+ jq -rs '[.[].tokens // 0] | add // 0' 2>/dev/null || echo 0)
170
+ fi
171
+ printf " %s %s tokens\n" "$dayLabel" "$dayTok"
172
+ done
173
+ ```
174
+
175
+ ### heartbeat
176
+
177
+ ```bash
178
+ echo "HEARTBEAT CONFIG — $agent_id"
179
+ echo "────────────────────────────────────────────────────────"
180
+ enabled=$(echo "$agentDef" | jq -r '.heartbeat.enabled // false')
181
+ interval=$(echo "$agentDef" | jq -r '.heartbeat.interval // 900')
182
+ lastHb=$(echo "$agentState" | jq -r '.last_heartbeat // "-"')
183
+
184
+ echo " Enabled: $enabled"
185
+ echo " Interval: ${interval}s"
186
+ echo " Last beat: $lastHb"
187
+ echo ""
188
+ echo "To toggle: /mastermind:instance --action toggle-heartbeat --org $org_name --agent-id $agent_id"
189
+ ```
190
+
191
+ ### skills
192
+
193
+ ```bash
194
+ echo "SKILLS — $agent_id"
195
+ echo "────────────────────────────────────────────────────────"
196
+ skillList=$(echo "$agentDef" | jq -r '(.skills // [])[]' 2>/dev/null)
197
+
198
+ if [ -z "$skillList" ]; then
199
+ echo " No skills assigned. Use /mastermind:skills to map skills to this agent."
200
+ else
201
+ while IFS= read -r sk; do
202
+ skillFile=".claude/skills/${sk//:///}.md"
203
+ [ -f "$skillFile" ] && desc=$(head -5 "$skillFile" | grep 'description:' | sed 's/description: //') || desc="(skill file not found)"
204
+ printf " %-30s %s\n" "$sk" "$desc"
205
+ done <<< "$skillList"
206
+ fi
207
+ ```
208
+
209
+ ### reset
210
+
211
+ ```bash
212
+ echo "Resetting agent state for '$agent_id'…"
213
+
214
+ tmp="${stateFile}.tmp"
215
+ if [ -f "$stateFile" ]; then
216
+ jq --arg id "$agent_id" \
217
+ '.agents[$id] = {"status":"idle","total_runs":0,"tokens_used":0,"last_run":null,"last_heartbeat":null}' \
218
+ "$stateFile" > "$tmp" && mv "$tmp" "$stateFile"
219
+ fi
220
+
221
+ echo "Agent '$agent_id' state reset. Run history is preserved in activity log."
222
+ echo "To reconfigure adapter: edit the role in /mastermind:org --action show (then edit org config)."
223
+ ```
224
+
225
+ ---
226
+
227
+ ## Step 3 — Return Output
228
+
229
+ ```yaml
230
+ domain: ops
231
+ status: complete
232
+ action: <action>
233
+ org: <org_name>
234
+ agent_id: <agent_id>
235
+ agent_status: <status>
236
+ ```
237
+
238
+ ---
239
+
240
+ ## Step 4 — Brain Write (standalone only)
241
+
242
+ If `caller` is not "command", follow _protocol.md Brain Write Procedure for domain `ops`.
@@ -0,0 +1,178 @@
1
+ ---
2
+ name: mastermind-agents
3
+ description: Mastermind agents — list, inspect, hire, pause, and remove agents in a running org. Shows status, last heartbeat, adapter config, and burn rate per agent.
4
+ type: domain-skill
5
+ default_mode: confirm
6
+ ---
7
+
8
+ # Mastermind Agents
9
+
10
+ This skill is invoked by `mastermind:agents` or directly via `/mastermind:agents`.
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 inspect (optional — lists all orgs if omitted)
18
+ - `action`: list | hire | pause | resume | remove | inspect
19
+ - `agent_id`: role id or agent slug (required for inspect/pause/resume/remove)
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
+ If `org_name` is provided, load `.monomind/orgs/<org_name>.json`. Otherwise list all orgs:
33
+
34
+ ```bash
35
+ ls .monomind/orgs/*.json 2>/dev/null | xargs -I{} basename {} .json
36
+ ```
37
+
38
+ If no orgs exist, print: "No orgs found. Run /mastermind:createorg to define one."
39
+
40
+ ---
41
+
42
+ ## Step 2 — Execute Action
43
+
44
+ ### list (default)
45
+
46
+ Display all agents in the org with status from state file:
47
+
48
+ ```bash
49
+ orgFile=".monomind/orgs/${org_name}.json"
50
+ stateFile=".monomind/orgs/${org_name}-state.json"
51
+
52
+ jq -r '.roles[] | "• [\(.id)] \(.title) agent=\(.agent_type) reports_to=\(.reports_to // "none")"' "$orgFile"
53
+
54
+ # Overlay runtime status from state file if present
55
+ if [ -f "$stateFile" ]; then
56
+ echo ""
57
+ echo "RUNTIME STATUS:"
58
+ jq -r '.agents // {} | to_entries[] | " \(.key): \(.value.status // "unknown") last_beat=\(.value.last_heartbeat // "never")"' "$stateFile" 2>/dev/null || true
59
+ fi
60
+ ```
61
+
62
+ Render as table:
63
+
64
+ ```
65
+ AGENTS — org: <org_name>
66
+ ──────────────────────────────────────────────────────
67
+ ID TITLE AGENT TYPE STATUS LAST HEARTBEAT
68
+ boss CEO / Boss coordinator running 2 min ago
69
+ content-writer Content Writer Content Creator idle 8 min ago
70
+ reviewer Content Reviewer reviewer waiting 8 min ago
71
+ ...
72
+ ```
73
+
74
+ ### inspect
75
+
76
+ Show full config + responsibilities + communication edges for a single agent:
77
+
78
+ ```bash
79
+ jq --arg id "$agent_id" '.roles[] | select(.id == $id)' "$orgFile"
80
+ jq --arg id "$agent_id" '.communication[] | select(.from == $id or .to == $id)' "$orgFile"
81
+ ```
82
+
83
+ ### hire
84
+
85
+ Add a new role to the org. Prompt the user for:
86
+ - `id` (slug, e.g. `seo-lead`), `title` (display name), `agent_type` (from mapping table in createorg.md), `responsibilities` (comma-separated), `reports_to` (role id or null)
87
+
88
+ **Adapter/model selection** — present this picker:
89
+
90
+ ```
91
+ ADAPTER / MODEL
92
+ ───────────────
93
+ Available Claude models:
94
+ 1. claude-sonnet-4-6 → balanced capability + speed (Recommended)
95
+ 2. claude-opus-4-7 → highest capability, slower
96
+ 3. claude-haiku-4-5 → fastest, lowest cost
97
+
98
+ Enter choice [1]:
99
+ ```
100
+
101
+ Set `adapter_config.model` from selection. Default: `claude-sonnet-4-6`.
102
+
103
+ Append to `.monomind/orgs/<org_name>.json` roles array using jq:
104
+
105
+ ```bash
106
+ # model from adapter picker (default: claude-sonnet-4-6)
107
+ adapter_model="${selected_model:-claude-sonnet-4-6}"
108
+
109
+ tmp="${orgFile}.tmp"
110
+ jq --arg id "$agent_id" \
111
+ --arg title "$title" \
112
+ --arg agent_type "$agent_type" \
113
+ --arg reports_to "${reports_to:-}" \
114
+ --arg model "$adapter_model" \
115
+ --argjson resp "$(echo "$responsibilities" | jq -R 'split(",") | map(ltrimstr(" "))')" \
116
+ '.roles += [{"id":$id,"title":$title,"agent_type":$agent_type,
117
+ "responsibilities":$resp,
118
+ "reports_to":($reports_to|if .=="" then null else . end),
119
+ "adapter_config":{"model":$model,"max_tokens":8192}}]' \
120
+ "$orgFile" > "$tmp" && mv "$tmp" "$orgFile"
121
+ echo "Hired: $title ($agent_type) → adapter: $adapter_model"
122
+ ```
123
+
124
+ Then emit `org:agent:hired` event to dashboard:
125
+
126
+ ```bash
127
+ REPO_ROOT=$(git rev-parse --show-toplevel 2>/dev/null || pwd)
128
+ CTRL_URL=$(jq -r '.url // "http://localhost:4242"' "$REPO_ROOT/.monomind/control.json" 2>/dev/null || echo "http://localhost:4242")
129
+ curl -s -X POST "${CTRL_URL}/api/mastermind/event" \
130
+ -H "Content-Type: application/json" \
131
+ -d "$(jq -cn --arg org "$org_name" --arg role "$agent_id" --arg title "$title" \
132
+ '{type:"org:agent:hired",org:$org,role:$role,title:$title,ts:(now*1000|floor)}')" || true
133
+ ```
134
+
135
+ ### pause / resume
136
+
137
+ Update state file:
138
+
139
+ ```bash
140
+ stateFile=".monomind/orgs/${org_name}-state.json"
141
+ [ ! -f "$stateFile" ] && echo '{"agents":{}}' > "$stateFile"
142
+ tmp="${stateFile}.tmp"
143
+ jq --arg id "$agent_id" --arg status "paused" \
144
+ '.agents[$id].status = $status | .agents[$id].updated_at = (now|todate)' \
145
+ "$stateFile" > "$tmp" && mv "$tmp" "$stateFile"
146
+ ```
147
+
148
+ Emit `org:agent:paused` / `org:agent:resumed` event.
149
+
150
+ ### remove
151
+
152
+ Confirm with user, then remove role from org config:
153
+
154
+ ```bash
155
+ tmp="${orgFile}.tmp"
156
+ jq --arg id "$agent_id" '.roles = [.roles[] | select(.id != $id)] | .communication = [.communication[] | select(.from != $id and .to != $id)]' \
157
+ "$orgFile" > "$tmp" && mv "$tmp" "$orgFile"
158
+ ```
159
+
160
+ ---
161
+
162
+ ## Step 3 — Return Output
163
+
164
+ ```yaml
165
+ domain: ops
166
+ status: complete
167
+ action: <action>
168
+ org: <org_name>
169
+ agents_count: <N>
170
+ ```
171
+
172
+ Print summary and any suggested next actions (e.g. "Run /mastermind:heartbeat to trigger a manual heartbeat for this agent").
173
+
174
+ ---
175
+
176
+ ## Step 4 — Brain Write (standalone only)
177
+
178
+ If `caller` is not "command", follow _protocol.md Brain Write Procedure for domain `ops`.
@@ -0,0 +1,259 @@
1
+ ---
2
+ name: mastermind-approval-detail
3
+ description: Mastermind approval-detail — deep inspection and action on a single approval request. View approval metadata, payload, comments, linked issues, and perform approve/reject/revision/resubmit actions. Mirrors ApprovalDetail.tsx.
4
+ type: domain-skill
5
+ default_mode: confirm
6
+ ---
7
+
8
+ # Mastermind Approval Detail
9
+
10
+ This skill is invoked by `mastermind:approval-detail` or directly via `/mastermind:approval-detail`.
11
+
12
+ ---
13
+
14
+ ## Inputs
15
+
16
+ - `brain_context`: BRAIN CONTEXT block (injected by command, or loaded below if standalone)
17
+ - `org_name`: org the approval belongs to (required)
18
+ - `approval_id`: approval id or short prefix (required)
19
+ - `action`: show | comments | linked-issues | comment | approve | reject | request-revision | resubmit
20
+ - `comment_body`: comment text (for comment action)
21
+ - `caller`: command | master
22
+
23
+ ---
24
+
25
+ ## Approval Statuses
26
+
27
+ | Status | Meaning |
28
+ |--------|---------|
29
+ | `pending` | Awaiting review — actionable |
30
+ | `approved` | Approved and resolved |
31
+ | `rejected` | Rejected and resolved |
32
+ | `revision_requested` | Agent asked to revise — still actionable |
33
+ | `resubmitted` | Agent resubmitted after revision |
34
+
35
+ ---
36
+
37
+ ## Approval Types
38
+
39
+ | Type | Description |
40
+ |------|-------------|
41
+ | `budget_override_required` | Agent needs to exceed budget cap |
42
+ | `agent_hire` | Agent is requesting to hire another agent |
43
+ | `tool_grant` | Agent requests a new tool permission |
44
+ | `action_confirm` | Agent requests confirmation before a destructive action |
45
+ | `custom` | Plugin-defined approval type |
46
+
47
+ ---
48
+
49
+ ## Step 0 — Brain Load (standalone only)
50
+
51
+ If `caller` is not "command", load brain context following _protocol.md Brain Load Procedure with namespace: `ops`.
52
+
53
+ ---
54
+
55
+ ## Step 1 — Load Approval
56
+
57
+ ```bash
58
+ orgFile=".monomind/orgs/${org_name}.json"
59
+ [ ! -f "$orgFile" ] && { echo "ERROR: Org '${org_name}' not found."; exit 1; }
60
+
61
+ approvalsFile=".monomind/orgs/${org_name}-approvals.json"
62
+ [ ! -f "$approvalsFile" ] && { echo "ERROR: No approvals file for org '${org_name}'."; exit 1; }
63
+
64
+ # Find approval by full id or prefix
65
+ approvalDef=$(jq -r --arg id "$approval_id" \
66
+ '.approvals[] | select(.id == $id or (.id | startswith($id)))' \
67
+ "$approvalsFile" | head -1)
68
+ [ -z "$approvalDef" ] && { echo "ERROR: Approval '${approval_id}' not found."; exit 1; }
69
+
70
+ approvalId=$(echo "$approvalDef" | jq -r '.id')
71
+ commentsFile=".monomind/orgs/${org_name}-approval-comments.jsonl"
72
+ ```
73
+
74
+ ---
75
+
76
+ ## Step 2 — Execute Action
77
+
78
+ ### show (default)
79
+
80
+ ```bash
81
+ echo "APPROVAL — ${approvalId}"
82
+ echo "────────────────────────────────────────────────────────"
83
+
84
+ echo "$approvalDef" | jq -r '
85
+ " ID: \(.id)",
86
+ " Type: \(.type // "unknown")",
87
+ " Status: \(.status // "pending")",
88
+ " Agent: \(.agentId // "(unknown)")",
89
+ " Created: \(.createdAt // "-")",
90
+ " Resolved: \(.resolvedAt // "-")"
91
+ '
92
+
93
+ echo ""
94
+ echo "PAYLOAD"
95
+ echo "────────────────────────────────────────────────────────"
96
+ echo "$approvalDef" | jq -r '.payload // {}' | jq .
97
+
98
+ status=$(echo "$approvalDef" | jq -r '.status // "pending"')
99
+ if [ "$status" = "pending" ] || [ "$status" = "revision_requested" ]; then
100
+ echo ""
101
+ echo "ACTIONS AVAILABLE"
102
+ echo " approve: --action approve"
103
+ echo " reject: --action reject"
104
+ echo " request revision: --action request-revision"
105
+ echo " add comment: --action comment --comment-body 'your notes'"
106
+ fi
107
+ ```
108
+
109
+ ### comments
110
+
111
+ ```bash
112
+ echo "COMMENTS — ${approvalId}"
113
+ echo "────────────────────────────────────────────────────────"
114
+
115
+ if [ ! -f "$commentsFile" ]; then
116
+ echo " No comments."
117
+ else
118
+ count=$(grep -c "\"approvalId\":\"${approvalId}\"" "$commentsFile" 2>/dev/null || echo 0)
119
+ echo " Total: $count"
120
+ echo ""
121
+ grep "\"approvalId\":\"${approvalId}\"" "$commentsFile" 2>/dev/null | while IFS= read -r line; do
122
+ author=$(echo "$line" | jq -r '.authorType // "user"')
123
+ body=$(echo "$line" | jq -r '.body // ""')
124
+ ts=$(echo "$line" | jq -r '.createdAt // "-"')
125
+ echo " [$ts] ($author)"
126
+ echo " $body"
127
+ echo ""
128
+ done
129
+ fi
130
+ ```
131
+
132
+ ### linked-issues
133
+
134
+ ```bash
135
+ issuesFile=".monomind/orgs/${org_name}-issues.json"
136
+ echo "LINKED ISSUES — ${approvalId}"
137
+ echo "────────────────────────────────────────────────────────"
138
+ printf "%-24s %-12s %s\n" "ID" "STATUS" "TITLE"
139
+ echo "────────────────────────────────────────────────────────"
140
+
141
+ linkedIds=$(echo "$approvalDef" | jq -r '(.linkedIssueIds // [])[]')
142
+ if [ -z "$linkedIds" ]; then
143
+ echo " No linked issues."
144
+ else
145
+ if [ -f "$issuesFile" ]; then
146
+ echo "$linkedIds" | while read -r iid; do
147
+ row=$(jq -r --arg id "$iid" '.issues[] | select(.id == $id) | [.id, (.status // "open"), (.title // "(no title)")] | @tsv' "$issuesFile")
148
+ [ -n "$row" ] && echo "$row" | while IFS=$'\t' read -r id st title; do
149
+ printf "%-24s %-12s %s\n" "$id" "$st" "$title"
150
+ done || printf "%-24s %-12s %s\n" "$iid" "(unknown)" "(not found)"
151
+ done
152
+ fi
153
+ fi
154
+ ```
155
+
156
+ ### comment
157
+
158
+ ```bash
159
+ [ -z "$comment_body" ] && { echo "ERROR: --comment-body required."; exit 1; }
160
+
161
+ ts=$(date -u +%Y-%m-%dT%H:%M:%SZ)
162
+ entry=$(jq -n \
163
+ --arg aid "$approvalId" \
164
+ --arg org "$org_name" \
165
+ --arg body "$comment_body" \
166
+ --arg ts "$ts" \
167
+ '{"approvalId":$aid,"org":$org,"authorType":"operator","body":$body,"createdAt":$ts}')
168
+
169
+ echo "$entry" >> "$commentsFile"
170
+
171
+ echo "Comment added to approval ${approvalId}."
172
+ echo " Body: $comment_body"
173
+ echo " At: $ts"
174
+ ```
175
+
176
+ ### approve
177
+
178
+ ```bash
179
+ status=$(echo "$approvalDef" | jq -r '.status // "pending"')
180
+ if [ "$status" != "pending" ] && [ "$status" != "revision_requested" ]; then
181
+ echo "ERROR: Approval is in status '$status' — cannot approve."
182
+ exit 1
183
+ fi
184
+
185
+ ts=$(date -u +%Y-%m-%dT%H:%M:%SZ)
186
+ tmp="${approvalsFile}.tmp"
187
+ jq --arg id "$approvalId" --arg ts "$ts" \
188
+ '.approvals = [.approvals[] | if .id == $id then
189
+ .status = "approved" | .resolvedAt = $ts | .resolvedBy = "operator"
190
+ else . end]' \
191
+ "$approvalsFile" > "$tmp" && mv "$tmp" "$approvalsFile"
192
+
193
+ echo "Approval '${approvalId}' APPROVED."
194
+ echo " Resolved at: $ts"
195
+ echo " Agent will be notified to proceed."
196
+ ```
197
+
198
+ ### reject
199
+
200
+ ```bash
201
+ ts=$(date -u +%Y-%m-%dT%H:%M:%SZ)
202
+ tmp="${approvalsFile}.tmp"
203
+ jq --arg id "$approvalId" --arg ts "$ts" \
204
+ '.approvals = [.approvals[] | if .id == $id then
205
+ .status = "rejected" | .resolvedAt = $ts | .resolvedBy = "operator"
206
+ else . end]' \
207
+ "$approvalsFile" > "$tmp" && mv "$tmp" "$approvalsFile"
208
+
209
+ echo "Approval '${approvalId}' REJECTED."
210
+ echo " Resolved at: $ts"
211
+ ```
212
+
213
+ ### request-revision
214
+
215
+ ```bash
216
+ ts=$(date -u +%Y-%m-%dT%H:%M:%SZ)
217
+ tmp="${approvalsFile}.tmp"
218
+ jq --arg id "$approvalId" --arg ts "$ts" \
219
+ '.approvals = [.approvals[] | if .id == $id then
220
+ .status = "revision_requested" | .revisionRequestedAt = $ts
221
+ else . end]' \
222
+ "$approvalsFile" > "$tmp" && mv "$tmp" "$approvalsFile"
223
+
224
+ echo "Revision requested for approval '${approvalId}'."
225
+ echo " Agent will be notified to revise and resubmit."
226
+ ```
227
+
228
+ ### resubmit
229
+
230
+ ```bash
231
+ ts=$(date -u +%Y-%m-%dT%H:%M:%SZ)
232
+ tmp="${approvalsFile}.tmp"
233
+ jq --arg id "$approvalId" --arg ts "$ts" \
234
+ '.approvals = [.approvals[] | if .id == $id then
235
+ .status = "pending" | .resubmittedAt = $ts
236
+ else . end]' \
237
+ "$approvalsFile" > "$tmp" && mv "$tmp" "$approvalsFile"
238
+
239
+ echo "Approval '${approvalId}' resubmitted (status reset to pending)."
240
+ ```
241
+
242
+ ---
243
+
244
+ ## Step 3 — Return Output
245
+
246
+ ```yaml
247
+ domain: ops
248
+ status: complete
249
+ action: <action>
250
+ org: <org_name>
251
+ approval_id: <approval_id>
252
+ approval_status: <status>
253
+ ```
254
+
255
+ ---
256
+
257
+ ## Step 4 — Brain Write (standalone only)
258
+
259
+ If `caller` is not "command", follow _protocol.md Brain Write Procedure for domain `ops`.