@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
|
@@ -69,53 +69,60 @@ For simple prompts (single agent, single output):
|
|
|
69
69
|
Set up the space and ideation board. The ideation board has a dedicated pipeline with six columns (not master's board).
|
|
70
70
|
|
|
71
71
|
```bash
|
|
72
|
+
# Compatible with macOS bash 3.2
|
|
72
73
|
project_name="${project_name:-$(basename "$PWD")}"
|
|
73
74
|
date=$(date -u +%Y-%m-%dT%H:%M:%SZ)
|
|
75
|
+
idea_canonical="${project_name}-idea"
|
|
74
76
|
|
|
75
|
-
# Find or create space
|
|
76
|
-
space_id=$(monotask space list 2>/dev/null | awk -F'
|
|
77
|
-
[ -z "$space_id" ] && space_id=$(monotask space create "$project_name" 2
|
|
77
|
+
# Find or create space (by exact name)
|
|
78
|
+
space_id=$(monotask space list 2>/dev/null | awk -F'|' '{gsub(/^ +| +$/,"",$1);gsub(/^ +| +$/,"",$2);if($2==n)print $1}' n="$project_name" | head -1)
|
|
79
|
+
[ -z "$space_id" ] && space_id=$(monotask space create "$project_name" 2>/dev/null | grep -oE '[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}')
|
|
78
80
|
[ -z "$space_id" ] && { echo "ERROR: Could not find or create space '$project_name'"; exit 1; }
|
|
79
|
-
```
|
|
80
|
-
|
|
81
|
-
**Memory-first board lookup:** Check memory for `"mastermind-idea board_id"` in namespace `monomind`. If a board ID is returned, use it as `BOARD_ID` and look up the existing column IDs. Otherwise, create the board:
|
|
82
|
-
|
|
83
|
-
```bash
|
|
84
|
-
BOARD_ID=$(monotask board create "Ideas & Innovation" --json | jq -r '.id // empty')
|
|
85
|
-
[ -z "$BOARD_ID" ] && { echo "ERROR: Failed to create Ideas & Innovation board"; exit 1; }
|
|
86
|
-
monotask space boards add "$space_id" "$BOARD_ID" >/dev/null 2>&1 || true
|
|
87
|
-
npx monomind@latest memory store --key "mastermind-idea board_id" --value "$BOARD_ID" --namespace monomind
|
|
88
|
-
|
|
89
|
-
# Create columns in pipeline order
|
|
90
|
-
COL_NEW=$(monotask column create "$BOARD_ID" "New" --json | jq -r '.id')
|
|
91
|
-
COL_EVALUATED=$(monotask column create "$BOARD_ID" "Evaluated" --json | jq -r '.id')
|
|
92
|
-
COL_ELABORATED=$(monotask column create "$BOARD_ID" "Elaborated" --json | jq -r '.id')
|
|
93
|
-
COL_TASKED=$(monotask column create "$BOARD_ID" "Tasked" --json | jq -r '.id')
|
|
94
|
-
COL_ICED=$(monotask column create "$BOARD_ID" "Iced" --json | jq -r '.id')
|
|
95
|
-
COL_REJECTED=$(monotask column create "$BOARD_ID" "Rejected" --json | jq -r '.id')
|
|
96
|
-
```
|
|
97
81
|
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
[ -z "$
|
|
112
|
-
[ -z "$
|
|
113
|
-
[ -z "$
|
|
82
|
+
# Find existing idea board by canonical name — reuse across runs (same pattern as master Step 6)
|
|
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)
|
|
85
|
+
|
|
86
|
+
if [ -n "$BOARD_ID" ]; then
|
|
87
|
+
echo "Reusing idea board: $BOARD_ID ($idea_canonical)"
|
|
88
|
+
columns=$(monotask column list "$BOARD_ID" --json)
|
|
89
|
+
COL_NEW=$(echo "$columns" | jq -r '.[] | select(.title == "New") | .id' | head -1)
|
|
90
|
+
COL_EVALUATED=$(echo "$columns" | jq -r '.[] | select(.title == "Evaluated") | .id' | head -1)
|
|
91
|
+
COL_ELABORATED=$(echo "$columns"| jq -r '.[] | select(.title == "Elaborated") | .id' | head -1)
|
|
92
|
+
COL_TASKED=$(echo "$columns" | jq -r '.[] | select(.title == "Tasked") | .id' | head -1)
|
|
93
|
+
COL_ICED=$(echo "$columns" | jq -r '.[] | select(.title == "Iced") | .id' | head -1)
|
|
94
|
+
COL_REJECTED=$(echo "$columns" | jq -r '.[] | select(.title == "Rejected") | .id' | head -1)
|
|
95
|
+
[ -z "$COL_NEW" ] && { echo "ERROR: 'New' column missing on board $BOARD_ID — was board created with wrong schema?"; exit 1; }
|
|
96
|
+
[ -z "$COL_EVALUATED" ] && { echo "ERROR: 'Evaluated' column missing on board $BOARD_ID"; exit 1; }
|
|
97
|
+
[ -z "$COL_ELABORATED" ] && { echo "ERROR: 'Elaborated' column missing on board $BOARD_ID"; exit 1; }
|
|
98
|
+
[ -z "$COL_TASKED" ] && { echo "ERROR: 'Tasked' column missing on board $BOARD_ID"; exit 1; }
|
|
99
|
+
[ -z "$COL_ICED" ] && { echo "ERROR: 'Iced' column missing on board $BOARD_ID"; exit 1; }
|
|
100
|
+
[ -z "$COL_REJECTED" ] && { echo "ERROR: 'Rejected' column missing on board $BOARD_ID"; exit 1; }
|
|
101
|
+
else
|
|
102
|
+
echo "Creating idea board: $idea_canonical"
|
|
103
|
+
BOARD_ID=$(monotask board create --space "$space_id" "$idea_canonical" --json 2>/dev/null | jq -r '.id // empty')
|
|
104
|
+
[ -z "$BOARD_ID" ] && { echo "ERROR: Failed to create idea board '$idea_canonical'"; exit 1; }
|
|
105
|
+
monotask space boards add "$space_id" "$BOARD_ID" >/dev/null 2>&1 || true
|
|
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')
|
|
112
|
+
fi
|
|
114
113
|
```
|
|
115
114
|
|
|
116
115
|
**After either branch above, validate and echo all values.** This is the canonical source for Step 4 Task construction.
|
|
117
116
|
|
|
118
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
|
+
|
|
119
126
|
# Validate BOARD_ID looks like a UUID before proceeding
|
|
120
127
|
[[ ! "$BOARD_ID" =~ ^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$ ]] && \
|
|
121
128
|
{ echo "ERROR: BOARD_ID '$BOARD_ID' is not a valid UUID — aborting to prevent board name corruption"; exit 1; }
|
|
@@ -146,20 +153,26 @@ TOP_N=6
|
|
|
146
153
|
|
|
147
154
|
# Select user/market/ops angle specialists
|
|
148
155
|
CATEGORIES="marketing strategy product academic specialized"
|
|
149
|
-
user_market_agents=$(jq
|
|
156
|
+
user_market_agents=$(jq \
|
|
150
157
|
--arg cats "$CATEGORIES" \
|
|
151
158
|
--arg kw "$(echo "$PROMPT" | tr '[:upper:]' '[:lower:]' | grep -oE '[a-z]{5,}' | sort -u | tr '\n' ' ')" \
|
|
152
159
|
--argjson n "$TOP_N" \
|
|
153
160
|
'[ .agents[] | select(.deprecated != true)
|
|
154
161
|
| select(.category as $c | ($cats | split(" ") | any(. == $c)))
|
|
155
162
|
| {name: .name, slug: .slug, category: .category,
|
|
156
|
-
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
|
+
)}
|
|
157
170
|
] | sort_by(-.score) | unique_by(.slug) | .[0:$n] | [.[].name]' \
|
|
158
171
|
"$REGISTRY" 2>/dev/null)
|
|
159
172
|
|
|
160
173
|
# Select technical angle specialists
|
|
161
174
|
CATEGORIES="engineering development architecture"
|
|
162
|
-
tech_agents=$(jq
|
|
175
|
+
tech_agents=$(jq \
|
|
163
176
|
--arg cats "$CATEGORIES" \
|
|
164
177
|
--argjson n 3 \
|
|
165
178
|
'[ .agents[] | select(.deprecated != true)
|
|
@@ -169,11 +182,14 @@ tech_agents=$(jq -r \
|
|
|
169
182
|
"$REGISTRY" 2>/dev/null)
|
|
170
183
|
|
|
171
184
|
# Merge: take top 6 from market/ops + top 2 from tech (cap at 8 total)
|
|
172
|
-
|
|
173
|
-
|
|
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)
|
|
174
189
|
|
|
175
|
-
# Fallback if registry missing
|
|
176
|
-
|
|
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"]'
|
|
177
193
|
|
|
178
194
|
echo "Selected specialists: $specialist_list"
|
|
179
195
|
```
|
|
@@ -248,6 +264,7 @@ For each unique idea, create one card in the New column (COL_NEW = ${COL_NEW}):
|
|
|
248
264
|
|
|
249
265
|
result=$(monotask card create "${BOARD_ID}" "${COL_NEW}" "<idea title ≤80 chars>" --json)
|
|
250
266
|
CARD_ID=$(echo "$result" | jq -r '.id // empty')
|
|
267
|
+
[ -z "$CARD_ID" ] && { echo "WARN: card creation failed for '<idea title>', skipping"; continue; }
|
|
251
268
|
monotask card set-description "${BOARD_ID}" "$CARD_ID" "<2-3 sentence description>"
|
|
252
269
|
monotask card comment add "${BOARD_ID}" "$CARD_ID" "CATEGORY: <feature | technical-baseline | business-operation>
|
|
253
270
|
SOURCE: <which specialist angle produced this>"
|
|
@@ -274,7 +291,8 @@ Parse the `IDEAS_OUTPUT` JSON block from the agent's response and assign it:
|
|
|
274
291
|
```bash
|
|
275
292
|
ideas_output_json='<paste the JSON array from IDEAS_OUTPUT here>'
|
|
276
293
|
```
|
|
277
|
-
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).
|
|
278
296
|
|
|
279
297
|
---
|
|
280
298
|
|
|
@@ -291,11 +309,11 @@ ideas_list=$(echo "$ideas_output_json" | jq -r \
|
|
|
291
309
|
**CRITICAL — Variable substitution required for Step 5 Task call:**
|
|
292
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.
|
|
293
311
|
|
|
294
|
-
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.
|
|
295
313
|
|
|
296
314
|
```javascript
|
|
297
315
|
Task({
|
|
298
|
-
subagent_type: "
|
|
316
|
+
subagent_type: "general-purpose",
|
|
299
317
|
description: "PM validation for project " + project_name,
|
|
300
318
|
run_in_background: false,
|
|
301
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.
|
|
@@ -323,23 +341,31 @@ For EVERY idea above, determine:
|
|
|
323
341
|
- skipElaboration: true (simple, no deep research needed) | false (edge cases should be explored) — only for evaluated
|
|
324
342
|
- rationale: 1-2 sentence value statement (evaluated), blocking question (iced), or rejection reason (rejected)
|
|
325
343
|
|
|
326
|
-
MANDATORY BOARD UPDATES —
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
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 '.[]')
|
|
343
369
|
|
|
344
370
|
IMPORTANT: set-impact and set-effort MUST be called for every evaluated and iced idea. Do not skip them.
|
|
345
371
|
|
|
@@ -366,7 +392,8 @@ After the PM agent completes, parse the `VERDICTS_OUTPUT` block from the agent's
|
|
|
366
392
|
```bash
|
|
367
393
|
verdicts_output_json='<paste the JSON array from VERDICTS_OUTPUT here>'
|
|
368
394
|
```
|
|
369
|
-
|
|
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).
|
|
370
397
|
|
|
371
398
|
---
|
|
372
399
|
|
|
@@ -376,9 +403,20 @@ This variable is used throughout Steps 6a and 6c to build idea lists, registry k
|
|
|
376
403
|
|
|
377
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:
|
|
378
405
|
```bash
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
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)] | .[]')
|
|
382
420
|
```
|
|
383
421
|
|
|
384
422
|
For ideas with `skipElaboration: false`, **split by category** before spawning agents:
|
|
@@ -386,19 +424,23 @@ For ideas with `skipElaboration: false`, **split by category** before spawning a
|
|
|
386
424
|
**Build `dev_ideas_list` and `ops_ideas_list` before constructing the Step 6a Task prompts:**
|
|
387
425
|
```bash
|
|
388
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.
|
|
389
429
|
dev_ideas_list=$(echo "$verdicts_output_json" | jq -r \
|
|
390
|
-
'.[] | select(.verdict == "evaluated") | select(.
|
|
430
|
+
'.[] | select(.verdict == "evaluated") | select(.skipElaboration != true)
|
|
431
|
+
| select(.category == "feature" or .category == "technical-baseline") |
|
|
391
432
|
"- card_id: \(.card_id)\n title: \(.title)\n category: \(.category)\n rationale: \(.rationale)\n"')
|
|
392
433
|
|
|
393
434
|
ops_ideas_list=$(echo "$verdicts_output_json" | jq -r \
|
|
394
|
-
'.[] | select(.verdict == "evaluated") | select(.
|
|
435
|
+
'.[] | select(.verdict == "evaluated") | select(.skipElaboration != true)
|
|
436
|
+
| select(.category == "business-operation") |
|
|
395
437
|
"- card_id: \(.card_id)\n title: \(.title)\n category: \(.category)\n rationale: \(.rationale)\n"')
|
|
396
438
|
```
|
|
397
439
|
|
|
398
440
|
**CRITICAL — Variable substitution required for Step 6a Task calls:**
|
|
399
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.
|
|
400
442
|
|
|
401
|
-
**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):
|
|
402
444
|
Spawn two agents in parallel via Task tool:
|
|
403
445
|
|
|
404
446
|
```javascript
|
|
@@ -457,7 +499,7 @@ END_ELABORATION_OUTPUT`
|
|
|
457
499
|
})
|
|
458
500
|
```
|
|
459
501
|
|
|
460
|
-
**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):
|
|
461
503
|
Spawn two agents in parallel via Task tool:
|
|
462
504
|
|
|
463
505
|
```javascript
|
|
@@ -516,7 +558,7 @@ END_ELABORATION_OUTPUT`
|
|
|
516
558
|
})
|
|
517
559
|
```
|
|
518
560
|
|
|
519
|
-
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`:
|
|
520
562
|
|
|
521
563
|
```bash
|
|
522
564
|
# Assign each agent's ELABORATION_OUTPUT JSON array from its output block:
|
|
@@ -525,29 +567,45 @@ dev_codebase_json='<ELABORATION_OUTPUT array from the dev code-explorer agent>'
|
|
|
525
567
|
ops_researcher_json='<ELABORATION_OUTPUT array from the ops researcher agent>'
|
|
526
568
|
ops_pm_json='<ELABORATION_OUTPUT array from the ops PM agent>'
|
|
527
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 '[]'
|
|
528
571
|
|
|
529
|
-
# 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).
|
|
530
575
|
dev_merged=$(jq -n \
|
|
531
576
|
--argjson r "$dev_researcher_json" \
|
|
532
577
|
--argjson c "$dev_codebase_json" \
|
|
533
578
|
--argjson v "$verdicts_output_json" \
|
|
534
|
-
'[$r[] |
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
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).
|
|
540
592
|
ops_merged=$(jq -n \
|
|
541
593
|
--argjson r "$ops_researcher_json" \
|
|
542
594
|
--argjson p "$ops_pm_json" \
|
|
543
595
|
--argjson v "$verdicts_output_json" \
|
|
544
|
-
'[$r[] |
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
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") }]')
|
|
548
606
|
|
|
549
607
|
# Combine both tracks
|
|
550
|
-
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"))
|
|
551
609
|
```
|
|
552
610
|
|
|
553
611
|
Use process substitution (not a pipeline) so the while loop runs in the main shell and variables remain in scope after `done`:
|
|
@@ -556,7 +614,8 @@ Use process substitution (not a pipeline) so the while loop runs in the main she
|
|
|
556
614
|
while IFS= read -r idea; do
|
|
557
615
|
CARD_ID=$(echo "$idea" | jq -r '.card_id')
|
|
558
616
|
category=$(echo "$idea" | jq -r '.category')
|
|
559
|
-
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"
|
|
560
619
|
|
|
561
620
|
if [ "$category" = "business-operation" ]; then
|
|
562
621
|
researcher_findings=$(echo "$idea" | jq -r '.researcher_findings')
|
|
@@ -599,7 +658,7 @@ done < <(echo "$merged_elaboration_json" | jq -c '.[]')
|
|
|
599
658
|
|
|
600
659
|
**Confirm mode only:** If `mode` is `confirm` (default), present a review table of all elaborated ideas to the user.
|
|
601
660
|
|
|
602
|
-
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:
|
|
603
662
|
- **Impact** and **Effort** come from `.impact` and `.effort` fields in `verdicts_output_json`
|
|
604
663
|
- **Track**: `feature` or `technical-baseline` → `dev`; `business-operation` → `ops`
|
|
605
664
|
|
|
@@ -640,7 +699,7 @@ Wait for the user's response before continuing. Do not spawn any agents until a
|
|
|
640
699
|
```bash
|
|
641
700
|
monotask card comment add "$BOARD_ID" "$CARD_ID" "User notes: <notes>"
|
|
642
701
|
```
|
|
643
|
-
- **"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`.
|
|
644
703
|
- Combined instructions ("remove 2,4 | add detail to 1: ...") are processed together.
|
|
645
704
|
|
|
646
705
|
After applying all user instructions, proceed to Step 6c with the remaining ideas.
|
|
@@ -655,11 +714,7 @@ After applying all user instructions, proceed to Step 6c with the remaining idea
|
|
|
655
714
|
REGISTRY=".monomind/registry.json"
|
|
656
715
|
|
|
657
716
|
# Dev decomposition agent — pick the most relevant engineering/architecture specialist
|
|
658
|
-
# Build keyword signal from elaborated dev idea titles (from VERDICTS_OUTPUT filtered above)
|
|
659
|
-
DEV_IDEA_CONTEXT=$(echo "$verdicts_output_json" | jq -r \
|
|
660
|
-
'[.[] | select(.verdict=="evaluated") | select(.category=="feature" or .category=="technical-baseline") | .title] | join(" ")')
|
|
661
717
|
dev_decomp_agent=$(jq -r \
|
|
662
|
-
--arg kw "$(echo "$DEV_IDEA_CONTEXT" | tr '[:upper:]' '[:lower:]' | grep -oE '[a-z]{5,}' | sort -u | tr '\n' ' ')" \
|
|
663
718
|
'[ .agents[] | select(.deprecated != true)
|
|
664
719
|
| select(.category == "engineering" or .category == "architecture")
|
|
665
720
|
| {name: .name,
|
|
@@ -677,10 +732,7 @@ dev_decomp_agent=$(jq -r \
|
|
|
677
732
|
dev_decomp_agent="${dev_decomp_agent:-Software Architect}"
|
|
678
733
|
|
|
679
734
|
# Ops decomposition agent — pick the most relevant strategy/sales/product specialist
|
|
680
|
-
OPS_IDEA_CONTEXT=$(echo "$verdicts_output_json" | jq -r \
|
|
681
|
-
'[.[] | select(.verdict=="evaluated") | select(.category=="business-operation") | .title] | join(" ")')
|
|
682
735
|
ops_decomp_agent=$(jq -r \
|
|
683
|
-
--arg kw "$(echo "$OPS_IDEA_CONTEXT" | tr '[:upper:]' '[:lower:]' | grep -oE '[a-z]{5,}' | sort -u | tr '\n' ' ')" \
|
|
684
736
|
'[ .agents[] | select(.deprecated != true)
|
|
685
737
|
| select(.category == "strategy" or .category == "sales" or .category == "product" or .category == "marketing")
|
|
686
738
|
| {name: .name,
|
|
@@ -704,13 +756,29 @@ echo "Dev decomp: $dev_decomp_agent | Ops decomp: $ops_decomp_agent"
|
|
|
704
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:
|
|
705
757
|
|
|
706
758
|
```bash
|
|
707
|
-
#
|
|
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).
|
|
708
770
|
dev_ideas_elaborated=$(echo "$verdicts_output_json" | jq -r \
|
|
709
|
-
|
|
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") |
|
|
710
775
|
"card_id: \(.card_id)\ntitle: \(.title)\ncategory: \(.category)\nrationale: \(.rationale)\nimpact: \(.impact) effort: \(.effort)"] | join("\n\n")')
|
|
711
776
|
|
|
712
777
|
ops_ideas_elaborated=$(echo "$verdicts_output_json" | jq -r \
|
|
713
|
-
|
|
778
|
+
--argjson blocked "$elaboration_blocked" \
|
|
779
|
+
'[.[] | select(.verdict=="evaluated")
|
|
780
|
+
| select(.card_id as $id | ($blocked | any(. == $id)) | not)
|
|
781
|
+
| select(.category=="business-operation") |
|
|
714
782
|
"card_id: \(.card_id)\ntitle: \(.title)\ncategory: \(.category)\nrationale: \(.rationale)\nimpact: \(.impact) effort: \(.effort)"] | join("\n\n")')
|
|
715
783
|
```
|
|
716
784
|
|
|
@@ -802,56 +870,77 @@ END_TASKS_OUTPUT`
|
|
|
802
870
|
|
|
803
871
|
**Dev task board** (`feature` / `technical-baseline` → `Implementation Tasks`):
|
|
804
872
|
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
```bash
|
|
808
|
-
TASK_BOARD_ID=$(monotask board create "Implementation Tasks" --json | jq -r '.id // empty')
|
|
809
|
-
monotask space boards add "$space_id" "$TASK_BOARD_ID" >/dev/null 2>&1 || true
|
|
810
|
-
npx monomind@latest memory store --key "implementation-tasks board_id" --value "$TASK_BOARD_ID" --namespace monomind
|
|
811
|
-
monotask column create "$TASK_BOARD_ID" "Backlog" --json >/dev/null
|
|
812
|
-
monotask column create "$TASK_BOARD_ID" "Todo" --json >/dev/null
|
|
813
|
-
monotask column create "$TASK_BOARD_ID" "In Progress" --json >/dev/null
|
|
814
|
-
monotask column create "$TASK_BOARD_ID" "Review" --json >/dev/null
|
|
815
|
-
monotask column create "$TASK_BOARD_ID" "Human in Loop" --json >/dev/null
|
|
816
|
-
monotask column create "$TASK_BOARD_ID" "Done" --json >/dev/null
|
|
817
|
-
```
|
|
873
|
+
Canonical board name: `${project_name}-tasks-dev`. Find-or-create:
|
|
818
874
|
|
|
819
|
-
Look up and validate column IDs:
|
|
820
875
|
```bash
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
[ -z "$
|
|
826
|
-
|
|
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
|
|
882
|
+
dev_task_canonical="${project_name}-tasks-dev"
|
|
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)
|
|
885
|
+
if [ -n "$TASK_BOARD_ID" ]; then
|
|
886
|
+
echo "Reusing dev task board: $TASK_BOARD_ID ($dev_task_canonical)"
|
|
887
|
+
task_columns=$(monotask column list "$TASK_BOARD_ID" --json)
|
|
888
|
+
TASK_COL_TODO=$(echo "$task_columns" | jq -r '.[] | select(.title=="Todo") | .id' | head -1)
|
|
889
|
+
TASK_COL_BACKLOG=$(echo "$task_columns" | jq -r '.[] | select(.title=="Backlog") | .id' | head -1)
|
|
890
|
+
else
|
|
891
|
+
echo "Creating dev task board: $dev_task_canonical"
|
|
892
|
+
TASK_BOARD_ID=$(monotask board create --space "$space_id" "$dev_task_canonical" --json 2>/dev/null | jq -r '.id // empty')
|
|
893
|
+
[ -z "$TASK_BOARD_ID" ] && { echo "ERROR: Failed to create dev task board"; exit 1; }
|
|
894
|
+
monotask space boards add "$space_id" "$TASK_BOARD_ID" >/dev/null 2>&1 || true
|
|
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')
|
|
897
|
+
monotask column create "$TASK_BOARD_ID" "In Progress" --json >/dev/null
|
|
898
|
+
monotask column create "$TASK_BOARD_ID" "Human in Loop" --json >/dev/null
|
|
899
|
+
monotask column create "$TASK_BOARD_ID" "Review" --json >/dev/null
|
|
900
|
+
monotask column create "$TASK_BOARD_ID" "Done" --json >/dev/null
|
|
901
|
+
monotask column create "$TASK_BOARD_ID" "Cancelled" --json >/dev/null
|
|
902
|
+
fi
|
|
903
|
+
[ -z "$TASK_BOARD_ID" ] && { echo "ERROR: TASK_BOARD_ID empty — aborting"; exit 1; }
|
|
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; }
|
|
827
906
|
```
|
|
828
907
|
|
|
829
908
|
---
|
|
830
909
|
|
|
831
910
|
**Ops task board** (`business-operation` → `Operations Tasks`):
|
|
832
911
|
|
|
833
|
-
|
|
912
|
+
Canonical board name: `${project_name}-tasks-ops`. Find-or-create:
|
|
834
913
|
|
|
835
914
|
```bash
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
monotask
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
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
|
|
920
|
+
ops_task_canonical="${project_name}-tasks-ops"
|
|
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)
|
|
923
|
+
if [ -n "$OPS_BOARD_ID" ]; then
|
|
924
|
+
echo "Reusing ops task board: $OPS_BOARD_ID ($ops_task_canonical)"
|
|
925
|
+
ops_columns=$(monotask column list "$OPS_BOARD_ID" --json)
|
|
926
|
+
OPS_COL_TODO=$(echo "$ops_columns" | jq -r '.[] | select(.title=="Todo") | .id' | head -1)
|
|
927
|
+
OPS_COL_BACKLOG=$(echo "$ops_columns" | jq -r '.[] | select(.title=="Backlog") | .id' | head -1)
|
|
928
|
+
else
|
|
929
|
+
echo "Creating ops task board: $ops_task_canonical"
|
|
930
|
+
OPS_BOARD_ID=$(monotask board create --space "$space_id" "$ops_task_canonical" --json 2>/dev/null | jq -r '.id // empty')
|
|
931
|
+
[ -z "$OPS_BOARD_ID" ] && { echo "ERROR: Failed to create ops task board"; exit 1; }
|
|
932
|
+
monotask space boards add "$space_id" "$OPS_BOARD_ID" >/dev/null 2>&1 || true
|
|
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')
|
|
935
|
+
monotask column create "$OPS_BOARD_ID" "In Progress" --json >/dev/null
|
|
936
|
+
monotask column create "$OPS_BOARD_ID" "Human in Loop" --json >/dev/null
|
|
937
|
+
monotask column create "$OPS_BOARD_ID" "Review" --json >/dev/null
|
|
938
|
+
monotask column create "$OPS_BOARD_ID" "Done" --json >/dev/null
|
|
939
|
+
monotask column create "$OPS_BOARD_ID" "Cancelled" --json >/dev/null
|
|
940
|
+
fi
|
|
941
|
+
[ -z "$OPS_BOARD_ID" ] && { echo "ERROR: OPS_BOARD_ID empty — aborting"; exit 1; }
|
|
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; }
|
|
855
944
|
```
|
|
856
945
|
|
|
857
946
|
---
|
|
@@ -863,13 +952,13 @@ OPS_COL_BACKLOG=$(echo "$ops_columns" | jq -r '.[] | select(.title == "Backlog")
|
|
|
863
952
|
dev_tasks_json='<TASKS_OUTPUT JSON array from dev decomp agent, or [] if no dev ideas>'
|
|
864
953
|
# Parse the TASKS_OUTPUT block from the ops decomp agent's response and assign:
|
|
865
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 '[]'
|
|
866
956
|
|
|
867
|
-
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"))
|
|
868
958
|
|
|
869
|
-
# Use
|
|
870
|
-
#
|
|
871
|
-
|
|
872
|
-
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)
|
|
873
962
|
|
|
874
963
|
while IFS= read -r task; do
|
|
875
964
|
parent_card_id=$(echo "$task" | jq -r '.parent_card_id')
|
|
@@ -881,59 +970,78 @@ while IFS= read -r task; do
|
|
|
881
970
|
has_prerequisites=$(echo "$task" | jq -r '.has_prerequisites')
|
|
882
971
|
|
|
883
972
|
if [ "$category" = "business-operation" ]; then
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
else
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
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
|
|
892
981
|
|
|
893
|
-
# Inherit impact and effort from parent idea — look up from verdicts_output_json by parent_card_id
|
|
894
|
-
parent_impact=$(echo "$verdicts_output_json" | jq -r --arg id "$parent_card_id" '.[] | select(.card_id == $id) | .impact // 5')
|
|
895
|
-
parent_effort=$(echo "$verdicts_output_json" | jq -r --arg id "$parent_card_id" '.[] | select(.card_id == $id) | .effort // 5')
|
|
896
|
-
# Default to 5 if lookup returned empty (e.g. parent_card_id was "UNKNOWN")
|
|
897
|
-
[ -z "$parent_impact" ] && parent_impact=5
|
|
898
|
-
[ -z "$parent_effort" ] && parent_effort=5
|
|
899
|
-
|
|
900
|
-
# Create task card as a proper subtask of the parent idea card (cross-board link)
|
|
901
|
-
# Signature: subtask add <PARENT_BOARD_ID> <PARENT_CARD_ID> <CHILD_BOARD_ID> <COL_ID> <TITLE>
|
|
902
|
-
TASK_CARD_ID=$(monotask card subtask add "$BOARD_ID" "$parent_card_id" "$TARGET_BOARD" "$COL_TARGET" "
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
monotask card set-
|
|
906
|
-
monotask card set-
|
|
907
|
-
monotask card
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
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"
|
|
919
1013
|
|
|
920
1014
|
done < <(echo "$merged_tasks_json" | jq -c '.[]')
|
|
921
1015
|
```
|
|
922
1016
|
|
|
923
1017
|
After the loop, annotate each parent idea card and move it to `Tasked`:
|
|
924
1018
|
```bash
|
|
925
|
-
for
|
|
926
|
-
|
|
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")
|
|
927
1023
|
monotask card comment add "$BOARD_ID" "$parent_card_id" \
|
|
928
|
-
"Subtasks created
|
|
1024
|
+
"Subtasks created:
|
|
1025
|
+
${subtask_list}"
|
|
929
1026
|
monotask card move "$BOARD_ID" "$parent_card_id" "$COL_TASKED" --json
|
|
930
1027
|
done
|
|
1028
|
+
rm -rf "$SUBTASK_TMPDIR"
|
|
931
1029
|
```
|
|
932
1030
|
|
|
933
|
-
For each entry in FLAGGED,
|
|
1031
|
+
For each entry in FLAGGED, parse the flagged JSON from both decomp agents' FLAGGED blocks and iterate:
|
|
934
1032
|
```bash
|
|
935
|
-
|
|
936
|
-
|
|
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 '.[]')
|
|
937
1045
|
```
|
|
938
1046
|
|
|
939
1047
|
---
|
|
@@ -942,6 +1050,30 @@ monotask card move "$BOARD_ID" "$flagged_card_id" "$COL_ICED" --json
|
|
|
942
1050
|
|
|
943
1051
|
Follow _protocol.md Brain Write Procedure (namespace: `idea`).
|
|
944
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
|
+
|
|
945
1077
|
Return unified output schema to caller:
|
|
946
1078
|
|
|
947
1079
|
```yaml
|
|
@@ -959,9 +1091,9 @@ lessons:
|
|
|
959
1091
|
next_actions:
|
|
960
1092
|
- <e.g. "run mastermind:build to prototype chosen direction">
|
|
961
1093
|
- <e.g. "run mastermind:research to validate top idea">
|
|
962
|
-
board_url: "monotask://<project_name
|
|
963
|
-
task_board_url: "monotask://<project_name
|
|
964
|
-
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"
|
|
965
1097
|
run_id: <ISO8601-timestamp>
|
|
966
1098
|
summary:
|
|
967
1099
|
ideas_generated: N
|