@monoes/monomindcli 1.9.1 → 1.9.2

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.
@@ -78,7 +78,8 @@ curl -s -X POST "http://localhost:4242/api/mastermind/event" \
78
78
  -d "$(jq -cn \
79
79
  --arg session "$session_id" \
80
80
  --arg org "$org_name" \
81
- '{type:"session:start",session:$session,domain:"ops",prompt:("Running org: "+$org),mode:"auto",ts:(now*1000|floor)}')" || true
81
+ --arg proj "$(pwd)" \
82
+ '{type:"session:start",session:$session,domain:"ops",prompt:("Running org: "+$org),mode:"auto",project:$proj,ts:(now*1000|floor)}')" || true
82
83
  ```
83
84
 
84
85
  Emit `domain:dispatch`:
@@ -0,0 +1,132 @@
1
+ ---
2
+ name: mastermind-agent-select
3
+ description: Shared utility — registry-aware agent selection for mastermind domain skills. Reads .monomind/registry.json and returns ranked agent slugs/names for a given task, prompt, and category filter. Include this logic wherever a domain skill needs to pick the best agent(s) instead of hardcoding types.
4
+ type: helper
5
+ ---
6
+
7
+ # Agent Selection from Registry
8
+
9
+ Use this pattern whenever a mastermind skill needs to select specialist agents. The registry lives at `.monomind/registry.json` and contains all 257+ available agent types with their category labels.
10
+
11
+ ---
12
+
13
+ ## Standard Selection Block
14
+
15
+ ```bash
16
+ # AGENT SELECTION — pick best agents for the current task
17
+ # Set these before the block:
18
+ # REGISTRY=".monomind/registry.json"
19
+ # PROMPT="<the user's prompt or idea description>"
20
+ # CATEGORIES="marketing strategy product" # space-separated; adjust per domain
21
+ # TOP_N=6 # how many agents to return
22
+
23
+ REGISTRY="${REGISTRY:-.monomind/registry.json}"
24
+
25
+ # 1. Extract candidates from the registry filtered by category
26
+ candidates=$(jq -r \
27
+ --arg cats "$CATEGORIES" \
28
+ '[ .agents[]
29
+ | select(.deprecated != true)
30
+ | select(
31
+ .category as $c |
32
+ ($cats | split(" ") | any(. == $c))
33
+ )
34
+ | {name: .name, slug: .slug, category: .category}
35
+ ] | unique_by(.slug) | .[]' \
36
+ "$REGISTRY")
37
+
38
+ # 2. Score each candidate by keyword overlap with the prompt
39
+ # Extract keywords from prompt (words ≥5 chars, lowercase)
40
+ keywords=$(echo "$PROMPT" | tr '[:upper:]' '[:lower:]' | grep -oE '[a-z]{5,}' | sort -u | tr '\n' ' ')
41
+
42
+ selected_agents=$(echo "$candidates" | jq -Rs \
43
+ --arg kw "$keywords" \
44
+ --argjson n "$TOP_N" \
45
+ '
46
+ [ split("\n")[] | select(length > 0) | fromjson ] |
47
+ map(
48
+ . as $agent |
49
+ ($kw | split(" ")) as $keywords |
50
+ ($agent.name | ascii_downcase) as $name |
51
+ ($agent.category | ascii_downcase) as $cat |
52
+ {
53
+ agent: $agent,
54
+ score: ([$keywords[] | if (($name | contains(.)) or ($cat | contains(.))) then 1 else 0 end] | add // 0)
55
+ }
56
+ ) |
57
+ sort_by(-.score) |
58
+ .[0:$n] |
59
+ map(.agent)
60
+ ')
61
+
62
+ echo "$selected_agents"
63
+ ```
64
+
65
+ The output is a JSON array of `{name, slug, category}` objects. Use `.name` as the `subagent_type` in Task calls, `.slug` for display.
66
+
67
+ ---
68
+
69
+ ## Category Map — which categories to filter per domain
70
+
71
+ | Domain / purpose | Categories to include |
72
+ |---|---|
73
+ | **Idea — user/market angles** | `marketing strategy product academic` |
74
+ | **Idea — technical angles** | `engineering development architecture` |
75
+ | **Idea — ops/business angles** | `sales strategy product project-management` |
76
+ | **Build** | `engineering development architecture devops testing` |
77
+ | **Marketing** | `marketing paid-media strategy` |
78
+ | **Sales** | `sales strategy product` |
79
+ | **Research** | `academic specialized strategy` |
80
+ | **Content** | `marketing specialized` |
81
+ | **Ops** | `project-management strategy support` |
82
+ | **Release** | `devops github engineering` |
83
+ | **Review** | `engineering testing analysis` |
84
+ | **Finance** | `strategy specialized` |
85
+
86
+ ---
87
+
88
+ ## Quick Pattern: pick ONE best agent for a specific task
89
+
90
+ ```bash
91
+ # Pick the single best agent for a task description
92
+ TASK_DESC="<one-line description of what this agent must do>"
93
+ CATS="engineering development"
94
+
95
+ best_agent=$(jq -r \
96
+ --arg cats "$CATS" \
97
+ --arg task "$(echo "$TASK_DESC" | tr '[:upper:]' '[:lower:]')" \
98
+ '[ .agents[]
99
+ | select(.deprecated != true)
100
+ | select(.category as $c | ($cats | split(" ") | any(. == $c)))
101
+ | {name: .name, slug: .slug,
102
+ score: (.name | ascii_downcase | if contains($task) then 2 else 0 end)}
103
+ ]
104
+ | sort_by(-.score)
105
+ | .[0].name // "coder"' \
106
+ "$REGISTRY")
107
+ ```
108
+
109
+ ---
110
+
111
+ ## Fallback
112
+
113
+ If the registry is missing or empty, fall back to these safe defaults per domain:
114
+
115
+ | Domain | Fallback agents |
116
+ |---|---|
117
+ | idea specialists | `researcher`, `Trend Researcher`, `Growth Hacker` |
118
+ | dev decomp | `Software Architect` |
119
+ | ops decomp | `Product Manager` |
120
+ | build | `coder`, `tester`, `reviewer` |
121
+ | marketing | `Content Creator`, `SEO Specialist` |
122
+ | sales | `Outbound Strategist`, `Deal Strategist` |
123
+
124
+ ---
125
+
126
+ ## Usage in a domain skill
127
+
128
+ 1. Set `REGISTRY`, `PROMPT`, `CATEGORIES`, `TOP_N`
129
+ 2. Run the Standard Selection Block
130
+ 3. Parse `selected_agents` JSON array
131
+ 4. Spawn Task agents using `.name` as `subagent_type`, one per entry
132
+ 5. If `selected_agents` is empty or registry missing: use the fallback list above
@@ -137,6 +137,7 @@ Every mastermind run MUST emit structured events to the live dashboard via WebFe
137
137
  "session": "<uuid-v4>",
138
138
  "prompt": "<resolved user prompt>",
139
139
  "mode": "auto|confirm",
140
+ "project": "<absolute path of current working directory>",
140
141
  "ts": 1234567890000
141
142
  }
142
143
  ```
@@ -212,6 +213,7 @@ WebFetch({
212
213
  session: crypto.randomUUID(), // or generate a timestamp-based ID
213
214
  prompt: resolvedPrompt,
214
215
  mode: mode,
216
+ project: process.cwd(), // REQUIRED: absolute path for multi-project support
215
217
  ts: Date.now()
216
218
  })
217
219
  })
@@ -234,6 +236,61 @@ WebFetch({
234
236
 
235
237
  ---
236
238
 
239
+ ## Monotask Space+Board Setup Procedure
240
+
241
+ **Always follow this exact order — never create a board without first ensuring a space exists.**
242
+
243
+ Every mastermind run that needs a task board MUST:
244
+ 1. Resolve the space (find existing or create new) — space name = `project_name`
245
+ 2. Create the board within that space
246
+ 3. Link the board to the space immediately after creation
247
+ 4. Create columns (Todo → Doing → Done)
248
+ 5. Create cards within those columns
249
+
250
+ 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.
251
+
252
+ ### Canonical bash block (substitute `<domain>` with: build, marketing, ops, content, etc.)
253
+
254
+ ```bash
255
+ # Step 1 — Resolve space (required; abort if it cannot be created)
256
+ project_name="${project_name:-$(basename "$PWD")}"
257
+ space_id=$(monotask space list 2>/dev/null | awk -F' \| ' -v n="$project_name" '$2==n{print $1}' | head -1)
258
+ [ -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}')
259
+ [ -z "$space_id" ] && { echo "ERROR: Could not find or create space '$project_name' — verify monotask is installed (monotask --version)"; exit 1; }
260
+
261
+ # Step 2 — Create board
262
+ board_id=$(monotask board create "<domain>" --json | jq -r '.id // empty')
263
+ [ -z "$board_id" ] && { echo "ERROR: Failed to create board '<domain>'"; exit 1; }
264
+
265
+ # Step 3 — Link board to space immediately
266
+ monotask space boards add "$space_id" "$board_id" >/dev/null 2>&1 || true
267
+
268
+ # Step 4 — Create columns
269
+ todo_col=$(monotask column create "$board_id" "Todo" --json | jq -r '.id')
270
+ doing_col=$(monotask column create "$board_id" "Doing" --json | jq -r '.id')
271
+ done_col=$(monotask column create "$board_id" "Done" --json | jq -r '.id')
272
+ ```
273
+
274
+ When master.md runs multiple domains, resolve the space **once** before the loop, then repeat steps 2–4 per domain:
275
+
276
+ ```bash
277
+ # Resolve space once
278
+ project_name="<resolved project_name>"
279
+ space_id=$(monotask space list 2>/dev/null | awk -F' \| ' -v n="$project_name" '$2==n{print $1}' | head -1)
280
+ [ -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}')
281
+ [ -z "$space_id" ] && { echo "ERROR: Could not find or create space '$project_name'"; exit 1; }
282
+
283
+ # Repeat per active domain (e.g. build, marketing, ops):
284
+ board_<domain>=$(monotask board create "<domain>" --json | jq -r '.id // empty')
285
+ [ -z "$board_<domain>" ] && { echo "ERROR: Failed to create <domain> board"; exit 1; }
286
+ monotask space boards add "$space_id" "$board_<domain>" >/dev/null 2>&1 || true
287
+ todo_<domain>=$(monotask column create "$board_<domain>" "Todo" --json | jq -r '.id')
288
+ doing_<domain>=$(monotask column create "$board_<domain>" "Doing" --json | jq -r '.id')
289
+ done_<domain>=$(monotask column create "$board_<domain>" "Done" --json | jq -r '.id')
290
+ ```
291
+
292
+ ---
293
+
237
294
  ## Monotask Task Briefing Standard
238
295
 
239
296
  Every monotask card MUST include ALL fields below in its description and comment. Agents read task cards cold — no back-channel context exists.
@@ -241,8 +298,8 @@ Every monotask card MUST include ALL fields below in its description and comment
241
298
  Create each card using `monotask card create`, then populate it. First resolve column IDs:
242
299
  ```bash
243
300
  columns=$(monotask column list "$BOARD_ID" --json)
244
- COL_TODO_ID=$(echo "$columns" | jq -r '.[] | select(.name == "Todo" or .name == "Backlog") | .id' | head -1)
245
- COL_DONE_ID=$(echo "$columns" | jq -r '.[] | select(.name == "Done") | .id' | head -1)
301
+ COL_TODO_ID=$(echo "$columns" | jq -r '.[] | select(.title == "Todo" or .title == "Backlog") | .id' | head -1)
302
+ COL_DONE_ID=$(echo "$columns" | jq -r '.[] | select(.title == "Done") | .id' | head -1)
246
303
  ```
247
304
  Then create the card:
248
305
  ```bash
@@ -46,7 +46,19 @@ If this skill is invoked directly (not by master):
46
46
 
47
47
  1. Load brain context following _protocol.md Brain Load Procedure (namespace: `build`)
48
48
  2. Run intake from _intake.md if prompt is vague
49
- 3. Create or find monotask space `<project_name>`, create board `development`
49
+ 3. Follow _protocol.md Monotask Space+Board Setup Procedure:
50
+ ```bash
51
+ project_name="${project_name:-$(basename "$PWD")}"
52
+ space_id=$(monotask space list 2>/dev/null | awk -F' \| ' -v n="$project_name" '$2==n{print $1}' | head -1)
53
+ [ -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}')
54
+ [ -z "$space_id" ] && { echo "ERROR: Could not find or create space '$project_name'"; exit 1; }
55
+ board_id=$(monotask board create "development" --json | jq -r '.id // empty')
56
+ [ -z "$board_id" ] && { echo "ERROR: Failed to create development board"; exit 1; }
57
+ monotask space boards add "$space_id" "$board_id" >/dev/null 2>&1 || true
58
+ todo_col=$(monotask column create "$board_id" "Todo" --json | jq -r '.id')
59
+ doing_col=$(monotask column create "$board_id" "Doing" --json | jq -r '.id')
60
+ done_col=$(monotask column create "$board_id" "Done" --json | jq -r '.id')
61
+ ```
50
62
  4. Proceed with complexity assessment below
51
63
  5. At end: follow _protocol.md Brain Write Procedure (namespace: `build`)
52
64
 
@@ -80,8 +92,8 @@ STEP 2 — CREATE TASKS
80
92
  For each task, create a monotask card on the project board. First look up column IDs and assign shell variables:
81
93
  ```bash
82
94
  columns=$(monotask column list "$BOARD_ID" --json)
83
- COL_TODO_ID=$(echo "$columns" | jq -r '.[] | select(.name == "Todo" or .name == "Backlog") | .id' | head -1)
84
- COL_DONE_ID=$(echo "$columns" | jq -r '.[] | select(.name == "Done") | .id' | head -1)
95
+ COL_TODO_ID=$(echo "$columns" | jq -r '.[] | select(.title == "Todo" or .title == "Backlog") | .id' | head -1)
96
+ COL_DONE_ID=$(echo "$columns" | jq -r '.[] | select(.title == "Done") | .id' | head -1)
85
97
  ```
86
98
  Then create the card:
87
99
  ```bash
@@ -67,7 +67,19 @@ If this skill is invoked directly (not by master):
67
67
 
68
68
  1. Load brain context following _protocol.md Brain Load Procedure (namespace: `content`)
69
69
  2. Run intake from _intake.md if prompt is vague
70
- 3. Create or find monotask space `<project_name>`, create board `content`
70
+ 3. Follow _protocol.md Monotask Space+Board Setup Procedure:
71
+ ```bash
72
+ project_name="${project_name:-$(basename "$PWD")}"
73
+ space_id=$(monotask space list 2>/dev/null | awk -F' \| ' -v n="$project_name" '$2==n{print $1}' | head -1)
74
+ [ -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}')
75
+ [ -z "$space_id" ] && { echo "ERROR: Could not find or create space '$project_name'"; exit 1; }
76
+ board_id=$(monotask board create "content" --json | jq -r '.id // empty')
77
+ [ -z "$board_id" ] && { echo "ERROR: Failed to create content board"; exit 1; }
78
+ monotask space boards add "$space_id" "$board_id" >/dev/null 2>&1 || true
79
+ todo_col=$(monotask column create "$board_id" "Todo" --json | jq -r '.id')
80
+ doing_col=$(monotask column create "$board_id" "Doing" --json | jq -r '.id')
81
+ done_col=$(monotask column create "$board_id" "Done" --json | jq -r '.id')
82
+ ```
71
83
  4. Proceed with complexity assessment below
72
84
  5. At end: follow _protocol.md Brain Write Procedure (namespace: `content`)
73
85
 
@@ -225,16 +225,24 @@ jq -n \
225
225
  > "${orgJson}.tmp" && mv "${orgJson}.tmp" "$orgJson"
226
226
  ```
227
227
 
228
- Create the monotask space, board, and default columns:
228
+ Create the monotask space, board, and default columns (space is required — abort before creating board if space fails):
229
229
  ```bash
230
+ # Step 1 — Space (required first)
230
231
  space_id=$(monotask space list 2>/dev/null | awk -F' \| ' -v n="$org_name" '$2==n{print $1}' | head -1)
231
232
  [ -z "$space_id" ] && space_id=$(monotask space create "$org_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}')
232
- board_id=$(monotask board create "org-tasks" --json | jq -r '.id')
233
- [ -z "$board_id" ] && { echo "ERROR: Failed to create monotask board — verify monotask is installed (run: monotask --version)"; exit 1; }
234
- todo_col_id=$(monotask column create "$board_id" "Todo" --json | jq -r '.id')
233
+ [ -z "$space_id" ] && { echo "ERROR: Could not find or create space '$org_name' — verify monotask is installed (run: monotask --version)"; exit 1; }
234
+
235
+ # Step 2 Board (created only after space is confirmed)
236
+ board_id=$(monotask board create "org-tasks" --json | jq -r '.id // empty')
237
+ [ -z "$board_id" ] && { echo "ERROR: Failed to create monotask board"; exit 1; }
238
+
239
+ # Step 3 — Link board to space immediately
240
+ monotask space boards add "$space_id" "$board_id" >/dev/null 2>&1 || true
241
+
242
+ # Step 4 — Columns
243
+ todo_col_id=$(monotask column create "$board_id" "Todo" --json | jq -r '.id')
235
244
  doing_col_id=$(monotask column create "$board_id" "Doing" --json | jq -r '.id')
236
- done_col_id=$(monotask column create "$board_id" "Done" --json | jq -r '.id')
237
- [ -n "$space_id" ] && monotask space boards add "$space_id" "$board_id" >/dev/null 2>&1 || true
245
+ done_col_id=$(monotask column create "$board_id" "Done" --json | jq -r '.id')
238
246
  ```
239
247
 
240
248
  Patch the saved org config with the board and column IDs:
@@ -45,7 +45,19 @@ If this skill is invoked directly (not by master):
45
45
 
46
46
  1. Load brain context following _protocol.md Brain Load Procedure (namespace: `finance`)
47
47
  2. Run intake from _intake.md if prompt is vague
48
- 3. Create or find monotask space `<project_name>`, create board `finance`
48
+ 3. Follow _protocol.md Monotask Space+Board Setup Procedure:
49
+ ```bash
50
+ project_name="${project_name:-$(basename "$PWD")}"
51
+ space_id=$(monotask space list 2>/dev/null | awk -F' \| ' -v n="$project_name" '$2==n{print $1}' | head -1)
52
+ [ -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}')
53
+ [ -z "$space_id" ] && { echo "ERROR: Could not find or create space '$project_name'"; exit 1; }
54
+ board_id=$(monotask board create "finance" --json | jq -r '.id // empty')
55
+ [ -z "$board_id" ] && { echo "ERROR: Failed to create finance board"; exit 1; }
56
+ monotask space boards add "$space_id" "$board_id" >/dev/null 2>&1 || true
57
+ todo_col=$(monotask column create "$board_id" "Todo" --json | jq -r '.id')
58
+ doing_col=$(monotask column create "$board_id" "Doing" --json | jq -r '.id')
59
+ done_col=$(monotask column create "$board_id" "Done" --json | jq -r '.id')
60
+ ```
49
61
  4. Proceed with complexity assessment below
50
62
  5. At end: follow _protocol.md Brain Write Procedure (namespace: `finance`)
51
63
 
@@ -79,8 +91,8 @@ STEP 2 — CREATE TASKS
79
91
  For each workstream, create a monotask card on the project board. First look up column IDs and assign shell variables:
80
92
  ```bash
81
93
  columns=$(monotask column list "$BOARD_ID" --json)
82
- COL_TODO_ID=$(echo "$columns" | jq -r '.[] | select(.name == "Todo" or .name == "Backlog") | .id' | head -1)
83
- COL_DONE_ID=$(echo "$columns" | jq -r '.[] | select(.name == "Done") | .id' | head -1)
94
+ COL_TODO_ID=$(echo "$columns" | jq -r '.[] | select(.title == "Todo" or .title == "Backlog") | .id' | head -1)
95
+ COL_DONE_ID=$(echo "$columns" | jq -r '.[] | select(.title == "Done") | .id' | head -1)
84
96
  ```
85
97
  Then create the card:
86
98
  ```bash