@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,190 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: mastermind-plugins
|
|
3
|
+
description: Mastermind plugins — install, enable, disable, uninstall, and inspect plugins for an org. Plugins extend agent capabilities with workers, events, and custom tools. Supports npm packages and local paths.
|
|
4
|
+
type: domain-skill
|
|
5
|
+
default_mode: confirm
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Mastermind Plugins
|
|
9
|
+
|
|
10
|
+
This skill is invoked by `mastermind:plugins` or directly via `/mastermind:plugins`.
|
|
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 manage plugins for (optional — uses global plugin registry if omitted)
|
|
18
|
+
- `action`: list | install | uninstall | enable | disable | status | examples
|
|
19
|
+
- `plugin_id`: plugin id or package name (required for uninstall/enable/disable/status)
|
|
20
|
+
- `package_name`: npm package or local path (required for install)
|
|
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 Plugin Registry
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
pluginsDir=".monomind/plugins"
|
|
35
|
+
mkdir -p "$pluginsDir"
|
|
36
|
+
registryFile="${pluginsDir}/registry.json"
|
|
37
|
+
[ ! -f "$registryFile" ] && echo '{"plugins":[]}' > "$registryFile"
|
|
38
|
+
|
|
39
|
+
# If org scoped, also check org-level plugin overrides
|
|
40
|
+
if [ -n "$org_name" ]; then
|
|
41
|
+
orgPluginsFile=".monomind/orgs/${org_name}-plugins.json"
|
|
42
|
+
[ ! -f "$orgPluginsFile" ] && echo '{"plugins":[]}' > "$orgPluginsFile"
|
|
43
|
+
fi
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
---
|
|
47
|
+
|
|
48
|
+
## Step 2 — Execute Action
|
|
49
|
+
|
|
50
|
+
### list (default)
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
echo "PLUGINS"
|
|
54
|
+
echo "──────────────────────────────────────────────────────────"
|
|
55
|
+
printf "%-28s %-12s %-10s %-10s %s\n" "ID / PACKAGE" "VERSION" "STATUS" "CATEGORY" "ERROR"
|
|
56
|
+
echo "──────────────────────────────────────────────────────────"
|
|
57
|
+
|
|
58
|
+
count=$(jq '.plugins | length' "$registryFile")
|
|
59
|
+
if [ "$count" -eq 0 ]; then
|
|
60
|
+
echo " No plugins installed. Use --action install --package-name <pkg> to add one."
|
|
61
|
+
else
|
|
62
|
+
jq -r '.plugins[] |
|
|
63
|
+
[
|
|
64
|
+
(.id // .packageName // "unknown"),
|
|
65
|
+
(.version // "-"),
|
|
66
|
+
(.status // "unknown"),
|
|
67
|
+
(.category // "general"),
|
|
68
|
+
(if .lastError then (.lastError | split("\n")[0] | .[0:40]) else "-" end)
|
|
69
|
+
] | @tsv' "$registryFile" | while IFS=$'\t' read -r id ver status cat err; do
|
|
70
|
+
statusColor=""
|
|
71
|
+
printf "%-28s %-12s %-10s %-10s %s\n" "$id" "$ver" "$status" "$cat" "$err"
|
|
72
|
+
done
|
|
73
|
+
fi
|
|
74
|
+
|
|
75
|
+
echo ""
|
|
76
|
+
echo "Total: $count plugin(s)"
|
|
77
|
+
[ -n "$org_name" ] && echo "Org overrides: $(jq '.plugins | length' "$orgPluginsFile" 2>/dev/null || echo 0)"
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
### examples
|
|
81
|
+
|
|
82
|
+
Show example/available plugins from the monomind registry:
|
|
83
|
+
|
|
84
|
+
```bash
|
|
85
|
+
echo "AVAILABLE PLUGINS (monomind registry)"
|
|
86
|
+
echo "──────────────────────────────────────"
|
|
87
|
+
cat <<'EXAMPLES'
|
|
88
|
+
@monomind/plugin-sentry — Error tracking and alerting
|
|
89
|
+
@monomind/plugin-github — GitHub issue/PR sync
|
|
90
|
+
@monomind/plugin-slack — Slack notifications and commands
|
|
91
|
+
@monomind/plugin-linear — Linear issue sync
|
|
92
|
+
@monomind/plugin-datadog — Metrics and monitoring
|
|
93
|
+
@monomind/plugin-vault — HashiCorp Vault secrets integration
|
|
94
|
+
@monomind/plugin-webhook — Generic inbound/outbound webhooks
|
|
95
|
+
@monomind/plugin-memory-ext — Extended memory backend
|
|
96
|
+
|
|
97
|
+
Install: /mastermind:plugins --action install --package-name @monomind/plugin-<name>
|
|
98
|
+
EXAMPLES
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
### install
|
|
102
|
+
|
|
103
|
+
```bash
|
|
104
|
+
[ -z "$package_name" ] && { echo "ERROR: --package-name required."; exit 1; }
|
|
105
|
+
|
|
106
|
+
isLocal=false
|
|
107
|
+
[[ "$package_name" == /* || "$package_name" == "./"* ]] && isLocal=true
|
|
108
|
+
|
|
109
|
+
# Generate a stable id
|
|
110
|
+
pluginId=$(echo "$package_name" | sed 's|[/@]|_|g' | tr -cd 'a-z0-9_-')
|
|
111
|
+
ts=$(date -u +%Y-%m-%dT%H:%M:%SZ)
|
|
112
|
+
|
|
113
|
+
tmp="${registryFile}.tmp"
|
|
114
|
+
jq --arg id "$pluginId" \
|
|
115
|
+
--arg pkg "$package_name" \
|
|
116
|
+
--argjson local "$isLocal" \
|
|
117
|
+
--arg ts "$ts" \
|
|
118
|
+
'.plugins = [.plugins[] | select(.id != $id)] +
|
|
119
|
+
[{"id":$id,"packageName":$pkg,"isLocalPath":$local,
|
|
120
|
+
"status":"installed","version":"latest","category":"general",
|
|
121
|
+
"installedAt":$ts,"lastError":null}]' \
|
|
122
|
+
"$registryFile" > "$tmp" && mv "$tmp" "$registryFile"
|
|
123
|
+
|
|
124
|
+
echo "Installed: $package_name (id: $pluginId)"
|
|
125
|
+
echo "NOTE: Agents must be restarted to load the new plugin."
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
Emit `org:plugin:installed` event:
|
|
129
|
+
|
|
130
|
+
```bash
|
|
131
|
+
REPO_ROOT=$(git rev-parse --show-toplevel 2>/dev/null || pwd)
|
|
132
|
+
CTRL_URL=$(jq -r '.url // "http://localhost:4242"' "$REPO_ROOT/.monomind/control.json" 2>/dev/null || echo "http://localhost:4242")
|
|
133
|
+
curl -s -X POST "${CTRL_URL}/api/mastermind/event" \
|
|
134
|
+
-H "Content-Type: application/json" \
|
|
135
|
+
-d "$(jq -cn --arg org "${org_name:-global}" --arg id "$pluginId" --arg pkg "$package_name" \
|
|
136
|
+
'{type:"org:plugin:installed",org:$org,plugin:$id,package:$pkg,ts:(now*1000|floor)}')" || true
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
### uninstall
|
|
140
|
+
|
|
141
|
+
```bash
|
|
142
|
+
[ -z "$plugin_id" ] && { echo "ERROR: --plugin-id required."; exit 1; }
|
|
143
|
+
echo "Uninstalling plugin '$plugin_id'…"
|
|
144
|
+
|
|
145
|
+
tmp="${registryFile}.tmp"
|
|
146
|
+
jq --arg id "$plugin_id" '.plugins = [.plugins[] | select(.id != $id)]' \
|
|
147
|
+
"$registryFile" > "$tmp" && mv "$tmp" "$registryFile"
|
|
148
|
+
echo "Uninstalled: $plugin_id"
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
### enable / disable
|
|
152
|
+
|
|
153
|
+
```bash
|
|
154
|
+
[ -z "$plugin_id" ] && { echo "ERROR: --plugin-id required."; exit 1; }
|
|
155
|
+
newStatus=$([ "$action" = "enable" ] && echo "installed" || echo "disabled")
|
|
156
|
+
|
|
157
|
+
tmp="${registryFile}.tmp"
|
|
158
|
+
jq --arg id "$plugin_id" --arg s "$newStatus" \
|
|
159
|
+
'.plugins = [.plugins[] | if .id == $id then .status = $s else . end]' \
|
|
160
|
+
"$registryFile" > "$tmp" && mv "$tmp" "$registryFile"
|
|
161
|
+
echo "Plugin '$plugin_id' → $newStatus"
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
### status
|
|
165
|
+
|
|
166
|
+
Show detailed status for a specific plugin:
|
|
167
|
+
|
|
168
|
+
```bash
|
|
169
|
+
[ -z "$plugin_id" ] && { echo "ERROR: --plugin-id required."; exit 1; }
|
|
170
|
+
jq --arg id "$plugin_id" '.plugins[] | select(.id == $id)' "$registryFile"
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
---
|
|
174
|
+
|
|
175
|
+
## Step 3 — Return Output
|
|
176
|
+
|
|
177
|
+
```yaml
|
|
178
|
+
domain: ops
|
|
179
|
+
status: complete
|
|
180
|
+
action: <action>
|
|
181
|
+
org: <org_name or global>
|
|
182
|
+
plugin_id: <id if applicable>
|
|
183
|
+
plugins_total: <N>
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
---
|
|
187
|
+
|
|
188
|
+
## Step 4 — Brain Write (standalone only)
|
|
189
|
+
|
|
190
|
+
If `caller` is not "command", follow _protocol.md Brain Write Procedure for domain `ops`.
|
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: mastermind-profile
|
|
3
|
+
description: Mastermind profile — view and edit the current operator profile (display name, preferences) and inspect any user's activity statistics, completion rate, and token usage. Merges ProfileSettings.tsx and UserProfile.tsx.
|
|
4
|
+
type: domain-skill
|
|
5
|
+
default_mode: confirm
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Mastermind Profile
|
|
9
|
+
|
|
10
|
+
This skill is invoked by `mastermind:profile` or directly via `/mastermind:profile`.
|
|
11
|
+
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
## Inputs
|
|
15
|
+
|
|
16
|
+
- `brain_context`: BRAIN CONTEXT block (injected by command, or loaded below if standalone)
|
|
17
|
+
- `action`: show | edit | view-user | stats
|
|
18
|
+
- `user_id`: user id to view (for view-user/stats; defaults to current operator)
|
|
19
|
+
- `org_name`: org context for per-org stats (optional)
|
|
20
|
+
- `display_name`: new display name (for edit)
|
|
21
|
+
- `email`: new email (for edit)
|
|
22
|
+
- `theme`: light | dark | system (for edit)
|
|
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 — Load Profile File
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
profileFile=".monomind/operator-profile.json"
|
|
37
|
+
[ ! -f "$profileFile" ] && cat > "$profileFile" <<'EOF'
|
|
38
|
+
{
|
|
39
|
+
"id": "local-operator",
|
|
40
|
+
"displayName": "Operator",
|
|
41
|
+
"email": "",
|
|
42
|
+
"theme": "system",
|
|
43
|
+
"avatarInitials": "OP",
|
|
44
|
+
"keyboardShortcutsEnabled": true,
|
|
45
|
+
"createdAt": null
|
|
46
|
+
}
|
|
47
|
+
EOF
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
---
|
|
51
|
+
|
|
52
|
+
## Step 2 — Execute Action
|
|
53
|
+
|
|
54
|
+
### show (default)
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
echo "OPERATOR PROFILE"
|
|
58
|
+
echo "────────────────────────────────────────────────────────"
|
|
59
|
+
jq -r '
|
|
60
|
+
" ID: \(.id // "local-operator")",
|
|
61
|
+
" Display name: \(.displayName // "(not set)")",
|
|
62
|
+
" Email: \(.email // "(not set)")",
|
|
63
|
+
" Theme: \(.theme // "system")",
|
|
64
|
+
" Initials: \(.avatarInitials // "OP")",
|
|
65
|
+
" Shortcuts: \(.keyboardShortcutsEnabled // true)",
|
|
66
|
+
" Created: \(.createdAt // "(local)")"
|
|
67
|
+
' "$profileFile"
|
|
68
|
+
|
|
69
|
+
echo ""
|
|
70
|
+
echo " To edit: --action edit --display-name 'New Name'"
|
|
71
|
+
echo " To view stats: --action stats"
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
### edit
|
|
75
|
+
|
|
76
|
+
```bash
|
|
77
|
+
if [ -z "$display_name" ] && [ -z "$email" ] && [ -z "$theme" ]; then
|
|
78
|
+
echo "ERROR: Provide at least one of: --display-name, --email, --theme (light|dark|system)"
|
|
79
|
+
exit 1
|
|
80
|
+
fi
|
|
81
|
+
|
|
82
|
+
case "${theme:-}" in
|
|
83
|
+
light|dark|system|"") : ;;
|
|
84
|
+
*) echo "ERROR: --theme must be light, dark, or system"; exit 1 ;;
|
|
85
|
+
esac
|
|
86
|
+
|
|
87
|
+
tmp="${profileFile}.tmp"
|
|
88
|
+
jq \
|
|
89
|
+
--arg name "${display_name:-}" \
|
|
90
|
+
--arg email "${email:-}" \
|
|
91
|
+
--arg theme "${theme:-}" \
|
|
92
|
+
'(if $name != "" then .displayName = $name else . end) |
|
|
93
|
+
(if $email != "" then .email = $email else . end) |
|
|
94
|
+
(if $theme != "" then .theme = $theme else . end) |
|
|
95
|
+
(if $name != "" then .avatarInitials = ($name | split(" ") |
|
|
96
|
+
map(select(length > 0) | .[0:1] | ascii_upcase) | .[0:2] | join(""))
|
|
97
|
+
else . end)' \
|
|
98
|
+
"$profileFile" > "$tmp" && mv "$tmp" "$profileFile"
|
|
99
|
+
|
|
100
|
+
echo "Profile updated."
|
|
101
|
+
jq -r '" displayName: \(.displayName) email: \(.email) theme: \(.theme)"' "$profileFile"
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
### view-user
|
|
105
|
+
|
|
106
|
+
```bash
|
|
107
|
+
targetId="${user_id:-local-operator}"
|
|
108
|
+
echo "USER PROFILE — $targetId"
|
|
109
|
+
echo "────────────────────────────────────────────────────────"
|
|
110
|
+
|
|
111
|
+
# Try to find in instance access file
|
|
112
|
+
accessFile=".monomind/instance-access.json"
|
|
113
|
+
if [ -f "$accessFile" ]; then
|
|
114
|
+
userEntry=$(jq -r --arg id "$targetId" '.users[] | select(.id == $id)' "$accessFile")
|
|
115
|
+
if [ -n "$userEntry" ]; then
|
|
116
|
+
isAdmin=$(echo "$userEntry" | jq -r '.isInstanceAdmin // false')
|
|
117
|
+
orgs=$(echo "$userEntry" | jq -r '(.companyAccess // []) | join(", ")')
|
|
118
|
+
echo " ID: $targetId"
|
|
119
|
+
echo " Instance admin: $isAdmin"
|
|
120
|
+
echo " Org access: ${orgs:-(none)}"
|
|
121
|
+
else
|
|
122
|
+
echo " ID: $targetId"
|
|
123
|
+
echo " (User not found in instance access registry)"
|
|
124
|
+
fi
|
|
125
|
+
else
|
|
126
|
+
echo " ID: $targetId (no instance access file)"
|
|
127
|
+
fi
|
|
128
|
+
|
|
129
|
+
echo ""
|
|
130
|
+
echo " For activity stats: --action stats --user-id $targetId"
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
### stats
|
|
134
|
+
|
|
135
|
+
```bash
|
|
136
|
+
targetId="${user_id:-local-operator}"
|
|
137
|
+
echo "ACTIVITY STATS — $targetId"
|
|
138
|
+
echo "────────────────────────────────────────────────────────"
|
|
139
|
+
|
|
140
|
+
# Scan activity files for user contributions
|
|
141
|
+
totalRuns=0; successRuns=0; totalInputTokens=0; totalOutputTokens=0
|
|
142
|
+
|
|
143
|
+
for actFile in data/mastermind-sessions.json .monomind/orgs/*-activity.jsonl; do
|
|
144
|
+
[ -f "$actFile" ] || continue
|
|
145
|
+
if echo "$actFile" | grep -q "\.jsonl$"; then
|
|
146
|
+
cnt=$(grep -c "\"actorId\":\"${targetId}\"" "$actFile" 2>/dev/null || echo 0)
|
|
147
|
+
succ=$(grep "\"actorId\":\"${targetId}\"" "$actFile" 2>/dev/null | grep -c '"outcome":"success"' || echo 0)
|
|
148
|
+
totalRuns=$((totalRuns + cnt))
|
|
149
|
+
successRuns=$((successRuns + succ))
|
|
150
|
+
fi
|
|
151
|
+
done
|
|
152
|
+
|
|
153
|
+
# Per-org if org_name set
|
|
154
|
+
if [ -n "$org_name" ]; then
|
|
155
|
+
issuesFile=".monomind/orgs/${org_name}-issues.json"
|
|
156
|
+
if [ -f "$issuesFile" ]; then
|
|
157
|
+
assigned=$(jq --arg uid "$targetId" '[.issues[] | select(.assigneeId == $uid)] | length' "$issuesFile")
|
|
158
|
+
echo " Issues assigned (org $org_name): $assigned"
|
|
159
|
+
fi
|
|
160
|
+
fi
|
|
161
|
+
|
|
162
|
+
completionRate=0
|
|
163
|
+
[ "$totalRuns" -gt 0 ] && completionRate=$((successRuns * 100 / totalRuns))
|
|
164
|
+
|
|
165
|
+
echo " Total runs tracked: $totalRuns"
|
|
166
|
+
echo " Successful runs: $successRuns"
|
|
167
|
+
echo " Completion rate: ${completionRate}%"
|
|
168
|
+
echo ""
|
|
169
|
+
echo " (Token usage stats require agent run logs with token tracking enabled)"
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
---
|
|
173
|
+
|
|
174
|
+
## Step 3 — Return Output
|
|
175
|
+
|
|
176
|
+
```yaml
|
|
177
|
+
domain: ops
|
|
178
|
+
status: complete
|
|
179
|
+
action: <action>
|
|
180
|
+
user_id: <user_id or local-operator>
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
---
|
|
184
|
+
|
|
185
|
+
## Step 4 — Brain Write (standalone only)
|
|
186
|
+
|
|
187
|
+
If `caller` is not "command", follow _protocol.md Brain Write Procedure for domain `ops`.
|
|
@@ -0,0 +1,249 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: mastermind-project-detail
|
|
3
|
+
description: Mastermind project-detail — deep per-project inspection and management. Tabs mirror Paperclip's ProjectDetail page: overview (metrics/issues), configuration (color/visibility/description), budget policy, workspaces, and linked issues list.
|
|
4
|
+
type: domain-skill
|
|
5
|
+
default_mode: auto
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Mastermind Project Detail
|
|
9
|
+
|
|
10
|
+
This skill is invoked by `mastermind:project-detail` or directly via `/mastermind:project-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 project belongs to (required)
|
|
18
|
+
- `project_id`: project id/slug (required)
|
|
19
|
+
- `action`: show | overview | issues | config | budget | workspaces
|
|
20
|
+
- `field`: config field to edit (name|description|color|visibility)
|
|
21
|
+
- `value`: new field value (for config --field)
|
|
22
|
+
- `budget_policy`: none | soft_limit | hard_limit (for budget action)
|
|
23
|
+
- `budget_limit`: token limit (integer, required if policy != none)
|
|
24
|
+
- `budget_period`: daily | weekly | monthly (default: daily)
|
|
25
|
+
- `caller`: command | master
|
|
26
|
+
|
|
27
|
+
---
|
|
28
|
+
|
|
29
|
+
## Project Colors
|
|
30
|
+
|
|
31
|
+
`red` | `orange` | `yellow` | `green` | `teal` | `blue` | `purple` | `pink` | `gray`
|
|
32
|
+
|
|
33
|
+
## Visibility
|
|
34
|
+
|
|
35
|
+
`private` — visible only to org members with access
|
|
36
|
+
`internal` — visible to all org members
|
|
37
|
+
`public` — visible to anyone with the link
|
|
38
|
+
|
|
39
|
+
---
|
|
40
|
+
|
|
41
|
+
## Step 0 — Brain Load (standalone only)
|
|
42
|
+
|
|
43
|
+
If `caller` is not "command", load brain context following _protocol.md Brain Load Procedure with namespace: `ops`.
|
|
44
|
+
|
|
45
|
+
---
|
|
46
|
+
|
|
47
|
+
## Step 1 — Load Project Data
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
orgFile=".monomind/orgs/${org_name}.json"
|
|
51
|
+
[ ! -f "$orgFile" ] && { echo "ERROR: Org '${org_name}' not found."; exit 1; }
|
|
52
|
+
|
|
53
|
+
projectsFile=".monomind/orgs/${org_name}-projects.json"
|
|
54
|
+
[ ! -f "$projectsFile" ] && { echo "ERROR: No projects file for org '$org_name'. Create via /mastermind:projects."; exit 1; }
|
|
55
|
+
|
|
56
|
+
projectDef=$(jq -r --arg id "$project_id" '.projects[] | select(.id == $id or .slug == $id)' "$projectsFile")
|
|
57
|
+
[ -z "$projectDef" ] && { echo "ERROR: Project '$project_id' not found in org '$org_name'."; exit 1; }
|
|
58
|
+
|
|
59
|
+
resolvedId=$(echo "$projectDef" | jq -r '.id')
|
|
60
|
+
issuesFile=".monomind/orgs/${org_name}-issues.json"
|
|
61
|
+
wsFile=".monomind/orgs/${org_name}-workspaces.json"
|
|
62
|
+
budgetFile=".monomind/orgs/${org_name}-budgets.json"
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
---
|
|
66
|
+
|
|
67
|
+
## Step 2 — Execute Action
|
|
68
|
+
|
|
69
|
+
### show (default) — same as overview
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
echo "PROJECT — $project_id @ $org_name"
|
|
73
|
+
echo "────────────────────────────────────────────────────────"
|
|
74
|
+
|
|
75
|
+
echo "$projectDef" | jq -r '
|
|
76
|
+
" ID: \(.id)",
|
|
77
|
+
" Name: \(.name // "(unnamed)")",
|
|
78
|
+
" Status: \(.status // "active")",
|
|
79
|
+
" Color: \(.color // "gray")",
|
|
80
|
+
" Visibility: \(.visibility // "internal")",
|
|
81
|
+
" Description: \(.description // "(none)")",
|
|
82
|
+
" Created: \(.created_at // "-")"
|
|
83
|
+
'
|
|
84
|
+
|
|
85
|
+
# Issues summary
|
|
86
|
+
if [ -f "$issuesFile" ]; then
|
|
87
|
+
totalIssues=$(jq --arg pid "$resolvedId" '[.issues[] | select(.project_id == $pid)] | length' "$issuesFile")
|
|
88
|
+
openIssues=$(jq --arg pid "$resolvedId" '[.issues[] | select(.project_id == $pid and .status == "open")] | length' "$issuesFile")
|
|
89
|
+
inProgIssues=$(jq --arg pid "$resolvedId" '[.issues[] | select(.project_id == $pid and .status == "in_progress")] | length' "$issuesFile")
|
|
90
|
+
doneIssues=$(jq --arg pid "$resolvedId" '[.issues[] | select(.project_id == $pid and .status == "done")] | length' "$issuesFile")
|
|
91
|
+
echo ""
|
|
92
|
+
echo "ISSUES"
|
|
93
|
+
echo " Total: $totalIssues"
|
|
94
|
+
echo " Open: $openIssues"
|
|
95
|
+
echo " In progress: $inProgIssues"
|
|
96
|
+
echo " Done: $doneIssues"
|
|
97
|
+
fi
|
|
98
|
+
|
|
99
|
+
# Workspaces summary
|
|
100
|
+
if [ -f "$wsFile" ]; then
|
|
101
|
+
wsCount=$(jq --arg pid "$resolvedId" '[.workspaces[] | select(.project_id == $pid)] | length' "$wsFile")
|
|
102
|
+
activeWs=$(jq --arg pid "$resolvedId" '[.workspaces[] | select(.project_id == $pid and .status == "active")] | length' "$wsFile")
|
|
103
|
+
echo ""
|
|
104
|
+
echo "WORKSPACES"
|
|
105
|
+
echo " Total: $wsCount | Active: $activeWs"
|
|
106
|
+
fi
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
### overview
|
|
110
|
+
|
|
111
|
+
Alias for `show` — print the overview section above.
|
|
112
|
+
|
|
113
|
+
### issues
|
|
114
|
+
|
|
115
|
+
```bash
|
|
116
|
+
echo "ISSUES — project: $project_id"
|
|
117
|
+
echo "────────────────────────────────────────────────────────"
|
|
118
|
+
printf "%-24s %-12s %-10s %s\n" "ID" "STATUS" "PRIORITY" "TITLE"
|
|
119
|
+
echo "────────────────────────────────────────────────────────"
|
|
120
|
+
|
|
121
|
+
if [ ! -f "$issuesFile" ]; then
|
|
122
|
+
echo " No issues file found."
|
|
123
|
+
else
|
|
124
|
+
count=0
|
|
125
|
+
jq -r --arg pid "$resolvedId" '.issues[] | select(.project_id == $pid) |
|
|
126
|
+
[.id, (.status // "open"), (.priority // "medium"), (.title // "(no title)")] | @tsv' \
|
|
127
|
+
"$issuesFile" | while IFS=$'\t' read -r id st pri title; do
|
|
128
|
+
printf "%-24s %-12s %-10s %s\n" "$id" "$st" "$pri" "$title"
|
|
129
|
+
count=$((count + 1))
|
|
130
|
+
done
|
|
131
|
+
fi
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
### config
|
|
135
|
+
|
|
136
|
+
```bash
|
|
137
|
+
echo "PROJECT CONFIG — $project_id"
|
|
138
|
+
echo "────────────────────────────────────────────────────────"
|
|
139
|
+
|
|
140
|
+
if [ -n "$field" ]; then
|
|
141
|
+
[ -z "$value" ] && { echo "ERROR: --value required when --field is set."; exit 1; }
|
|
142
|
+
validFields="name description color visibility status"
|
|
143
|
+
echo "$validFields" | tr ' ' '\n' | grep -qx "$field" || {
|
|
144
|
+
echo "ERROR: Unknown field '$field'. Valid: $validFields"; exit 1
|
|
145
|
+
}
|
|
146
|
+
if [ "$field" = "color" ]; then
|
|
147
|
+
case "$value" in red|orange|yellow|green|teal|blue|purple|pink|gray) : ;; *)
|
|
148
|
+
echo "ERROR: color must be one of: red orange yellow green teal blue purple pink gray"; exit 1 ;;
|
|
149
|
+
esac
|
|
150
|
+
fi
|
|
151
|
+
if [ "$field" = "visibility" ]; then
|
|
152
|
+
case "$value" in private|internal|public) : ;; *)
|
|
153
|
+
echo "ERROR: visibility must be one of: private, internal, public"; exit 1 ;;
|
|
154
|
+
esac
|
|
155
|
+
fi
|
|
156
|
+
ts=$(date -u +%Y-%m-%dT%H:%M:%SZ)
|
|
157
|
+
tmp="${projectsFile}.tmp"
|
|
158
|
+
jq --arg id "$resolvedId" --arg f "$field" --arg v "$value" --arg ts "$ts" \
|
|
159
|
+
'.projects = [.projects[] | if .id == $id then .[$f] = $v | .updated_at = $ts else . end]' \
|
|
160
|
+
"$projectsFile" > "$tmp" && mv "$tmp" "$projectsFile"
|
|
161
|
+
echo "Updated: $field = $value"
|
|
162
|
+
else
|
|
163
|
+
echo "$projectDef" | jq '{name, description, color, visibility, status}'
|
|
164
|
+
fi
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
### budget
|
|
168
|
+
|
|
169
|
+
```bash
|
|
170
|
+
echo "BUDGET POLICY — $project_id"
|
|
171
|
+
echo "────────────────────────────────────────────────────────"
|
|
172
|
+
|
|
173
|
+
[ ! -f "$budgetFile" ] && echo '{"budgets":[]}' > "$budgetFile"
|
|
174
|
+
|
|
175
|
+
existing=$(jq -r --arg pid "$resolvedId" '.budgets[] | select(.project_id == $pid)' "$budgetFile")
|
|
176
|
+
if [ -z "$existing" ]; then
|
|
177
|
+
echo " No budget policy set."
|
|
178
|
+
else
|
|
179
|
+
echo "$existing" | jq -r '
|
|
180
|
+
" Policy: \(.policy // "none")",
|
|
181
|
+
" Limit: \(.limit_tokens // "unlimited") tokens",
|
|
182
|
+
" Period: \(.period // "daily")"
|
|
183
|
+
'
|
|
184
|
+
fi
|
|
185
|
+
|
|
186
|
+
if [ -n "$budget_policy" ]; then
|
|
187
|
+
case "$budget_policy" in none|soft_limit|hard_limit) : ;; *)
|
|
188
|
+
echo "ERROR: --budget-policy must be none, soft_limit, or hard_limit"; exit 1 ;;
|
|
189
|
+
esac
|
|
190
|
+
[ "$budget_policy" != "none" ] && [ -z "$budget_limit" ] && {
|
|
191
|
+
echo "ERROR: --budget-limit required for '$budget_policy' policy."; exit 1
|
|
192
|
+
}
|
|
193
|
+
ts=$(date -u +%Y-%m-%dT%H:%M:%SZ)
|
|
194
|
+
tmp="${budgetFile}.tmp"
|
|
195
|
+
jq --arg pid "$resolvedId" \
|
|
196
|
+
--arg policy "$budget_policy" \
|
|
197
|
+
--argjson limit "${budget_limit:-0}" \
|
|
198
|
+
--arg period "${budget_period:-daily}" \
|
|
199
|
+
--arg ts "$ts" \
|
|
200
|
+
'.budgets = [.budgets[] | select(.project_id != $pid)] +
|
|
201
|
+
[{"project_id":$pid,"policy":$policy,
|
|
202
|
+
"limit_tokens":(if $policy != "none" then $limit else null end),
|
|
203
|
+
"period":$period,"updatedAt":$ts}]' \
|
|
204
|
+
"$budgetFile" > "$tmp" && mv "$tmp" "$budgetFile"
|
|
205
|
+
echo ""
|
|
206
|
+
echo "Budget policy updated: $budget_policy"
|
|
207
|
+
[ "$budget_policy" != "none" ] && echo " Limit: $budget_limit tokens / ${budget_period:-daily}"
|
|
208
|
+
fi
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
### workspaces
|
|
212
|
+
|
|
213
|
+
```bash
|
|
214
|
+
echo "WORKSPACES — project: $project_id"
|
|
215
|
+
echo "────────────────────────────────────────────────────────"
|
|
216
|
+
|
|
217
|
+
if [ ! -f "$wsFile" ]; then
|
|
218
|
+
echo " No workspaces file."
|
|
219
|
+
else
|
|
220
|
+
printf "%-20s %-12s %-18s %-8s %s\n" "ID" "STATUS" "AGENT" "BRANCH" "PATH"
|
|
221
|
+
echo "────────────────────────────────────────────────────────"
|
|
222
|
+
count=0
|
|
223
|
+
jq -r --arg pid "$resolvedId" '.workspaces[] | select(.project_id == $pid) |
|
|
224
|
+
[.id, (.status // "unknown"), (.agent_id // "(none)"), (.branch // "?"), (.worktree_path // "-")] | @tsv' \
|
|
225
|
+
"$wsFile" | while IFS=$'\t' read -r id st ag br path; do
|
|
226
|
+
printf "%-20s %-12s %-18s %-8s %s\n" "$id" "$st" "$ag" "$br" "$path"
|
|
227
|
+
count=$((count + 1))
|
|
228
|
+
done
|
|
229
|
+
fi
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
---
|
|
233
|
+
|
|
234
|
+
## Step 3 — Return Output
|
|
235
|
+
|
|
236
|
+
```yaml
|
|
237
|
+
domain: ops
|
|
238
|
+
status: complete
|
|
239
|
+
action: <action>
|
|
240
|
+
org: <org_name>
|
|
241
|
+
project_id: <project_id>
|
|
242
|
+
project_status: <status>
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
---
|
|
246
|
+
|
|
247
|
+
## Step 4 — Brain Write (standalone only)
|
|
248
|
+
|
|
249
|
+
If `caller` is not "command", follow _protocol.md Brain Write Procedure for domain `ops`.
|