@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,255 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: mastermind-goal-detail
|
|
3
|
+
description: Mastermind goal-detail — deep per-goal inspection and management. Show sub-goal tree, linked projects, edit title/status/description/priority, add child goals, and close or reopen a single goal within an org.
|
|
4
|
+
type: domain-skill
|
|
5
|
+
default_mode: auto
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Mastermind Goal Detail
|
|
9
|
+
|
|
10
|
+
This skill is invoked by `mastermind:goal-detail` or directly via `/mastermind:goal-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 goal belongs to (required)
|
|
18
|
+
- `goal_id`: goal id/slug (required)
|
|
19
|
+
- `action`: show | tree | projects | edit | add-child | close | reopen
|
|
20
|
+
- `field`: field to edit (title | description | status | priority | parent_id)
|
|
21
|
+
- `value`: new field value (required for edit)
|
|
22
|
+
- `child_title`: title for the new child goal (required for add-child)
|
|
23
|
+
- `child_description`: description for the new child goal (optional)
|
|
24
|
+
- `caller`: command | master
|
|
25
|
+
|
|
26
|
+
---
|
|
27
|
+
|
|
28
|
+
## Goal Status Flow
|
|
29
|
+
|
|
30
|
+
```
|
|
31
|
+
open → in_progress → done
|
|
32
|
+
└──────────────────┘ (can reopen)
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## Priority Levels
|
|
36
|
+
|
|
37
|
+
`critical` | `high` | `medium` | `low`
|
|
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 Goal 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
|
+
goalsFile=".monomind/orgs/${org_name}-goals.json"
|
|
54
|
+
[ ! -f "$goalsFile" ] && { echo "ERROR: No goals file for org '$org_name'. Create goals via /mastermind:goals."; exit 1; }
|
|
55
|
+
|
|
56
|
+
goalDef=$(jq -r --arg id "$goal_id" '.goals[] | select(.id == $id or .slug == $id)' "$goalsFile")
|
|
57
|
+
[ -z "$goalDef" ] && { echo "ERROR: Goal '$goal_id' not found in org '$org_name'."; exit 1; }
|
|
58
|
+
|
|
59
|
+
resolvedId=$(echo "$goalDef" | jq -r '.id')
|
|
60
|
+
projectsFile=".monomind/orgs/${org_name}-projects.json"
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
---
|
|
64
|
+
|
|
65
|
+
## Step 2 — Execute Action
|
|
66
|
+
|
|
67
|
+
### show (default)
|
|
68
|
+
|
|
69
|
+
```bash
|
|
70
|
+
echo "GOAL DETAIL — $goal_id @ $org_name"
|
|
71
|
+
echo "────────────────────────────────────────────────────────"
|
|
72
|
+
|
|
73
|
+
echo "$goalDef" | jq -r '
|
|
74
|
+
" ID: \(.id)",
|
|
75
|
+
" Title: \(.title // "(no title)")",
|
|
76
|
+
" Status: \(.status // "open")",
|
|
77
|
+
" Priority: \(.priority // "medium")",
|
|
78
|
+
" Parent: \(.parent_id // "(root goal)")",
|
|
79
|
+
" Created: \(.created_at // "-")",
|
|
80
|
+
" Updated: \(.updated_at // "-")"
|
|
81
|
+
'
|
|
82
|
+
|
|
83
|
+
# Sub-goals count
|
|
84
|
+
subCount=$(jq --arg pid "$resolvedId" '[.goals[] | select(.parent_id == $pid)] | length' "$goalsFile" 2>/dev/null || echo 0)
|
|
85
|
+
doneCount=$(jq --arg pid "$resolvedId" '[.goals[] | select(.parent_id == $pid and .status == "done")] | length' "$goalsFile" 2>/dev/null || echo 0)
|
|
86
|
+
echo " Sub-goals: $subCount total, $doneCount done"
|
|
87
|
+
|
|
88
|
+
# Linked projects
|
|
89
|
+
projCount=$(echo "$goalDef" | jq -r '(.linked_projects // []) | length')
|
|
90
|
+
echo " Projects: $projCount linked"
|
|
91
|
+
|
|
92
|
+
# Description
|
|
93
|
+
desc=$(echo "$goalDef" | jq -r '.description // ""')
|
|
94
|
+
if [ -n "$desc" ]; then
|
|
95
|
+
echo ""
|
|
96
|
+
echo "DESCRIPTION"
|
|
97
|
+
echo "────────────────────────────────────────────────────────"
|
|
98
|
+
echo "$desc"
|
|
99
|
+
fi
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
### tree
|
|
103
|
+
|
|
104
|
+
```bash
|
|
105
|
+
echo "SUB-GOAL TREE — $goal_id"
|
|
106
|
+
echo "────────────────────────────────────────────────────────"
|
|
107
|
+
|
|
108
|
+
function print_tree() {
|
|
109
|
+
local pid="$1"
|
|
110
|
+
local indent="$2"
|
|
111
|
+
local children
|
|
112
|
+
children=$(jq -r --arg pid "$pid" '.goals[] | select(.parent_id == $pid) |
|
|
113
|
+
[.id, (.status // "open"), (.title // "(no title)")] | @tsv' "$goalsFile" 2>/dev/null)
|
|
114
|
+
while IFS=$'\t' read -r cid cst ctitle; do
|
|
115
|
+
[ -z "$cid" ] && continue
|
|
116
|
+
echo "${indent}[${cst}] ${ctitle} (${cid})"
|
|
117
|
+
print_tree "$cid" " ${indent}"
|
|
118
|
+
done <<< "$children"
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
# Print root goal
|
|
122
|
+
rootTitle=$(echo "$goalDef" | jq -r '.title // "(no title)"')
|
|
123
|
+
rootStatus=$(echo "$goalDef" | jq -r '.status // "open"')
|
|
124
|
+
echo "[${rootStatus}] ${rootTitle} (${resolvedId})"
|
|
125
|
+
print_tree "$resolvedId" " "
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
### projects
|
|
129
|
+
|
|
130
|
+
```bash
|
|
131
|
+
echo "LINKED PROJECTS — $goal_id"
|
|
132
|
+
echo "────────────────────────────────────────────────────────"
|
|
133
|
+
|
|
134
|
+
linkedIds=$(echo "$goalDef" | jq -r '(.linked_projects // [])[]')
|
|
135
|
+
if [ -z "$linkedIds" ]; then
|
|
136
|
+
echo " No linked projects."
|
|
137
|
+
else
|
|
138
|
+
while IFS= read -r pid; do
|
|
139
|
+
[ -z "$pid" ] && continue
|
|
140
|
+
if [ -f "$projectsFile" ]; then
|
|
141
|
+
projInfo=$(jq -r --arg id "$pid" '.projects[] | select(.id == $id) |
|
|
142
|
+
" [\(.status // "active")] \(.name // $id) — \(.description // "")"' "$projectsFile" 2>/dev/null)
|
|
143
|
+
[ -n "$projInfo" ] && echo "$projInfo" || echo " [$pid] (project not found in projects file)"
|
|
144
|
+
else
|
|
145
|
+
echo " $pid"
|
|
146
|
+
fi
|
|
147
|
+
done <<< "$linkedIds"
|
|
148
|
+
fi
|
|
149
|
+
|
|
150
|
+
echo ""
|
|
151
|
+
echo "Issues referencing this goal:"
|
|
152
|
+
issuesFile=".monomind/orgs/${org_name}-issues.json"
|
|
153
|
+
if [ -f "$issuesFile" ]; then
|
|
154
|
+
count=$(jq --arg gid "$resolvedId" '[.issues[] | select(.goal_id == $gid)] | length' "$issuesFile" 2>/dev/null || echo 0)
|
|
155
|
+
echo " $count issue(s) linked to this goal."
|
|
156
|
+
fi
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
### edit
|
|
160
|
+
|
|
161
|
+
```bash
|
|
162
|
+
[ -z "$field" ] && { echo "ERROR: --field required (title|description|status|priority|parent_id)."; exit 1; }
|
|
163
|
+
[ -z "$value" ] && { echo "ERROR: --value required."; exit 1; }
|
|
164
|
+
|
|
165
|
+
validFields="title description status priority parent_id"
|
|
166
|
+
echo "$validFields" | tr ' ' '\n' | grep -qx "$field" || {
|
|
167
|
+
echo "ERROR: Unknown field '$field'. Valid: $validFields"; exit 1
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
if [ "$field" = "status" ]; then
|
|
171
|
+
case "$value" in open|in_progress|done|cancelled) : ;; *)
|
|
172
|
+
echo "ERROR: status must be one of: open, in_progress, done, cancelled"; exit 1 ;;
|
|
173
|
+
esac
|
|
174
|
+
fi
|
|
175
|
+
if [ "$field" = "priority" ]; then
|
|
176
|
+
case "$value" in critical|high|medium|low) : ;; *)
|
|
177
|
+
echo "ERROR: priority must be one of: critical, high, medium, low"; exit 1 ;;
|
|
178
|
+
esac
|
|
179
|
+
fi
|
|
180
|
+
|
|
181
|
+
ts=$(date -u +%Y-%m-%dT%H:%M:%SZ)
|
|
182
|
+
tmp="${goalsFile}.tmp"
|
|
183
|
+
jq --arg id "$resolvedId" --arg field "$field" --arg val "$value" --arg ts "$ts" \
|
|
184
|
+
'.goals = [.goals[] | if .id == $id then .[$field] = $val | .updated_at = $ts else . end]' \
|
|
185
|
+
"$goalsFile" > "$tmp" && mv "$tmp" "$goalsFile"
|
|
186
|
+
|
|
187
|
+
echo "Goal '$goal_id' updated: $field = $value"
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
### add-child
|
|
191
|
+
|
|
192
|
+
```bash
|
|
193
|
+
[ -z "$child_title" ] && { echo "ERROR: --child-title required."; exit 1; }
|
|
194
|
+
|
|
195
|
+
childId="goal-$(openssl rand -hex 4 2>/dev/null || python3 -c 'import secrets; print(secrets.token_hex(4))')"
|
|
196
|
+
ts=$(date -u +%Y-%m-%dT%H:%M:%SZ)
|
|
197
|
+
|
|
198
|
+
tmp="${goalsFile}.tmp"
|
|
199
|
+
jq --arg id "$childId" \
|
|
200
|
+
--arg title "$child_title" \
|
|
201
|
+
--arg desc "${child_description:-}" \
|
|
202
|
+
--arg pid "$resolvedId" \
|
|
203
|
+
--arg ts "$ts" \
|
|
204
|
+
'.goals += [{"id":$id,"title":$title,
|
|
205
|
+
"description":(if $desc != "" then $desc else null end),
|
|
206
|
+
"parent_id":$pid,"status":"open","priority":"medium",
|
|
207
|
+
"linked_projects":[],"created_at":$ts,"updated_at":$ts}]' \
|
|
208
|
+
"$goalsFile" > "$tmp" && mv "$tmp" "$goalsFile"
|
|
209
|
+
|
|
210
|
+
echo "Sub-goal created: $childId"
|
|
211
|
+
echo " Title: $child_title"
|
|
212
|
+
echo " Parent: $goal_id"
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
### close
|
|
216
|
+
|
|
217
|
+
```bash
|
|
218
|
+
ts=$(date -u +%Y-%m-%dT%H:%M:%SZ)
|
|
219
|
+
tmp="${goalsFile}.tmp"
|
|
220
|
+
jq --arg id "$resolvedId" --arg ts "$ts" \
|
|
221
|
+
'.goals = [.goals[] | if .id == $id then .status = "done" | .updated_at = $ts | .closed_at = $ts else . end]' \
|
|
222
|
+
"$goalsFile" > "$tmp" && mv "$tmp" "$goalsFile"
|
|
223
|
+
echo "Goal '$goal_id' → done."
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
### reopen
|
|
227
|
+
|
|
228
|
+
```bash
|
|
229
|
+
ts=$(date -u +%Y-%m-%dT%H:%M:%SZ)
|
|
230
|
+
tmp="${goalsFile}.tmp"
|
|
231
|
+
jq --arg id "$resolvedId" --arg ts "$ts" \
|
|
232
|
+
'.goals = [.goals[] | if .id == $id then .status = "open" | .updated_at = $ts | .closed_at = null else . end]' \
|
|
233
|
+
"$goalsFile" > "$tmp" && mv "$tmp" "$goalsFile"
|
|
234
|
+
echo "Goal '$goal_id' → reopened."
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
---
|
|
238
|
+
|
|
239
|
+
## Step 3 — Return Output
|
|
240
|
+
|
|
241
|
+
```yaml
|
|
242
|
+
domain: ops
|
|
243
|
+
status: complete
|
|
244
|
+
action: <action>
|
|
245
|
+
org: <org_name>
|
|
246
|
+
goal_id: <goal_id>
|
|
247
|
+
goal_status: <status>
|
|
248
|
+
sub_goals: <N>
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
---
|
|
252
|
+
|
|
253
|
+
## Step 4 — Brain Write (standalone only)
|
|
254
|
+
|
|
255
|
+
If `caller` is not "command", follow _protocol.md Brain Write Procedure for domain `ops`.
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: mastermind-goals
|
|
3
|
+
description: Mastermind goals — define, track, and visualize hierarchical goals for an org. Goals link to tasks, have progress metrics, and form a goal tree.
|
|
4
|
+
type: domain-skill
|
|
5
|
+
default_mode: confirm
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Mastermind Goals
|
|
9
|
+
|
|
10
|
+
This skill is invoked by `mastermind:goals` or directly via `/mastermind:goals`.
|
|
11
|
+
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
## Inputs
|
|
15
|
+
|
|
16
|
+
- `brain_context`: BRAIN CONTEXT block
|
|
17
|
+
- `org_name`: org whose goals to manage
|
|
18
|
+
- `action`: list | add | update | link | close
|
|
19
|
+
- `goal_title`: title for add
|
|
20
|
+
- `goal_id`: slug for update/link/close
|
|
21
|
+
- `parent_goal`: parent goal slug (for hierarchy)
|
|
22
|
+
- `status`: active | achieved | paused | cancelled
|
|
23
|
+
- `metric`: success metric description (e.g. "100 blog posts published")
|
|
24
|
+
- `caller`: command | master
|
|
25
|
+
|
|
26
|
+
---
|
|
27
|
+
|
|
28
|
+
## Step 0 — Brain Load (standalone only)
|
|
29
|
+
|
|
30
|
+
If `caller` is not "command", load brain context following _protocol.md Brain Load Procedure with namespace: `ops`.
|
|
31
|
+
|
|
32
|
+
---
|
|
33
|
+
|
|
34
|
+
## Step 1 — Load Goals State
|
|
35
|
+
|
|
36
|
+
Goals are stored in `.monomind/orgs/<org_name>-goals.json`. Create if missing:
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
goalsFile=".monomind/orgs/${org_name}-goals.json"
|
|
40
|
+
[ ! -f "$goalsFile" ] && echo '{"goals":[]}' > "$goalsFile"
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
---
|
|
44
|
+
|
|
45
|
+
## Step 2 — Execute Action
|
|
46
|
+
|
|
47
|
+
### list (default)
|
|
48
|
+
|
|
49
|
+
Render goal tree with progress metrics. Goals without a `parent` are root goals; child goals are indented:
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
jq -r '
|
|
53
|
+
def tree(gs; pid):
|
|
54
|
+
gs | map(select(.parent == pid)) | .[] |
|
|
55
|
+
(" " * (.depth // 0)) + "[\(.id)] \(.title) [\(.status // "active")] \(.metric // "")" ,
|
|
56
|
+
tree(gs; .id);
|
|
57
|
+
.goals | tree(.; null)
|
|
58
|
+
' "$goalsFile" 2>/dev/null || jq -r '.goals[] | "[\(.id)] \(.title) [\(.status // "active")]"' "$goalsFile"
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
Render as:
|
|
62
|
+
```
|
|
63
|
+
GOALS — org: <org_name>
|
|
64
|
+
──────────────────────────────────────
|
|
65
|
+
[grow-audience] Grow audience to 10k followers [active]
|
|
66
|
+
[content-output] Publish 3 posts/week [active] metric: 3 posts/week
|
|
67
|
+
[blog-drafts] 5 draft articles in pipeline [active]
|
|
68
|
+
[improve-seo] Rank top 10 for target keywords [active]
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
### add
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
goal_slug=$(echo "$goal_title" | tr '[:upper:]' '[:lower:]' | sed 's/[^a-z0-9]/-/g' | tr -s '-')
|
|
75
|
+
tmp="${goalsFile}.tmp"
|
|
76
|
+
jq --arg id "$goal_slug" \
|
|
77
|
+
--arg title "$goal_title" \
|
|
78
|
+
--arg parent "${parent_goal:-}" \
|
|
79
|
+
--arg status "active" \
|
|
80
|
+
--arg metric "${metric:-}" \
|
|
81
|
+
--arg created_at "$(date -u +%Y-%m-%dT%H:%M:%SZ)" \
|
|
82
|
+
'.goals += [{"id":$id,"title":$title,"parent":($parent|if .=="" then null else . end),"status":$status,"metric":$metric,"created_at":$created_at,"tasks":[]}]' \
|
|
83
|
+
"$goalsFile" > "$tmp" && mv "$tmp" "$goalsFile"
|
|
84
|
+
echo "Goal added: $goal_slug"
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
Emit `org:goal:created` event to dashboard.
|
|
88
|
+
|
|
89
|
+
### update
|
|
90
|
+
|
|
91
|
+
Update goal status or metric:
|
|
92
|
+
|
|
93
|
+
```bash
|
|
94
|
+
tmp="${goalsFile}.tmp"
|
|
95
|
+
jq --arg id "$goal_id" \
|
|
96
|
+
--arg status "${status:-}" \
|
|
97
|
+
--arg metric "${metric:-}" \
|
|
98
|
+
'.goals = [.goals[] | if .id == $id then
|
|
99
|
+
(if $status != "" then .status = $status else . end) |
|
|
100
|
+
(if $metric != "" then .metric = $metric else . end) |
|
|
101
|
+
(.updated_at = (now|todate))
|
|
102
|
+
else . end]' \
|
|
103
|
+
"$goalsFile" > "$tmp" && mv "$tmp" "$goalsFile"
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
### link
|
|
107
|
+
|
|
108
|
+
Link a task id to a goal (append to goal's tasks array):
|
|
109
|
+
|
|
110
|
+
```bash
|
|
111
|
+
tmp="${goalsFile}.tmp"
|
|
112
|
+
jq --arg id "$goal_id" --arg task "$task_id" \
|
|
113
|
+
'.goals = [.goals[] | if .id == $id then .tasks += [$task] else . end]' \
|
|
114
|
+
"$goalsFile" > "$tmp" && mv "$tmp" "$goalsFile"
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
### close
|
|
118
|
+
|
|
119
|
+
Mark goal as achieved and timestamp:
|
|
120
|
+
|
|
121
|
+
```bash
|
|
122
|
+
tmp="${goalsFile}.tmp"
|
|
123
|
+
jq --arg id "$goal_id" \
|
|
124
|
+
'.goals = [.goals[] | if .id == $id then .status = "achieved" | .achieved_at = (now|todate) else . end]' \
|
|
125
|
+
"$goalsFile" > "$tmp" && mv "$tmp" "$goalsFile"
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
Emit `org:goal:achieved` event.
|
|
129
|
+
|
|
130
|
+
---
|
|
131
|
+
|
|
132
|
+
## Step 3 — Return Output
|
|
133
|
+
|
|
134
|
+
```yaml
|
|
135
|
+
domain: ops
|
|
136
|
+
status: complete
|
|
137
|
+
action: <action>
|
|
138
|
+
org: <org_name>
|
|
139
|
+
goal_id: <goal_id if applicable>
|
|
140
|
+
goals_file: .monomind/orgs/<org_name>-goals.json
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
Suggest next: "Link tasks to this goal with /mastermind:tasks link or /mastermind:goals link --goal-id <id> --task-id <card_id>"
|
|
144
|
+
|
|
145
|
+
---
|
|
146
|
+
|
|
147
|
+
## Step 4 — Brain Write (standalone only)
|
|
148
|
+
|
|
149
|
+
If `caller` is not "command", follow _protocol.md Brain Write Procedure for domain `ops`.
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: mastermind-heartbeat
|
|
3
|
+
description: Mastermind heartbeat — trigger a manual heartbeat for a specific agent in a running org. The agent wakes, checks its task queue, executes pending work, and reports back.
|
|
4
|
+
type: domain-skill
|
|
5
|
+
default_mode: auto
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Mastermind Heartbeat
|
|
9
|
+
|
|
10
|
+
This skill is invoked by `mastermind:heartbeat` or directly via `/mastermind:heartbeat`.
|
|
11
|
+
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
## Inputs
|
|
15
|
+
|
|
16
|
+
- `brain_context`: BRAIN CONTEXT block
|
|
17
|
+
- `org_name`: org the agent belongs to
|
|
18
|
+
- `agent_id`: role id of the agent to wake (e.g. `content-writer`)
|
|
19
|
+
- `context`: optional additional context/instructions to pass to the agent during this heartbeat
|
|
20
|
+
- `source`: timer | on_demand | assignment | automation (default: on_demand)
|
|
21
|
+
- `timeout_min`: minutes to wait for completion (default: 10)
|
|
22
|
+
- `caller`: command | master
|
|
23
|
+
|
|
24
|
+
---
|
|
25
|
+
|
|
26
|
+
## Step 0 — Brain Load (standalone only)
|
|
27
|
+
|
|
28
|
+
If `caller` is not "command", load brain context following _protocol.md Brain Load Procedure with namespace: `ops`.
|
|
29
|
+
|
|
30
|
+
---
|
|
31
|
+
|
|
32
|
+
## Step 1 — Load Org Config
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
orgFile=".monomind/orgs/${org_name}.json"
|
|
36
|
+
stateFile=".monomind/orgs/${org_name}-state.json"
|
|
37
|
+
|
|
38
|
+
[ ! -f "$orgFile" ] && { echo "ERROR: Org '${org_name}' not found. Run /mastermind:createorg first."; exit 1; }
|
|
39
|
+
|
|
40
|
+
board_id=$(jq -r '.board_id // empty' "$orgFile")
|
|
41
|
+
todo_col=$(jq -r '.todo_col_id // empty' "$orgFile")
|
|
42
|
+
doing_col=$(jq -r '.doing_col_id // empty' "$orgFile")
|
|
43
|
+
done_col=$(jq -r '.done_col_id // empty' "$orgFile")
|
|
44
|
+
memNs="org:${org_name}"
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
---
|
|
48
|
+
|
|
49
|
+
## Step 2 — Validate Agent
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
agentConfig=$(jq --arg id "$agent_id" '.roles[] | select(.id == $id)' "$orgFile")
|
|
53
|
+
[ -z "$agentConfig" ] && { echo "ERROR: Agent '$agent_id' not found in org '$org_name'."; exit 1; }
|
|
54
|
+
|
|
55
|
+
agentTitle=$(echo "$agentConfig" | jq -r '.title')
|
|
56
|
+
agentType=$(echo "$agentConfig" | jq -r '.agent_type')
|
|
57
|
+
agentResp=$(echo "$agentConfig" | jq -r '.responsibilities | join("; ")')
|
|
58
|
+
reportsTo=$(echo "$agentConfig" | jq -r '.reports_to // "none"')
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
---
|
|
62
|
+
|
|
63
|
+
## Step 3 — Update State and Emit heartbeat:start
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
[ ! -f "$stateFile" ] && echo '{"agents":{}}' > "$stateFile"
|
|
67
|
+
tmp="${stateFile}.tmp"
|
|
68
|
+
jq --arg id "$agent_id" --arg ts "$(date -u +%Y-%m-%dT%H:%M:%SZ)" --arg source "${source:-on_demand}" \
|
|
69
|
+
'.agents[$id].last_heartbeat = $ts | .agents[$id].status = "running" | .agents[$id].heartbeat_source = $source' \
|
|
70
|
+
"$stateFile" > "$tmp" && mv "$tmp" "$stateFile"
|
|
71
|
+
|
|
72
|
+
REPO_ROOT=$(git rev-parse --show-toplevel 2>/dev/null || pwd)
|
|
73
|
+
CTRL_URL=$(jq -r '.url // "http://localhost:4242"' "$REPO_ROOT/.monomind/control.json" 2>/dev/null || echo "http://localhost:4242")
|
|
74
|
+
curl -s -X POST "${CTRL_URL}/api/mastermind/event" \
|
|
75
|
+
-H "Content-Type: application/json" \
|
|
76
|
+
-d "$(jq -cn \
|
|
77
|
+
--arg org "$org_name" \
|
|
78
|
+
--arg role "$agent_id" \
|
|
79
|
+
--arg title "$agentTitle" \
|
|
80
|
+
--arg source "${source:-on_demand}" \
|
|
81
|
+
'{type:"org:heartbeat:start",org:$org,role:$role,title:$title,source:$source,ts:(now*1000|floor)}')" || true
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
---
|
|
85
|
+
|
|
86
|
+
## Step 4 — Spawn Agent for One Heartbeat Cycle
|
|
87
|
+
|
|
88
|
+
```javascript
|
|
89
|
+
Task({
|
|
90
|
+
subagent_type: agentType,
|
|
91
|
+
description: `Heartbeat for ${agentTitle} in org "${org_name}"`,
|
|
92
|
+
run_in_background: false,
|
|
93
|
+
prompt: `You are ${agentTitle} in the autonomous organization "${org_name}".
|
|
94
|
+
|
|
95
|
+
This is a HEARTBEAT CYCLE — a single work session triggered ${source || "on_demand"}.
|
|
96
|
+
|
|
97
|
+
YOUR ROLE: ${agentTitle}
|
|
98
|
+
YOUR RESPONSIBILITIES: ${agentResp}
|
|
99
|
+
REPORTS TO: ${reportsTo}
|
|
100
|
+
MEMORY NAMESPACE: ${memNs}
|
|
101
|
+
|
|
102
|
+
${context ? `CONTEXT / INSTRUCTIONS FOR THIS HEARTBEAT:\n${context}\n\n` : ""}
|
|
103
|
+
|
|
104
|
+
TASK BOARD:
|
|
105
|
+
- board_id: ${board_id}
|
|
106
|
+
- Todo column: ${todo_col}
|
|
107
|
+
- Doing column: ${doing_col}
|
|
108
|
+
- Done column: ${done_col}
|
|
109
|
+
|
|
110
|
+
HEARTBEAT PROCEDURE:
|
|
111
|
+
1. Check your task queue — unclaimed cards with "role:${agent_id}" label in Todo:
|
|
112
|
+
monotask card list ${board_id} --col ${todo_col} --json | jq '[.[] | select((.labels // []) | index("role:${agent_id}")) | select((.labels // []) | index("claimed") | not)]'
|
|
113
|
+
|
|
114
|
+
2. For each unclaimed task:
|
|
115
|
+
a. Move to Doing: monotask card move ${board_id} $CARD_ID ${doing_col}
|
|
116
|
+
b. Add "claimed" label: monotask card label add ${board_id} $CARD_ID "claimed"
|
|
117
|
+
c. Execute the work described in the task title
|
|
118
|
+
d. Store output: npx monomind@latest memory store --key "${memNs}:output:${agent_id}:$CARD_ID" --namespace "${memNs}" --value "<your output>"
|
|
119
|
+
e. Move to Done: monotask card move ${board_id} $CARD_ID ${done_col}
|
|
120
|
+
|
|
121
|
+
3. If no tasks, check memory for any pending instructions:
|
|
122
|
+
npx monomind@latest memory search --query "instruction ${agent_id}" --namespace "${memNs}"
|
|
123
|
+
|
|
124
|
+
4. Report completion — emit heartbeat:complete event:
|
|
125
|
+
CTRL_URL=$(jq -r '.url // "http://localhost:4242"' "$(git rev-parse --show-toplevel 2>/dev/null || pwd)/.monomind/control.json" 2>/dev/null || echo "http://localhost:4242")
|
|
126
|
+
curl -s -X POST "${CTRL_URL}/api/mastermind/event" -H "Content-Type: application/json" \
|
|
127
|
+
-d "$(jq -cn --arg org "${org_name}" --arg role "${agent_id}" --arg title "${agentTitle}" \
|
|
128
|
+
'{type:"org:heartbeat:complete",org:$org,role:$role,title:$title,ts:(now*1000|floor)}')" || true
|
|
129
|
+
|
|
130
|
+
Complete your tasks then exit. This is a single heartbeat cycle, not a persistent loop.`
|
|
131
|
+
})
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
---
|
|
135
|
+
|
|
136
|
+
## Step 5 — Update State After Completion
|
|
137
|
+
|
|
138
|
+
```bash
|
|
139
|
+
tmp="${stateFile}.tmp"
|
|
140
|
+
jq --arg id "$agent_id" --arg ts "$(date -u +%Y-%m-%dT%H:%M:%SZ)" \
|
|
141
|
+
'.agents[$id].status = "idle" | .agents[$id].last_heartbeat_complete = $ts' \
|
|
142
|
+
"$stateFile" > "$tmp" && mv "$tmp" "$stateFile"
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
---
|
|
146
|
+
|
|
147
|
+
## Step 6 — Return Output
|
|
148
|
+
|
|
149
|
+
```yaml
|
|
150
|
+
domain: ops
|
|
151
|
+
status: complete
|
|
152
|
+
org: <org_name>
|
|
153
|
+
agent_id: <agent_id>
|
|
154
|
+
agent_title: <agentTitle>
|
|
155
|
+
heartbeat_source: <source>
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
Print: "Heartbeat complete for <agentTitle>. Check outputs with: npx monomind@latest memory search --namespace org:<org_name>"
|
|
159
|
+
|
|
160
|
+
---
|
|
161
|
+
|
|
162
|
+
## Step 7 — Brain Write (standalone only)
|
|
163
|
+
|
|
164
|
+
If `caller` is not "command", follow _protocol.md Brain Write Procedure for domain `ops`.
|