@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
|
@@ -80,7 +80,8 @@ space_id=$(monotask space list 2>/dev/null | awk -F'|' '{gsub(/^ +| +$/,"",$1);g
|
|
|
80
80
|
[ -z "$space_id" ] && { echo "ERROR: Could not find or create space '$project_name'"; exit 1; }
|
|
81
81
|
|
|
82
82
|
# Find existing idea board by canonical name — reuse across runs (same pattern as master Step 6)
|
|
83
|
-
|
|
83
|
+
# board list format is "uuid: name" (colon-space separator, NOT pipe)
|
|
84
|
+
BOARD_ID=$(monotask board list 2>/dev/null | awk -F': ' '{gsub(/^ +| +$/,"",$1);gsub(/^ +| +$/,"",$2);if($2==n)print $1}' n="$idea_canonical" | head -1)
|
|
84
85
|
|
|
85
86
|
if [ -n "$BOARD_ID" ]; then
|
|
86
87
|
echo "Reusing idea board: $BOARD_ID ($idea_canonical)"
|
|
@@ -102,18 +103,26 @@ else
|
|
|
102
103
|
BOARD_ID=$(monotask board create --space "$space_id" "$idea_canonical" --json 2>/dev/null | jq -r '.id // empty')
|
|
103
104
|
[ -z "$BOARD_ID" ] && { echo "ERROR: Failed to create idea board '$idea_canonical'"; exit 1; }
|
|
104
105
|
monotask space boards add "$space_id" "$BOARD_ID" >/dev/null 2>&1 || true
|
|
105
|
-
COL_NEW=$(monotask column create "$BOARD_ID" "New" --json | jq -r '.id')
|
|
106
|
-
COL_EVALUATED=$(monotask column create "$BOARD_ID" "Evaluated" --json | jq -r '.id')
|
|
107
|
-
COL_ELABORATED=$(monotask column create "$BOARD_ID" "Elaborated" --json | jq -r '.id')
|
|
108
|
-
COL_TASKED=$(monotask column create "$BOARD_ID" "Tasked" --json | jq -r '.id')
|
|
109
|
-
COL_ICED=$(monotask column create "$BOARD_ID" "Iced" --json | jq -r '.id')
|
|
110
|
-
COL_REJECTED=$(monotask column create "$BOARD_ID" "Rejected" --json | jq -r '.id')
|
|
106
|
+
COL_NEW=$(monotask column create "$BOARD_ID" "New" --json | jq -r '.id // empty')
|
|
107
|
+
COL_EVALUATED=$(monotask column create "$BOARD_ID" "Evaluated" --json | jq -r '.id // empty')
|
|
108
|
+
COL_ELABORATED=$(monotask column create "$BOARD_ID" "Elaborated" --json | jq -r '.id // empty')
|
|
109
|
+
COL_TASKED=$(monotask column create "$BOARD_ID" "Tasked" --json | jq -r '.id // empty')
|
|
110
|
+
COL_ICED=$(monotask column create "$BOARD_ID" "Iced" --json | jq -r '.id // empty')
|
|
111
|
+
COL_REJECTED=$(monotask column create "$BOARD_ID" "Rejected" --json | jq -r '.id // empty')
|
|
111
112
|
fi
|
|
112
113
|
```
|
|
113
114
|
|
|
114
115
|
**After either branch above, validate and echo all values.** This is the canonical source for Step 4 Task construction.
|
|
115
116
|
|
|
116
117
|
```bash
|
|
118
|
+
# Guard all column IDs — catches silent jq failures in the create branch
|
|
119
|
+
[ -z "$COL_NEW" ] && { echo "ERROR: COL_NEW empty after board setup"; exit 1; }
|
|
120
|
+
[ -z "$COL_EVALUATED" ] && { echo "ERROR: COL_EVALUATED empty after board setup"; exit 1; }
|
|
121
|
+
[ -z "$COL_ELABORATED" ] && { echo "ERROR: COL_ELABORATED empty after board setup"; exit 1; }
|
|
122
|
+
[ -z "$COL_TASKED" ] && { echo "ERROR: COL_TASKED empty after board setup"; exit 1; }
|
|
123
|
+
[ -z "$COL_ICED" ] && { echo "ERROR: COL_ICED empty after board setup"; exit 1; }
|
|
124
|
+
[ -z "$COL_REJECTED" ] && { echo "ERROR: COL_REJECTED empty after board setup"; exit 1; }
|
|
125
|
+
|
|
117
126
|
# Validate BOARD_ID looks like a UUID before proceeding
|
|
118
127
|
[[ ! "$BOARD_ID" =~ ^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$ ]] && \
|
|
119
128
|
{ echo "ERROR: BOARD_ID '$BOARD_ID' is not a valid UUID — aborting to prevent board name corruption"; exit 1; }
|
|
@@ -144,20 +153,26 @@ TOP_N=6
|
|
|
144
153
|
|
|
145
154
|
# Select user/market/ops angle specialists
|
|
146
155
|
CATEGORIES="marketing strategy product academic specialized"
|
|
147
|
-
user_market_agents=$(jq
|
|
156
|
+
user_market_agents=$(jq \
|
|
148
157
|
--arg cats "$CATEGORIES" \
|
|
149
158
|
--arg kw "$(echo "$PROMPT" | tr '[:upper:]' '[:lower:]' | grep -oE '[a-z]{5,}' | sort -u | tr '\n' ' ')" \
|
|
150
159
|
--argjson n "$TOP_N" \
|
|
151
160
|
'[ .agents[] | select(.deprecated != true)
|
|
152
161
|
| select(.category as $c | ($cats | split(" ") | any(. == $c)))
|
|
153
162
|
| {name: .name, slug: .slug, category: .category,
|
|
154
|
-
score: (
|
|
163
|
+
score: (
|
|
164
|
+
(.name | ascii_downcase) as $n |
|
|
165
|
+
# Score on ANY keyword match (mirrors master.md pick_domain_manager scoring)
|
|
166
|
+
(if ($kw | length) > 0
|
|
167
|
+
then ([$kw | split(" ")[] | select(length > 0) | if ($n | contains(.)) then 1 else 0 end] | add // 0)
|
|
168
|
+
else 0 end)
|
|
169
|
+
)}
|
|
155
170
|
] | sort_by(-.score) | unique_by(.slug) | .[0:$n] | [.[].name]' \
|
|
156
171
|
"$REGISTRY" 2>/dev/null)
|
|
157
172
|
|
|
158
173
|
# Select technical angle specialists
|
|
159
174
|
CATEGORIES="engineering development architecture"
|
|
160
|
-
tech_agents=$(jq
|
|
175
|
+
tech_agents=$(jq \
|
|
161
176
|
--arg cats "$CATEGORIES" \
|
|
162
177
|
--argjson n 3 \
|
|
163
178
|
'[ .agents[] | select(.deprecated != true)
|
|
@@ -167,11 +182,14 @@ tech_agents=$(jq -r \
|
|
|
167
182
|
"$REGISTRY" 2>/dev/null)
|
|
168
183
|
|
|
169
184
|
# Merge: take top 6 from market/ops + top 2 from tech (cap at 8 total)
|
|
170
|
-
|
|
171
|
-
|
|
185
|
+
# Both variables hold JSON arrays (no -r flag) — use jq -s add to merge properly
|
|
186
|
+
specialist_list=$(jq -s 'add // [] | unique | .[0:8]' \
|
|
187
|
+
<(printf '%s' "$user_market_agents") \
|
|
188
|
+
<(printf '%s' "$tech_agents") 2>/dev/null)
|
|
172
189
|
|
|
173
|
-
# Fallback if registry missing
|
|
174
|
-
|
|
190
|
+
# Fallback if registry missing or returned an empty array — need at least 2 specialists
|
|
191
|
+
specialist_count=$(echo "$specialist_list" | jq 'length // 0' 2>/dev/null || echo 0)
|
|
192
|
+
[ "$specialist_count" -lt 2 ] && specialist_list='["researcher","Trend Researcher","Growth Hacker","UX Researcher","Content Creator","Account Strategist"]'
|
|
175
193
|
|
|
176
194
|
echo "Selected specialists: $specialist_list"
|
|
177
195
|
```
|
|
@@ -246,6 +264,7 @@ For each unique idea, create one card in the New column (COL_NEW = ${COL_NEW}):
|
|
|
246
264
|
|
|
247
265
|
result=$(monotask card create "${BOARD_ID}" "${COL_NEW}" "<idea title ≤80 chars>" --json)
|
|
248
266
|
CARD_ID=$(echo "$result" | jq -r '.id // empty')
|
|
267
|
+
[ -z "$CARD_ID" ] && { echo "WARN: card creation failed for '<idea title>', skipping"; continue; }
|
|
249
268
|
monotask card set-description "${BOARD_ID}" "$CARD_ID" "<2-3 sentence description>"
|
|
250
269
|
monotask card comment add "${BOARD_ID}" "$CARD_ID" "CATEGORY: <feature | technical-baseline | business-operation>
|
|
251
270
|
SOURCE: <which specialist angle produced this>"
|
|
@@ -272,7 +291,8 @@ Parse the `IDEAS_OUTPUT` JSON block from the agent's response and assign it:
|
|
|
272
291
|
```bash
|
|
273
292
|
ideas_output_json='<paste the JSON array from IDEAS_OUTPUT here>'
|
|
274
293
|
```
|
|
275
|
-
If
|
|
294
|
+
If the `IDEAS_OUTPUT` block is absent from the agent's response (agent error, timeout, or unrecoverable failure), set `ideas_output_json='[]'` and treat as zero ideas.
|
|
295
|
+
If zero ideas were returned, report "Idea Manager produced no ideas." — skip Steps 5–6 and proceed to Step 7 (Brain Write).
|
|
276
296
|
|
|
277
297
|
---
|
|
278
298
|
|
|
@@ -289,11 +309,11 @@ ideas_list=$(echo "$ideas_output_json" | jq -r \
|
|
|
289
309
|
**CRITICAL — Variable substitution required for Step 5 Task call:**
|
|
290
310
|
Before constructing the Task prompt below, read the literal UUID values from the `=== IDEA BOARD LITERAL VALUES ===` echo block (Step 3) and embed them as hard-coded strings. Also embed the full `brain_context`, `prompt`, and `ideas_list` (built above) as literal text. Replace every `${BOARD_ID}`, `${COL_EVALUATED}`, `${COL_ICED}`, `${COL_REJECTED}`, `${brain_context}`, `${prompt}`, `${project_name}`, `${date}`, and `${ideas_list}` with its actual value before calling Task — the agent receives unsubstituted `${...}` strings verbatim and silently skips every board update.
|
|
291
311
|
|
|
292
|
-
Spawn a single `
|
|
312
|
+
Spawn a single `general-purpose` agent via the Task tool. Do NOT use `Product Manager` — that agent type lacks Bash tool access and cannot execute `monotask` CLI commands. The evaluator agent produces verdicts and executes all board updates directly via Bash.
|
|
293
313
|
|
|
294
314
|
```javascript
|
|
295
315
|
Task({
|
|
296
|
-
subagent_type: "
|
|
316
|
+
subagent_type: "general-purpose",
|
|
297
317
|
description: "PM validation for project " + project_name,
|
|
298
318
|
run_in_background: false,
|
|
299
319
|
prompt: `SAFETY CHECK: Verify that the BOARD_ID you received matches UUID format xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx (8-4-4-4-12 hex chars). If it does not, STOP and report "ERROR: BOARD_ID not substituted — received: <value>". Do NOT call monotask board create, space create, or column create. Your only job is evaluating cards and running impact/effort updates on existing cards.
|
|
@@ -321,23 +341,31 @@ For EVERY idea above, determine:
|
|
|
321
341
|
- skipElaboration: true (simple, no deep research needed) | false (edge cases should be explored) — only for evaluated
|
|
322
342
|
- rationale: 1-2 sentence value statement (evaluated), blocking question (iced), or rejection reason (rejected)
|
|
323
343
|
|
|
324
|
-
MANDATORY BOARD UPDATES —
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
344
|
+
MANDATORY BOARD UPDATES — after determining all verdicts, build your verdicts as a JSON array and iterate over it:
|
|
345
|
+
|
|
346
|
+
# Paste your full VERDICTS_OUTPUT array here as verdicts_json (before outputting the block)
|
|
347
|
+
verdicts_json='[ ... your verdict objects ... ]'
|
|
348
|
+
while IFS= read -r row; do
|
|
349
|
+
CARD_ID=$(echo "$row" | jq -r '.card_id')
|
|
350
|
+
verdict=$(echo "$row" | jq -r '.verdict')
|
|
351
|
+
impact=$(echo "$row" | jq -r '.impact')
|
|
352
|
+
effort=$(echo "$row" | jq -r '.effort')
|
|
353
|
+
rationale=$(echo "$row" | jq -r '.rationale')
|
|
354
|
+
if [ "$verdict" = "evaluated" ]; then
|
|
355
|
+
monotask card move "${BOARD_ID}" "$CARD_ID" "${COL_EVALUATED}" --json
|
|
356
|
+
monotask card set-impact "${BOARD_ID}" "$CARD_ID" "$impact"
|
|
357
|
+
monotask card set-effort "${BOARD_ID}" "$CARD_ID" "$effort"
|
|
358
|
+
monotask card comment add "${BOARD_ID}" "$CARD_ID" "Value: $rationale"
|
|
359
|
+
elif [ "$verdict" = "iced" ]; then
|
|
360
|
+
monotask card move "${BOARD_ID}" "$CARD_ID" "${COL_ICED}" --json
|
|
361
|
+
monotask card set-impact "${BOARD_ID}" "$CARD_ID" "$impact"
|
|
362
|
+
monotask card set-effort "${BOARD_ID}" "$CARD_ID" "$effort"
|
|
363
|
+
monotask card comment add "${BOARD_ID}" "$CARD_ID" "Blocked: $rationale"
|
|
364
|
+
elif [ "$verdict" = "rejected" ]; then
|
|
365
|
+
monotask card move "${BOARD_ID}" "$CARD_ID" "${COL_REJECTED}" --json
|
|
366
|
+
monotask card comment add "${BOARD_ID}" "$CARD_ID" "Rejected: $rationale"
|
|
367
|
+
fi
|
|
368
|
+
done < <(echo "$verdicts_json" | jq -c '.[]')
|
|
341
369
|
|
|
342
370
|
IMPORTANT: set-impact and set-effort MUST be called for every evaluated and iced idea. Do not skip them.
|
|
343
371
|
|
|
@@ -364,7 +392,8 @@ After the PM agent completes, parse the `VERDICTS_OUTPUT` block from the agent's
|
|
|
364
392
|
```bash
|
|
365
393
|
verdicts_output_json='<paste the JSON array from VERDICTS_OUTPUT here>'
|
|
366
394
|
```
|
|
367
|
-
|
|
395
|
+
If the `VERDICTS_OUTPUT` block is absent (agent error or malformed output), set `verdicts_output_json='[]'` — all ideas will be treated as iced and Step 6 will be skipped.
|
|
396
|
+
This variable is used throughout Steps 6a and 6c to build idea lists, registry keywords, and inherit impact/effort scores — it must be set before proceeding. If **all** ideas are iced or rejected, output a summary table — skip Step 6 and proceed to Step 7 (Brain Write).
|
|
368
397
|
|
|
369
398
|
---
|
|
370
399
|
|
|
@@ -374,9 +403,20 @@ This variable is used throughout Steps 6a and 6c to build idea lists, registry k
|
|
|
374
403
|
|
|
375
404
|
For any evaluated idea with `skipElaboration: true`, move it directly to `Elaborated`, set a description, and write a rationale comment so future readers understand why no deep elaboration was needed:
|
|
376
405
|
```bash
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
406
|
+
while IFS= read -r skip_idea; do
|
|
407
|
+
CARD_ID=$(echo "$skip_idea" | jq -r '.card_id')
|
|
408
|
+
skip_title=$(echo "$skip_idea" | jq -r '.title')
|
|
409
|
+
skip_rationale=$(echo "$skip_idea" | jq -r '.rationale // "No rationale provided"')
|
|
410
|
+
skip_impact=$(echo "$skip_idea" | jq -r '.impact // 5')
|
|
411
|
+
skip_effort=$(echo "$skip_idea" | jq -r '.effort // 5')
|
|
412
|
+
monotask card set-description "$BOARD_ID" "$CARD_ID" "Elaboration skipped — PM assessed this as straightforward.
|
|
413
|
+
|
|
414
|
+
Rationale: $skip_rationale
|
|
415
|
+
|
|
416
|
+
Impact: $skip_impact/10 | Effort: $skip_effort/10"
|
|
417
|
+
monotask card move "$BOARD_ID" "$CARD_ID" "$COL_ELABORATED" --json
|
|
418
|
+
monotask card comment add "$BOARD_ID" "$CARD_ID" "Elaboration skipped: PM assessed this idea as straightforward with no significant unknowns. Rationale: $skip_rationale"
|
|
419
|
+
done < <(echo "$verdicts_output_json" | jq -c '[.[] | select(.verdict == "evaluated") | select(.skipElaboration == true)] | .[]')
|
|
380
420
|
```
|
|
381
421
|
|
|
382
422
|
For ideas with `skipElaboration: false`, **split by category** before spawning agents:
|
|
@@ -384,19 +424,23 @@ For ideas with `skipElaboration: false`, **split by category** before spawning a
|
|
|
384
424
|
**Build `dev_ideas_list` and `ops_ideas_list` before constructing the Step 6a Task prompts:**
|
|
385
425
|
```bash
|
|
386
426
|
# Filter VERDICTS_OUTPUT (parsed in Step 5) by category and format as literal text.
|
|
427
|
+
# IMPORTANT: exclude skipElaboration:true ideas — they were already moved to Elaborated above
|
|
428
|
+
# and must not be sent to elaboration agents again.
|
|
387
429
|
dev_ideas_list=$(echo "$verdicts_output_json" | jq -r \
|
|
388
|
-
'.[] | select(.verdict == "evaluated") | select(.
|
|
430
|
+
'.[] | select(.verdict == "evaluated") | select(.skipElaboration != true)
|
|
431
|
+
| select(.category == "feature" or .category == "technical-baseline") |
|
|
389
432
|
"- card_id: \(.card_id)\n title: \(.title)\n category: \(.category)\n rationale: \(.rationale)\n"')
|
|
390
433
|
|
|
391
434
|
ops_ideas_list=$(echo "$verdicts_output_json" | jq -r \
|
|
392
|
-
'.[] | select(.verdict == "evaluated") | select(.
|
|
435
|
+
'.[] | select(.verdict == "evaluated") | select(.skipElaboration != true)
|
|
436
|
+
| select(.category == "business-operation") |
|
|
393
437
|
"- card_id: \(.card_id)\n title: \(.title)\n category: \(.category)\n rationale: \(.rationale)\n"')
|
|
394
438
|
```
|
|
395
439
|
|
|
396
440
|
**CRITICAL — Variable substitution required for Step 6a Task calls:**
|
|
397
441
|
Elaboration agents run in isolated Task contexts. Before constructing each Task prompt, replace every `${brain_context}`, `${dev_ideas_list}`, and `${ops_ideas_list}` with the actual literal text — `brain_context` from the brain load, `dev_ideas_list` and `ops_ideas_list` built above. Do NOT leave any `${...}` placeholders in the prompt — the agent receives them as literal dollar-sign strings and produces empty ELABORATION_OUTPUT blocks.
|
|
398
442
|
|
|
399
|
-
**Dev ideas** (`feature` or `technical-baseline`):
|
|
443
|
+
**Dev ideas** (`feature` or `technical-baseline`) — **skip if `dev_ideas_list` is empty** (no evaluated feature/technical-baseline ideas without skipElaboration; set `dev_researcher_json='[]'` and `dev_codebase_json='[]'` instead and do not spawn these agents):
|
|
400
444
|
Spawn two agents in parallel via Task tool:
|
|
401
445
|
|
|
402
446
|
```javascript
|
|
@@ -455,7 +499,7 @@ END_ELABORATION_OUTPUT`
|
|
|
455
499
|
})
|
|
456
500
|
```
|
|
457
501
|
|
|
458
|
-
**Business-operation ideas** (`business-operation`):
|
|
502
|
+
**Business-operation ideas** (`business-operation`) — **skip if `ops_ideas_list` is empty** (no evaluated business-operation ideas without skipElaboration; set `ops_researcher_json='[]'` and `ops_pm_json='[]'` instead and do not spawn these agents):
|
|
459
503
|
Spawn two agents in parallel via Task tool:
|
|
460
504
|
|
|
461
505
|
```javascript
|
|
@@ -514,7 +558,7 @@ END_ELABORATION_OUTPUT`
|
|
|
514
558
|
})
|
|
515
559
|
```
|
|
516
560
|
|
|
517
|
-
Wait for all background agents to complete (
|
|
561
|
+
Wait for all spawned background elaboration agents to complete before proceeding (0, 2, or 4 agents depending on which lists were non-empty — see guards above). Then build `merged_elaboration_json` by merging agent outputs per `card_id` and injecting `category` from `verdicts_output_json`:
|
|
518
562
|
|
|
519
563
|
```bash
|
|
520
564
|
# Assign each agent's ELABORATION_OUTPUT JSON array from its output block:
|
|
@@ -523,29 +567,45 @@ dev_codebase_json='<ELABORATION_OUTPUT array from the dev code-explorer agent>'
|
|
|
523
567
|
ops_researcher_json='<ELABORATION_OUTPUT array from the ops researcher agent>'
|
|
524
568
|
ops_pm_json='<ELABORATION_OUTPUT array from the ops PM agent>'
|
|
525
569
|
# Use '[]' for any track that had no ideas (e.g. if all ideas were dev, set ops_* to '[]')
|
|
570
|
+
# If an ELABORATION_OUTPUT block is absent from an agent's response (error/timeout), set that variable to '[]'
|
|
526
571
|
|
|
527
|
-
# Merge dev track: join researcher + codebase
|
|
572
|
+
# Merge dev track: full outer join researcher + codebase by card_id, inject category from verdicts.
|
|
573
|
+
# Use union of card_ids from both agents — if one agent skips a card the other covers, it's preserved.
|
|
574
|
+
# blocking_issue: take from whichever agent found one (researcher OR codebase).
|
|
528
575
|
dev_merged=$(jq -n \
|
|
529
576
|
--argjson r "$dev_researcher_json" \
|
|
530
577
|
--argjson c "$dev_codebase_json" \
|
|
531
578
|
--argjson v "$verdicts_output_json" \
|
|
532
|
-
'[$r[] |
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
579
|
+
'([$r[], $c[]] | map(.card_id) | unique) as $ids |
|
|
580
|
+
[$ids[] | . as $id |
|
|
581
|
+
{ card_id: $id,
|
|
582
|
+
blocking_issue: (
|
|
583
|
+
([$r[] | select(.card_id == $id)] | first | .blocking_issue // null) //
|
|
584
|
+
([$c[] | select(.card_id == $id)] | first | .blocking_issue // null)
|
|
585
|
+
),
|
|
586
|
+
researcher_findings: ([$r[] | select(.card_id == $id)] | first | .findings // ""),
|
|
587
|
+
codebase_findings: ([$c[] | select(.card_id == $id)] | first | .findings // ""),
|
|
588
|
+
category: ([$v[] | select(.card_id == $id)] | first | .category // "feature") }]')
|
|
589
|
+
|
|
590
|
+
# Merge ops track: full outer join researcher + PM findings by card_id, inject category.
|
|
591
|
+
# blocking_issue: take from whichever agent found one (researcher OR PM).
|
|
538
592
|
ops_merged=$(jq -n \
|
|
539
593
|
--argjson r "$ops_researcher_json" \
|
|
540
594
|
--argjson p "$ops_pm_json" \
|
|
541
595
|
--argjson v "$verdicts_output_json" \
|
|
542
|
-
'[$r[] |
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
596
|
+
'([$r[], $p[]] | map(.card_id) | unique) as $ids |
|
|
597
|
+
[$ids[] | . as $id |
|
|
598
|
+
{ card_id: $id,
|
|
599
|
+
blocking_issue: (
|
|
600
|
+
([$r[] | select(.card_id == $id)] | first | .blocking_issue // null) //
|
|
601
|
+
([$p[] | select(.card_id == $id)] | first | .blocking_issue // null)
|
|
602
|
+
),
|
|
603
|
+
researcher_findings: ([$r[] | select(.card_id == $id)] | first | .findings // ""),
|
|
604
|
+
pm_findings: ([$p[] | select(.card_id == $id)] | first | .findings // ""),
|
|
605
|
+
category: ([$v[] | select(.card_id == $id)] | first | .category // "business-operation") }]')
|
|
546
606
|
|
|
547
607
|
# Combine both tracks
|
|
548
|
-
merged_elaboration_json=$(jq -s 'add' <(echo "$dev_merged") <(echo "$ops_merged"))
|
|
608
|
+
merged_elaboration_json=$(jq -s 'add // []' <(echo "$dev_merged") <(echo "$ops_merged"))
|
|
549
609
|
```
|
|
550
610
|
|
|
551
611
|
Use process substitution (not a pipeline) so the while loop runs in the main shell and variables remain in scope after `done`:
|
|
@@ -554,7 +614,8 @@ Use process substitution (not a pipeline) so the while loop runs in the main she
|
|
|
554
614
|
while IFS= read -r idea; do
|
|
555
615
|
CARD_ID=$(echo "$idea" | jq -r '.card_id')
|
|
556
616
|
category=$(echo "$idea" | jq -r '.category')
|
|
557
|
-
blocking_issue=$(echo "$idea" | jq -r '.blocking_issue //
|
|
617
|
+
blocking_issue=$(echo "$idea" | jq -r '.blocking_issue // ""')
|
|
618
|
+
[ "$blocking_issue" = "null" ] && blocking_issue="" # guard against agents outputting the string "null"
|
|
558
619
|
|
|
559
620
|
if [ "$category" = "business-operation" ]; then
|
|
560
621
|
researcher_findings=$(echo "$idea" | jq -r '.researcher_findings')
|
|
@@ -597,7 +658,7 @@ done < <(echo "$merged_elaboration_json" | jq -c '.[]')
|
|
|
597
658
|
|
|
598
659
|
**Confirm mode only:** If `mode` is `confirm` (default), present a review table of all elaborated ideas to the user.
|
|
599
660
|
|
|
600
|
-
Build the table from `verdicts_output_json` (filtered to `verdict == "evaluated"`). For each row:
|
|
661
|
+
Build the table from `verdicts_output_json` (filtered to `verdict == "evaluated"` AND `card_id` not in the set of ideas with a non-null `blocking_issue` in `merged_elaboration_json`). Exclude ideas iced during elaboration — they are already in the `Iced` column and must not appear in this review. For each row:
|
|
601
662
|
- **Impact** and **Effort** come from `.impact` and `.effort` fields in `verdicts_output_json`
|
|
602
663
|
- **Track**: `feature` or `technical-baseline` → `dev`; `business-operation` → `ops`
|
|
603
664
|
|
|
@@ -638,7 +699,7 @@ Wait for the user's response before continuing. Do not spawn any agents until a
|
|
|
638
699
|
```bash
|
|
639
700
|
monotask card comment add "$BOARD_ID" "$CARD_ID" "User notes: <notes>"
|
|
640
701
|
```
|
|
641
|
-
- **"stop"**: skip Step 6c
|
|
702
|
+
- **"stop"**: skip Step 6c. Proceed directly to Step 7 (Brain Write). Print a summary of ideas in Elaborated/Iced/Rejected and return `status: partial`.
|
|
642
703
|
- Combined instructions ("remove 2,4 | add detail to 1: ...") are processed together.
|
|
643
704
|
|
|
644
705
|
After applying all user instructions, proceed to Step 6c with the remaining ideas.
|
|
@@ -653,11 +714,7 @@ After applying all user instructions, proceed to Step 6c with the remaining idea
|
|
|
653
714
|
REGISTRY=".monomind/registry.json"
|
|
654
715
|
|
|
655
716
|
# Dev decomposition agent — pick the most relevant engineering/architecture specialist
|
|
656
|
-
# Build keyword signal from elaborated dev idea titles (from VERDICTS_OUTPUT filtered above)
|
|
657
|
-
DEV_IDEA_CONTEXT=$(echo "$verdicts_output_json" | jq -r \
|
|
658
|
-
'[.[] | select(.verdict=="evaluated") | select(.category=="feature" or .category=="technical-baseline") | .title] | join(" ")')
|
|
659
717
|
dev_decomp_agent=$(jq -r \
|
|
660
|
-
--arg kw "$(echo "$DEV_IDEA_CONTEXT" | tr '[:upper:]' '[:lower:]' | grep -oE '[a-z]{5,}' | sort -u | tr '\n' ' ')" \
|
|
661
718
|
'[ .agents[] | select(.deprecated != true)
|
|
662
719
|
| select(.category == "engineering" or .category == "architecture")
|
|
663
720
|
| {name: .name,
|
|
@@ -675,10 +732,7 @@ dev_decomp_agent=$(jq -r \
|
|
|
675
732
|
dev_decomp_agent="${dev_decomp_agent:-Software Architect}"
|
|
676
733
|
|
|
677
734
|
# Ops decomposition agent — pick the most relevant strategy/sales/product specialist
|
|
678
|
-
OPS_IDEA_CONTEXT=$(echo "$verdicts_output_json" | jq -r \
|
|
679
|
-
'[.[] | select(.verdict=="evaluated") | select(.category=="business-operation") | .title] | join(" ")')
|
|
680
735
|
ops_decomp_agent=$(jq -r \
|
|
681
|
-
--arg kw "$(echo "$OPS_IDEA_CONTEXT" | tr '[:upper:]' '[:lower:]' | grep -oE '[a-z]{5,}' | sort -u | tr '\n' ' ')" \
|
|
682
736
|
'[ .agents[] | select(.deprecated != true)
|
|
683
737
|
| select(.category == "strategy" or .category == "sales" or .category == "product" or .category == "marketing")
|
|
684
738
|
| {name: .name,
|
|
@@ -702,13 +756,29 @@ echo "Dev decomp: $dev_decomp_agent | Ops decomp: $ops_decomp_agent"
|
|
|
702
756
|
Before constructing each Task prompt, replace `${brain_context}`, `${prompt}`, `${project_name}`, `${dev_ideas_elaborated}`, and `${ops_ideas_elaborated}` with actual literal text. Also substitute the `subagent_type` values: replace `dev_decomp_agent` and `ops_decomp_agent` with the string values echoed by the registry selection above (e.g. `"Software Architect"`). Build those lists from the VERDICTS_OUTPUT and ELABORATION_OUTPUT results:
|
|
703
757
|
|
|
704
758
|
```bash
|
|
705
|
-
#
|
|
759
|
+
# Collect IDs of cards iced during elaboration (blocking_issue was set) — exclude from decomposition.
|
|
760
|
+
# merged_elaboration_json covers agent-elaborated ideas only (not skipElaboration:true ones).
|
|
761
|
+
elaboration_blocked=$(echo "$merged_elaboration_json" | jq \
|
|
762
|
+
'[.[] | select(.blocking_issue != null and .blocking_issue != "" and .blocking_issue != "null") | .card_id]')
|
|
763
|
+
# Safeguard: if jq failed (e.g. null input), default to empty array so decomp proceeds safely
|
|
764
|
+
[ -z "$elaboration_blocked" ] && elaboration_blocked='[]'
|
|
765
|
+
|
|
766
|
+
# Build elaborated idea lists for decomposition agents.
|
|
767
|
+
# Include: evaluated ideas (PM verdict) that were NOT iced during elaboration.
|
|
768
|
+
# This covers both skipElaboration:true ideas and agent-elaborated ideas in the Elaborated column.
|
|
769
|
+
# Use `any(. == $id)` not `contains([$id])` — contains does substring matching on strings (wrong for UUIDs).
|
|
706
770
|
dev_ideas_elaborated=$(echo "$verdicts_output_json" | jq -r \
|
|
707
|
-
|
|
771
|
+
--argjson blocked "$elaboration_blocked" \
|
|
772
|
+
'[.[] | select(.verdict=="evaluated")
|
|
773
|
+
| select(.card_id as $id | ($blocked | any(. == $id)) | not)
|
|
774
|
+
| select(.category=="feature" or .category=="technical-baseline") |
|
|
708
775
|
"card_id: \(.card_id)\ntitle: \(.title)\ncategory: \(.category)\nrationale: \(.rationale)\nimpact: \(.impact) effort: \(.effort)"] | join("\n\n")')
|
|
709
776
|
|
|
710
777
|
ops_ideas_elaborated=$(echo "$verdicts_output_json" | jq -r \
|
|
711
|
-
|
|
778
|
+
--argjson blocked "$elaboration_blocked" \
|
|
779
|
+
'[.[] | select(.verdict=="evaluated")
|
|
780
|
+
| select(.card_id as $id | ($blocked | any(. == $id)) | not)
|
|
781
|
+
| select(.category=="business-operation") |
|
|
712
782
|
"card_id: \(.card_id)\ntitle: \(.title)\ncategory: \(.category)\nrationale: \(.rationale)\nimpact: \(.impact) effort: \(.effort)"] | join("\n\n")')
|
|
713
783
|
```
|
|
714
784
|
|
|
@@ -803,8 +873,15 @@ END_TASKS_OUTPUT`
|
|
|
803
873
|
Canonical board name: `${project_name}-tasks-dev`. Find-or-create:
|
|
804
874
|
|
|
805
875
|
```bash
|
|
876
|
+
# space_id from Step 3 is gone (each Bash tool call is a new shell).
|
|
877
|
+
# Re-derive from project_name so board creation works correctly on first run.
|
|
878
|
+
if [ -z "$space_id" ]; then
|
|
879
|
+
space_id=$(monotask space list 2>/dev/null | awk -F'|' '{gsub(/^ +| +$/,"",$1);gsub(/^ +| +$/,"",$2);if($2==n)print $1}' n="$project_name" | head -1)
|
|
880
|
+
[ -z "$space_id" ] && { echo "ERROR: space '$project_name' not found — run Step 3 first"; exit 1; }
|
|
881
|
+
fi
|
|
806
882
|
dev_task_canonical="${project_name}-tasks-dev"
|
|
807
|
-
|
|
883
|
+
# board list format is "uuid: name" (colon-space separator, NOT pipe)
|
|
884
|
+
TASK_BOARD_ID=$(monotask board list 2>/dev/null | awk -F': ' '{gsub(/^ +| +$/,"",$1);gsub(/^ +| +$/,"",$2);if($2==n)print $1}' n="$dev_task_canonical" | head -1)
|
|
808
885
|
if [ -n "$TASK_BOARD_ID" ]; then
|
|
809
886
|
echo "Reusing dev task board: $TASK_BOARD_ID ($dev_task_canonical)"
|
|
810
887
|
task_columns=$(monotask column list "$TASK_BOARD_ID" --json)
|
|
@@ -815,8 +892,8 @@ else
|
|
|
815
892
|
TASK_BOARD_ID=$(monotask board create --space "$space_id" "$dev_task_canonical" --json 2>/dev/null | jq -r '.id // empty')
|
|
816
893
|
[ -z "$TASK_BOARD_ID" ] && { echo "ERROR: Failed to create dev task board"; exit 1; }
|
|
817
894
|
monotask space boards add "$space_id" "$TASK_BOARD_ID" >/dev/null 2>&1 || true
|
|
818
|
-
TASK_COL_BACKLOG=$(monotask column create "$TASK_BOARD_ID" "Backlog" --json | jq -r '.id')
|
|
819
|
-
TASK_COL_TODO=$(monotask column create "$TASK_BOARD_ID" "Todo" --json | jq -r '.id')
|
|
895
|
+
TASK_COL_BACKLOG=$(monotask column create "$TASK_BOARD_ID" "Backlog" --json | jq -r '.id // empty')
|
|
896
|
+
TASK_COL_TODO=$(monotask column create "$TASK_BOARD_ID" "Todo" --json | jq -r '.id // empty')
|
|
820
897
|
monotask column create "$TASK_BOARD_ID" "In Progress" --json >/dev/null
|
|
821
898
|
monotask column create "$TASK_BOARD_ID" "Human in Loop" --json >/dev/null
|
|
822
899
|
monotask column create "$TASK_BOARD_ID" "Review" --json >/dev/null
|
|
@@ -825,6 +902,7 @@ else
|
|
|
825
902
|
fi
|
|
826
903
|
[ -z "$TASK_BOARD_ID" ] && { echo "ERROR: TASK_BOARD_ID empty — aborting"; exit 1; }
|
|
827
904
|
[ -z "$TASK_COL_TODO" ] && { echo "ERROR: Could not find Todo column on dev task board"; exit 1; }
|
|
905
|
+
[ -z "$TASK_COL_BACKLOG" ] && { echo "ERROR: Could not find Backlog column on dev task board"; exit 1; }
|
|
828
906
|
```
|
|
829
907
|
|
|
830
908
|
---
|
|
@@ -834,8 +912,14 @@ fi
|
|
|
834
912
|
Canonical board name: `${project_name}-tasks-ops`. Find-or-create:
|
|
835
913
|
|
|
836
914
|
```bash
|
|
915
|
+
# Restore space_id if not available (same pattern as dev task board block above).
|
|
916
|
+
if [ -z "$space_id" ]; then
|
|
917
|
+
space_id=$(monotask space list 2>/dev/null | awk -F'|' '{gsub(/^ +| +$/,"",$1);gsub(/^ +| +$/,"",$2);if($2==n)print $1}' n="$project_name" | head -1)
|
|
918
|
+
[ -z "$space_id" ] && { echo "ERROR: space '$project_name' not found"; exit 1; }
|
|
919
|
+
fi
|
|
837
920
|
ops_task_canonical="${project_name}-tasks-ops"
|
|
838
|
-
|
|
921
|
+
# board list format is "uuid: name" (colon-space separator, NOT pipe)
|
|
922
|
+
OPS_BOARD_ID=$(monotask board list 2>/dev/null | awk -F': ' '{gsub(/^ +| +$/,"",$1);gsub(/^ +| +$/,"",$2);if($2==n)print $1}' n="$ops_task_canonical" | head -1)
|
|
839
923
|
if [ -n "$OPS_BOARD_ID" ]; then
|
|
840
924
|
echo "Reusing ops task board: $OPS_BOARD_ID ($ops_task_canonical)"
|
|
841
925
|
ops_columns=$(monotask column list "$OPS_BOARD_ID" --json)
|
|
@@ -846,8 +930,8 @@ else
|
|
|
846
930
|
OPS_BOARD_ID=$(monotask board create --space "$space_id" "$ops_task_canonical" --json 2>/dev/null | jq -r '.id // empty')
|
|
847
931
|
[ -z "$OPS_BOARD_ID" ] && { echo "ERROR: Failed to create ops task board"; exit 1; }
|
|
848
932
|
monotask space boards add "$space_id" "$OPS_BOARD_ID" >/dev/null 2>&1 || true
|
|
849
|
-
OPS_COL_BACKLOG=$(monotask column create "$OPS_BOARD_ID" "Backlog" --json | jq -r '.id')
|
|
850
|
-
OPS_COL_TODO=$(monotask column create "$OPS_BOARD_ID" "Todo" --json | jq -r '.id')
|
|
933
|
+
OPS_COL_BACKLOG=$(monotask column create "$OPS_BOARD_ID" "Backlog" --json | jq -r '.id // empty')
|
|
934
|
+
OPS_COL_TODO=$(monotask column create "$OPS_BOARD_ID" "Todo" --json | jq -r '.id // empty')
|
|
851
935
|
monotask column create "$OPS_BOARD_ID" "In Progress" --json >/dev/null
|
|
852
936
|
monotask column create "$OPS_BOARD_ID" "Human in Loop" --json >/dev/null
|
|
853
937
|
monotask column create "$OPS_BOARD_ID" "Review" --json >/dev/null
|
|
@@ -856,6 +940,7 @@ else
|
|
|
856
940
|
fi
|
|
857
941
|
[ -z "$OPS_BOARD_ID" ] && { echo "ERROR: OPS_BOARD_ID empty — aborting"; exit 1; }
|
|
858
942
|
[ -z "$OPS_COL_TODO" ] && { echo "ERROR: Could not find Todo column on ops task board"; exit 1; }
|
|
943
|
+
[ -z "$OPS_COL_BACKLOG" ] && { echo "ERROR: Could not find Backlog column on ops task board"; exit 1; }
|
|
859
944
|
```
|
|
860
945
|
|
|
861
946
|
---
|
|
@@ -867,13 +952,13 @@ fi
|
|
|
867
952
|
dev_tasks_json='<TASKS_OUTPUT JSON array from dev decomp agent, or [] if no dev ideas>'
|
|
868
953
|
# Parse the TASKS_OUTPUT block from the ops decomp agent's response and assign:
|
|
869
954
|
ops_tasks_json='<TASKS_OUTPUT JSON array from ops decomp agent, or [] if no ops ideas>'
|
|
955
|
+
# If TASKS_OUTPUT block is absent from an agent's response (error/timeout), set that variable to '[]'
|
|
870
956
|
|
|
871
|
-
merged_tasks_json=$(jq -s 'add' <(echo "$dev_tasks_json") <(echo "$ops_tasks_json"))
|
|
957
|
+
merged_tasks_json=$(jq -s 'add // []' <(echo "$dev_tasks_json") <(echo "$ops_tasks_json"))
|
|
872
958
|
|
|
873
|
-
# Use
|
|
874
|
-
#
|
|
875
|
-
|
|
876
|
-
declare -A parent_subtask_summaries # parent_card_id -> newline-separated task summary lines
|
|
959
|
+
# Use a temp directory to accumulate per-parent subtask summaries (bash 3.2 compatible —
|
|
960
|
+
# avoids declare -A associative arrays which require bash 4.3+)
|
|
961
|
+
SUBTASK_TMPDIR=$(mktemp -d)
|
|
877
962
|
|
|
878
963
|
while IFS= read -r task; do
|
|
879
964
|
parent_card_id=$(echo "$task" | jq -r '.parent_card_id')
|
|
@@ -885,59 +970,78 @@ while IFS= read -r task; do
|
|
|
885
970
|
has_prerequisites=$(echo "$task" | jq -r '.has_prerequisites')
|
|
886
971
|
|
|
887
972
|
if [ "$category" = "business-operation" ]; then
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
else
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
fi
|
|
973
|
+
TARGET_BOARD="$OPS_BOARD_ID"
|
|
974
|
+
COL_TARGET=$([ "$has_prerequisites" = "true" ] && echo "$OPS_COL_BACKLOG" || echo "$OPS_COL_TODO")
|
|
975
|
+
BOARD_LABEL="Operations Tasks"
|
|
976
|
+
else
|
|
977
|
+
TARGET_BOARD="$TASK_BOARD_ID"
|
|
978
|
+
COL_TARGET=$([ "$has_prerequisites" = "true" ] && echo "$TASK_COL_BACKLOG" || echo "$TASK_COL_TODO")
|
|
979
|
+
BOARD_LABEL="Implementation Tasks"
|
|
980
|
+
fi
|
|
896
981
|
|
|
897
|
-
# Inherit impact and effort from parent idea — look up from verdicts_output_json by parent_card_id
|
|
898
|
-
parent_impact=$(echo "$verdicts_output_json" | jq -r --arg id "$parent_card_id" '.[] | select(.card_id == $id) | .impact // 5')
|
|
899
|
-
parent_effort=$(echo "$verdicts_output_json" | jq -r --arg id "$parent_card_id" '.[] | select(.card_id == $id) | .effort // 5')
|
|
900
|
-
# Default to 5 if lookup returned empty (e.g. parent_card_id was "UNKNOWN")
|
|
901
|
-
[ -z "$parent_impact" ] && parent_impact=5
|
|
902
|
-
[ -z "$parent_effort" ] && parent_effort=5
|
|
903
|
-
|
|
904
|
-
# Create task card as a proper subtask of the parent idea card (cross-board link)
|
|
905
|
-
# Signature: subtask add <PARENT_BOARD_ID> <PARENT_CARD_ID> <CHILD_BOARD_ID> <COL_ID> <TITLE>
|
|
906
|
-
TASK_CARD_ID=$(monotask card subtask add "$BOARD_ID" "$parent_card_id" "$TARGET_BOARD" "$COL_TARGET" "
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
monotask card set-
|
|
910
|
-
monotask card set-
|
|
911
|
-
monotask card
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
982
|
+
# Inherit impact and effort from parent idea — look up from verdicts_output_json by parent_card_id
|
|
983
|
+
parent_impact=$(echo "$verdicts_output_json" | jq -r --arg id "$parent_card_id" '.[] | select(.card_id == $id) | .impact // 5')
|
|
984
|
+
parent_effort=$(echo "$verdicts_output_json" | jq -r --arg id "$parent_card_id" '.[] | select(.card_id == $id) | .effort // 5')
|
|
985
|
+
# Default to 5 if lookup returned empty (e.g. parent_card_id was "UNKNOWN")
|
|
986
|
+
[ -z "$parent_impact" ] && parent_impact=5
|
|
987
|
+
[ -z "$parent_effort" ] && parent_effort=5
|
|
988
|
+
|
|
989
|
+
# Create task card as a proper subtask of the parent idea card (cross-board link)
|
|
990
|
+
# Signature: subtask add <PARENT_BOARD_ID> <PARENT_CARD_ID> <CHILD_BOARD_ID> <COL_ID> <TITLE>
|
|
991
|
+
TASK_CARD_ID=$(monotask card subtask add "$BOARD_ID" "$parent_card_id" "$TARGET_BOARD" "$COL_TARGET" "$title" --json | jq -r '.id // empty')
|
|
992
|
+
[ -z "$TASK_CARD_ID" ] && { echo "WARN: subtask creation failed for '$title' (parent: $parent_card_id), skipping"; continue; }
|
|
993
|
+
# Set the task description as the primary content field
|
|
994
|
+
monotask card set-description "$TARGET_BOARD" "$TASK_CARD_ID" "$description"
|
|
995
|
+
monotask card set-impact "$TARGET_BOARD" "$TASK_CARD_ID" "$parent_impact"
|
|
996
|
+
monotask card set-effort "$TARGET_BOARD" "$TASK_CARD_ID" "$parent_effort"
|
|
997
|
+
# Derive parent idea title for the comment
|
|
998
|
+
parent_idea_title=$(echo "$verdicts_output_json" | jq -r --arg id "$parent_card_id" '.[] | select(.card_id == $id) | .title // "unknown"')
|
|
999
|
+
prompt_prefix=$(echo "$prompt" | cut -c1-100)
|
|
1000
|
+
monotask card comment add "$TARGET_BOARD" "$TASK_CARD_ID" \
|
|
1001
|
+
"SOURCE: mastermind:idea | $prompt_prefix
|
|
1002
|
+
AGENT: $agent
|
|
1003
|
+
TASK EFFORT: $task_effort/10
|
|
1004
|
+
PARENT IDEA IMPACT: $parent_impact/10 PARENT IDEA EFFORT: $parent_effort/10
|
|
1005
|
+
CATEGORY: $category
|
|
1006
|
+
PARENT IDEA: $parent_idea_title (card: $parent_card_id on ideation board)"
|
|
1007
|
+
monotask card label add "$TARGET_BOARD" "$TASK_CARD_ID" "mastermind:idea"
|
|
1008
|
+
monotask card label add "$TARGET_BOARD" "$TASK_CARD_ID" "category:$category"
|
|
1009
|
+
|
|
1010
|
+
# Append subtask summary line to per-parent file (replaces declare -A accumulation)
|
|
1011
|
+
printf ' - %s (agent: %s, effort: %s/10, board: %s)\n' \
|
|
1012
|
+
"$title" "$agent" "$task_effort" "$BOARD_LABEL" >> "$SUBTASK_TMPDIR/$parent_card_id"
|
|
923
1013
|
|
|
924
1014
|
done < <(echo "$merged_tasks_json" | jq -c '.[]')
|
|
925
1015
|
```
|
|
926
1016
|
|
|
927
1017
|
After the loop, annotate each parent idea card and move it to `Tasked`:
|
|
928
1018
|
```bash
|
|
929
|
-
for
|
|
930
|
-
|
|
1019
|
+
for summary_file in "$SUBTASK_TMPDIR"/*; do
|
|
1020
|
+
[ -f "$summary_file" ] || continue
|
|
1021
|
+
parent_card_id=$(basename "$summary_file")
|
|
1022
|
+
subtask_list=$(cat "$summary_file")
|
|
931
1023
|
monotask card comment add "$BOARD_ID" "$parent_card_id" \
|
|
932
|
-
"Subtasks created
|
|
1024
|
+
"Subtasks created:
|
|
1025
|
+
${subtask_list}"
|
|
933
1026
|
monotask card move "$BOARD_ID" "$parent_card_id" "$COL_TASKED" --json
|
|
934
1027
|
done
|
|
1028
|
+
rm -rf "$SUBTASK_TMPDIR"
|
|
935
1029
|
```
|
|
936
1030
|
|
|
937
|
-
For each entry in FLAGGED,
|
|
1031
|
+
For each entry in FLAGGED, parse the flagged JSON from both decomp agents' FLAGGED blocks and iterate:
|
|
938
1032
|
```bash
|
|
939
|
-
|
|
940
|
-
|
|
1033
|
+
# Collect flagged entries from both decomp agents
|
|
1034
|
+
dev_flagged_json='<FLAGGED array from dev decomp agent, or [] if none>'
|
|
1035
|
+
ops_flagged_json='<FLAGGED array from ops decomp agent, or [] if none>'
|
|
1036
|
+
# If FLAGGED block is absent from an agent's response, set that variable to '[]'
|
|
1037
|
+
merged_flagged_json=$(jq -s 'add // []' <(echo "$dev_flagged_json") <(echo "$ops_flagged_json"))
|
|
1038
|
+
|
|
1039
|
+
while IFS= read -r flagged; do
|
|
1040
|
+
flagged_card_id=$(echo "$flagged" | jq -r '.card_id')
|
|
1041
|
+
flagged_question=$(echo "$flagged" | jq -r '.question // "Needs clarification before decomposition"')
|
|
1042
|
+
monotask card comment add "$BOARD_ID" "$flagged_card_id" "Needs clarification: $flagged_question"
|
|
1043
|
+
monotask card move "$BOARD_ID" "$flagged_card_id" "$COL_ICED" --json
|
|
1044
|
+
done < <(echo "$merged_flagged_json" | jq -c '.[]')
|
|
941
1045
|
```
|
|
942
1046
|
|
|
943
1047
|
---
|
|
@@ -946,6 +1050,30 @@ monotask card move "$BOARD_ID" "$flagged_card_id" "$COL_ICED" --json
|
|
|
946
1050
|
|
|
947
1051
|
Follow _protocol.md Brain Write Procedure (namespace: `idea`).
|
|
948
1052
|
|
|
1053
|
+
**Write domain output to session file** so master Step 9 aggregation can include this domain. Skip silently if running standalone (no SESSION_ID in current.json):
|
|
1054
|
+
|
|
1055
|
+
```bash
|
|
1056
|
+
REPO_ROOT=$(git rev-parse --show-toplevel 2>/dev/null || pwd)
|
|
1057
|
+
SESSION_ID=$(jq -r '.sessionId // empty' "$REPO_ROOT/.monomind/sessions/current.json" 2>/dev/null)
|
|
1058
|
+
if [ -n "$SESSION_ID" ]; then
|
|
1059
|
+
mkdir -p "$REPO_ROOT/.monomind/sessions/${SESSION_ID}"
|
|
1060
|
+
CTRL_URL=$(jq -r '.url // "http://localhost:4242"' "$REPO_ROOT/.monomind/control.json" 2>/dev/null || echo "http://localhost:4242")
|
|
1061
|
+
# LLM: substitute <status>: complete (all steps ran), partial (some skipped), blocked (critical error)
|
|
1062
|
+
# LLM: substitute next_actions with actual suggestions derived from this run's top ideas
|
|
1063
|
+
jq -n \
|
|
1064
|
+
--arg domain "idea" \
|
|
1065
|
+
--arg status "<status>" \
|
|
1066
|
+
--argjson artifacts '[]' \
|
|
1067
|
+
--argjson next_actions '["<next_action_1>","<next_action_2>"]' \
|
|
1068
|
+
'{domain:$domain,status:$status,artifacts:$artifacts,next_actions:$next_actions}' \
|
|
1069
|
+
> "$REPO_ROOT/.monomind/sessions/${SESSION_ID}/idea.json"
|
|
1070
|
+
curl -s -o /dev/null -X POST "${CTRL_URL}/api/mastermind/event" \
|
|
1071
|
+
-H "Content-Type: application/json" \
|
|
1072
|
+
-d "$(jq -cn --arg sid "$SESSION_ID" --arg status "<status>" \
|
|
1073
|
+
'{type:"domain:complete",session:$sid,domain:"idea",status:$status,ts:(now*1000|floor)}')" || true
|
|
1074
|
+
fi
|
|
1075
|
+
```
|
|
1076
|
+
|
|
949
1077
|
Return unified output schema to caller:
|
|
950
1078
|
|
|
951
1079
|
```yaml
|
|
@@ -963,9 +1091,9 @@ lessons:
|
|
|
963
1091
|
next_actions:
|
|
964
1092
|
- <e.g. "run mastermind:build to prototype chosen direction">
|
|
965
1093
|
- <e.g. "run mastermind:research to validate top idea">
|
|
966
|
-
board_url: "monotask://<project_name
|
|
967
|
-
task_board_url: "monotask://<project_name
|
|
968
|
-
ops_task_board_url: "monotask://<project_name
|
|
1094
|
+
board_url: "monotask://<project_name>/${project_name}-idea"
|
|
1095
|
+
task_board_url: "monotask://<project_name>/${project_name}-tasks-dev"
|
|
1096
|
+
ops_task_board_url: "monotask://<project_name>/${project_name}-tasks-ops"
|
|
969
1097
|
run_id: <ISO8601-timestamp>
|
|
970
1098
|
summary:
|
|
971
1099
|
ideas_generated: N
|