@monoes/monomindcli 1.9.17 → 1.10.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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 +63 -37
- 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 +28 -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 +250 -122
- 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 +2 -2
- 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,315 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: mastermind-instance-settings
|
|
3
|
+
description: Mastermind instance-settings — instance-level administration covering general settings (auth, backup retention, keyboard shortcuts, AI feedback), experimental features (liveness auto-recovery), and user→company access grants. Extends mastermind:instance with InstanceGeneralSettings, InstanceExperimentalSettings, and InstanceAccess.
|
|
4
|
+
type: domain-skill
|
|
5
|
+
default_mode: confirm
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Mastermind Instance Settings
|
|
9
|
+
|
|
10
|
+
This skill is invoked by `mastermind:instance-settings` or directly via `/mastermind:instance-settings`.
|
|
11
|
+
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
## Inputs
|
|
15
|
+
|
|
16
|
+
- `brain_context`: BRAIN CONTEXT block (injected by command, or loaded below if standalone)
|
|
17
|
+
- `action`: show | general | experimental | access | set | toggle-liveness | preview-liveness | grant-access | revoke-access | set-admin | unset-admin
|
|
18
|
+
- `key`: general setting key to update (for `set` action)
|
|
19
|
+
- `value`: value to set (for `set` action)
|
|
20
|
+
- `user_id`: user id (for grant-access / revoke-access / set-admin / unset-admin)
|
|
21
|
+
- `org_name`: org name to grant/revoke access to (for grant-access / revoke-access)
|
|
22
|
+
- `search`: search query for user lookup (for access action)
|
|
23
|
+
- `caller`: command | master
|
|
24
|
+
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
## General Settings Keys
|
|
28
|
+
|
|
29
|
+
| Key | Type | Description |
|
|
30
|
+
|-----|------|-------------|
|
|
31
|
+
| `censorUsernameInLogs` | bool | Redact usernames from log output |
|
|
32
|
+
| `keyboardShortcutsEnabled` | bool | Enable keyboard shortcut navigation |
|
|
33
|
+
| `aiFeedbackSharingEnabled` | bool | Share feedback with AI provider |
|
|
34
|
+
| `dailyBackupRetentionDays` | int | Days to keep daily backups |
|
|
35
|
+
| `weeklyBackupRetentionWeeks` | int | Weeks to keep weekly backups |
|
|
36
|
+
| `monthlyBackupRetentionMonths` | int | Months to keep monthly backups |
|
|
37
|
+
|
|
38
|
+
## Experimental Settings
|
|
39
|
+
|
|
40
|
+
| Key | Type | Description |
|
|
41
|
+
|-----|------|-------------|
|
|
42
|
+
| `livenessAutoRecoveryEnabled` | bool | Auto-create recovery tasks for stalled issues |
|
|
43
|
+
| `livenessAutoRecoveryLookbackHours` | int | Hours to look back for stalled issues |
|
|
44
|
+
|
|
45
|
+
---
|
|
46
|
+
|
|
47
|
+
## Step 0 — Brain Load (standalone only)
|
|
48
|
+
|
|
49
|
+
If `caller` is not "command", load brain context following _protocol.md Brain Load Procedure with namespace: `ops`.
|
|
50
|
+
|
|
51
|
+
---
|
|
52
|
+
|
|
53
|
+
## Step 1 — Load Instance Config
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
instanceFile=".monomind/instance.json"
|
|
57
|
+
[ ! -f "$instanceFile" ] && echo '{"general":{},"experimental":{},"access":{"users":[]}}' > "$instanceFile"
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
---
|
|
61
|
+
|
|
62
|
+
## Step 2 — Execute Action
|
|
63
|
+
|
|
64
|
+
### show (default)
|
|
65
|
+
|
|
66
|
+
```bash
|
|
67
|
+
echo "INSTANCE SETTINGS"
|
|
68
|
+
echo "────────────────────────────────────────────────────────"
|
|
69
|
+
|
|
70
|
+
general=$(jq -r '.general // {}' "$instanceFile")
|
|
71
|
+
exp=$(jq -r '.experimental // {}' "$instanceFile")
|
|
72
|
+
|
|
73
|
+
echo "GENERAL"
|
|
74
|
+
echo " censorUsernameInLogs: $(echo "$general" | jq -r '.censorUsernameInLogs // false')"
|
|
75
|
+
echo " keyboardShortcutsEnabled: $(echo "$general" | jq -r '.keyboardShortcutsEnabled // true')"
|
|
76
|
+
echo " aiFeedbackSharingEnabled: $(echo "$general" | jq -r '.aiFeedbackSharingEnabled // false')"
|
|
77
|
+
echo " dailyBackupRetentionDays: $(echo "$general" | jq -r '.dailyBackupRetentionDays // 7')"
|
|
78
|
+
echo " weeklyBackupRetentionWeeks: $(echo "$general" | jq -r '.weeklyBackupRetentionWeeks // 4')"
|
|
79
|
+
echo " monthlyBackupRetentionMonths: $(echo "$general" | jq -r '.monthlyBackupRetentionMonths // 12')"
|
|
80
|
+
|
|
81
|
+
echo ""
|
|
82
|
+
echo "EXPERIMENTAL"
|
|
83
|
+
echo " livenessAutoRecoveryEnabled: $(echo "$exp" | jq -r '.livenessAutoRecoveryEnabled // false')"
|
|
84
|
+
echo " livenessAutoRecoveryLookbackHours: $(echo "$exp" | jq -r '.livenessAutoRecoveryLookbackHours // 24')"
|
|
85
|
+
|
|
86
|
+
echo ""
|
|
87
|
+
echo " To modify: --action set --key <key> --value <value>"
|
|
88
|
+
echo " To view users: --action access"
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
### general
|
|
92
|
+
|
|
93
|
+
```bash
|
|
94
|
+
echo "GENERAL SETTINGS"
|
|
95
|
+
echo "────────────────────────────────────────────────────────"
|
|
96
|
+
jq -r '.general // {}' "$instanceFile" | jq .
|
|
97
|
+
|
|
98
|
+
echo ""
|
|
99
|
+
echo "BACKUP RETENTION PRESETS"
|
|
100
|
+
echo " Daily: 7d / 14d / 30d / 60d / 90d"
|
|
101
|
+
echo " Weekly: 4w / 8w / 12w / 26w / 52w"
|
|
102
|
+
echo " Monthly: 3m / 6m / 12m / 24m"
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
### experimental
|
|
106
|
+
|
|
107
|
+
```bash
|
|
108
|
+
echo "EXPERIMENTAL SETTINGS"
|
|
109
|
+
echo "────────────────────────────────────────────────────────"
|
|
110
|
+
jq -r '.experimental // {}' "$instanceFile" | jq .
|
|
111
|
+
|
|
112
|
+
enabled=$(jq -r '.experimental.livenessAutoRecoveryEnabled // false' "$instanceFile")
|
|
113
|
+
hours=$(jq -r '.experimental.livenessAutoRecoveryLookbackHours // 24' "$instanceFile")
|
|
114
|
+
|
|
115
|
+
echo ""
|
|
116
|
+
echo "LIVENESS AUTO-RECOVERY"
|
|
117
|
+
echo " Enabled: $enabled"
|
|
118
|
+
echo " Lookback hours: $hours"
|
|
119
|
+
echo ""
|
|
120
|
+
echo " Toggle: --action toggle-liveness"
|
|
121
|
+
echo " Preview: --action preview-liveness"
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
### set
|
|
125
|
+
|
|
126
|
+
```bash
|
|
127
|
+
[ -z "$key" ] && { echo "ERROR: --key required."; exit 1; }
|
|
128
|
+
[ -z "$value" ] && { echo "ERROR: --value required."; exit 1; }
|
|
129
|
+
|
|
130
|
+
# Determine target section
|
|
131
|
+
section="general"
|
|
132
|
+
case "$key" in
|
|
133
|
+
livenessAutoRecovery*) section="experimental" ;;
|
|
134
|
+
esac
|
|
135
|
+
|
|
136
|
+
# Coerce booleans and integers
|
|
137
|
+
typedValue="$value"
|
|
138
|
+
case "$value" in
|
|
139
|
+
true|false) typedValue=$(echo "$value") ;;
|
|
140
|
+
*[0-9]*) echo "$value" | grep -qE '^[0-9]+$' && typedValue="$value" ;;
|
|
141
|
+
esac
|
|
142
|
+
|
|
143
|
+
tmp="${instanceFile}.tmp"
|
|
144
|
+
jq --arg section "$section" --arg k "$key" --argjson v "$(
|
|
145
|
+
if echo "$typedValue" | grep -qE '^(true|false|[0-9]+)$'; then echo "$typedValue"; else echo "\"$typedValue\""; fi
|
|
146
|
+
)" \
|
|
147
|
+
'.[$section][$k] = $v' \
|
|
148
|
+
"$instanceFile" > "$tmp" && mv "$tmp" "$instanceFile"
|
|
149
|
+
|
|
150
|
+
echo "Instance setting updated: [$section] $key = $typedValue"
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
### toggle-liveness
|
|
154
|
+
|
|
155
|
+
```bash
|
|
156
|
+
current=$(jq -r '.experimental.livenessAutoRecoveryEnabled // false' "$instanceFile")
|
|
157
|
+
if [ "$current" = "true" ]; then
|
|
158
|
+
newVal=false
|
|
159
|
+
else
|
|
160
|
+
newVal=true
|
|
161
|
+
fi
|
|
162
|
+
|
|
163
|
+
tmp="${instanceFile}.tmp"
|
|
164
|
+
jq --argjson v "$newVal" '.experimental.livenessAutoRecoveryEnabled = $v' \
|
|
165
|
+
"$instanceFile" > "$tmp" && mv "$tmp" "$instanceFile"
|
|
166
|
+
|
|
167
|
+
echo "Liveness auto-recovery toggled: $newVal"
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
### preview-liveness
|
|
171
|
+
|
|
172
|
+
```bash
|
|
173
|
+
hours=$(jq -r '.experimental.livenessAutoRecoveryLookbackHours // 24' "$instanceFile")
|
|
174
|
+
echo "LIVENESS AUTO-RECOVERY PREVIEW"
|
|
175
|
+
echo " Lookback: last ${hours} hours"
|
|
176
|
+
echo "────────────────────────────────────────────────────────"
|
|
177
|
+
echo " (Preview runs against live issue graph.)"
|
|
178
|
+
echo " To enable: --action toggle-liveness"
|
|
179
|
+
echo ""
|
|
180
|
+
echo " Checking activity files for stalled issues…"
|
|
181
|
+
cutoff=$(date -u -v-${hours}H +%Y-%m-%dT%H:%M:%SZ 2>/dev/null || date -u --date="${hours} hours ago" +%Y-%m-%dT%H:%M:%SZ 2>/dev/null)
|
|
182
|
+
|
|
183
|
+
# Count potentially stalled issues across all orgs
|
|
184
|
+
stalledCount=0
|
|
185
|
+
for issuesFile in .monomind/orgs/*-issues.json; do
|
|
186
|
+
[ -f "$issuesFile" ] || continue
|
|
187
|
+
cnt=$(jq --arg cutoff "$cutoff" \
|
|
188
|
+
'[.issues[] | select(.status == "in_progress" and (.lastActivityAt // .createdAt // "") < $cutoff)] | length' \
|
|
189
|
+
"$issuesFile" 2>/dev/null || echo 0)
|
|
190
|
+
stalledCount=$((stalledCount + cnt))
|
|
191
|
+
done
|
|
192
|
+
|
|
193
|
+
echo " Potentially stalled issues (in_progress, no activity since cutoff): $stalledCount"
|
|
194
|
+
[ "$stalledCount" -gt 0 ] && echo " Run --action toggle-liveness to enable auto-recovery."
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
### access
|
|
198
|
+
|
|
199
|
+
```bash
|
|
200
|
+
search="${search:-}"
|
|
201
|
+
accessFile=".monomind/instance-access.json"
|
|
202
|
+
[ ! -f "$accessFile" ] && echo '{"users":[]}' > "$accessFile"
|
|
203
|
+
|
|
204
|
+
echo "INSTANCE ACCESS — USER DIRECTORY"
|
|
205
|
+
echo " Search: ${search:-(all)}"
|
|
206
|
+
echo "────────────────────────────────────────────────────────"
|
|
207
|
+
printf "%-32s %-20s %-10s %s\n" "USER ID" "NAME" "ADMIN" "COMPANIES"
|
|
208
|
+
echo "────────────────────────────────────────────────────────"
|
|
209
|
+
|
|
210
|
+
jq -r --arg q "$search" '.users[] |
|
|
211
|
+
select($q == "" or (.id | ascii_downcase | contains($q | ascii_downcase))
|
|
212
|
+
or (.name // "" | ascii_downcase | contains($q | ascii_downcase))) |
|
|
213
|
+
[.id, (.name // "(unnamed)"), (if .isInstanceAdmin then "yes" else "no" end),
|
|
214
|
+
((.companyAccess // []) | length | tostring)] | @tsv' \
|
|
215
|
+
"$accessFile" | while IFS=$'\t' read -r uid name admin count; do
|
|
216
|
+
printf "%-32s %-20s %-10s %s orgs\n" "$uid" "$name" "$admin" "$count"
|
|
217
|
+
done
|
|
218
|
+
|
|
219
|
+
echo ""
|
|
220
|
+
echo " Grant org access: --action grant-access --user-id <uid> --org-name <org>"
|
|
221
|
+
echo " Revoke org access: --action revoke-access --user-id <uid> --org-name <org>"
|
|
222
|
+
echo " Make instance admin: --action set-admin --user-id <uid>"
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
### grant-access
|
|
226
|
+
|
|
227
|
+
```bash
|
|
228
|
+
[ -z "$user_id" ] && { echo "ERROR: --user-id required."; exit 1; }
|
|
229
|
+
[ -z "$org_name" ] && { echo "ERROR: --org-name required."; exit 1; }
|
|
230
|
+
|
|
231
|
+
accessFile=".monomind/instance-access.json"
|
|
232
|
+
[ ! -f "$accessFile" ] && echo '{"users":[]}' > "$accessFile"
|
|
233
|
+
|
|
234
|
+
ts=$(date -u +%Y-%m-%dT%H:%M:%SZ)
|
|
235
|
+
tmp="${accessFile}.tmp"
|
|
236
|
+
jq --arg uid "$user_id" --arg org "$org_name" --arg ts "$ts" \
|
|
237
|
+
'.users = (
|
|
238
|
+
if any(.users[]; .id == $uid) then
|
|
239
|
+
[.users[] | if .id == $uid then
|
|
240
|
+
.companyAccess = ((.companyAccess // []) | if any(.[]; . == $org) then . else . + [$org] end)
|
|
241
|
+
else . end]
|
|
242
|
+
else
|
|
243
|
+
.users + [{"id": $uid, "companyAccess": [$org], "isInstanceAdmin": false, "grantedAt": $ts}]
|
|
244
|
+
end)' \
|
|
245
|
+
"$accessFile" > "$tmp" && mv "$tmp" "$accessFile"
|
|
246
|
+
|
|
247
|
+
echo "Access granted: user '$user_id' → org '$org_name'"
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
### revoke-access
|
|
251
|
+
|
|
252
|
+
```bash
|
|
253
|
+
[ -z "$user_id" ] && { echo "ERROR: --user-id required."; exit 1; }
|
|
254
|
+
[ -z "$org_name" ] && { echo "ERROR: --org-name required."; exit 1; }
|
|
255
|
+
|
|
256
|
+
accessFile=".monomind/instance-access.json"
|
|
257
|
+
[ ! -f "$accessFile" ] && { echo "No access file found."; exit 1; }
|
|
258
|
+
|
|
259
|
+
tmp="${accessFile}.tmp"
|
|
260
|
+
jq --arg uid "$user_id" --arg org "$org_name" \
|
|
261
|
+
'.users = [.users[] | if .id == $uid then
|
|
262
|
+
.companyAccess = [(.companyAccess // [])[] | select(. != $org)]
|
|
263
|
+
else . end]' \
|
|
264
|
+
"$accessFile" > "$tmp" && mv "$tmp" "$accessFile"
|
|
265
|
+
|
|
266
|
+
echo "Access revoked: user '$user_id' from org '$org_name'"
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
### set-admin
|
|
270
|
+
|
|
271
|
+
```bash
|
|
272
|
+
[ -z "$user_id" ] && { echo "ERROR: --user-id required."; exit 1; }
|
|
273
|
+
|
|
274
|
+
accessFile=".monomind/instance-access.json"
|
|
275
|
+
[ ! -f "$accessFile" ] && echo '{"users":[]}' > "$accessFile"
|
|
276
|
+
|
|
277
|
+
tmp="${accessFile}.tmp"
|
|
278
|
+
jq --arg uid "$user_id" \
|
|
279
|
+
'.users = (if any(.users[]; .id == $uid) then
|
|
280
|
+
[.users[] | if .id == $uid then .isInstanceAdmin = true else . end]
|
|
281
|
+
else .users + [{"id":$uid,"companyAccess":[],"isInstanceAdmin":true}] end)' \
|
|
282
|
+
"$accessFile" > "$tmp" && mv "$tmp" "$accessFile"
|
|
283
|
+
|
|
284
|
+
echo "User '$user_id' granted instance admin role."
|
|
285
|
+
```
|
|
286
|
+
|
|
287
|
+
### unset-admin
|
|
288
|
+
|
|
289
|
+
```bash
|
|
290
|
+
[ -z "$user_id" ] && { echo "ERROR: --user-id required."; exit 1; }
|
|
291
|
+
|
|
292
|
+
accessFile=".monomind/instance-access.json"
|
|
293
|
+
tmp="${accessFile}.tmp"
|
|
294
|
+
jq --arg uid "$user_id" \
|
|
295
|
+
'.users = [.users[] | if .id == $uid then .isInstanceAdmin = false else . end]' \
|
|
296
|
+
"$accessFile" > "$tmp" && mv "$tmp" "$accessFile"
|
|
297
|
+
|
|
298
|
+
echo "Instance admin revoked for user '$user_id'."
|
|
299
|
+
```
|
|
300
|
+
|
|
301
|
+
---
|
|
302
|
+
|
|
303
|
+
## Step 3 — Return Output
|
|
304
|
+
|
|
305
|
+
```yaml
|
|
306
|
+
domain: ops
|
|
307
|
+
status: complete
|
|
308
|
+
action: <action>
|
|
309
|
+
```
|
|
310
|
+
|
|
311
|
+
---
|
|
312
|
+
|
|
313
|
+
## Step 4 — Brain Write (standalone only)
|
|
314
|
+
|
|
315
|
+
If `caller` is not "command", follow _protocol.md Brain Write Procedure for domain `ops`.
|
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: mastermind-instance
|
|
3
|
+
description: Mastermind instance — global instance-level settings including scheduler heartbeat management across all orgs, system-wide configuration, and cross-org health overview.
|
|
4
|
+
type: domain-skill
|
|
5
|
+
default_mode: auto
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Mastermind Instance
|
|
9
|
+
|
|
10
|
+
This skill is invoked by `mastermind:instance` or directly via `/mastermind:instance`.
|
|
11
|
+
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
## Inputs
|
|
15
|
+
|
|
16
|
+
- `brain_context`: BRAIN CONTEXT block (injected by command, or loaded below if standalone)
|
|
17
|
+
- `action`: show | heartbeats | toggle-heartbeat | set | health
|
|
18
|
+
- `agent_id`: agent id (required for toggle-heartbeat)
|
|
19
|
+
- `org_name`: org filter (optional)
|
|
20
|
+
- `key`: config key to set (for `set` action)
|
|
21
|
+
- `value`: value to set
|
|
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 Instance Config
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
instanceFile=".monomind/instance.json"
|
|
36
|
+
if [ ! -f "$instanceFile" ]; then
|
|
37
|
+
cat > "$instanceFile" <<'EOF'
|
|
38
|
+
{
|
|
39
|
+
"version": "1.0",
|
|
40
|
+
"scheduler": {
|
|
41
|
+
"enabled": true,
|
|
42
|
+
"default_heartbeat_interval": 900,
|
|
43
|
+
"max_concurrent_heartbeats": 4
|
|
44
|
+
},
|
|
45
|
+
"limits": {
|
|
46
|
+
"max_orgs": 20,
|
|
47
|
+
"max_agents_per_org": 50,
|
|
48
|
+
"max_tokens_per_day": 10000000
|
|
49
|
+
},
|
|
50
|
+
"heartbeat_agents": []
|
|
51
|
+
}
|
|
52
|
+
EOF
|
|
53
|
+
fi
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
---
|
|
57
|
+
|
|
58
|
+
## Step 2 — Execute Action
|
|
59
|
+
|
|
60
|
+
### show (default)
|
|
61
|
+
|
|
62
|
+
Display global instance configuration:
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
echo "MONOMIND INSTANCE SETTINGS"
|
|
66
|
+
echo "──────────────────────────────────────────"
|
|
67
|
+
jq -r '
|
|
68
|
+
" Version: \(.version // "1.0")",
|
|
69
|
+
" Scheduler enabled: \(.scheduler.enabled // true)",
|
|
70
|
+
" Heartbeat interval: \(.scheduler.default_heartbeat_interval // 900)s",
|
|
71
|
+
" Max concurrent beats: \(.scheduler.max_concurrent_heartbeats // 4)",
|
|
72
|
+
"",
|
|
73
|
+
"LIMITS",
|
|
74
|
+
" Max orgs: \(.limits.max_orgs // 20)",
|
|
75
|
+
" Max agents/org: \(.limits.max_agents_per_org // 50)",
|
|
76
|
+
" Max tokens/day: \(.limits.max_tokens_per_day // 10000000)"
|
|
77
|
+
' "$instanceFile"
|
|
78
|
+
|
|
79
|
+
echo ""
|
|
80
|
+
echo "ORGS"
|
|
81
|
+
orgs=$(ls .monomind/orgs/*.json 2>/dev/null | grep -v '\-state\|-goals\|-routines\|-approvals\|-projects\|-worktrees\|-secrets\|-members\|-adapters\|-plugins' | wc -l | tr -d ' ')
|
|
82
|
+
echo " Active orgs: $orgs"
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
### heartbeats
|
|
86
|
+
|
|
87
|
+
List all agents across all orgs that have scheduled heartbeats:
|
|
88
|
+
|
|
89
|
+
```bash
|
|
90
|
+
echo "SCHEDULER HEARTBEATS"
|
|
91
|
+
echo "────────────────────────────────────────────────────────"
|
|
92
|
+
printf "%-20s %-20s %-14s %-10s %s\n" "ORG" "AGENT" "INTERVAL" "ENABLED" "LAST RUN"
|
|
93
|
+
echo "────────────────────────────────────────────────────────"
|
|
94
|
+
|
|
95
|
+
found=0
|
|
96
|
+
for orgF in .monomind/orgs/*.json; do
|
|
97
|
+
[[ "$orgF" == *-state* || "$orgF" == *-goals* || "$orgF" == *-routines* || "$orgF" == *-approvals* ]] && continue
|
|
98
|
+
[[ "$orgF" == *-projects* || "$orgF" == *-worktrees* || "$orgF" == *-members* || "$orgF" == *-adapters* ]] && continue
|
|
99
|
+
[[ "$orgF" == *-plugins* || "$orgF" == *-bootstrap* ]] && continue
|
|
100
|
+
|
|
101
|
+
orgName=$(basename "$orgF" .json)
|
|
102
|
+
[ -n "$org_name" ] && [ "$orgName" != "$org_name" ] && continue
|
|
103
|
+
|
|
104
|
+
stateFile=".monomind/orgs/${orgName}-state.json"
|
|
105
|
+
jq -r --arg org "$orgName" '
|
|
106
|
+
.roles[] |
|
|
107
|
+
select(.heartbeat.enabled == true or (.runtimeConfig.heartbeat.enabled == true)) |
|
|
108
|
+
[$org, .id,
|
|
109
|
+
((.heartbeat.interval // .runtimeConfig.heartbeat.interval // "900") | tostring) + "s",
|
|
110
|
+
"yes",
|
|
111
|
+
"-"]
|
|
112
|
+
| @tsv' "$orgF" 2>/dev/null | while IFS=$'\t' read -r org agent interval enabled lastrun; do
|
|
113
|
+
printf "%-20s %-20s %-14s %-10s %s\n" "$org" "$agent" "$interval" "$enabled" "$lastrun"
|
|
114
|
+
found=$((found + 1))
|
|
115
|
+
done
|
|
116
|
+
done
|
|
117
|
+
|
|
118
|
+
[ "$found" -eq 0 ] && echo " No scheduled heartbeat agents found. Configure via /mastermind:heartbeat."
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
### toggle-heartbeat
|
|
122
|
+
|
|
123
|
+
Enable or disable the scheduler heartbeat for a specific agent:
|
|
124
|
+
|
|
125
|
+
```bash
|
|
126
|
+
[ -z "$agent_id" ] && { echo "ERROR: --agent-id required."; exit 1; }
|
|
127
|
+
[ -z "$org_name" ] && { echo "ERROR: --org required."; exit 1; }
|
|
128
|
+
|
|
129
|
+
orgFile=".monomind/orgs/${org_name}.json"
|
|
130
|
+
[ ! -f "$orgFile" ] && { echo "ERROR: Org '${org_name}' not found."; exit 1; }
|
|
131
|
+
|
|
132
|
+
# Get current state
|
|
133
|
+
current=$(jq -r --arg id "$agent_id" \
|
|
134
|
+
'.roles[] | select(.id == $id) | .heartbeat.enabled // false' "$orgFile" 2>/dev/null || echo "false")
|
|
135
|
+
newState=$([ "$current" = "true" ] && echo "false" || echo "true")
|
|
136
|
+
|
|
137
|
+
tmp="${orgFile}.tmp"
|
|
138
|
+
jq --arg id "$agent_id" --argjson enabled "$newState" \
|
|
139
|
+
'.roles = [.roles[] | if .id == $id then .heartbeat.enabled = $enabled else . end]' \
|
|
140
|
+
"$orgFile" > "$tmp" && mv "$tmp" "$orgFile"
|
|
141
|
+
|
|
142
|
+
echo "Heartbeat for '$agent_id' → $([ "$newState" = "true" ] && echo 'ENABLED' || echo 'DISABLED')"
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
### set
|
|
146
|
+
|
|
147
|
+
Update an instance-level config value:
|
|
148
|
+
|
|
149
|
+
```bash
|
|
150
|
+
[ -z "$key" ] && { echo "ERROR: --key required."; exit 1; }
|
|
151
|
+
[ -z "$value" ] && { echo "ERROR: --value required."; exit 1; }
|
|
152
|
+
|
|
153
|
+
tmp="${instanceFile}.tmp"
|
|
154
|
+
case "$key" in
|
|
155
|
+
scheduler.enabled)
|
|
156
|
+
jq --argjson v "$([ "$value" = "true" ] && echo true || echo false)" '.scheduler.enabled = $v' "$instanceFile" > "$tmp" ;;
|
|
157
|
+
scheduler.default_heartbeat_interval)
|
|
158
|
+
[[ "$value" =~ ^[0-9]+$ ]] || { echo "ERROR: value must be integer seconds."; exit 1; }
|
|
159
|
+
jq --argjson v "$value" '.scheduler.default_heartbeat_interval = $v' "$instanceFile" > "$tmp" ;;
|
|
160
|
+
scheduler.max_concurrent_heartbeats)
|
|
161
|
+
[[ "$value" =~ ^[0-9]+$ ]] || { echo "ERROR: value must be integer."; exit 1; }
|
|
162
|
+
jq --argjson v "$value" '.scheduler.max_concurrent_heartbeats = $v' "$instanceFile" > "$tmp" ;;
|
|
163
|
+
limits.max_orgs)
|
|
164
|
+
jq --argjson v "$value" '.limits.max_orgs = $v' "$instanceFile" > "$tmp" ;;
|
|
165
|
+
limits.max_tokens_per_day)
|
|
166
|
+
jq --argjson v "$value" '.limits.max_tokens_per_day = $v' "$instanceFile" > "$tmp" ;;
|
|
167
|
+
*)
|
|
168
|
+
echo "ERROR: Unknown key '$key'. Valid keys: scheduler.enabled, scheduler.default_heartbeat_interval, scheduler.max_concurrent_heartbeats, limits.max_orgs, limits.max_tokens_per_day"
|
|
169
|
+
exit 1 ;;
|
|
170
|
+
esac
|
|
171
|
+
mv "$tmp" "$instanceFile"
|
|
172
|
+
echo "Set: $key = $value"
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
### health
|
|
176
|
+
|
|
177
|
+
Cross-org health overview:
|
|
178
|
+
|
|
179
|
+
```bash
|
|
180
|
+
echo "INSTANCE HEALTH"
|
|
181
|
+
echo "────────────────────────────────────────────────────────"
|
|
182
|
+
total_orgs=0
|
|
183
|
+
total_running=0
|
|
184
|
+
total_alerts=0
|
|
185
|
+
total_pending=0
|
|
186
|
+
|
|
187
|
+
for orgF in .monomind/orgs/*.json; do
|
|
188
|
+
[[ "$orgF" == *-state* || "$orgF" == *-goals* || "$orgF" == *-routines* || "$orgF" == *-approvals* ]] && continue
|
|
189
|
+
[[ "$orgF" == *-projects* || "$orgF" == *-worktrees* || "$orgF" == *-members* || "$orgF" == *-adapters* ]] && continue
|
|
190
|
+
[[ "$orgF" == *-plugins* || "$orgF" == *-bootstrap* ]] && continue
|
|
191
|
+
|
|
192
|
+
orgName=$(basename "$orgF" .json)
|
|
193
|
+
total_orgs=$((total_orgs + 1))
|
|
194
|
+
stateFile=".monomind/orgs/${orgName}-state.json"
|
|
195
|
+
approvalsFile=".monomind/orgs/${orgName}-approvals.json"
|
|
196
|
+
|
|
197
|
+
if [ -f "$stateFile" ]; then
|
|
198
|
+
running=$(jq '[.agents // {} | to_entries[] | select(.value.status == "running")] | length' "$stateFile" 2>/dev/null || echo 0)
|
|
199
|
+
total_running=$((total_running + running))
|
|
200
|
+
fi
|
|
201
|
+
if [ -f "$approvalsFile" ]; then
|
|
202
|
+
pending=$(jq '[.approvals[] | select(.status == "pending")] | length' "$approvalsFile" 2>/dev/null || echo 0)
|
|
203
|
+
total_pending=$((total_pending + pending))
|
|
204
|
+
fi
|
|
205
|
+
done
|
|
206
|
+
|
|
207
|
+
echo " Total orgs: $total_orgs"
|
|
208
|
+
echo " Running agents: $total_running"
|
|
209
|
+
echo " Pending approvals:$total_pending"
|
|
210
|
+
echo ""
|
|
211
|
+
[ "$total_running" -gt 0 ] && echo " ✓ System is active." || echo " ◌ No agents running."
|
|
212
|
+
[ "$total_pending" -gt 0 ] && echo " ⚠ $total_pending approval(s) need attention. Run /mastermind:inbox."
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
---
|
|
216
|
+
|
|
217
|
+
## Step 3 — Return Output
|
|
218
|
+
|
|
219
|
+
```yaml
|
|
220
|
+
domain: ops
|
|
221
|
+
status: complete
|
|
222
|
+
action: <action>
|
|
223
|
+
total_orgs: <N>
|
|
224
|
+
scheduler_enabled: <true|false>
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
---
|
|
228
|
+
|
|
229
|
+
## Step 4 — Brain Write (standalone only)
|
|
230
|
+
|
|
231
|
+
If `caller` is not "command", follow _protocol.md Brain Write Procedure for domain `ops`.
|