@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,244 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: mastermind-project-workspace
|
|
3
|
+
description: Mastermind project-workspace — configure a project-level workspace (not an execution workspace). Manages source type, visibility, repo URL/ref, branch, cwd, setup/cleanup commands, remote provider, remote workspace ref, runtime config JSON, and shared workspace key. Mirrors ProjectWorkspaceDetail.tsx.
|
|
4
|
+
type: domain-skill
|
|
5
|
+
default_mode: confirm
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Mastermind Project Workspace
|
|
9
|
+
|
|
10
|
+
This skill is invoked by `mastermind:project-workspace` or directly via `/mastermind:project-workspace`.
|
|
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 (required)
|
|
19
|
+
- `workspace_id`: workspace id within the project (required)
|
|
20
|
+
- `action`: show | config | runtime | provision | teardown
|
|
21
|
+
- `name`: display name for workspace (for config)
|
|
22
|
+
- `source_type`: local_path | non_git_path | git_repo | remote_managed (for config)
|
|
23
|
+
- `visibility`: default | advanced (for config)
|
|
24
|
+
- `cwd`: absolute local path (for config; required if source_type is local_path/non_git_path)
|
|
25
|
+
- `repo_url`: remote repository URL (for config)
|
|
26
|
+
- `repo_ref`: git ref/commit (for config)
|
|
27
|
+
- `default_ref`: default branch name (for config)
|
|
28
|
+
- `setup_command`: command to run after workspace creation (for config)
|
|
29
|
+
- `cleanup_command`: command to run before workspace teardown (for config)
|
|
30
|
+
- `remote_provider`: remote provider identifier (for config; use with remote_managed)
|
|
31
|
+
- `remote_workspace_ref`: remote workspace reference ID (for config; use with remote_managed)
|
|
32
|
+
- `shared_workspace_key`: key to share this workspace across agents (for config)
|
|
33
|
+
- `runtime_config`: JSON string with workspaceRuntime config overrides (for runtime)
|
|
34
|
+
- `caller`: command | master
|
|
35
|
+
|
|
36
|
+
---
|
|
37
|
+
|
|
38
|
+
## Source Types
|
|
39
|
+
|
|
40
|
+
| Type | Label | Required fields |
|
|
41
|
+
|------|-------|----------------|
|
|
42
|
+
| `local_path` | Local git checkout | `cwd` (absolute path) |
|
|
43
|
+
| `non_git_path` | Local non-git path | `cwd` (absolute path) |
|
|
44
|
+
| `git_repo` | Remote git repo | `repo_url` |
|
|
45
|
+
| `remote_managed` | Remote-managed workspace | `remote_workspace_ref` or `repo_url` |
|
|
46
|
+
|
|
47
|
+
## Visibility
|
|
48
|
+
|
|
49
|
+
| Value | Description |
|
|
50
|
+
|-------|-------------|
|
|
51
|
+
| `default` | Shown to all agents in the project |
|
|
52
|
+
| `advanced` | Hidden by default; shown only when explicitly selected |
|
|
53
|
+
|
|
54
|
+
---
|
|
55
|
+
|
|
56
|
+
## Step 0 — Brain Load (standalone only)
|
|
57
|
+
|
|
58
|
+
If `caller` is not "command", load brain context following _protocol.md Brain Load Procedure with namespace: `ops`.
|
|
59
|
+
|
|
60
|
+
---
|
|
61
|
+
|
|
62
|
+
## Step 1 — Load Workspace
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
orgFile=".monomind/orgs/${org_name}.json"
|
|
66
|
+
[ ! -f "$orgFile" ] && { echo "ERROR: Org '${org_name}' not found."; exit 1; }
|
|
67
|
+
|
|
68
|
+
projectsFile=".monomind/orgs/${org_name}-projects.json"
|
|
69
|
+
[ ! -f "$projectsFile" ] && { echo "ERROR: No projects file for org '${org_name}'."; exit 1; }
|
|
70
|
+
|
|
71
|
+
# Find project
|
|
72
|
+
projDef=$(jq -r --arg pid "$project_id" '.projects[] | select(.id == $pid or .name == $pid)' "$projectsFile")
|
|
73
|
+
[ -z "$projDef" ] && { echo "ERROR: Project '$project_id' not found."; exit 1; }
|
|
74
|
+
|
|
75
|
+
# Load project workspaces file
|
|
76
|
+
pwsFile=".monomind/orgs/${org_name}-project-workspaces.json"
|
|
77
|
+
[ ! -f "$pwsFile" ] && echo '{"workspaces":[]}' > "$pwsFile"
|
|
78
|
+
|
|
79
|
+
wsDef=$(jq -r --arg wid "$workspace_id" --arg pid "$project_id" \
|
|
80
|
+
'.workspaces[] | select(.id == $wid and (.project_id == $pid or .projectId == $pid))' \
|
|
81
|
+
"$pwsFile")
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
---
|
|
85
|
+
|
|
86
|
+
## Step 2 — Execute Action
|
|
87
|
+
|
|
88
|
+
### show (default)
|
|
89
|
+
|
|
90
|
+
```bash
|
|
91
|
+
echo "PROJECT WORKSPACE — $workspace_id @ $project_id ($org_name)"
|
|
92
|
+
echo "────────────────────────────────────────────────────────"
|
|
93
|
+
|
|
94
|
+
if [ -z "$wsDef" ]; then
|
|
95
|
+
echo " Workspace '$workspace_id' not found in project '$project_id'."
|
|
96
|
+
echo " List workspaces: /mastermind:workspaces --org $org_name"
|
|
97
|
+
exit 0
|
|
98
|
+
fi
|
|
99
|
+
|
|
100
|
+
echo "$wsDef" | jq -r '
|
|
101
|
+
" ID: \(.id)",
|
|
102
|
+
" Name: \(.name // "(unnamed)")",
|
|
103
|
+
" Source type: \(.sourceType // .source_type // "local_path")",
|
|
104
|
+
" Visibility: \(.visibility // "default")",
|
|
105
|
+
" CWD: \(.cwd // "(none)")",
|
|
106
|
+
" Repo URL: \(.repoUrl // .repo_url // "(none)")",
|
|
107
|
+
" Repo ref: \(.repoRef // .repo_ref // "(default)")",
|
|
108
|
+
" Default ref: \(.defaultRef // .default_ref // "(default branch)")",
|
|
109
|
+
" Setup command: \(.setupCommand // .setup_command // "(none)")",
|
|
110
|
+
" Cleanup command: \(.cleanupCommand // .cleanup_command // "(none)")",
|
|
111
|
+
" Remote provider: \(.remoteProvider // .remote_provider // "(none)")",
|
|
112
|
+
" Remote ws ref: \(.remoteWorkspaceRef // .remote_workspace_ref // "(none)")",
|
|
113
|
+
" Shared key: \(.sharedWorkspaceKey // .shared_workspace_key // "(none)")"
|
|
114
|
+
'
|
|
115
|
+
|
|
116
|
+
rtConfig=$(echo "$wsDef" | jq -r '.runtimeConfig.workspaceRuntime // null')
|
|
117
|
+
echo ""
|
|
118
|
+
echo "RUNTIME CONFIG: $([ "$rtConfig" = "null" ] && echo '(none)' || echo "$rtConfig" | jq -c .)"
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
### config
|
|
122
|
+
|
|
123
|
+
```bash
|
|
124
|
+
if [ -z "$wsDef" ]; then
|
|
125
|
+
echo "ERROR: Workspace '$workspace_id' not found."
|
|
126
|
+
exit 1
|
|
127
|
+
fi
|
|
128
|
+
|
|
129
|
+
ts=$(date -u +%Y-%m-%dT%H:%M:%SZ)
|
|
130
|
+
tmp="${pwsFile}.tmp"
|
|
131
|
+
jq \
|
|
132
|
+
--arg wid "$workspace_id" \
|
|
133
|
+
--arg pid "$project_id" \
|
|
134
|
+
--arg name "${name:-}" \
|
|
135
|
+
--arg st "${source_type:-}" \
|
|
136
|
+
--arg vis "${visibility:-}" \
|
|
137
|
+
--arg cwd_ "${cwd:-}" \
|
|
138
|
+
--arg repoUrl "${repo_url:-}" \
|
|
139
|
+
--arg repoRef "${repo_ref:-}" \
|
|
140
|
+
--arg defaultRef "${default_ref:-}" \
|
|
141
|
+
--arg setupCmd "${setup_command:-}" \
|
|
142
|
+
--arg cleanupCmd "${cleanup_command:-}" \
|
|
143
|
+
--arg remoteProvider "${remote_provider:-}" \
|
|
144
|
+
--arg remoteRef "${remote_workspace_ref:-}" \
|
|
145
|
+
--arg sharedKey "${shared_workspace_key:-}" \
|
|
146
|
+
--arg ts "$ts" \
|
|
147
|
+
'.workspaces = [.workspaces[] | if (.id == $wid and (.project_id == $pid or .projectId == $pid)) then
|
|
148
|
+
(if $name != "" then .name = $name else . end) |
|
|
149
|
+
(if $st != "" then .sourceType = $st else . end) |
|
|
150
|
+
(if $vis != "" then .visibility = $vis else . end) |
|
|
151
|
+
(if $cwd_ != "" then .cwd = $cwd_ else . end) |
|
|
152
|
+
(if $repoUrl != "" then .repoUrl = $repoUrl else . end) |
|
|
153
|
+
(if $repoRef != "" then .repoRef = $repoRef else . end) |
|
|
154
|
+
(if $defaultRef != "" then .defaultRef = $defaultRef else . end) |
|
|
155
|
+
(if $setupCmd != "" then .setupCommand = $setupCmd else . end) |
|
|
156
|
+
(if $cleanupCmd != "" then .cleanupCommand = $cleanupCmd else . end) |
|
|
157
|
+
(if $remoteProvider != "" then .remoteProvider = $remoteProvider else . end) |
|
|
158
|
+
(if $remoteRef != "" then .remoteWorkspaceRef = $remoteRef else . end) |
|
|
159
|
+
(if $sharedKey != "" then .sharedWorkspaceKey = $sharedKey else . end) |
|
|
160
|
+
.updatedAt = $ts
|
|
161
|
+
else . end]' \
|
|
162
|
+
"$pwsFile" > "$tmp" && mv "$tmp" "$pwsFile"
|
|
163
|
+
|
|
164
|
+
echo "Project workspace '$workspace_id' config updated."
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
### runtime
|
|
168
|
+
|
|
169
|
+
```bash
|
|
170
|
+
[ -z "$runtime_config" ] && { echo "ERROR: --runtime-config (JSON string) required."; exit 1; }
|
|
171
|
+
|
|
172
|
+
# Validate JSON
|
|
173
|
+
parsed=$(echo "$runtime_config" | python3 -c "import json,sys; d=json.load(sys.stdin); print(json.dumps(d))" 2>&1) || {
|
|
174
|
+
echo "ERROR: --runtime-config must be valid JSON: $parsed"
|
|
175
|
+
exit 1
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
ts=$(date -u +%Y-%m-%dT%H:%M:%SZ)
|
|
179
|
+
tmp="${pwsFile}.tmp"
|
|
180
|
+
jq --arg wid "$workspace_id" --arg pid "$project_id" --argjson rt "$parsed" --arg ts "$ts" \
|
|
181
|
+
'.workspaces = [.workspaces[] | if (.id == $wid and (.project_id == $pid or .projectId == $pid)) then
|
|
182
|
+
.runtimeConfig = {"workspaceRuntime": $rt} | .updatedAt = $ts
|
|
183
|
+
else . end]' \
|
|
184
|
+
"$pwsFile" > "$tmp" && mv "$tmp" "$pwsFile"
|
|
185
|
+
|
|
186
|
+
echo "Runtime config updated for workspace '$workspace_id'."
|
|
187
|
+
echo " Keys: $(echo "$parsed" | python3 -c "import json,sys; d=json.load(sys.stdin); print(', '.join(d.keys()))")"
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
### provision
|
|
191
|
+
|
|
192
|
+
```bash
|
|
193
|
+
setupCmd=$(echo "$wsDef" | jq -r '.setupCommand // .setup_command // ""')
|
|
194
|
+
wsPath=$(echo "$wsDef" | jq -r '.cwd // ""')
|
|
195
|
+
|
|
196
|
+
echo "PROVISION — $workspace_id"
|
|
197
|
+
echo "────────────────────────────────────────────────────────"
|
|
198
|
+
if [ -z "$setupCmd" ]; then
|
|
199
|
+
echo " No setup command configured."
|
|
200
|
+
echo " Set one: --action config --setup-command 'npm install'"
|
|
201
|
+
else
|
|
202
|
+
echo " Command: $setupCmd"
|
|
203
|
+
echo " CWD: ${wsPath:-(none)}"
|
|
204
|
+
if [ -d "$wsPath" ] && [ -n "$setupCmd" ]; then
|
|
205
|
+
echo " Executing…"
|
|
206
|
+
(cd "$wsPath" && eval "$setupCmd") && echo " Provision complete." || echo " Provision command exited with error."
|
|
207
|
+
fi
|
|
208
|
+
fi
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
### teardown
|
|
212
|
+
|
|
213
|
+
```bash
|
|
214
|
+
cleanupCmd=$(echo "$wsDef" | jq -r '.cleanupCommand // .cleanup_command // ""')
|
|
215
|
+
wsPath=$(echo "$wsDef" | jq -r '.cwd // ""')
|
|
216
|
+
|
|
217
|
+
echo "TEARDOWN — $workspace_id"
|
|
218
|
+
echo "────────────────────────────────────────────────────────"
|
|
219
|
+
if [ -z "$cleanupCmd" ]; then
|
|
220
|
+
echo " No cleanup command configured."
|
|
221
|
+
else
|
|
222
|
+
echo " Command: $cleanupCmd"
|
|
223
|
+
[ -d "$wsPath" ] && (cd "$wsPath" && eval "$cleanupCmd") && echo " Teardown complete." || echo " No path or teardown error."
|
|
224
|
+
fi
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
---
|
|
228
|
+
|
|
229
|
+
## Step 3 — Return Output
|
|
230
|
+
|
|
231
|
+
```yaml
|
|
232
|
+
domain: ops
|
|
233
|
+
status: complete
|
|
234
|
+
action: <action>
|
|
235
|
+
org: <org_name>
|
|
236
|
+
project_id: <project_id>
|
|
237
|
+
workspace_id: <workspace_id>
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
---
|
|
241
|
+
|
|
242
|
+
## Step 4 — Brain Write (standalone only)
|
|
243
|
+
|
|
244
|
+
If `caller` is not "command", follow _protocol.md Brain Write Procedure for domain `ops`.
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: mastermind-projects
|
|
3
|
+
description: Mastermind projects — create and manage scoped project workspaces within an org. Group tasks under named projects, assign agents to projects, and track project-level status.
|
|
4
|
+
type: domain-skill
|
|
5
|
+
default_mode: confirm
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Mastermind Projects
|
|
9
|
+
|
|
10
|
+
This skill is invoked by `mastermind:projects` or directly via `/mastermind:projects`.
|
|
11
|
+
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
## Inputs
|
|
15
|
+
|
|
16
|
+
- `brain_context`: BRAIN CONTEXT block
|
|
17
|
+
- `org_name`: org to manage projects for
|
|
18
|
+
- `action`: list | add | archive | assign | status
|
|
19
|
+
- `project_name`: display name (for add)
|
|
20
|
+
- `project_id`: slug (for archive/assign/status)
|
|
21
|
+
- `agent_id`: role id to assign as project lead
|
|
22
|
+
- `description`: project description
|
|
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 Projects State
|
|
34
|
+
|
|
35
|
+
Projects are stored in `.monomind/orgs/<org_name>-projects.json`:
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
projectsFile=".monomind/orgs/${org_name}-projects.json"
|
|
39
|
+
[ ! -f "$projectsFile" ] && echo '{"projects":[]}' > "$projectsFile"
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
---
|
|
43
|
+
|
|
44
|
+
## Step 2 — Execute Action
|
|
45
|
+
|
|
46
|
+
### list (default)
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
jq -r '
|
|
50
|
+
.projects[] |
|
|
51
|
+
"[\(.id)] \(.name) lead=\(.lead_agent // "unassigned") status=\(.status // "active") tasks=\(.task_count // 0)\n \(.description // "")"
|
|
52
|
+
' "$projectsFile" 2>/dev/null || echo "No projects yet."
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
Render as:
|
|
56
|
+
```
|
|
57
|
+
PROJECTS — org: <org_name>
|
|
58
|
+
──────────────────────────────────────────────────────
|
|
59
|
+
[homepage-redesign] Homepage Redesign
|
|
60
|
+
Lead: content-writer | Status: active | Tasks: 7
|
|
61
|
+
A full redesign of the company homepage with new copy and visuals.
|
|
62
|
+
|
|
63
|
+
[q2-seo-push] Q2 SEO Push
|
|
64
|
+
Lead: seo-specialist | Status: active | Tasks: 12
|
|
65
|
+
Target 10 high-volume keywords for Q2.
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
### add
|
|
69
|
+
|
|
70
|
+
```bash
|
|
71
|
+
project_id=$(echo "$project_name" | tr '[:upper:]' '[:lower:]' | sed 's/[^a-z0-9]/-/g' | tr -s '-')
|
|
72
|
+
tmp="${projectsFile}.tmp"
|
|
73
|
+
jq --arg id "$project_id" \
|
|
74
|
+
--arg name "$project_name" \
|
|
75
|
+
--arg desc "${description:-}" \
|
|
76
|
+
--arg lead "${agent_id:-}" \
|
|
77
|
+
'.projects += [{"id":$id,"name":$name,"description":$desc,"lead_agent":($lead|if .=="" then null else . end),
|
|
78
|
+
"status":"active","task_count":0,"created_at":(now|todate)}]' \
|
|
79
|
+
"$projectsFile" > "$tmp" && mv "$tmp" "$projectsFile"
|
|
80
|
+
echo "Project created: $project_id"
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
Emit `org:project:created` event to dashboard.
|
|
84
|
+
|
|
85
|
+
### assign
|
|
86
|
+
|
|
87
|
+
Set the lead agent for a project:
|
|
88
|
+
|
|
89
|
+
```bash
|
|
90
|
+
tmp="${projectsFile}.tmp"
|
|
91
|
+
jq --arg id "$project_id" --arg agent "$agent_id" \
|
|
92
|
+
'.projects = [.projects[] | if .id == $id then .lead_agent = $agent | .updated_at = (now|todate) else . end]' \
|
|
93
|
+
"$projectsFile" > "$tmp" && mv "$tmp" "$projectsFile"
|
|
94
|
+
echo "Assigned $agent_id as lead for project $project_id"
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
### archive
|
|
98
|
+
|
|
99
|
+
```bash
|
|
100
|
+
tmp="${projectsFile}.tmp"
|
|
101
|
+
jq --arg id "$project_id" \
|
|
102
|
+
'.projects = [.projects[] | if .id == $id then .status = "archived" | .archived_at = (now|todate) else . end]' \
|
|
103
|
+
"$projectsFile" > "$tmp" && mv "$tmp" "$projectsFile"
|
|
104
|
+
echo "Project $project_id archived."
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
### status
|
|
108
|
+
|
|
109
|
+
Show project summary with linked tasks from the board:
|
|
110
|
+
|
|
111
|
+
```bash
|
|
112
|
+
project=$(jq --arg id "$project_id" '.projects[] | select(.id == $id)' "$projectsFile")
|
|
113
|
+
echo "$project" | jq .
|
|
114
|
+
|
|
115
|
+
# If board exists, count tasks tagged with this project
|
|
116
|
+
orgFile=".monomind/orgs/${org_name}.json"
|
|
117
|
+
board_id=$(jq -r '.board_id // empty' "$orgFile")
|
|
118
|
+
if [ -n "$board_id" ]; then
|
|
119
|
+
todo_col=$(jq -r '.todo_col_id // empty' "$orgFile")
|
|
120
|
+
doing_col=$(jq -r '.doing_col_id // empty' "$orgFile")
|
|
121
|
+
done_col=$(jq -r '.done_col_id // empty' "$orgFile")
|
|
122
|
+
echo "Tasks on board tagged project:$project_id:"
|
|
123
|
+
for col in "$todo_col" "$doing_col" "$done_col"; do
|
|
124
|
+
monotask card list $board_id --col $col --json 2>/dev/null | \
|
|
125
|
+
jq -r --arg p "project:$project_id" '[.[] | select((.labels // []) | index($p))] | length' 2>/dev/null
|
|
126
|
+
done
|
|
127
|
+
fi
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
---
|
|
131
|
+
|
|
132
|
+
## Using Projects in Task Management
|
|
133
|
+
|
|
134
|
+
When creating tasks with `/mastermind:tasks`, tag them to a project:
|
|
135
|
+
|
|
136
|
+
```bash
|
|
137
|
+
monotask card label add $board_id $CARD_ID "project:<project_id>"
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
When running org agents, include the project context in task prompts:
|
|
141
|
+
|
|
142
|
+
```
|
|
143
|
+
This task belongs to project "<project_name>": <description>
|
|
144
|
+
Report your output tagged with project_id: <project_id>
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
---
|
|
148
|
+
|
|
149
|
+
## Step 3 — Return Output
|
|
150
|
+
|
|
151
|
+
```yaml
|
|
152
|
+
domain: ops
|
|
153
|
+
status: complete
|
|
154
|
+
action: <action>
|
|
155
|
+
org: <org_name>
|
|
156
|
+
project_id: <project_id if applicable>
|
|
157
|
+
projects_file: .monomind/orgs/<org_name>-projects.json
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
---
|
|
161
|
+
|
|
162
|
+
## Step 4 — Brain Write (standalone only)
|
|
163
|
+
|
|
164
|
+
If `caller` is not "command", follow _protocol.md Brain Write Procedure for domain `ops`.
|
|
@@ -0,0 +1,253 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: mastermind-routine-detail
|
|
3
|
+
description: Mastermind routine-detail — deep inspection and management of a single routine: trigger config (schedule/webhook), variables, concurrency/catchup policies, run history, webhook rotation, and revision tracking.
|
|
4
|
+
type: domain-skill
|
|
5
|
+
default_mode: auto
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Mastermind Routine Detail
|
|
9
|
+
|
|
10
|
+
This skill is invoked by `mastermind:routine-detail` or directly via `/mastermind:routine-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 routine belongs to (required)
|
|
18
|
+
- `routine_id`: routine id/slug (required)
|
|
19
|
+
- `action`: show | runs | config | variables | rotate-webhook | revisions
|
|
20
|
+
- `days`: lookback window for run history (default 14)
|
|
21
|
+
- `var_key`: variable key (for variables --set)
|
|
22
|
+
- `var_value`: variable value
|
|
23
|
+
- `caller`: command | master
|
|
24
|
+
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
## Trigger Types
|
|
28
|
+
|
|
29
|
+
| Kind | Description |
|
|
30
|
+
|------|-------------|
|
|
31
|
+
| `schedule` | Cron expression — agent fires on schedule |
|
|
32
|
+
| `webhook` | HTTP POST to generated endpoint; signed via signing_mode |
|
|
33
|
+
|
|
34
|
+
## Signing Modes (webhook only)
|
|
35
|
+
|
|
36
|
+
| Mode | Description |
|
|
37
|
+
|------|-------------|
|
|
38
|
+
| `none` | No signature verification |
|
|
39
|
+
| `bearer` | Authorization: Bearer <token> header |
|
|
40
|
+
| `hmac_sha256` | X-Hub-Signature-256 header (HMAC-SHA256 of body) |
|
|
41
|
+
| `github_hmac` | GitHub-style HMAC — identical to hmac_sha256 + secret stored in mastermind:secrets |
|
|
42
|
+
|
|
43
|
+
## Concurrency Policies
|
|
44
|
+
|
|
45
|
+
| Policy | Behavior |
|
|
46
|
+
|--------|----------|
|
|
47
|
+
| `coalesce_if_active` | Skip trigger if a run is already active; record as coalesced |
|
|
48
|
+
| `always_enqueue` | Always create a new run regardless of active runs |
|
|
49
|
+
| `skip_if_active` | Silently discard trigger if a run is active |
|
|
50
|
+
|
|
51
|
+
## Catchup Policies (schedule only)
|
|
52
|
+
|
|
53
|
+
| Policy | Behavior |
|
|
54
|
+
|--------|----------|
|
|
55
|
+
| `skip_missed` | Missed scheduled runs are discarded |
|
|
56
|
+
| `enqueue_missed_with_cap` | Enqueue missed runs up to `catchup_cap` (default 3) |
|
|
57
|
+
|
|
58
|
+
---
|
|
59
|
+
|
|
60
|
+
## Step 0 — Brain Load (standalone only)
|
|
61
|
+
|
|
62
|
+
If `caller` is not "command", load brain context following _protocol.md Brain Load Procedure with namespace: `ops`.
|
|
63
|
+
|
|
64
|
+
---
|
|
65
|
+
|
|
66
|
+
## Step 1 — Load Routine Data
|
|
67
|
+
|
|
68
|
+
```bash
|
|
69
|
+
orgFile=".monomind/orgs/${org_name}.json"
|
|
70
|
+
[ ! -f "$orgFile" ] && { echo "ERROR: Org '${org_name}' not found."; exit 1; }
|
|
71
|
+
|
|
72
|
+
routinesFile=".monomind/orgs/${org_name}-routines.json"
|
|
73
|
+
[ ! -f "$routinesFile" ] && { echo "ERROR: No routines file for org '$org_name'. Create routines first via /mastermind:runorg."; exit 1; }
|
|
74
|
+
|
|
75
|
+
routineDef=$(jq -r --arg id "$routine_id" '.routines[] | select(.id == $id)' "$routinesFile")
|
|
76
|
+
[ -z "$routineDef" ] && { echo "ERROR: Routine '$routine_id' not found in org '$org_name'."; exit 1; }
|
|
77
|
+
|
|
78
|
+
stateFile=".monomind/orgs/${org_name}-state.json"
|
|
79
|
+
days=${days:-14}
|
|
80
|
+
cutoff=$(date -u -v-${days}d +%Y-%m-%dT%H:%M:%SZ 2>/dev/null || date -u -d "${days} days ago" +%Y-%m-%dT%H:%M:%SZ 2>/dev/null || echo "")
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
---
|
|
84
|
+
|
|
85
|
+
## Step 2 — Execute Action
|
|
86
|
+
|
|
87
|
+
### show (default)
|
|
88
|
+
|
|
89
|
+
```bash
|
|
90
|
+
echo "ROUTINE DETAIL — $routine_id @ $org_name"
|
|
91
|
+
echo "────────────────────────────────────────────────────────"
|
|
92
|
+
|
|
93
|
+
echo "$routineDef" | jq -r '
|
|
94
|
+
" ID: \(.id)",
|
|
95
|
+
" Name: \(.name // "-")",
|
|
96
|
+
" Assigned agent: \(.agent_id // "(any)")",
|
|
97
|
+
" Enabled: \(.enabled // false)",
|
|
98
|
+
"",
|
|
99
|
+
"TRIGGER",
|
|
100
|
+
" Kind: \(.trigger.kind // "schedule")",
|
|
101
|
+
(if (.trigger.kind // "schedule") == "schedule" then
|
|
102
|
+
" Cron: \(.trigger.cron // "-")",
|
|
103
|
+
" Catchup policy: \(.catchup_policy // "skip_missed")",
|
|
104
|
+
" Catchup cap: \(.catchup_cap // 3 | tostring)"
|
|
105
|
+
else
|
|
106
|
+
" Endpoint: \(.trigger.endpoint // "(not generated)")",
|
|
107
|
+
" Signing mode: \(.trigger.signing_mode // "none")"
|
|
108
|
+
end),
|
|
109
|
+
"",
|
|
110
|
+
"CONCURRENCY",
|
|
111
|
+
" Policy: \(.concurrency_policy // "coalesce_if_active")",
|
|
112
|
+
"",
|
|
113
|
+
"VARIABLES",
|
|
114
|
+
" Count: \((.variables // {}) | length | tostring)"
|
|
115
|
+
'
|
|
116
|
+
|
|
117
|
+
# Show last run summary from state
|
|
118
|
+
lastRun=$([ -f "$stateFile" ] && jq -r --arg id "$routine_id" '.routines[$id].last_run // "-"' "$stateFile" || echo "-")
|
|
119
|
+
runCount=$([ -f "$stateFile" ] && jq -r --arg id "$routine_id" '.routines[$id].run_count // 0' "$stateFile" || echo "0")
|
|
120
|
+
echo ""
|
|
121
|
+
echo " Last run: $lastRun"
|
|
122
|
+
echo " Run count: $runCount"
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
### runs
|
|
126
|
+
|
|
127
|
+
```bash
|
|
128
|
+
echo "RUN HISTORY — $routine_id (last ${days} days)"
|
|
129
|
+
echo "────────────────────────────────────────────────────────"
|
|
130
|
+
printf "%-26s %-12s %-8s %-14s %s\n" "TIMESTAMP" "STATUS" "TOKENS" "TRIGGER KIND" "COALESCED"
|
|
131
|
+
echo "────────────────────────────────────────────────────────"
|
|
132
|
+
|
|
133
|
+
runsFile=".monomind/orgs/${org_name}-routine-runs.jsonl"
|
|
134
|
+
found=0
|
|
135
|
+
|
|
136
|
+
if [ -f "$runsFile" ]; then
|
|
137
|
+
while IFS= read -r line; do
|
|
138
|
+
rid=$(echo "$line" | jq -r '.routine_id // ""')
|
|
139
|
+
[ "$rid" != "$routine_id" ] && continue
|
|
140
|
+
ts=$(echo "$line" | jq -r '.ts // ""')
|
|
141
|
+
[ -n "$cutoff" ] && [ "$ts" \< "$cutoff" ] && continue
|
|
142
|
+
st=$(echo "$line" | jq -r '.status // "-"')
|
|
143
|
+
tok=$(echo "$line" | jq -r '.tokens // "-"')
|
|
144
|
+
tkind=$(echo "$line" | jq -r '.trigger_kind // "schedule"')
|
|
145
|
+
coal=$(echo "$line" | jq -r 'if .coalesced then "yes" else "-" end')
|
|
146
|
+
printf "%-26s %-12s %-8s %-14s %s\n" "$ts" "$st" "$tok" "$tkind" "$coal"
|
|
147
|
+
found=$((found + 1))
|
|
148
|
+
done < "$runsFile"
|
|
149
|
+
fi
|
|
150
|
+
|
|
151
|
+
[ "$found" -eq 0 ] && echo " No runs in the last $days days."
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
### config
|
|
155
|
+
|
|
156
|
+
```bash
|
|
157
|
+
echo "FULL CONFIG — $routine_id"
|
|
158
|
+
echo "────────────────────────────────────────────────────────"
|
|
159
|
+
echo "$routineDef" | jq 'del(.variables)'
|
|
160
|
+
echo ""
|
|
161
|
+
echo "TRIGGER DETAIL"
|
|
162
|
+
echo "$routineDef" | jq '.trigger'
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
### variables
|
|
166
|
+
|
|
167
|
+
```bash
|
|
168
|
+
echo "VARIABLES — $routine_id"
|
|
169
|
+
echo "────────────────────────────────────────────────────────"
|
|
170
|
+
|
|
171
|
+
vars=$(echo "$routineDef" | jq -r '.variables // {} | to_entries[] | " \(.key) = \(.value)"')
|
|
172
|
+
[ -z "$vars" ] && echo " No variables defined." || echo "$vars"
|
|
173
|
+
|
|
174
|
+
# Set a variable if var_key provided
|
|
175
|
+
if [ -n "$var_key" ]; then
|
|
176
|
+
[ -z "$var_value" ] && { echo "ERROR: --var-value required when setting a variable."; exit 1; }
|
|
177
|
+
tmp="${routinesFile}.tmp"
|
|
178
|
+
jq --arg id "$routine_id" --arg k "$var_key" --arg v "$var_value" \
|
|
179
|
+
'.routines = [.routines[] | if .id == $id then .variables[$k] = $v else . end]' \
|
|
180
|
+
"$routinesFile" > "$tmp" && mv "$tmp" "$routinesFile"
|
|
181
|
+
echo ""
|
|
182
|
+
echo "Set variable: $var_key = $var_value"
|
|
183
|
+
fi
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
### rotate-webhook
|
|
187
|
+
|
|
188
|
+
```bash
|
|
189
|
+
triggerKind=$(echo "$routineDef" | jq -r '.trigger.kind // "schedule"')
|
|
190
|
+
[ "$triggerKind" != "webhook" ] && { echo "ERROR: Routine '$routine_id' is not a webhook-triggered routine."; exit 1; }
|
|
191
|
+
|
|
192
|
+
newToken=$(openssl rand -hex 24 2>/dev/null || python3 -c "import secrets; print(secrets.token_hex(24))")
|
|
193
|
+
newEndpoint="/api/webhook/${org_name}/${routine_id}/${newToken}"
|
|
194
|
+
ts=$(date -u +%Y-%m-%dT%H:%M:%SZ)
|
|
195
|
+
|
|
196
|
+
tmp="${routinesFile}.tmp"
|
|
197
|
+
jq --arg id "$routine_id" --arg ep "$newEndpoint" --arg ts "$ts" \
|
|
198
|
+
'.routines = [.routines[] | if .id == $id then
|
|
199
|
+
.trigger.endpoint = $ep | .trigger.rotated_at = $ts
|
|
200
|
+
else . end]' \
|
|
201
|
+
"$routinesFile" > "$tmp" && mv "$tmp" "$routinesFile"
|
|
202
|
+
|
|
203
|
+
echo "Webhook rotated for '$routine_id'"
|
|
204
|
+
echo " New endpoint: $newEndpoint"
|
|
205
|
+
echo " Rotated at: $ts"
|
|
206
|
+
echo ""
|
|
207
|
+
echo "Update your webhook source to use the new endpoint."
|
|
208
|
+
signingMode=$(echo "$routineDef" | jq -r '.trigger.signing_mode // "none"')
|
|
209
|
+
[ "$signingMode" != "none" ] && echo " Signing mode '$signingMode' is unchanged — re-generate the signing secret if required."
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
### revisions
|
|
213
|
+
|
|
214
|
+
```bash
|
|
215
|
+
revisionsFile=".monomind/orgs/${org_name}-routine-revisions.jsonl"
|
|
216
|
+
echo "REVISIONS — $routine_id"
|
|
217
|
+
echo "────────────────────────────────────────────────────────"
|
|
218
|
+
|
|
219
|
+
if [ ! -f "$revisionsFile" ]; then
|
|
220
|
+
echo " No revision history found."
|
|
221
|
+
else
|
|
222
|
+
found=0
|
|
223
|
+
while IFS= read -r line; do
|
|
224
|
+
rid=$(echo "$line" | jq -r '.routine_id // ""')
|
|
225
|
+
[ "$rid" != "$routine_id" ] && continue
|
|
226
|
+
ts=$(echo "$line" | jq -r '.ts // ""')
|
|
227
|
+
who=$(echo "$line" | jq -r '.changed_by // "system"')
|
|
228
|
+
what=$(echo "$line" | jq -r '.change_summary // "-"')
|
|
229
|
+
printf " [%s] by %-16s %s\n" "$ts" "$who" "$what"
|
|
230
|
+
found=$((found + 1))
|
|
231
|
+
done < "$revisionsFile"
|
|
232
|
+
[ "$found" -eq 0 ] && echo " No revisions found for '$routine_id'."
|
|
233
|
+
fi
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
---
|
|
237
|
+
|
|
238
|
+
## Step 3 — Return Output
|
|
239
|
+
|
|
240
|
+
```yaml
|
|
241
|
+
domain: ops
|
|
242
|
+
status: complete
|
|
243
|
+
action: <action>
|
|
244
|
+
org: <org_name>
|
|
245
|
+
routine_id: <routine_id>
|
|
246
|
+
trigger_kind: <schedule|webhook>
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
---
|
|
250
|
+
|
|
251
|
+
## Step 4 — Brain Write (standalone only)
|
|
252
|
+
|
|
253
|
+
If `caller` is not "command", follow _protocol.md Brain Write Procedure for domain `ops`.
|