@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.
- package/.claude/commands/mastermind/_repeat.md +182 -39
- package/.claude/commands/mastermind/architect.md +17 -11
- package/.claude/commands/mastermind/brain.md +4 -0
- package/.claude/commands/mastermind/build.md +4 -0
- package/.claude/commands/mastermind/content.md +4 -0
- package/.claude/commands/mastermind/createorg.md +5 -3
- package/.claude/commands/mastermind/finance.md +4 -0
- package/.claude/commands/mastermind/idea.md +4 -0
- package/.claude/commands/mastermind/marketing.md +4 -0
- package/.claude/commands/mastermind/master.md +100 -46
- package/.claude/commands/mastermind/ops.md +4 -0
- package/.claude/commands/mastermind/release.md +4 -0
- package/.claude/commands/mastermind/research.md +4 -0
- package/.claude/commands/mastermind/review.md +4 -0
- package/.claude/commands/mastermind/runorg.md +5 -3
- package/.claude/commands/mastermind/sales.md +4 -0
- package/.claude/commands/mastermind/techport.md +9 -0
- package/.claude/commands/monomind/do.md +5 -1
- package/.claude/commands/monomind/idea.md +5 -1
- package/.claude/commands/monomind/improve.md +5 -1
- package/.claude/commands/monomind/repeat.md +85 -29
- package/.claude/commands/monomind/review.md +6 -2
- package/.claude/commands/monomind/understand.md +10 -8
- package/.claude/helpers/extras-registry.json +235 -235
- package/.claude/helpers/graphify-freshen.cjs +13 -1
- package/.claude/helpers/hook-handler.cjs +1 -1
- package/.claude/helpers/router.cjs +4 -1
- package/.claude/skills/mastermind/_protocol.md +37 -21
- package/.claude/skills/mastermind/access.md +236 -0
- package/.claude/skills/mastermind/activity.md +191 -0
- package/.claude/skills/mastermind/adapter-manager.md +259 -0
- package/.claude/skills/mastermind/adapters.md +204 -0
- package/.claude/skills/mastermind/agent-detail.md +242 -0
- package/.claude/skills/mastermind/agents.md +178 -0
- package/.claude/skills/mastermind/approval-detail.md +259 -0
- package/.claude/skills/mastermind/approve.md +181 -0
- package/.claude/skills/mastermind/architect.md +24 -8
- package/.claude/skills/mastermind/backup.md +197 -0
- package/.claude/skills/mastermind/bootstrap.md +190 -0
- package/.claude/skills/mastermind/budgets.md +237 -0
- package/.claude/skills/mastermind/companies.md +256 -0
- package/.claude/skills/mastermind/costs.md +151 -0
- package/.claude/skills/mastermind/createorg.md +23 -5
- package/.claude/skills/mastermind/diagnose.md +249 -0
- package/.claude/skills/mastermind/env.md +198 -0
- package/.claude/skills/mastermind/environments.md +250 -0
- package/.claude/skills/mastermind/export.md +324 -0
- package/.claude/skills/mastermind/goal-detail.md +255 -0
- package/.claude/skills/mastermind/goals.md +149 -0
- package/.claude/skills/mastermind/heartbeat.md +164 -0
- package/.claude/skills/mastermind/idea.md +318 -186
- package/.claude/skills/mastermind/import.md +281 -0
- package/.claude/skills/mastermind/inbox.md +214 -0
- package/.claude/skills/mastermind/instance-settings.md +315 -0
- package/.claude/skills/mastermind/instance.md +231 -0
- package/.claude/skills/mastermind/invite-landing.md +227 -0
- package/.claude/skills/mastermind/invites.md +254 -0
- package/.claude/skills/mastermind/issue-detail.md +291 -0
- package/.claude/skills/mastermind/issues.md +235 -0
- package/.claude/skills/mastermind/join-queue.md +170 -0
- package/.claude/skills/mastermind/liveness.md +392 -0
- package/.claude/skills/mastermind/memory.md +321 -0
- package/.claude/skills/mastermind/my-issues.md +146 -0
- package/.claude/skills/mastermind/new-agent.md +241 -0
- package/.claude/skills/mastermind/org-chart.md +207 -0
- package/.claude/skills/mastermind/org-settings.md +217 -0
- package/.claude/skills/mastermind/plan-to-tasks.md +136 -0
- package/.claude/skills/mastermind/plugin-manager.md +241 -0
- package/.claude/skills/mastermind/plugin-settings.md +273 -0
- package/.claude/skills/mastermind/plugins.md +190 -0
- package/.claude/skills/mastermind/profile.md +187 -0
- package/.claude/skills/mastermind/project-detail.md +249 -0
- package/.claude/skills/mastermind/project-workspace.md +244 -0
- package/.claude/skills/mastermind/projects.md +164 -0
- package/.claude/skills/mastermind/routine-detail.md +253 -0
- package/.claude/skills/mastermind/routines.md +202 -0
- package/.claude/skills/mastermind/runorg.md +74 -9
- package/.claude/skills/mastermind/search.md +186 -0
- package/.claude/skills/mastermind/secrets.md +199 -0
- package/.claude/skills/mastermind/skills.md +156 -0
- package/.claude/skills/mastermind/tasks.md +149 -0
- package/.claude/skills/mastermind/techport.md +5 -5
- package/.claude/skills/mastermind/threads.md +259 -0
- package/.claude/skills/mastermind/tree-control.md +250 -0
- package/.claude/skills/mastermind/wiki.md +314 -0
- package/.claude/skills/mastermind/workspace-detail.md +317 -0
- package/.claude/skills/mastermind/workspaces.md +261 -0
- package/.claude/skills/mastermind/worktree.md +187 -0
- package/dist/src/init/executor.js +8 -8
- package/dist/src/init/executor.js.map +1 -1
- package/dist/src/init/statusline-generator.d.ts.map +1 -1
- package/dist/src/init/statusline-generator.js +12 -0
- package/dist/src/init/statusline-generator.js.map +1 -1
- package/dist/src/ui/.monomind/data/ranked-context.json +1 -1
- package/dist/src/ui/.monomind/loops/mastermind-review-1778664132789.json +16 -0
- package/dist/src/ui/.monomind/sessions/current.json +5 -5
- package/dist/src/ui/.monomind/sessions/session-1776778451399.json +15 -0
- package/dist/src/ui/dashboard.html +3030 -181
- package/dist/src/ui/data/mastermind-events.jsonl +8 -0
- package/dist/src/ui/data/mastermind-sessions.json +1 -0
- package/dist/src/ui/server.mjs +738 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/.claude/skills/.monomind/data/ranked-context.json +0 -5
- package/.claude/skills/.monomind/sessions/current.json +0 -13
- package/.claude/skills/.monomind/sessions/session-1777829336455.json +0 -15
- package/.claude/skills/.monomind/sessions/session-1777831614725.json +0 -15
- package/.claude/skills/.monomind/sessions/session-1777832095857.json +0 -15
- package/.claude/skills/.monomind/sessions/session-1777839814183.json +0 -15
- package/.claude/skills/.monomind/sessions/session-1777841847131.json +0 -15
- package/.claude/skills/.monomind/sessions/session-1777843309463.json +0 -15
- package/.claude/skills/.monomind/sessions/session-1777880867159.json +0 -15
- package/.claude/skills/.monomind/sessions/session-1777881884593.json +0 -15
- package/.claude/skills/.monomind/sessions/session-1777884090471.json +0 -15
- package/.claude/skills/.monomind/sessions/session-1777884808221.json +0 -15
- package/.claude/skills/.monomind/sessions/session-1777885672155.json +0 -15
- package/.claude/skills/.monomind/sessions/session-1777886852818.json +0 -15
- package/.claude/skills/.monomind/sessions/session-1777896532690.json +0 -15
|
@@ -0,0 +1,241 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: mastermind-new-agent
|
|
3
|
+
description: Mastermind new-agent — wizard to hire/create a new agent within an org. Configures adapter type, model, role name, reports_to hierarchy, governance policy, skill assignments, and budget. Writes the new role to the org config file.
|
|
4
|
+
type: domain-skill
|
|
5
|
+
default_mode: confirm
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Mastermind New Agent
|
|
9
|
+
|
|
10
|
+
This skill is invoked by `mastermind:new-agent` or directly via `/mastermind:new-agent`.
|
|
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 add the agent to (required)
|
|
18
|
+
- `action`: create | preview | list-roles | list-adapters
|
|
19
|
+
- `agent_id`: unique slug for the new agent (required for create; auto-generated if omitted)
|
|
20
|
+
- `title`: display title for the agent (required for create)
|
|
21
|
+
- `adapter_type`: claude-local | gemini-local | codex-local | cursor | opencode | hermes | http | acpx (default: claude-local)
|
|
22
|
+
- `model`: model identifier (e.g. claude-sonnet-4-6, claude-opus-4-7, gemini-2.0-flash)
|
|
23
|
+
- `max_tokens`: max tokens per run (default: 8192)
|
|
24
|
+
- `reports_to`: parent agent id in the hierarchy (null = top-level)
|
|
25
|
+
- `governance`: auto | board | strict (default: inherit from org)
|
|
26
|
+
- `skills`: comma-separated skill names to assign (e.g. mastermind:tasks,mastermind:goals)
|
|
27
|
+
- `budget_tokens`: per-run token budget cap (optional)
|
|
28
|
+
- `heartbeat_enabled`: true | false (default: false)
|
|
29
|
+
- `heartbeat_interval`: heartbeat interval in seconds (default: 900)
|
|
30
|
+
- `system_prompt`: brief system prompt override (optional)
|
|
31
|
+
- `caller`: command | master
|
|
32
|
+
|
|
33
|
+
---
|
|
34
|
+
|
|
35
|
+
## Adapter Types
|
|
36
|
+
|
|
37
|
+
| Type | Description | Default Model |
|
|
38
|
+
|------|-------------|---------------|
|
|
39
|
+
| `claude-local` | Claude via Anthropic API | claude-sonnet-4-6 |
|
|
40
|
+
| `gemini-local` | Gemini via Google API | gemini-2.0-flash |
|
|
41
|
+
| `codex-local` | OpenAI Codex | gpt-4o |
|
|
42
|
+
| `cursor` | Cursor IDE agent | cursor-default |
|
|
43
|
+
| `opencode` | OpenCode agent | opencode-default |
|
|
44
|
+
| `hermes` | Hermes local model | hermes-3 |
|
|
45
|
+
| `http` | Custom HTTP adapter | (custom) |
|
|
46
|
+
| `acpx` | ACPX protocol | (custom) |
|
|
47
|
+
|
|
48
|
+
---
|
|
49
|
+
|
|
50
|
+
## Step 0 — Brain Load (standalone only)
|
|
51
|
+
|
|
52
|
+
If `caller` is not "command", load brain context following _protocol.md Brain Load Procedure with namespace: `ops`.
|
|
53
|
+
|
|
54
|
+
---
|
|
55
|
+
|
|
56
|
+
## Step 1 — Load Org
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
orgFile=".monomind/orgs/${org_name}.json"
|
|
60
|
+
[ ! -f "$orgFile" ] && { echo "ERROR: Org '${org_name}' not found."; exit 1; }
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
---
|
|
64
|
+
|
|
65
|
+
## Step 2 — Execute Action
|
|
66
|
+
|
|
67
|
+
### list-adapters
|
|
68
|
+
|
|
69
|
+
```bash
|
|
70
|
+
echo "AVAILABLE ADAPTERS"
|
|
71
|
+
echo "────────────────────────────────────────────────────────"
|
|
72
|
+
cat <<'ADAPTERS'
|
|
73
|
+
claude-local Claude via Anthropic API (recommended)
|
|
74
|
+
Models: claude-sonnet-4-6, claude-opus-4-7, claude-haiku-4-5
|
|
75
|
+
gemini-local Gemini via Google AI
|
|
76
|
+
Models: gemini-2.0-flash, gemini-1.5-pro
|
|
77
|
+
codex-local OpenAI Codex
|
|
78
|
+
Models: gpt-4o, gpt-4o-mini, o3-mini
|
|
79
|
+
cursor Cursor IDE agent
|
|
80
|
+
opencode OpenCode agent
|
|
81
|
+
hermes Hermes local LLM (Ollama)
|
|
82
|
+
http Custom HTTP adapter endpoint
|
|
83
|
+
acpx ACPX protocol adapter
|
|
84
|
+
ADAPTERS
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
### list-roles
|
|
88
|
+
|
|
89
|
+
```bash
|
|
90
|
+
echo "CURRENT ROLES IN ORG: $org_name"
|
|
91
|
+
echo "────────────────────────────────────────────────────────"
|
|
92
|
+
printf "%-22s %-20s %-14s %s\n" "ID" "TITLE" "ADAPTER" "REPORTS TO"
|
|
93
|
+
echo "────────────────────────────────────────────────────────"
|
|
94
|
+
jq -r '.roles[] |
|
|
95
|
+
[.id, (.title // "-"), (.adapter.type // "claude-local"), (.reports_to // "(root)")] | @tsv' \
|
|
96
|
+
"$orgFile" | while IFS=$'\t' read -r id title adapter rt; do
|
|
97
|
+
printf "%-22s %-20s %-14s %s\n" "$id" "$title" "$adapter" "$rt"
|
|
98
|
+
done
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
### preview
|
|
102
|
+
|
|
103
|
+
```bash
|
|
104
|
+
[ -z "$title" ] && { echo "ERROR: --title required for preview."; exit 1; }
|
|
105
|
+
|
|
106
|
+
adapterType="${adapter_type:-claude-local}"
|
|
107
|
+
modelId="${model}"
|
|
108
|
+
# Default model per adapter
|
|
109
|
+
if [ -z "$modelId" ]; then
|
|
110
|
+
case "$adapterType" in
|
|
111
|
+
claude-local) modelId="claude-sonnet-4-6" ;;
|
|
112
|
+
gemini-local) modelId="gemini-2.0-flash" ;;
|
|
113
|
+
codex-local) modelId="gpt-4o" ;;
|
|
114
|
+
cursor) modelId="cursor-default" ;;
|
|
115
|
+
opencode) modelId="opencode-default" ;;
|
|
116
|
+
hermes) modelId="hermes-3" ;;
|
|
117
|
+
*) modelId="(custom)" ;;
|
|
118
|
+
esac
|
|
119
|
+
fi
|
|
120
|
+
|
|
121
|
+
# Generate slug if not set
|
|
122
|
+
agentIdPreview="${agent_id}"
|
|
123
|
+
if [ -z "$agentIdPreview" ]; then
|
|
124
|
+
agentIdPreview=$(echo "$title" | tr '[:upper:]' '[:lower:]' | tr -cs 'a-z0-9' '-' | sed 's/^-//;s/-$//')
|
|
125
|
+
fi
|
|
126
|
+
|
|
127
|
+
echo "PREVIEW — new agent to be added to org '$org_name'"
|
|
128
|
+
echo "────────────────────────────────────────────────────────"
|
|
129
|
+
echo " ID: $agentIdPreview"
|
|
130
|
+
echo " Title: $title"
|
|
131
|
+
echo " Adapter: $adapterType / $modelId"
|
|
132
|
+
echo " Max tokens: ${max_tokens:-8192}"
|
|
133
|
+
echo " Reports to: ${reports_to:-(root/top-level)}"
|
|
134
|
+
echo " Governance: ${governance:-inherit}"
|
|
135
|
+
echo " Skills: ${skills:-(none)}"
|
|
136
|
+
echo " Budget: ${budget_tokens:-(unlimited)}"
|
|
137
|
+
echo " Heartbeat: ${heartbeat_enabled:-false} (${heartbeat_interval:-900}s)"
|
|
138
|
+
[ -n "$system_prompt" ] && echo " Prompt: $system_prompt"
|
|
139
|
+
echo ""
|
|
140
|
+
echo "Run with --action create to add this agent to the org."
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
### create
|
|
144
|
+
|
|
145
|
+
```bash
|
|
146
|
+
[ -z "$title" ] && { echo "ERROR: --title required."; exit 1; }
|
|
147
|
+
|
|
148
|
+
adapterType="${adapter_type:-claude-local}"
|
|
149
|
+
modelId="${model}"
|
|
150
|
+
if [ -z "$modelId" ]; then
|
|
151
|
+
case "$adapterType" in
|
|
152
|
+
claude-local) modelId="claude-sonnet-4-6" ;;
|
|
153
|
+
gemini-local) modelId="gemini-2.0-flash" ;;
|
|
154
|
+
codex-local) modelId="gpt-4o" ;;
|
|
155
|
+
cursor) modelId="cursor-default" ;;
|
|
156
|
+
opencode) modelId="opencode-default" ;;
|
|
157
|
+
hermes) modelId="hermes-3" ;;
|
|
158
|
+
*) modelId="(custom)" ;;
|
|
159
|
+
esac
|
|
160
|
+
fi
|
|
161
|
+
|
|
162
|
+
# Generate id from title if not provided
|
|
163
|
+
if [ -z "$agent_id" ]; then
|
|
164
|
+
agent_id=$(echo "$title" | tr '[:upper:]' '[:lower:]' | tr -cs 'a-z0-9' '-' | sed 's/^-//;s/-$//')
|
|
165
|
+
fi
|
|
166
|
+
|
|
167
|
+
# Check for duplicate id
|
|
168
|
+
duplicate=$(jq -r --arg id "$agent_id" '[.roles[] | select(.id == $id)] | length' "$orgFile")
|
|
169
|
+
[ "$duplicate" -gt 0 ] && { echo "ERROR: Agent id '$agent_id' already exists in org '$org_name'. Use --agent-id to specify a unique id."; exit 1; }
|
|
170
|
+
|
|
171
|
+
# Validate reports_to if set
|
|
172
|
+
if [ -n "$reports_to" ]; then
|
|
173
|
+
parentExists=$(jq -r --arg pid "$reports_to" '[.roles[] | select(.id == $pid)] | length' "$orgFile")
|
|
174
|
+
[ "$parentExists" -eq 0 ] && echo "WARNING: Parent agent '$reports_to' not found in org. Setting anyway."
|
|
175
|
+
fi
|
|
176
|
+
|
|
177
|
+
# Build skills array
|
|
178
|
+
skillsArray="[]"
|
|
179
|
+
if [ -n "$skills" ]; then
|
|
180
|
+
skillsArray=$(echo "$skills" | tr ',' '\n' | jq -Rsc 'split("\n") | map(select(. != ""))')
|
|
181
|
+
fi
|
|
182
|
+
|
|
183
|
+
ts=$(date -u +%Y-%m-%dT%H:%M:%SZ)
|
|
184
|
+
|
|
185
|
+
tmp="${orgFile}.tmp"
|
|
186
|
+
jq --arg id "$agent_id" \
|
|
187
|
+
--arg title "$title" \
|
|
188
|
+
--arg adapter "$adapterType" \
|
|
189
|
+
--arg model "$modelId" \
|
|
190
|
+
--argjson maxTok "${max_tokens:-8192}" \
|
|
191
|
+
--arg rt "${reports_to:-}" \
|
|
192
|
+
--arg gov "${governance:-}" \
|
|
193
|
+
--argjson skills "$skillsArray" \
|
|
194
|
+
--argjson budget "${budget_tokens:-null}" \
|
|
195
|
+
--argjson hbEnabled "${heartbeat_enabled:-false}" \
|
|
196
|
+
--argjson hbInterval "${heartbeat_interval:-900}" \
|
|
197
|
+
--arg prompt "${system_prompt:-}" \
|
|
198
|
+
--arg ts "$ts" \
|
|
199
|
+
'.roles += [{
|
|
200
|
+
"id": $id,
|
|
201
|
+
"title": $title,
|
|
202
|
+
"adapter": {"type": $adapter, "model": $model, "max_tokens": $maxTok},
|
|
203
|
+
"reports_to": (if $rt != "" then $rt else null end),
|
|
204
|
+
"governance": (if $gov != "" then $gov else null end),
|
|
205
|
+
"skills": $skills,
|
|
206
|
+
"budget_tokens": $budget,
|
|
207
|
+
"heartbeat": {"enabled": $hbEnabled, "interval": $hbInterval},
|
|
208
|
+
"system_prompt": (if $prompt != "" then $prompt else null end),
|
|
209
|
+
"created_at": $ts
|
|
210
|
+
}]' \
|
|
211
|
+
"$orgFile" > "$tmp" && mv "$tmp" "$orgFile"
|
|
212
|
+
|
|
213
|
+
echo "Agent created: $agent_id"
|
|
214
|
+
echo " Title: $title"
|
|
215
|
+
echo " Adapter: $adapterType / $modelId"
|
|
216
|
+
echo " Reports: ${reports_to:-(root)}"
|
|
217
|
+
echo " Skills: ${skills:-(none)}"
|
|
218
|
+
echo ""
|
|
219
|
+
echo "Org '${org_name}' now has $(jq '.roles | length' "$orgFile") agent(s)."
|
|
220
|
+
echo "View: /mastermind:agent-detail --org $org_name --agent-id $agent_id"
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
---
|
|
224
|
+
|
|
225
|
+
## Step 3 — Return Output
|
|
226
|
+
|
|
227
|
+
```yaml
|
|
228
|
+
domain: ops
|
|
229
|
+
status: complete
|
|
230
|
+
action: <action>
|
|
231
|
+
org: <org_name>
|
|
232
|
+
agent_id: <agent_id>
|
|
233
|
+
adapter_type: <type>
|
|
234
|
+
model: <model>
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
---
|
|
238
|
+
|
|
239
|
+
## Step 4 — Brain Write (standalone only)
|
|
240
|
+
|
|
241
|
+
If `caller` is not "command", follow _protocol.md Brain Write Procedure for domain `ops`.
|
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: mastermind-org-chart
|
|
3
|
+
description: Mastermind org-chart — generates a text-based ASCII org chart for an org showing the agent hierarchy, adapter types, heartbeat status, and reports-to relationships. Supports tree view, flat list, and JSON export. Mirrors OrgChart.tsx canvas view as a CLI-friendly format.
|
|
4
|
+
type: domain-skill
|
|
5
|
+
default_mode: auto
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Mastermind Org Chart
|
|
9
|
+
|
|
10
|
+
This skill is invoked by `mastermind:org-chart` or directly via `/mastermind:org-chart`.
|
|
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 chart (required)
|
|
18
|
+
- `action`: show | flat | export | search
|
|
19
|
+
- `query`: search term to filter agents in the chart (for search)
|
|
20
|
+
- `output_file`: file path for JSON export (for export; default: stdout)
|
|
21
|
+
- `depth`: max depth to render (default: unlimited)
|
|
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 — Load Org Roles
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
orgFile=".monomind/orgs/${org_name}.json"
|
|
36
|
+
[ ! -f "$orgFile" ] && { echo "ERROR: Org '${org_name}' not found."; exit 1; }
|
|
37
|
+
|
|
38
|
+
roles=$(jq -r '.roles // []' "$orgFile")
|
|
39
|
+
roleCount=$(echo "$roles" | jq 'length')
|
|
40
|
+
|
|
41
|
+
# Load heartbeat state if available
|
|
42
|
+
stateFile=".monomind/orgs/${org_name}-state.json"
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
---
|
|
46
|
+
|
|
47
|
+
## Step 2 — Execute Action
|
|
48
|
+
|
|
49
|
+
### show (default)
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
echo "ORG CHART — $org_name"
|
|
53
|
+
echo "════════════════════════════════════════════════════════"
|
|
54
|
+
|
|
55
|
+
[ "$roleCount" -eq 0 ] && {
|
|
56
|
+
echo " No agents in org '$org_name'."
|
|
57
|
+
echo " Add one: /mastermind:new-agent --org $org_name --title 'My Agent'"
|
|
58
|
+
exit 0
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
# Build parent→children map using Python for recursive ASCII tree
|
|
62
|
+
python3 - "$orgFile" "$stateFile" "${depth:-99}" <<'PYEOF'
|
|
63
|
+
import json, sys, os
|
|
64
|
+
|
|
65
|
+
orgFile = sys.argv[1]
|
|
66
|
+
stateFile = sys.argv[2] if len(sys.argv) > 2 else None
|
|
67
|
+
maxDepth = int(sys.argv[3]) if len(sys.argv) > 3 else 99
|
|
68
|
+
|
|
69
|
+
with open(orgFile) as f:
|
|
70
|
+
org = json.load(f)
|
|
71
|
+
|
|
72
|
+
roles = org.get("roles", [])
|
|
73
|
+
|
|
74
|
+
# Load heartbeat state
|
|
75
|
+
hb = {}
|
|
76
|
+
if stateFile and os.path.exists(stateFile):
|
|
77
|
+
try:
|
|
78
|
+
with open(stateFile) as f:
|
|
79
|
+
state = json.load(f)
|
|
80
|
+
for r in state.get("roles", []):
|
|
81
|
+
hb[r.get("id", "")] = r.get("last_heartbeat")
|
|
82
|
+
except Exception:
|
|
83
|
+
pass
|
|
84
|
+
|
|
85
|
+
# Build child map
|
|
86
|
+
children = {}
|
|
87
|
+
for r in roles:
|
|
88
|
+
pid = r.get("reports_to") or "__root__"
|
|
89
|
+
children.setdefault(pid, []).append(r)
|
|
90
|
+
|
|
91
|
+
def render(nodes, prefix="", depth=0):
|
|
92
|
+
if depth > maxDepth:
|
|
93
|
+
return
|
|
94
|
+
for i, r in enumerate(nodes):
|
|
95
|
+
is_last = (i == len(nodes) - 1)
|
|
96
|
+
connector = "└── " if is_last else "├── "
|
|
97
|
+
child_prefix = prefix + (" " if is_last else "│ ")
|
|
98
|
+
rid = r.get("id", "?")
|
|
99
|
+
title = r.get("title", rid)
|
|
100
|
+
adapter = r.get("adapter", {})
|
|
101
|
+
atype = adapter.get("type", "?") if isinstance(adapter, dict) else str(adapter)
|
|
102
|
+
model = adapter.get("model", "") if isinstance(adapter, dict) else ""
|
|
103
|
+
hb_status = "♡" if rid not in hb or not hb[rid] else "♥"
|
|
104
|
+
gov = r.get("governance") or ""
|
|
105
|
+
gov_str = f" [{gov}]" if gov else ""
|
|
106
|
+
model_str = f"/{model}" if model else ""
|
|
107
|
+
print(f"{prefix}{connector}{title} ({atype}{model_str}){gov_str} {hb_status}")
|
|
108
|
+
kids = children.get(rid, [])
|
|
109
|
+
if kids:
|
|
110
|
+
render(kids, child_prefix, depth + 1)
|
|
111
|
+
|
|
112
|
+
roots = children.get("__root__", [])
|
|
113
|
+
# Include agents whose reports_to points to a non-existent id
|
|
114
|
+
all_ids = {r.get("id") for r in roles}
|
|
115
|
+
for r in roles:
|
|
116
|
+
pid = r.get("reports_to")
|
|
117
|
+
if pid and pid not in all_ids and r not in roots:
|
|
118
|
+
roots.append(r)
|
|
119
|
+
|
|
120
|
+
render(roots)
|
|
121
|
+
PYEOF
|
|
122
|
+
|
|
123
|
+
echo ""
|
|
124
|
+
echo " $roleCount agent(s) · ♥ heartbeat active ♡ no heartbeat"
|
|
125
|
+
echo " Add agent: /mastermind:new-agent --org $org_name --title 'Role Name'"
|
|
126
|
+
echo " Agent detail: /mastermind:agent-detail --org $org_name --agent-id <id>"
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
### flat
|
|
130
|
+
|
|
131
|
+
```bash
|
|
132
|
+
echo "AGENTS — $org_name (flat list)"
|
|
133
|
+
echo "────────────────────────────────────────────────────────"
|
|
134
|
+
printf "%-24s %-20s %-16s %-20s %s\n" "ID" "TITLE" "ADAPTER" "MODEL" "REPORTS TO"
|
|
135
|
+
echo "────────────────────────────────────────────────────────"
|
|
136
|
+
|
|
137
|
+
echo "$roles" | jq -r '.[] |
|
|
138
|
+
[.id, (.title // "-"), (.adapter.type // "?"), (.adapter.model // "-"),
|
|
139
|
+
(.reports_to // "(root)")] | @tsv' | \
|
|
140
|
+
while IFS=$'\t' read -r id title adapter model rt; do
|
|
141
|
+
printf "%-24s %-20s %-16s %-20s %s\n" "$id" "$title" "$adapter" "$model" "$rt"
|
|
142
|
+
done
|
|
143
|
+
|
|
144
|
+
echo ""
|
|
145
|
+
echo "Total: $roleCount"
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
### search
|
|
149
|
+
|
|
150
|
+
```bash
|
|
151
|
+
[ -z "$query" ] && { echo "ERROR: --query required."; exit 1; }
|
|
152
|
+
|
|
153
|
+
echo "AGENT SEARCH — $org_name query: '$query'"
|
|
154
|
+
echo "────────────────────────────────────────────────────────"
|
|
155
|
+
printf "%-24s %-20s %-16s %s\n" "ID" "TITLE" "ADAPTER" "REPORTS TO"
|
|
156
|
+
echo "────────────────────────────────────────────────────────"
|
|
157
|
+
|
|
158
|
+
ql=$(echo "$query" | tr '[:upper:]' '[:lower:]')
|
|
159
|
+
echo "$roles" | jq -r --arg q "$ql" '.[] |
|
|
160
|
+
select(
|
|
161
|
+
(.id | ascii_downcase | contains($q)) or
|
|
162
|
+
(.title // "" | ascii_downcase | contains($q)) or
|
|
163
|
+
(.adapter.type // "" | ascii_downcase | contains($q)) or
|
|
164
|
+
(.adapter.model // "" | ascii_downcase | contains($q))
|
|
165
|
+
) |
|
|
166
|
+
[.id, (.title // "-"), (.adapter.type // "?"), (.reports_to // "(root)")] | @tsv' | \
|
|
167
|
+
while IFS=$'\t' read -r id title adapter rt; do
|
|
168
|
+
printf "%-24s %-20s %-16s %s\n" "$id" "$title" "$adapter" "$rt"
|
|
169
|
+
done
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
### export
|
|
173
|
+
|
|
174
|
+
```bash
|
|
175
|
+
outFile="${output_file:-}"
|
|
176
|
+
ts=$(date -u +%Y-%m-%dT%H:%M:%SZ)
|
|
177
|
+
|
|
178
|
+
payload=$(jq --arg org "$org_name" --arg ts "$ts" \
|
|
179
|
+
'{org: $org, exportedAt: $ts, roles: (.roles // [])}' \
|
|
180
|
+
"$orgFile")
|
|
181
|
+
|
|
182
|
+
if [ -n "$outFile" ]; then
|
|
183
|
+
mkdir -p "$(dirname "$outFile")"
|
|
184
|
+
echo "$payload" > "$outFile"
|
|
185
|
+
echo "Org chart exported: $outFile ($roleCount agents)"
|
|
186
|
+
else
|
|
187
|
+
echo "$payload" | jq .
|
|
188
|
+
fi
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
---
|
|
192
|
+
|
|
193
|
+
## Step 3 — Return Output
|
|
194
|
+
|
|
195
|
+
```yaml
|
|
196
|
+
domain: ops
|
|
197
|
+
status: complete
|
|
198
|
+
action: <action>
|
|
199
|
+
org: <org_name>
|
|
200
|
+
agent_count: <N>
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
---
|
|
204
|
+
|
|
205
|
+
## Step 4 — Brain Write (standalone only)
|
|
206
|
+
|
|
207
|
+
If `caller` is not "command", follow _protocol.md Brain Write Procedure for domain `ops`.
|
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: mastermind-org-settings
|
|
3
|
+
description: Mastermind org-settings — edit org configuration (name, goal, topology, governance, budget), export org as portable JSON, and import an org from a previously exported file.
|
|
4
|
+
type: domain-skill
|
|
5
|
+
default_mode: confirm
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Mastermind Org Settings
|
|
9
|
+
|
|
10
|
+
This skill is invoked by `mastermind:org-settings` or directly via `/mastermind:org-settings`.
|
|
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 configure (required)
|
|
18
|
+
- `action`: show | edit | export | import
|
|
19
|
+
- `field`: field to edit (name, goal, topology, governance, budget_tokens, alert_threshold, ceo_adapter)
|
|
20
|
+
- `value`: new value for the field
|
|
21
|
+
- `export_path`: path to write exported JSON (default: `.monomind/exports/<org_name>-<timestamp>.json`)
|
|
22
|
+
- `import_path`: path to JSON file to import from
|
|
23
|
+
- `caller`: command | master
|
|
24
|
+
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
## Step 0 — Brain Load (standalone only)
|
|
28
|
+
|
|
29
|
+
If `caller` is not "command", load brain context following _protocol.md Brain Load Procedure with namespace: `ops`.
|
|
30
|
+
|
|
31
|
+
---
|
|
32
|
+
|
|
33
|
+
## Step 1 — Resolve Org
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
orgFile=".monomind/orgs/${org_name}.json"
|
|
37
|
+
[ ! -f "$orgFile" ] && { echo "ERROR: Org '${org_name}' not found. Run /mastermind:createorg first."; exit 1; }
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
---
|
|
41
|
+
|
|
42
|
+
## Step 2 — Execute Action
|
|
43
|
+
|
|
44
|
+
### show (default)
|
|
45
|
+
|
|
46
|
+
Display current org config in a readable format:
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
echo "ORG SETTINGS — ${org_name}"
|
|
50
|
+
echo "──────────────────────────────────────────"
|
|
51
|
+
jq -r '
|
|
52
|
+
" Name: \(.name // .org_name // "-")",
|
|
53
|
+
" Goal: \(.goal // "-")",
|
|
54
|
+
" Topology: \(.topology // "hierarchical")",
|
|
55
|
+
" Max Agents: \(.max_agents // 8)",
|
|
56
|
+
" Governance: \(.governance.policy // "auto")",
|
|
57
|
+
" Budget: \(.run_config.budget_tokens // 0) tokens",
|
|
58
|
+
" Alert at: \((.run_config.alert_threshold // 0.8) * 100 | floor)%",
|
|
59
|
+
" CEO Adapter: \(.run_config.ceo_adapter // "claude-sonnet-4-6")",
|
|
60
|
+
" Roles: \(.roles | length) agents"
|
|
61
|
+
' "$orgFile"
|
|
62
|
+
echo ""
|
|
63
|
+
echo " Run /mastermind:org-settings --org ${org_name} --action edit --field <field> --value <value>"
|
|
64
|
+
echo " Fields: name | goal | topology | governance | budget_tokens | alert_threshold | ceo_adapter"
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
### edit
|
|
68
|
+
|
|
69
|
+
Update a single field in the org config:
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
field="${field}"
|
|
73
|
+
value="${value}"
|
|
74
|
+
tmp="${orgFile}.tmp"
|
|
75
|
+
|
|
76
|
+
case "$field" in
|
|
77
|
+
name)
|
|
78
|
+
jq --arg v "$value" '.name = $v' "$orgFile" > "$tmp" && mv "$tmp" "$orgFile"
|
|
79
|
+
echo "Updated: name → $value"
|
|
80
|
+
;;
|
|
81
|
+
goal)
|
|
82
|
+
jq --arg v "$value" '.goal = $v' "$orgFile" > "$tmp" && mv "$tmp" "$orgFile"
|
|
83
|
+
echo "Updated: goal → $value"
|
|
84
|
+
;;
|
|
85
|
+
topology)
|
|
86
|
+
case "$value" in hierarchical|mesh|hierarchical-mesh|adaptive|star|ring) : ;; *)
|
|
87
|
+
echo "ERROR: topology must be one of: hierarchical, mesh, hierarchical-mesh, adaptive, star, ring"; exit 1 ;;
|
|
88
|
+
esac
|
|
89
|
+
jq --arg v "$value" '.topology = $v' "$orgFile" > "$tmp" && mv "$tmp" "$orgFile"
|
|
90
|
+
echo "Updated: topology → $value"
|
|
91
|
+
;;
|
|
92
|
+
governance)
|
|
93
|
+
case "$value" in auto|board|strict) : ;; *)
|
|
94
|
+
echo "ERROR: governance must be one of: auto, board, strict"; exit 1 ;;
|
|
95
|
+
esac
|
|
96
|
+
jq --arg v "$value" '.governance.policy = $v' "$orgFile" > "$tmp" && mv "$tmp" "$orgFile"
|
|
97
|
+
echo "Updated: governance → $value"
|
|
98
|
+
;;
|
|
99
|
+
budget_tokens)
|
|
100
|
+
[[ "$value" =~ ^[0-9]+$ ]] || { echo "ERROR: budget_tokens must be a positive integer"; exit 1; }
|
|
101
|
+
jq --argjson v "$value" '.run_config.budget_tokens = $v' "$orgFile" > "$tmp" && mv "$tmp" "$orgFile"
|
|
102
|
+
echo "Updated: budget_tokens → $value"
|
|
103
|
+
;;
|
|
104
|
+
alert_threshold)
|
|
105
|
+
# accept 0.0–1.0 or 0–100
|
|
106
|
+
if [[ "$value" =~ ^[0-9]+$ ]] && [ "$value" -gt 1 ]; then
|
|
107
|
+
value=$(awk "BEGIN{printf \"%.2f\",$value/100}")
|
|
108
|
+
fi
|
|
109
|
+
jq --argjson v "$value" '.run_config.alert_threshold = $v' "$orgFile" > "$tmp" && mv "$tmp" "$orgFile"
|
|
110
|
+
echo "Updated: alert_threshold → $value"
|
|
111
|
+
;;
|
|
112
|
+
ceo_adapter)
|
|
113
|
+
case "$value" in claude-sonnet-4-6|claude-opus-4-7|claude-haiku-4-5) : ;; *)
|
|
114
|
+
echo "ERROR: ceo_adapter must be one of: claude-sonnet-4-6, claude-opus-4-7, claude-haiku-4-5"; exit 1 ;;
|
|
115
|
+
esac
|
|
116
|
+
jq --arg v "$value" '.run_config.ceo_adapter = $v' "$orgFile" > "$tmp" && mv "$tmp" "$orgFile"
|
|
117
|
+
echo "Updated: ceo_adapter → $value"
|
|
118
|
+
;;
|
|
119
|
+
*)
|
|
120
|
+
echo "ERROR: Unknown field '$field'. Valid fields: name, goal, topology, governance, budget_tokens, alert_threshold, ceo_adapter"
|
|
121
|
+
exit 1
|
|
122
|
+
;;
|
|
123
|
+
esac
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
Emit `org:settings:updated` event:
|
|
127
|
+
|
|
128
|
+
```bash
|
|
129
|
+
REPO_ROOT=$(git rev-parse --show-toplevel 2>/dev/null || pwd)
|
|
130
|
+
CTRL_URL=$(jq -r '.url // "http://localhost:4242"' "$REPO_ROOT/.monomind/control.json" 2>/dev/null || echo "http://localhost:4242")
|
|
131
|
+
curl -s -X POST "${CTRL_URL}/api/mastermind/event" \
|
|
132
|
+
-H "Content-Type: application/json" \
|
|
133
|
+
-d "$(jq -cn --arg org "$org_name" --arg field "$field" --arg value "$value" \
|
|
134
|
+
'{type:"org:settings:updated",org:$org,field:$field,value:$value,ts:(now*1000|floor)}')" || true
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
### export
|
|
138
|
+
|
|
139
|
+
Export the full org config (minus secrets) to a portable JSON:
|
|
140
|
+
|
|
141
|
+
```bash
|
|
142
|
+
mkdir -p ".monomind/exports"
|
|
143
|
+
timestamp=$(date +%Y%m%d-%H%M%S)
|
|
144
|
+
outPath="${export_path:-.monomind/exports/${org_name}-${timestamp}.json}"
|
|
145
|
+
|
|
146
|
+
# Merge all org data files into one export bundle
|
|
147
|
+
jq -n \
|
|
148
|
+
--slurpfile config "$orgFile" \
|
|
149
|
+
--slurpfile goals ".monomind/orgs/${org_name}-goals.json" 2>/dev/null \
|
|
150
|
+
--slurpfile routines ".monomind/orgs/${org_name}-routines.json" 2>/dev/null \
|
|
151
|
+
--slurpfile projects ".monomind/orgs/${org_name}-projects.json" 2>/dev/null \
|
|
152
|
+
'{
|
|
153
|
+
exported_at: (now|todate),
|
|
154
|
+
format_version: "1.0",
|
|
155
|
+
config: ($config[0] // {}),
|
|
156
|
+
goals: ($goals[0].goals // []),
|
|
157
|
+
routines: ($routines[0].routines // []),
|
|
158
|
+
projects: ($projects[0].projects // [])
|
|
159
|
+
}' > "$outPath"
|
|
160
|
+
|
|
161
|
+
echo "Exported: $outPath"
|
|
162
|
+
echo "$(wc -c < "$outPath") bytes — share this file to recreate the org on another machine."
|
|
163
|
+
echo "Import with: /mastermind:org-settings --action import --import-path $outPath"
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
### import
|
|
167
|
+
|
|
168
|
+
Import an org from a previously exported bundle:
|
|
169
|
+
|
|
170
|
+
```bash
|
|
171
|
+
[ ! -f "$import_path" ] && { echo "ERROR: Import file not found: $import_path"; exit 1; }
|
|
172
|
+
|
|
173
|
+
# Validate format
|
|
174
|
+
fmt=$(jq -r '.format_version // "unknown"' "$import_path" 2>/dev/null || echo "unknown")
|
|
175
|
+
[ "$fmt" != "1.0" ] && echo "Warning: format_version '$fmt' — attempting import anyway."
|
|
176
|
+
|
|
177
|
+
importedName=$(jq -r '.config.name // .config.org_name // "unnamed"' "$import_path")
|
|
178
|
+
targetOrg="${org_name:-$importedName}"
|
|
179
|
+
mkdir -p ".monomind/orgs"
|
|
180
|
+
|
|
181
|
+
# Write config
|
|
182
|
+
jq '.config' "$import_path" > ".monomind/orgs/${targetOrg}.json"
|
|
183
|
+
|
|
184
|
+
# Write goals if present
|
|
185
|
+
goalsData=$(jq '.goals // []' "$import_path")
|
|
186
|
+
[ "$goalsData" != "[]" ] && echo "{\"goals\":$goalsData}" > ".monomind/orgs/${targetOrg}-goals.json"
|
|
187
|
+
|
|
188
|
+
# Write routines if present
|
|
189
|
+
routinesData=$(jq '.routines // []' "$import_path")
|
|
190
|
+
[ "$routinesData" != "[]" ] && echo "{\"routines\":$routinesData}" > ".monomind/orgs/${targetOrg}-routines.json"
|
|
191
|
+
|
|
192
|
+
# Write projects if present
|
|
193
|
+
projectsData=$(jq '.projects // []' "$import_path")
|
|
194
|
+
[ "$projectsData" != "[]" ] && echo "{\"projects\":$projectsData}" > ".monomind/orgs/${targetOrg}-projects.json"
|
|
195
|
+
|
|
196
|
+
echo "Imported org '${targetOrg}' from ${import_path}"
|
|
197
|
+
echo "Agents: $(jq '.config.roles | length' "$import_path")"
|
|
198
|
+
echo "Run /mastermind:env --org ${targetOrg} --action validate to check provider keys."
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
---
|
|
202
|
+
|
|
203
|
+
## Step 3 — Return Output
|
|
204
|
+
|
|
205
|
+
```yaml
|
|
206
|
+
domain: ops
|
|
207
|
+
status: complete
|
|
208
|
+
action: <action>
|
|
209
|
+
org: <org_name>
|
|
210
|
+
field: <field if edit>
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
---
|
|
214
|
+
|
|
215
|
+
## Step 4 — Brain Write (standalone only)
|
|
216
|
+
|
|
217
|
+
If `caller` is not "command", follow _protocol.md Brain Write Procedure for domain `ops`.
|