@monoes/monomindcli 1.9.15 → 1.9.16
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.
|
@@ -166,89 +166,77 @@ If mode = auto: proceed immediately.
|
|
|
166
166
|
|
|
167
167
|
Follow the Monotask Space+Board Setup Procedure from `_protocol.md`. Resolve the space **once**, then create one board per active domain. Use `project_name` as the space name so all boards across repos and domains share the same space.
|
|
168
168
|
|
|
169
|
-
|
|
170
|
-
# Require bash 4.3+ for associative arrays and namerefs (local -n introduced in 4.3)
|
|
171
|
-
# macOS ships bash 3.2; install via: brew install bash
|
|
172
|
-
(( BASH_VERSINFO[0] * 100 + BASH_VERSINFO[1] < 403 )) && \
|
|
173
|
-
{ echo "ERROR: bash 4.3+ required for namerefs (current: $BASH_VERSION). Install: brew install bash"; exit 1; }
|
|
169
|
+
**Board naming convention:** Every board is named `<project_name>-<domain>` (e.g. `factory-idea`, `factory-build`). This canonical name is stable across runs — mastermind finds the existing board instead of creating a new one every time.
|
|
174
170
|
|
|
171
|
+
```bash
|
|
172
|
+
# Compatible with macOS bash 3.2 — no associative arrays, uses jq accumulation instead
|
|
175
173
|
REPO_ROOT=$(git rev-parse --show-toplevel 2>/dev/null || pwd)
|
|
176
174
|
SESSION_STATE="$REPO_ROOT/.monomind/sessions/current.json"
|
|
177
175
|
|
|
178
|
-
# Reload persisted context (this is a fresh shell; Step 3 wrote these)
|
|
179
176
|
SESSION_ID=$(jq -r '.sessionId // empty' "$SESSION_STATE" 2>/dev/null)
|
|
180
177
|
[ -z "$SESSION_ID" ] && { echo "ERROR: SESSION_ID missing in current.json — run Step 3 first"; exit 1; }
|
|
181
178
|
project_name=$(jq -r '.project_name // ""' "$SESSION_STATE")
|
|
182
179
|
[ -z "$project_name" ] && { echo "ERROR: project_name is empty in current.json — run Step 3 first"; exit 1; }
|
|
183
180
|
resolved_prompt=$(jq -r '.prompt // ""' "$SESSION_STATE")
|
|
184
181
|
|
|
185
|
-
# domains_needed: NOT yet in current.json at this point — must be LLM-substituted inline.
|
|
186
182
|
# LLM: replace DOMAINS_LIST_HERE with space-separated domain names, e.g.: build marketing sales
|
|
187
|
-
|
|
183
|
+
domains_needed="DOMAINS_LIST_HERE"
|
|
184
|
+
[ "$domains_needed" = "DOMAINS_LIST_HERE" ] && { echo "ERROR: LLM did not substitute DOMAINS_LIST_HERE"; exit 1; }
|
|
185
|
+
[ -z "$domains_needed" ] && { echo "ERROR: domains_needed is empty — nothing to do"; exit 1; }
|
|
188
186
|
|
|
189
|
-
# Resolve space once
|
|
190
|
-
|
|
191
|
-
space_id=$(monotask space list 2>/dev/null | awk -F'|' '{gsub(/^ +| +$/,"",$2); if($2==n) gsub(/^ +| +$/,"",$1); if($2==n) print $1}' n="$project_name" | head -1)
|
|
187
|
+
# Resolve space once — find existing by exact name or create
|
|
188
|
+
space_id=$(monotask space list 2>/dev/null | awk -F'|' '{gsub(/^ +| +$/,"",$1);gsub(/^ +| +$/,"",$2);if($2==n)print $1}' n="$project_name" | head -1)
|
|
192
189
|
[ -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}')
|
|
193
190
|
[ -z "$space_id" ] && { echo "ERROR: Could not find or create space '$project_name'"; exit 1; }
|
|
191
|
+
echo "Space: $space_id ($project_name)"
|
|
194
192
|
|
|
195
|
-
#
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
# Hydrate domain_goals from Step 4's current.json write — prevents Step 4 extraction being clobbered
|
|
199
|
-
# Use NUL-delimited pairs (not @tsv) to safely handle backslashes, tabs, and other special chars in goals
|
|
200
|
-
while IFS= read -r -d '' k && IFS= read -r -d '' v; do
|
|
201
|
-
[[ -n "$k" ]] && domain_goals[$k]="$v"
|
|
202
|
-
done < <(jq -j '.domain_goals // {} | to_entries[] | (.key + "\u0000" + (.value // "") + "\u0000")' "$SESSION_STATE" 2>/dev/null)
|
|
193
|
+
# jq accumulation state (replaces bash 4.3+ associative arrays)
|
|
194
|
+
state_patch='{}'
|
|
203
195
|
|
|
204
|
-
# Loop over every active domain — LLM: replace DOMAINS_LIST_HERE with the resolved domain list
|
|
205
|
-
domains_needed="DOMAINS_LIST_HERE"
|
|
206
|
-
[ "$domains_needed" = "DOMAINS_LIST_HERE" ] && { echo "ERROR: LLM did not substitute DOMAINS_LIST_HERE with domain names"; exit 1; }
|
|
207
|
-
[ -z "$domains_needed" ] && { echo "ERROR: domains_needed is empty — nothing to do"; exit 1; }
|
|
208
196
|
for domain in $domains_needed; do
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
[ -
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
197
|
+
canonical="${project_name}-${domain}"
|
|
198
|
+
|
|
199
|
+
# Find existing board by canonical name — reuse across runs
|
|
200
|
+
board_id=$(monotask board list 2>/dev/null | awk -F'|' '{gsub(/^ +| +$/,"",$1);gsub(/^ +| +$/,"",$2);if($2==n)print $1}' n="$canonical" | head -1)
|
|
201
|
+
|
|
202
|
+
if [ -n "$board_id" ]; then
|
|
203
|
+
echo "Reusing board: $board_id ($canonical)"
|
|
204
|
+
# Fetch existing column IDs
|
|
205
|
+
cols_json=$(monotask column list "$board_id" --json 2>/dev/null || echo '[]')
|
|
206
|
+
todo_col=$(echo "$cols_json" | jq -r '[.[] | select(.title=="Todo" or .title=="Backlog")] | .[0].id // empty')
|
|
207
|
+
doing_col=$(echo "$cols_json" | jq -r '[.[] | select(.title=="Doing" or .title=="In Progress")] | .[0].id // empty')
|
|
208
|
+
done_col=$(echo "$cols_json" | jq -r '[.[] | select(.title=="Done")] | .[0].id // empty')
|
|
209
|
+
else
|
|
210
|
+
echo "Creating board: $canonical"
|
|
211
|
+
board_id=$(monotask board create --space "$space_id" "$canonical" --json 2>/dev/null | jq -r '.id // empty')
|
|
212
|
+
[ -z "$board_id" ] && { echo "ERROR: Failed to create board '$canonical'"; exit 1; }
|
|
213
|
+
monotask space boards add "$space_id" "$board_id" >/dev/null 2>&1 || true
|
|
214
|
+
todo_col=$(monotask column create "$board_id" "Todo" --json | jq -r '.id // empty')
|
|
215
|
+
[ -z "$todo_col" ] && { echo "ERROR: Failed to create Todo column for $domain"; exit 1; }
|
|
216
|
+
doing_col=$(monotask column create "$board_id" "Doing" --json | jq -r '.id // empty')
|
|
217
|
+
[ -z "$doing_col" ] && { echo "ERROR: Failed to create Doing column for $domain"; exit 1; }
|
|
218
|
+
done_col=$(monotask column create "$board_id" "Done" --json | jq -r '.id // empty')
|
|
219
|
+
[ -z "$done_col" ] && { echo "ERROR: Failed to create Done column for $domain"; exit 1; }
|
|
220
|
+
fi
|
|
226
221
|
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
_to_json_map() {
|
|
230
|
-
local -n _arr=$1
|
|
231
|
-
for k in "${!_arr[@]}"; do
|
|
232
|
-
jq -n --arg k "$k" --arg v "${_arr[$k]}" '{key:$k,value:$v}'
|
|
233
|
-
done | jq -s 'from_entries // {}'
|
|
234
|
-
}
|
|
235
|
-
domains_goals_json=$(_to_json_map domain_goals)
|
|
236
|
-
board_ids_json=$(_to_json_map board_ids)
|
|
237
|
-
todo_cols_json=$(_to_json_map todo_cols)
|
|
238
|
-
doing_cols_json=$(_to_json_map doing_cols)
|
|
239
|
-
done_cols_json=$(_to_json_map done_cols)
|
|
222
|
+
domain_goal=$(jq -r --arg d "$domain" '.domain_goals[$d] // empty' "$SESSION_STATE")
|
|
223
|
+
[ -z "$domain_goal" ] && domain_goal="$resolved_prompt"
|
|
240
224
|
|
|
225
|
+
state_patch=$(echo "$state_patch" | jq \
|
|
226
|
+
--arg d "$domain" --arg b "$board_id" \
|
|
227
|
+
--arg t "$todo_col" --arg g "$doing_col" --arg e "$done_col" \
|
|
228
|
+
--arg goal "$domain_goal" \
|
|
229
|
+
'.board_ids[$d]=$b | .todo_cols[$d]=$t | .doing_cols[$d]=$g | .done_cols[$d]=$e | .domain_goals[$d]=$goal')
|
|
230
|
+
|
|
231
|
+
echo "DOMAIN=$domain BOARD=$board_id TODO=$todo_col DOING=$doing_col DONE=$done_col"
|
|
232
|
+
done
|
|
233
|
+
|
|
234
|
+
# Persist to current.json — one atomic merge
|
|
241
235
|
jq --arg domains "$domains_needed" \
|
|
242
|
-
--argjson
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
--argjson dones "$done_cols_json" \
|
|
247
|
-
'. + {domains_needed:($domains | split(" ") | map(select(length>0))),
|
|
248
|
-
domain_goals:$goals, board_ids:$boards,
|
|
249
|
-
todo_cols:$todos, doing_cols:$doings, done_cols:$dones}' \
|
|
250
|
-
"$REPO_ROOT/.monomind/sessions/current.json" > "$REPO_ROOT/.monomind/sessions/current.json.tmp" \
|
|
251
|
-
&& mv "$REPO_ROOT/.monomind/sessions/current.json.tmp" "$REPO_ROOT/.monomind/sessions/current.json"
|
|
236
|
+
--argjson patch "$state_patch" \
|
|
237
|
+
'. + $patch + {domains_needed:($domains | split(" ") | map(select(length>0)))}' \
|
|
238
|
+
"$SESSION_STATE" > "$SESSION_STATE.tmp" && mv "$SESSION_STATE.tmp" "$SESSION_STATE"
|
|
239
|
+
echo "Session state saved to current.json"
|
|
252
240
|
```
|
|
253
241
|
|
|
254
242
|
### Step 7 — Spawn Domain Managers
|
|
@@ -247,53 +247,78 @@ curl -s -o /dev/null -X POST "http://localhost:4242/api/mastermind/event" \
|
|
|
247
247
|
|
|
248
248
|
**Always follow this exact order — never create a board without first ensuring a space exists.**
|
|
249
249
|
|
|
250
|
+
**Board naming convention:** Boards are named `<project_name>-<domain>` (e.g. `factory-idea`, `factory-build`). This canonical name is stable across runs — find the existing board first, create only if it does not exist.
|
|
251
|
+
|
|
250
252
|
Every mastermind run that needs a task board MUST:
|
|
251
253
|
1. Resolve the space (find existing or create new) — space name = `project_name`
|
|
252
|
-
2.
|
|
253
|
-
3.
|
|
254
|
-
4. Create
|
|
255
|
-
5. Create cards within those columns
|
|
254
|
+
2. Find existing board by canonical name `<project_name>-<domain>` or create it with `--space`
|
|
255
|
+
3. Fetch column IDs from existing board OR create columns for new board
|
|
256
|
+
4. Create cards within those columns
|
|
256
257
|
|
|
257
258
|
If the user is running across multiple repos for the same project, they MUST use the same `project_name` so all boards land in one space.
|
|
258
259
|
|
|
259
260
|
### Canonical bash block (substitute `<domain>` with: build, marketing, ops, content, etc.)
|
|
260
261
|
|
|
261
262
|
```bash
|
|
262
|
-
#
|
|
263
|
+
# Compatible with macOS bash 3.2
|
|
263
264
|
project_name="${project_name:-$(basename "$PWD")}"
|
|
264
|
-
|
|
265
|
-
[ -z "$space_id" ] && space_id=$(monotask space create "$project_name" 2>&1 | grep -oE '[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}')
|
|
266
|
-
[ -z "$space_id" ] && { echo "ERROR: Could not find or create space '$project_name' — verify monotask is installed (monotask --version)"; exit 1; }
|
|
265
|
+
canonical="${project_name}-<domain>"
|
|
267
266
|
|
|
268
|
-
# Step
|
|
269
|
-
|
|
270
|
-
[ -z "$
|
|
271
|
-
|
|
272
|
-
# Step 3 — Link board to space immediately
|
|
273
|
-
monotask space boards add "$space_id" "$board_id" >/dev/null 2>&1 || true
|
|
267
|
+
# Step 1 — Resolve space
|
|
268
|
+
space_id=$(monotask space list 2>/dev/null | awk -F'|' '{gsub(/^ +| +$/,"",$1);gsub(/^ +| +$/,"",$2);if($2==n)print $1}' n="$project_name" | head -1)
|
|
269
|
+
[ -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}')
|
|
270
|
+
[ -z "$space_id" ] && { echo "ERROR: Could not find or create space '$project_name' — verify monotask is installed (monotask --version)"; exit 1; }
|
|
274
271
|
|
|
275
|
-
# Step
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
272
|
+
# Step 2 — Find existing board by canonical name or create
|
|
273
|
+
board_id=$(monotask board list 2>/dev/null | awk -F'|' '{gsub(/^ +| +$/,"",$1);gsub(/^ +| +$/,"",$2);if($2==n)print $1}' n="$canonical" | head -1)
|
|
274
|
+
if [ -n "$board_id" ]; then
|
|
275
|
+
# Step 3a — Fetch column IDs from existing board
|
|
276
|
+
cols_json=$(monotask column list "$board_id" --json 2>/dev/null || echo '[]')
|
|
277
|
+
todo_col=$(echo "$cols_json" | jq -r '[.[] | select(.title=="Todo" or .title=="Backlog")] | .[0].id // empty')
|
|
278
|
+
doing_col=$(echo "$cols_json" | jq -r '[.[] | select(.title=="Doing" or .title=="In Progress")] | .[0].id // empty')
|
|
279
|
+
done_col=$(echo "$cols_json" | jq -r '[.[] | select(.title=="Done")] | .[0].id // empty')
|
|
280
|
+
else
|
|
281
|
+
# Step 3b — Create board and columns
|
|
282
|
+
board_id=$(monotask board create --space "$space_id" "$canonical" --json | jq -r '.id // empty')
|
|
283
|
+
[ -z "$board_id" ] && { echo "ERROR: Failed to create board '$canonical'"; exit 1; }
|
|
284
|
+
monotask space boards add "$space_id" "$board_id" >/dev/null 2>&1 || true
|
|
285
|
+
todo_col=$(monotask column create "$board_id" "Todo" --json | jq -r '.id')
|
|
286
|
+
doing_col=$(monotask column create "$board_id" "Doing" --json | jq -r '.id')
|
|
287
|
+
done_col=$(monotask column create "$board_id" "Done" --json | jq -r '.id')
|
|
288
|
+
fi
|
|
279
289
|
```
|
|
280
290
|
|
|
281
|
-
When master.md runs multiple domains, resolve the space **once** before the loop, then repeat steps 2–
|
|
291
|
+
When master.md runs multiple domains, resolve the space **once** before the loop, then repeat steps 2–3 per domain using jq accumulation (no bash 4.3+ needed):
|
|
282
292
|
|
|
283
293
|
```bash
|
|
284
|
-
#
|
|
294
|
+
# Compatible with macOS bash 3.2 — jq accumulation instead of declare -A
|
|
285
295
|
project_name="<resolved project_name>"
|
|
286
|
-
space_id=$(monotask space list 2>/dev/null | awk -F'
|
|
287
|
-
[ -z "$space_id" ] && space_id=$(monotask space create "$project_name" 2
|
|
296
|
+
space_id=$(monotask space list 2>/dev/null | awk -F'|' '{gsub(/^ +| +$/,"",$1);gsub(/^ +| +$/,"",$2);if($2==n)print $1}' n="$project_name" | head -1)
|
|
297
|
+
[ -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}')
|
|
288
298
|
[ -z "$space_id" ] && { echo "ERROR: Could not find or create space '$project_name'"; exit 1; }
|
|
289
299
|
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
monotask
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
300
|
+
state_patch='{}'
|
|
301
|
+
for domain in build marketing ops; do # substitute actual domain list
|
|
302
|
+
canonical="${project_name}-${domain}"
|
|
303
|
+
board_id=$(monotask board list 2>/dev/null | awk -F'|' '{gsub(/^ +| +$/,"",$1);gsub(/^ +| +$/,"",$2);if($2==n)print $1}' n="$canonical" | head -1)
|
|
304
|
+
if [ -n "$board_id" ]; then
|
|
305
|
+
cols_json=$(monotask column list "$board_id" --json 2>/dev/null || echo '[]')
|
|
306
|
+
todo_col=$(echo "$cols_json" | jq -r '[.[] | select(.title=="Todo" or .title=="Backlog")] | .[0].id // empty')
|
|
307
|
+
doing_col=$(echo "$cols_json" | jq -r '[.[] | select(.title=="Doing" or .title=="In Progress")] | .[0].id // empty')
|
|
308
|
+
done_col=$(echo "$cols_json" | jq -r '[.[] | select(.title=="Done")] | .[0].id // empty')
|
|
309
|
+
else
|
|
310
|
+
board_id=$(monotask board create --space "$space_id" "$canonical" --json | jq -r '.id // empty')
|
|
311
|
+
[ -z "$board_id" ] && { echo "ERROR: Failed to create $canonical board"; exit 1; }
|
|
312
|
+
monotask space boards add "$space_id" "$board_id" >/dev/null 2>&1 || true
|
|
313
|
+
todo_col=$(monotask column create "$board_id" "Todo" --json | jq -r '.id')
|
|
314
|
+
doing_col=$(monotask column create "$board_id" "Doing" --json | jq -r '.id')
|
|
315
|
+
done_col=$(monotask column create "$board_id" "Done" --json | jq -r '.id')
|
|
316
|
+
fi
|
|
317
|
+
state_patch=$(echo "$state_patch" | jq \
|
|
318
|
+
--arg d "$domain" --arg b "$board_id" \
|
|
319
|
+
--arg t "$todo_col" --arg g "$doing_col" --arg e "$done_col" \
|
|
320
|
+
'.board_ids[$d]=$b | .todo_cols[$d]=$t | .doing_cols[$d]=$g | .done_cols[$d]=$e')
|
|
321
|
+
done
|
|
297
322
|
```
|
|
298
323
|
|
|
299
324
|
---
|
|
@@ -105,6 +105,12 @@ COL_ELABORATED=$(echo "$columns"| jq -r '.[] | select(.title == "Elaborated") |
|
|
|
105
105
|
COL_TASKED=$(echo "$columns" | jq -r '.[] | select(.title == "Tasked") | .id' | head -1)
|
|
106
106
|
COL_ICED=$(echo "$columns" | jq -r '.[] | select(.title == "Iced") | .id' | head -1)
|
|
107
107
|
COL_REJECTED=$(echo "$columns" | jq -r '.[] | select(.title == "Rejected") | .id' | head -1)
|
|
108
|
+
[ -z "$COL_NEW" ] && { echo "ERROR: Could not find 'New' column on BOARD_ID=$BOARD_ID"; exit 1; }
|
|
109
|
+
[ -z "$COL_EVALUATED" ] && { echo "ERROR: Could not find 'Evaluated' column on BOARD_ID=$BOARD_ID"; exit 1; }
|
|
110
|
+
[ -z "$COL_ELABORATED" ] && { echo "ERROR: Could not find 'Elaborated' column on BOARD_ID=$BOARD_ID"; exit 1; }
|
|
111
|
+
[ -z "$COL_TASKED" ] && { echo "ERROR: Could not find 'Tasked' column on BOARD_ID=$BOARD_ID"; exit 1; }
|
|
112
|
+
[ -z "$COL_ICED" ] && { echo "ERROR: Could not find 'Iced' column on BOARD_ID=$BOARD_ID"; exit 1; }
|
|
113
|
+
[ -z "$COL_REJECTED" ] && { echo "ERROR: Could not find 'Rejected' column on BOARD_ID=$BOARD_ID"; exit 1; }
|
|
108
114
|
```
|
|
109
115
|
|
|
110
116
|
**After either branch above, validate and echo all values.** This is the canonical source for Step 4 Task construction.
|
|
@@ -510,44 +516,81 @@ END_ELABORATION_OUTPUT`
|
|
|
510
516
|
})
|
|
511
517
|
```
|
|
512
518
|
|
|
513
|
-
|
|
519
|
+
Wait for all background agents to complete (do not proceed until all — or two, if only one category — return ELABORATION_OUTPUT blocks). Then build `merged_elaboration_json` by merging agent outputs per `card_id` and injecting `category` from `verdicts_output_json`:
|
|
514
520
|
|
|
515
521
|
```bash
|
|
516
|
-
#
|
|
517
|
-
|
|
518
|
-
|
|
522
|
+
# Assign each agent's ELABORATION_OUTPUT JSON array from its output block:
|
|
523
|
+
dev_researcher_json='<ELABORATION_OUTPUT array from the dev researcher agent>'
|
|
524
|
+
dev_codebase_json='<ELABORATION_OUTPUT array from the dev code-explorer agent>'
|
|
525
|
+
ops_researcher_json='<ELABORATION_OUTPUT array from the ops researcher agent>'
|
|
526
|
+
ops_pm_json='<ELABORATION_OUTPUT array from the ops PM agent>'
|
|
527
|
+
# Use '[]' for any track that had no ideas (e.g. if all ideas were dev, set ops_* to '[]')
|
|
528
|
+
|
|
529
|
+
# Merge dev track: join researcher + codebase findings by card_id, inject category from verdicts
|
|
530
|
+
dev_merged=$(jq -n \
|
|
531
|
+
--argjson r "$dev_researcher_json" \
|
|
532
|
+
--argjson c "$dev_codebase_json" \
|
|
533
|
+
--argjson v "$verdicts_output_json" \
|
|
534
|
+
'[$r[] | {card_id: .card_id, blocking_issue: .blocking_issue,
|
|
535
|
+
researcher_findings: .findings,
|
|
536
|
+
codebase_findings: ([$c[] | select(.card_id == .card_id)] | first | .findings // ""),
|
|
537
|
+
category: ([$v[] | select(.card_id == .card_id)] | first | .category // "feature")}]')
|
|
538
|
+
|
|
539
|
+
# Merge ops track: join researcher + PM findings by card_id, inject category
|
|
540
|
+
ops_merged=$(jq -n \
|
|
541
|
+
--argjson r "$ops_researcher_json" \
|
|
542
|
+
--argjson p "$ops_pm_json" \
|
|
543
|
+
--argjson v "$verdicts_output_json" \
|
|
544
|
+
'[$r[] | {card_id: .card_id, blocking_issue: .blocking_issue,
|
|
545
|
+
researcher_findings: .findings,
|
|
546
|
+
pm_findings: ([$p[] | select(.card_id == .card_id)] | first | .findings // ""),
|
|
547
|
+
category: ([$v[] | select(.card_id == .card_id)] | first | .category // "business-operation")}]')
|
|
548
|
+
|
|
549
|
+
# Combine both tracks
|
|
550
|
+
merged_elaboration_json=$(jq -s 'add' <(echo "$dev_merged") <(echo "$ops_merged"))
|
|
551
|
+
```
|
|
552
|
+
|
|
553
|
+
Use process substitution (not a pipeline) so the while loop runs in the main shell and variables remain in scope after `done`:
|
|
554
|
+
|
|
555
|
+
```bash
|
|
556
|
+
while IFS= read -r idea; do
|
|
557
|
+
CARD_ID=$(echo "$idea" | jq -r '.card_id')
|
|
558
|
+
category=$(echo "$idea" | jq -r '.category')
|
|
559
|
+
blocking_issue=$(echo "$idea" | jq -r '.blocking_issue // empty')
|
|
560
|
+
|
|
561
|
+
if [ "$category" = "business-operation" ]; then
|
|
562
|
+
researcher_findings=$(echo "$idea" | jq -r '.researcher_findings')
|
|
563
|
+
pm_findings=$(echo "$idea" | jq -r '.pm_findings')
|
|
564
|
+
monotask card set-description "$BOARD_ID" "$CARD_ID" "## Elaboration Findings
|
|
519
565
|
|
|
520
566
|
### Industry context & benchmarks:
|
|
521
|
-
|
|
567
|
+
$researcher_findings
|
|
522
568
|
|
|
523
569
|
### Feasibility & stakeholder impact:
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
570
|
+
$pm_findings"
|
|
571
|
+
monotask card comment add "$BOARD_ID" "$CARD_ID" "Industry context & benchmarks: $researcher_findings"
|
|
572
|
+
monotask card comment add "$BOARD_ID" "$CARD_ID" "Feasibility & stakeholder impact: $pm_findings"
|
|
573
|
+
else
|
|
574
|
+
researcher_findings=$(echo "$idea" | jq -r '.researcher_findings')
|
|
575
|
+
codebase_findings=$(echo "$idea" | jq -r '.codebase_findings')
|
|
576
|
+
monotask card set-description "$BOARD_ID" "$CARD_ID" "## Elaboration Findings
|
|
528
577
|
|
|
529
578
|
### Edge cases & prior art:
|
|
530
|
-
|
|
579
|
+
$researcher_findings
|
|
531
580
|
|
|
532
581
|
### Codebase constraints:
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
monotask card
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
monotask card
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
# If neither agent found a blocking issue:
|
|
546
|
-
monotask card move "$BOARD_ID" "$CARD_ID" "$COL_ELABORATED" --json
|
|
547
|
-
|
|
548
|
-
# If either agent found a blocking issue (mutually exclusive with the above):
|
|
549
|
-
monotask card move "$BOARD_ID" "$CARD_ID" "$COL_ICED" --json
|
|
550
|
-
monotask card comment add "$BOARD_ID" "$CARD_ID" "Blocked during elaboration: <issue>"
|
|
582
|
+
$codebase_findings"
|
|
583
|
+
monotask card comment add "$BOARD_ID" "$CARD_ID" "Edge cases & prior art: $researcher_findings"
|
|
584
|
+
monotask card comment add "$BOARD_ID" "$CARD_ID" "Codebase constraints: $codebase_findings"
|
|
585
|
+
fi
|
|
586
|
+
|
|
587
|
+
if [ -n "$blocking_issue" ]; then
|
|
588
|
+
monotask card move "$BOARD_ID" "$CARD_ID" "$COL_ICED" --json
|
|
589
|
+
monotask card comment add "$BOARD_ID" "$CARD_ID" "Blocked during elaboration: $blocking_issue"
|
|
590
|
+
else
|
|
591
|
+
monotask card move "$BOARD_ID" "$CARD_ID" "$COL_ELABORATED" --json
|
|
592
|
+
fi
|
|
593
|
+
done < <(echo "$merged_elaboration_json" | jq -c '.[]')
|
|
551
594
|
```
|
|
552
595
|
|
|
553
596
|
#### 6b. User Confirmation Gate
|
|
@@ -556,6 +599,10 @@ monotask card comment add "$BOARD_ID" "$CARD_ID" "Blocked during elaboration: <i
|
|
|
556
599
|
|
|
557
600
|
**Confirm mode only:** If `mode` is `confirm` (default), present a review table of all elaborated ideas to the user.
|
|
558
601
|
|
|
602
|
+
Build the table from `verdicts_output_json` (filtered to `verdict == "evaluated"`). For each row:
|
|
603
|
+
- **Impact** and **Effort** come from `.impact` and `.effort` fields in `verdicts_output_json`
|
|
604
|
+
- **Track**: `feature` or `technical-baseline` → `dev`; `business-operation` → `ops`
|
|
605
|
+
|
|
559
606
|
Print this exact format:
|
|
560
607
|
|
|
561
608
|
```
|
|
@@ -654,7 +701,7 @@ echo "Dev decomp: $dev_decomp_agent | Ops decomp: $ops_decomp_agent"
|
|
|
654
701
|
```
|
|
655
702
|
|
|
656
703
|
**CRITICAL — Variable substitution required for Step 6c Task calls:**
|
|
657
|
-
Before constructing each Task prompt, replace `${brain_context}`, `${prompt}`, `${project_name}`,
|
|
704
|
+
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:
|
|
658
705
|
|
|
659
706
|
```bash
|
|
660
707
|
# Build elaborated idea lists including card comments (full context for decomposition agents)
|
|
@@ -809,10 +856,31 @@ OPS_COL_BACKLOG=$(echo "$ops_columns" | jq -r '.[] | select(.title == "Backlog")
|
|
|
809
856
|
|
|
810
857
|
---
|
|
811
858
|
|
|
812
|
-
**
|
|
859
|
+
**Assign TASKS_OUTPUT from each decomposition agent, then merge and iterate:**
|
|
813
860
|
|
|
814
861
|
```bash
|
|
815
|
-
|
|
862
|
+
# Parse the TASKS_OUTPUT block from the dev decomp agent's response and assign:
|
|
863
|
+
dev_tasks_json='<TASKS_OUTPUT JSON array from dev decomp agent, or [] if no dev ideas>'
|
|
864
|
+
# Parse the TASKS_OUTPUT block from the ops decomp agent's response and assign:
|
|
865
|
+
ops_tasks_json='<TASKS_OUTPUT JSON array from ops decomp agent, or [] if no ops ideas>'
|
|
866
|
+
|
|
867
|
+
merged_tasks_json=$(jq -s 'add' <(echo "$dev_tasks_json") <(echo "$ops_tasks_json"))
|
|
868
|
+
|
|
869
|
+
# Use process substitution (not a pipeline) so variables set inside the loop
|
|
870
|
+
# remain in scope after done — needed for the parent-annotation step below.
|
|
871
|
+
# Also initialise the subtask-accumulator map before the loop.
|
|
872
|
+
declare -A parent_subtask_summaries # parent_card_id -> newline-separated task summary lines
|
|
873
|
+
|
|
874
|
+
while IFS= read -r task; do
|
|
875
|
+
parent_card_id=$(echo "$task" | jq -r '.parent_card_id')
|
|
876
|
+
title=$(echo "$task" | jq -r '.title')
|
|
877
|
+
description=$(echo "$task" | jq -r '.description')
|
|
878
|
+
category=$(echo "$task" | jq -r '.category')
|
|
879
|
+
agent=$(echo "$task" | jq -r '.agent')
|
|
880
|
+
task_effort=$(echo "$task" | jq -r '.effort')
|
|
881
|
+
has_prerequisites=$(echo "$task" | jq -r '.has_prerequisites')
|
|
882
|
+
|
|
883
|
+
if [ "$category" = "business-operation" ]; then
|
|
816
884
|
TARGET_BOARD="$OPS_BOARD_ID"
|
|
817
885
|
COL_TARGET=$([ "$has_prerequisites" = "true" ] && echo "$OPS_COL_BACKLOG" || echo "$OPS_COL_TODO")
|
|
818
886
|
BOARD_LABEL="Operations Tasks"
|
|
@@ -823,8 +891,11 @@ else
|
|
|
823
891
|
fi
|
|
824
892
|
|
|
825
893
|
# Inherit impact and effort from parent idea — look up from verdicts_output_json by parent_card_id
|
|
826
|
-
parent_impact=$(echo "$verdicts_output_json" | jq -r --arg id "$parent_card_id" '.[] | select(.card_id == $id) | .impact')
|
|
827
|
-
parent_effort=$(echo "$verdicts_output_json" | jq -r --arg id "$parent_card_id" '.[] | select(.card_id == $id) | .effort')
|
|
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
|
|
828
899
|
|
|
829
900
|
# Create task card as a proper subtask of the parent idea card (cross-board link)
|
|
830
901
|
# Signature: subtask add <PARENT_BOARD_ID> <PARENT_CARD_ID> <CHILD_BOARD_ID> <COL_ID> <TITLE>
|
|
@@ -841,14 +912,22 @@ PARENT IDEA IMPACT: <parent_impact>/10 PARENT IDEA EFFORT: <parent_effort>/10
|
|
|
841
912
|
CATEGORY: <category>
|
|
842
913
|
PARENT IDEA: <idea title> (card: <parent_card_id> on ideation board)"
|
|
843
914
|
monotask card label add "$TARGET_BOARD" "$TASK_CARD_ID" "mastermind:idea"
|
|
844
|
-
monotask card label add "$TARGET_BOARD" "$TASK_CARD_ID" "category
|
|
915
|
+
monotask card label add "$TARGET_BOARD" "$TASK_CARD_ID" "category:$category"
|
|
916
|
+
|
|
917
|
+
# Accumulate subtask summary for this parent (used in the post-loop annotation step)
|
|
918
|
+
parent_subtask_summaries[$parent_card_id]+=" - $title (agent: $agent, effort: $task_effort/10, board: $BOARD_LABEL)\n"
|
|
919
|
+
|
|
920
|
+
done < <(echo "$merged_tasks_json" | jq -c '.[]')
|
|
845
921
|
```
|
|
846
922
|
|
|
847
|
-
|
|
923
|
+
After the loop, annotate each parent idea card and move it to `Tasked`:
|
|
848
924
|
```bash
|
|
849
|
-
|
|
850
|
-
"
|
|
851
|
-
monotask card
|
|
925
|
+
for parent_card_id in "${!parent_subtask_summaries[@]}"; do
|
|
926
|
+
subtask_list="${parent_subtask_summaries[$parent_card_id]}"
|
|
927
|
+
monotask card comment add "$BOARD_ID" "$parent_card_id" \
|
|
928
|
+
"Subtasks created:\n${subtask_list}"
|
|
929
|
+
monotask card move "$BOARD_ID" "$parent_card_id" "$COL_TASKED" --json
|
|
930
|
+
done
|
|
852
931
|
```
|
|
853
932
|
|
|
854
933
|
For each entry in FLAGGED, move the idea to `Iced`:
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@monoes/monomindcli",
|
|
3
|
-
"version": "1.9.
|
|
3
|
+
"version": "1.9.16",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Monomind CLI - Enterprise AI agent orchestration with 60+ specialized agents, swarm coordination, MCP server, self-learning hooks, and vector memory for Claude Code",
|
|
6
6
|
"main": "dist/src/index.js",
|