monomind 2.3.2 → 2.3.3

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.
Files changed (30) hide show
  1. package/package.json +1 -1
  2. package/packages/@monomind/cli/.claude/commands/mastermind/_repeat.md +9 -9
  3. package/packages/@monomind/cli/.claude/commands/mastermind/approve.md +2 -2
  4. package/packages/@monomind/cli/.claude/commands/mastermind/architect.md +3 -3
  5. package/packages/@monomind/cli/.claude/commands/mastermind/createorg.md +4 -4
  6. package/packages/@monomind/cli/.claude/commands/mastermind/master.md +3 -3
  7. package/packages/@monomind/cli/.claude/commands/mastermind/repeat.md +5 -5
  8. package/packages/@monomind/cli/.claude/commands/mastermind/runorg.md +3 -3
  9. package/packages/@monomind/cli/.claude/commands/mastermind/stoporg.md +1 -1
  10. package/packages/@monomind/cli/.claude/helpers/control-start.cjs +52 -4
  11. package/packages/@monomind/cli/.claude/helpers/event-logger.cjs +9 -1
  12. package/packages/@monomind/cli/.claude/helpers/handlers/capture-handler.cjs +9 -1
  13. package/packages/@monomind/cli/.claude/helpers/handlers/route-handler.cjs +43 -13
  14. package/packages/@monomind/cli/.claude/skills/mastermind-skills/_protocol.md +1 -1
  15. package/packages/@monomind/cli/.claude/skills/mastermind-skills/_repeat.md +3 -3
  16. package/packages/@monomind/cli/.claude/skills/mastermind-skills/adapters.md +1 -1
  17. package/packages/@monomind/cli/.claude/skills/mastermind-skills/agents.md +1 -1
  18. package/packages/@monomind/cli/.claude/skills/mastermind-skills/architect.md +8 -8
  19. package/packages/@monomind/cli/.claude/skills/mastermind-skills/backup.md +1 -1
  20. package/packages/@monomind/cli/.claude/skills/mastermind-skills/bootstrap.md +1 -1
  21. package/packages/@monomind/cli/.claude/skills/mastermind-skills/costs.md +1 -1
  22. package/packages/@monomind/cli/.claude/skills/mastermind-skills/heartbeat.md +2 -2
  23. package/packages/@monomind/cli/.claude/skills/mastermind-skills/idea.md +1 -1
  24. package/packages/@monomind/cli/.claude/skills/mastermind-skills/monitor.md +2 -2
  25. package/packages/@monomind/cli/.claude/skills/mastermind-skills/org-settings.md +1 -1
  26. package/packages/@monomind/cli/.claude/skills/mastermind-skills/plugins.md +1 -1
  27. package/packages/@monomind/cli/.claude/skills/mastermind-skills/runorg.md +28 -22
  28. package/packages/@monomind/cli/.claude/skills/mastermind-skills/stoporg.md +2 -2
  29. package/packages/@monomind/cli/dist/src/ui/server.mjs +75 -0
  30. package/packages/@monomind/cli/package.json +1 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "monomind",
3
- "version": "2.3.2",
3
+ "version": "2.3.3",
4
4
  "description": "Open-source CLI extension for Claude Code. Adds an MCP server with a codebase knowledge graph, persistent memory, multi-agent coordination, and reusable slash commands. MIT licensed, runs locally, no data leaves your machine.",
5
5
  "main": "dist/index.js",
6
6
  "type": "module",
@@ -80,7 +80,7 @@ fi
80
80
  ```bash
81
81
  REPO_ROOT=$(git rev-parse --show-toplevel 2>/dev/null || pwd)
82
82
  CTRL_URL=$(jq -r '.url // "http://localhost:4242"' "$REPO_ROOT/.monomind/control.json" 2>/dev/null || echo "http://localhost:4242")
83
- curl -s -X POST "${CTRL_URL}/api/mastermind/event" \
83
+ curl -s -X POST "${CTRL_URL}/api/mastermind/event" -H "x-monomind-token: $(cat "${REPO_ROOT:-$(git rev-parse --show-toplevel 2>/dev/null || pwd)}/.monomind/dashboard-token" 2>/dev/null || true)" \
84
84
  -H "Content-Type: application/json" \
85
85
  -d "{\"type\":\"loop:hil:waiting\",\"loopId\":\"${LOOP_ID}\",\"hilFile\":\"${HIL_FILE}\",\"rep\":<current_rep>,\"ts\":$(date +%s)000}" || true
86
86
  ```
@@ -97,7 +97,7 @@ fi
97
97
  ```bash
98
98
  REPO_ROOT=$(git rev-parse --show-toplevel 2>/dev/null || pwd)
99
99
  CTRL_URL=$(jq -r '.url // "http://localhost:4242"' "$REPO_ROOT/.monomind/control.json" 2>/dev/null || echo "http://localhost:4242")
100
- curl -s -X POST "${CTRL_URL}/api/mastermind/event" \
100
+ curl -s -X POST "${CTRL_URL}/api/mastermind/event" -H "x-monomind-token: $(cat "${REPO_ROOT:-$(git rev-parse --show-toplevel 2>/dev/null || pwd)}/.monomind/dashboard-token" 2>/dev/null || true)" \
101
101
  -H "Content-Type: application/json" \
102
102
  -d "{\"type\":\"loop:hil:resolved\",\"loopId\":\"${LOOP_ID}\",\"rep\":<current_rep>,\"ts\":$(date +%s)000}" || true
103
103
  ```
@@ -185,7 +185,7 @@ If neither condition is true, skip to Section 4.
185
185
  CTRL_URL=$(jq -r '.url // "http://localhost:4242"' "$REPO_ROOT/.monomind/control.json" 2>/dev/null || echo "http://localhost:4242")
186
186
  # For tillend mode, repeat field is the safety cap
187
187
  REPEAT_VAL=$( [ "<tillend_mode>" = "true" ] && echo "<tillend_maxruns>(cap)" || echo "<repeat_count>" )
188
- curl -s -X POST "${CTRL_URL}/api/mastermind/event" \
188
+ curl -s -X POST "${CTRL_URL}/api/mastermind/event" -H "x-monomind-token: $(cat "${REPO_ROOT:-$(git rev-parse --show-toplevel 2>/dev/null || pwd)}/.monomind/dashboard-token" 2>/dev/null || true)" \
189
189
  -H "Content-Type: application/json" \
190
190
  -d "{\"type\":\"loop:start\",\"loopId\":\"${LOOP_ID}\",\"command\":\"/<command>\",\"mode\":\"$( [ '<tillend_mode>' = 'true' ] && echo 'tillend' || echo 'repeat' )\",\"repeat\":\"${REPEAT_VAL}\",\"wait\":<wait_seconds>,\"ts\":$(date +%s)000}" || true
191
191
  ```
@@ -274,7 +274,7 @@ RECENT_HIL=$(find . -maxdepth 3 \( -name "humaninloop*.md" -o -name "humaninloop
274
274
  ```bash
275
275
  REPO_ROOT=$(git rev-parse --show-toplevel 2>/dev/null || pwd)
276
276
  CTRL_URL=$(jq -r '.url // "http://localhost:4242"' "$REPO_ROOT/.monomind/control.json" 2>/dev/null || echo "http://localhost:4242")
277
- curl -s -X POST "${CTRL_URL}/api/mastermind/event" \
277
+ curl -s -X POST "${CTRL_URL}/api/mastermind/event" -H "x-monomind-token: $(cat "${REPO_ROOT:-$(git rev-parse --show-toplevel 2>/dev/null || pwd)}/.monomind/dashboard-token" 2>/dev/null || true)" \
278
278
  -H "Content-Type: application/json" \
279
279
  -d "{\"type\":\"loop:hil\",\"loopId\":\"${LOOP_ID}\",\"command\":\"/<command>\",\"hilFile\":\"${HIL_FILE}\",\"rep\":<current_rep>,\"files\":$(echo "$RECENT_HIL" | grep -v '^$' | jq -R . | jq -cs .),\"ts\":$(date +%s)000}" || true
280
280
  ```
@@ -300,7 +300,7 @@ RECENT_HIL=$(find . -maxdepth 3 \( -name "humaninloop*.md" -o -name "humaninloop
300
300
  ```bash
301
301
  REPO_ROOT=$(git rev-parse --show-toplevel 2>/dev/null || pwd)
302
302
  CTRL_URL=$(jq -r '.url // "http://localhost:4242"' "$REPO_ROOT/.monomind/control.json" 2>/dev/null || echo "http://localhost:4242")
303
- curl -s -X POST "${CTRL_URL}/api/mastermind/event" \
303
+ curl -s -X POST "${CTRL_URL}/api/mastermind/event" -H "x-monomind-token: $(cat "${REPO_ROOT:-$(git rev-parse --show-toplevel 2>/dev/null || pwd)}/.monomind/dashboard-token" 2>/dev/null || true)" \
304
304
  -H "Content-Type: application/json" \
305
305
  -d "{\"type\":\"loop:complete\",\"loopId\":\"${LOOP_ID}\",\"command\":\"/<command>\",\"ranReps\":<repeat_count>,\"hilPending\":true,\"ts\":$(date +%s)000}" || true
306
306
  ```
@@ -364,7 +364,7 @@ Only if `GIT_CHANGES` was empty, answer these two questions about this run:
364
364
  ```bash
365
365
  REPO_ROOT=$(git rev-parse --show-toplevel 2>/dev/null || pwd)
366
366
  CTRL_URL=$(jq -r '.url // "http://localhost:4242"' "$REPO_ROOT/.monomind/control.json" 2>/dev/null || echo "http://localhost:4242")
367
- curl -s -X POST "${CTRL_URL}/api/mastermind/event" \
367
+ curl -s -X POST "${CTRL_URL}/api/mastermind/event" -H "x-monomind-token: $(cat "${REPO_ROOT:-$(git rev-parse --show-toplevel 2>/dev/null || pwd)}/.monomind/dashboard-token" 2>/dev/null || true)" \
368
368
  -H "Content-Type: application/json" \
369
369
  -d "{\"type\":\"loop:complete\",\"loopId\":\"${LOOP_ID}\",\"command\":\"/<command>\",\"mode\":\"tillend\",\"ranReps\":<current_rep>,\"reason\":\"empty-round\",\"ts\":$(date +%s)000}" || true
370
370
  ```
@@ -381,7 +381,7 @@ Only if `GIT_CHANGES` was empty, answer these two questions about this run:
381
381
  ```bash
382
382
  REPO_ROOT=$(git rev-parse --show-toplevel 2>/dev/null || pwd)
383
383
  CTRL_URL=$(jq -r '.url // "http://localhost:4242"' "$REPO_ROOT/.monomind/control.json" 2>/dev/null || echo "http://localhost:4242")
384
- curl -s -X POST "${CTRL_URL}/api/mastermind/event" \
384
+ curl -s -X POST "${CTRL_URL}/api/mastermind/event" -H "x-monomind-token: $(cat "${REPO_ROOT:-$(git rev-parse --show-toplevel 2>/dev/null || pwd)}/.monomind/dashboard-token" 2>/dev/null || true)" \
385
385
  -H "Content-Type: application/json" \
386
386
  -d "{\"type\":\"loop:complete\",\"loopId\":\"${LOOP_ID}\",\"command\":\"/<command>\",\"mode\":\"tillend\",\"ranReps\":<current_rep>,\"reason\":\"safety-cap\",\"ts\":$(date +%s)000}" || true
387
387
  ```
@@ -404,7 +404,7 @@ Only if `GIT_CHANGES` was empty, answer these two questions about this run:
404
404
  ```bash
405
405
  REPO_ROOT=$(git rev-parse --show-toplevel 2>/dev/null || pwd)
406
406
  CTRL_URL=$(jq -r '.url // "http://localhost:4242"' "$REPO_ROOT/.monomind/control.json" 2>/dev/null || echo "http://localhost:4242")
407
- curl -s -X POST "${CTRL_URL}/api/mastermind/event" \
407
+ curl -s -X POST "${CTRL_URL}/api/mastermind/event" -H "x-monomind-token: $(cat "${REPO_ROOT:-$(git rev-parse --show-toplevel 2>/dev/null || pwd)}/.monomind/dashboard-token" 2>/dev/null || true)" \
408
408
  -H "Content-Type: application/json" \
409
409
  -d "{\"type\":\"loop:complete\",\"loopId\":\"${LOOP_ID}\",\"command\":\"/<command>\",\"ranReps\":<repeat_count>,\"ts\":$(date +%s)000}" || true
410
410
  ```
@@ -452,7 +452,7 @@ Emit `loop:tick`:
452
452
  ```bash
453
453
  REPO_ROOT=$(git rev-parse --show-toplevel 2>/dev/null || pwd)
454
454
  CTRL_URL=$(jq -r '.url // "http://localhost:4242"' "$REPO_ROOT/.monomind/control.json" 2>/dev/null || echo "http://localhost:4242")
455
- curl -s -X POST "${CTRL_URL}/api/mastermind/event" \
455
+ curl -s -X POST "${CTRL_URL}/api/mastermind/event" -H "x-monomind-token: $(cat "${REPO_ROOT:-$(git rev-parse --show-toplevel 2>/dev/null || pwd)}/.monomind/dashboard-token" 2>/dev/null || true)" \
456
456
  -H "Content-Type: application/json" \
457
457
  -d "{\"type\":\"loop:tick\",\"loopId\":\"${LOOP_ID}\",\"command\":\"/<command>\",\"mode\":\"${LOOP_TYPE}\",\"completedRep\":<current_rep>,\"nextRep\":<next_rep>,\"nextAt\":${NEXT_AT},\"ts\":$(date +%s)000}" || true
458
458
  ```
@@ -65,7 +65,7 @@ CTRL_URL=$(jq -r '.url // "http://localhost:4242"' "$REPO_ROOT/.monomind/control
65
65
 
66
66
  Emit `session:start`:
67
67
  ```bash
68
- curl -s -X POST "${CTRL_URL}/api/mastermind/event" \
68
+ curl -s -X POST "${CTRL_URL}/api/mastermind/event" -H "x-monomind-token: $(cat "${REPO_ROOT:-$(git rev-parse --show-toplevel 2>/dev/null || pwd)}/.monomind/dashboard-token" 2>/dev/null || true)" \
69
69
  -H "Content-Type: application/json" \
70
70
  -d "$(jq -cn \
71
71
  --arg session "$session_id" \
@@ -78,7 +78,7 @@ Invoke `Skill("mastermind-skills:approve")` passing: brain_context, org_name, ac
78
78
 
79
79
  After skill returns: note the status. Emit `session:complete`:
80
80
  ```bash
81
- curl -s -X POST "${CTRL_URL}/api/mastermind/event" \
81
+ curl -s -X POST "${CTRL_URL}/api/mastermind/event" -H "x-monomind-token: $(cat "${REPO_ROOT:-$(git rev-parse --show-toplevel 2>/dev/null || pwd)}/.monomind/dashboard-token" 2>/dev/null || true)" \
82
82
  -H "Content-Type: application/json" \
83
83
  -d "$(jq -cn \
84
84
  --arg session "$session_id" \
@@ -28,14 +28,14 @@ CTRL_URL=$(jq -r '.url // "http://localhost:4242"' "$REPO_ROOT/.monomind/control
28
28
 
29
29
  Emit `session:start` before invoking the skill (use curl — WebFetch is blocked for localhost in Claude Code runtimes). Before executing the curl below, substitute the generated sessionId for `<sessionId>`:
30
30
  ```bash
31
- curl -s -X POST "${CTRL_URL}/api/mastermind/event" \
31
+ curl -s -X POST "${CTRL_URL}/api/mastermind/event" -H "x-monomind-token: $(cat "${REPO_ROOT:-$(git rev-parse --show-toplevel 2>/dev/null || pwd)}/.monomind/dashboard-token" 2>/dev/null || true)" \
32
32
  -H "Content-Type: application/json" \
33
33
  -d '{"type":"session:start","session":"<sessionId>","domain":"architect","prompt":'"$(jq -Rn --arg p "$prompt" '$p')"',"ts":'"$(date +%s)"'000}' || true
34
34
  ```
35
35
 
36
36
  Emit `domain:dispatch` immediately after session:start. Before executing the curl below, substitute the generated sessionId for `<sessionId>`:
37
37
  ```bash
38
- curl -s -X POST "${CTRL_URL}/api/mastermind/event" \
38
+ curl -s -X POST "${CTRL_URL}/api/mastermind/event" -H "x-monomind-token: $(cat "${REPO_ROOT:-$(git rev-parse --show-toplevel 2>/dev/null || pwd)}/.monomind/dashboard-token" 2>/dev/null || true)" \
39
39
  -H "Content-Type: application/json" \
40
40
  -d '{"type":"domain:dispatch","session":"<sessionId>","domain":"architect","ts":'"$(date +%s)"'000}' || true
41
41
  ```
@@ -44,7 +44,7 @@ Invoke `Skill("mastermind-skills:architect")` passing: brain_context, prompt, pr
44
44
 
45
45
  After skill returns: note the status from the skill's output (`complete`, `partial`, or `blocked`). Emit `session:complete` using that status, then follow _protocol.md Brain Write Procedure for domain `architect`. Before executing the curl below, substitute the generated sessionId for `<sessionId>` and the skill's actual status for `<status>`:
46
46
  ```bash
47
- curl -s -X POST "${CTRL_URL}/api/mastermind/event" \
47
+ curl -s -X POST "${CTRL_URL}/api/mastermind/event" -H "x-monomind-token: $(cat "${REPO_ROOT:-$(git rev-parse --show-toplevel 2>/dev/null || pwd)}/.monomind/dashboard-token" 2>/dev/null || true)" \
48
48
  -H "Content-Type: application/json" \
49
49
  -d '{"type":"session:complete","session":"<sessionId>","domain":"architect","status":"<status>","domains":["architect"],"ts":'"$(date +%s)"'000}' || true
50
50
  ```
@@ -85,7 +85,7 @@ Stop after listing. Do not proceed to skill invocation.
85
85
  npx -y monomind@latest org delete "${delete_name}" --yes || {
86
86
  REPO_ROOT=$(git rev-parse --show-toplevel 2>/dev/null || pwd)
87
87
  CTRL_URL=$(jq -r '.url // "http://localhost:4242"' "$REPO_ROOT/.monomind/control.json" 2>/dev/null || echo "http://localhost:4242")
88
- result=$(curl -s -X DELETE "${CTRL_URL}/api/orgs/${delete_name}")
88
+ result=$(curl -s -X DELETE -H "x-monomind-token: $(cat "${REPO_ROOT:-$(git rev-parse --show-toplevel 2>/dev/null || pwd)}/.monomind/dashboard-token" 2>/dev/null || true)" "${CTRL_URL}/api/orgs/${delete_name}")
89
89
  echo "$result" | jq -r 'if .ok then "Org '\'''"${delete_name}"'''\'' deleted." else "Error: " + (.error // "unknown") end'
90
90
  }
91
91
  ```
@@ -106,7 +106,7 @@ CTRL_URL=$(jq -r '.url // "http://localhost:4242"' "$REPO_ROOT/.monomind/control
106
106
 
107
107
  Emit `session:start` to dashboard:
108
108
  ```bash
109
- curl -s -X POST "${CTRL_URL}/api/mastermind/event" \
109
+ curl -s -X POST "${CTRL_URL}/api/mastermind/event" -H "x-monomind-token: $(cat "${REPO_ROOT:-$(git rev-parse --show-toplevel 2>/dev/null || pwd)}/.monomind/dashboard-token" 2>/dev/null || true)" \
110
110
  -H "Content-Type: application/json" \
111
111
  -d "$(jq -cn \
112
112
  --arg session "$session_id" \
@@ -118,7 +118,7 @@ curl -s -X POST "${CTRL_URL}/api/mastermind/event" \
118
118
 
119
119
  Emit `domain:dispatch`:
120
120
  ```bash
121
- curl -s -X POST "${CTRL_URL}/api/mastermind/event" \
121
+ curl -s -X POST "${CTRL_URL}/api/mastermind/event" -H "x-monomind-token: $(cat "${REPO_ROOT:-$(git rev-parse --show-toplevel 2>/dev/null || pwd)}/.monomind/dashboard-token" 2>/dev/null || true)" \
122
122
  -H "Content-Type: application/json" \
123
123
  -d "$(jq -cn \
124
124
  --arg session "$session_id" \
@@ -129,7 +129,7 @@ Invoke `Skill("mastermind-skills:createorg")` passing: brain_context, prompt, or
129
129
 
130
130
  After skill returns: note the status (`complete`, `partial`, or `blocked`). Emit `session:complete`:
131
131
  ```bash
132
- curl -s -X POST "${CTRL_URL}/api/mastermind/event" \
132
+ curl -s -X POST "${CTRL_URL}/api/mastermind/event" -H "x-monomind-token: $(cat "${REPO_ROOT:-$(git rev-parse --show-toplevel 2>/dev/null || pwd)}/.monomind/dashboard-token" 2>/dev/null || true)" \
133
133
  -H "Content-Type: application/json" \
134
134
  -d "$(jq -cn \
135
135
  --arg session "$session_id" \
@@ -338,7 +338,7 @@ jq -n --arg sid "$SESSION_ID" --arg proj "$project_name" --arg prompt "$resolved
338
338
  && mv "$MONO_DIR/sessions/current.json.tmp" \
339
339
  "$MONO_DIR/sessions/current.json"
340
340
  CTRL_URL=$(jq -r '.url // "http://localhost:4242"' "$REPO_ROOT/.monomind/control.json" 2>/dev/null || echo "http://localhost:4242")
341
- curl -s -o /dev/null -X POST "${CTRL_URL}/api/mastermind/event" \
341
+ curl -s -o /dev/null -X POST "${CTRL_URL}/api/mastermind/event" -H "x-monomind-token: $(cat "${REPO_ROOT:-$(git rev-parse --show-toplevel 2>/dev/null || pwd)}/.monomind/dashboard-token" 2>/dev/null || true)" \
342
342
  -H "Content-Type: application/json" \
343
343
  -d "$(jq -cn --arg sid "$SESSION_ID" --arg prompt "$resolved_prompt" --arg mode "$mode" --arg proj "$REPO_ROOT" \
344
344
  '{type:"session:start",session:$sid,prompt:$prompt,mode:$mode,project:$proj,ts:(now*1000|floor)}')" || true
@@ -715,7 +715,7 @@ domains_needed=$(jq -r '.domains_needed[]? // empty' "$SESSION_STATE" | grep -v
715
715
  for domain in $domains_needed; do
716
716
  goal=$(jq -r --arg d "$domain" '.domain_goals[$d] // empty' "$SESSION_STATE")
717
717
  [ -z "$goal" ] && goal=$(jq -r '.prompt // ""' "$SESSION_STATE")
718
- curl -s -o /dev/null -X POST "${CTRL_URL}/api/mastermind/event" \
718
+ curl -s -o /dev/null -X POST "${CTRL_URL}/api/mastermind/event" -H "x-monomind-token: $(cat "${REPO_ROOT:-$(git rev-parse --show-toplevel 2>/dev/null || pwd)}/.monomind/dashboard-token" 2>/dev/null || true)" \
719
719
  -H "Content-Type: application/json" \
720
720
  -d "$(jq -cn --arg sid "$SESSION_ID" --arg d "$domain" --arg cmd "$goal" \
721
721
  '{type:"domain:dispatch",session:$sid,domain:$d,cmd:$cmd,ts:(now*1000|floor)}')" || true
@@ -889,7 +889,7 @@ echo "overall_status=$overall_status completed_domains=${completed_domains[*]}"
889
889
 
890
890
  completed_domains_json=$(jq -n '$ARGS.positional' --args "${completed_domains[@]}")
891
891
 
892
- curl -s -o /dev/null -X POST "${CTRL_URL}/api/mastermind/event" \
892
+ curl -s -o /dev/null -X POST "${CTRL_URL}/api/mastermind/event" -H "x-monomind-token: $(cat "${REPO_ROOT:-$(git rev-parse --show-toplevel 2>/dev/null || pwd)}/.monomind/dashboard-token" 2>/dev/null || true)" \
893
893
  -H "Content-Type: application/json" \
894
894
  -d "$(jq -cn \
895
895
  --arg sid "$SESSION_ID" \
@@ -101,7 +101,7 @@ EOF
101
101
  echo "LOOP_ID=${LOOP_ID}"
102
102
  REPO_ROOT=$(git rev-parse --show-toplevel 2>/dev/null || pwd)
103
103
  CTRL_URL=$(jq -r '.url // "http://localhost:4242"' "$REPO_ROOT/.monomind/control.json" 2>/dev/null || echo "http://localhost:4242")
104
- curl -s -X POST "${CTRL_URL}/api/mastermind/event" \
104
+ curl -s -X POST "${CTRL_URL}/api/mastermind/event" -H "x-monomind-token: $(cat "${REPO_ROOT:-$(git rev-parse --show-toplevel 2>/dev/null || pwd)}/.monomind/dashboard-token" 2>/dev/null || true)" \
105
105
  -H "Content-Type: application/json" \
106
106
  -d "{\"type\":\"loop:start\",\"loopId\":\"${LOOP_ID}\",\"command\":\"/mastermind:repeat\",\"mode\":\"${LOOP_TYPE}\",\"maxReps\":${LOOP_MAXREPS},\"interval\":<INTERVAL>,\"ts\":$(date +%s)000}" || true
107
107
  ```
@@ -165,7 +165,7 @@ If `TILLEND_EMPTY=true`:
165
165
  rm -f ".monomind/loops/<LOOP_ID>.json" ".monomind/loops/<LOOP_ID>.stop"
166
166
  REPO_ROOT=$(git rev-parse --show-toplevel 2>/dev/null || pwd)
167
167
  CTRL_URL=$(jq -r '.url // "http://localhost:4242"' "$REPO_ROOT/.monomind/control.json" 2>/dev/null || echo "http://localhost:4242")
168
- curl -s -X POST "${CTRL_URL}/api/mastermind/event" \
168
+ curl -s -X POST "${CTRL_URL}/api/mastermind/event" -H "x-monomind-token: $(cat "${REPO_ROOT:-$(git rev-parse --show-toplevel 2>/dev/null || pwd)}/.monomind/dashboard-token" 2>/dev/null || true)" \
169
169
  -H "Content-Type: application/json" \
170
170
  -d "{\"type\":\"loop:complete\",\"loopId\":\"<LOOP_ID>\",\"command\":\"/mastermind:repeat\",\"mode\":\"tillend\",\"ranReps\":<PREV_REP>,\"reason\":\"empty-round\",\"ts\":$(date +%s)000}" || true
171
171
  ```
@@ -178,7 +178,7 @@ If `--tillend` is active AND `CURRENT_REP > MAXRUNS` (safety cap reached):
178
178
  rm -f ".monomind/loops/<LOOP_ID>.json" ".monomind/loops/<LOOP_ID>.stop"
179
179
  REPO_ROOT=$(git rev-parse --show-toplevel 2>/dev/null || pwd)
180
180
  CTRL_URL=$(jq -r '.url // "http://localhost:4242"' "$REPO_ROOT/.monomind/control.json" 2>/dev/null || echo "http://localhost:4242")
181
- curl -s -X POST "${CTRL_URL}/api/mastermind/event" \
181
+ curl -s -X POST "${CTRL_URL}/api/mastermind/event" -H "x-monomind-token: $(cat "${REPO_ROOT:-$(git rev-parse --show-toplevel 2>/dev/null || pwd)}/.monomind/dashboard-token" 2>/dev/null || true)" \
182
182
  -H "Content-Type: application/json" \
183
183
  -d "{\"type\":\"loop:complete\",\"loopId\":\"<LOOP_ID>\",\"command\":\"/mastermind:repeat\",\"mode\":\"tillend\",\"ranReps\":<PREV_REP>,\"reason\":\"safety-cap\",\"ts\":$(date +%s)000}" || true
184
184
  ```
@@ -193,7 +193,7 @@ Remove the state file and emit loop:complete:
193
193
  rm -f ".monomind/loops/<LOOP_ID>.json" ".monomind/loops/<LOOP_ID>.stop"
194
194
  REPO_ROOT=$(git rev-parse --show-toplevel 2>/dev/null || pwd)
195
195
  CTRL_URL=$(jq -r '.url // "http://localhost:4242"' "$REPO_ROOT/.monomind/control.json" 2>/dev/null || echo "http://localhost:4242")
196
- curl -s -X POST "${CTRL_URL}/api/mastermind/event" \
196
+ curl -s -X POST "${CTRL_URL}/api/mastermind/event" -H "x-monomind-token: $(cat "${REPO_ROOT:-$(git rev-parse --show-toplevel 2>/dev/null || pwd)}/.monomind/dashboard-token" 2>/dev/null || true)" \
197
197
  -H "Content-Type: application/json" \
198
198
  -d "{\"type\":\"loop:complete\",\"loopId\":\"<LOOP_ID>\",\"command\":\"/mastermind:repeat\",\"ranReps\":<MAX_REPS>,\"ts\":$(date +%s)000}" || true
199
199
  ```
@@ -229,7 +229,7 @@ cat > ".monomind/loops/<LOOP_ID>.json" << EOF
229
229
  EOF
230
230
  REPO_ROOT=$(git rev-parse --show-toplevel 2>/dev/null || pwd)
231
231
  CTRL_URL=$(jq -r '.url // "http://localhost:4242"' "$REPO_ROOT/.monomind/control.json" 2>/dev/null || echo "http://localhost:4242")
232
- curl -s -X POST "${CTRL_URL}/api/mastermind/event" \
232
+ curl -s -X POST "${CTRL_URL}/api/mastermind/event" -H "x-monomind-token: $(cat "${REPO_ROOT:-$(git rev-parse --show-toplevel 2>/dev/null || pwd)}/.monomind/dashboard-token" 2>/dev/null || true)" \
233
233
  -H "Content-Type: application/json" \
234
234
  -d "{\"type\":\"loop:tick\",\"loopId\":\"<LOOP_ID>\",\"command\":\"/mastermind:repeat\",\"mode\":\"${LOOP_TYPE}\",\"completedRep\":<PREV_REP>,\"nextRep\":<CURRENT_REP>,\"nextAt\":${NEXT_AT},\"ts\":$(date +%s)000}" || true
235
235
  ```
@@ -103,7 +103,7 @@ session_id="${session_id:-mm-$(date -u +%Y%m%dT%H%M%S)}"
103
103
 
104
104
  Emit `session:start` to dashboard:
105
105
  ```bash
106
- curl -s -X POST "${CTRL_URL}/api/mastermind/event" \
106
+ curl -s -X POST "${CTRL_URL}/api/mastermind/event" -H "x-monomind-token: $(cat "${REPO_ROOT:-$(git rev-parse --show-toplevel 2>/dev/null || pwd)}/.monomind/dashboard-token" 2>/dev/null || true)" \
107
107
  -H "Content-Type: application/json" \
108
108
  -d "$(jq -cn \
109
109
  --arg session "$session_id" \
@@ -114,7 +114,7 @@ curl -s -X POST "${CTRL_URL}/api/mastermind/event" \
114
114
 
115
115
  Emit `domain:dispatch`:
116
116
  ```bash
117
- curl -s -X POST "${CTRL_URL}/api/mastermind/event" \
117
+ curl -s -X POST "${CTRL_URL}/api/mastermind/event" -H "x-monomind-token: $(cat "${REPO_ROOT:-$(git rev-parse --show-toplevel 2>/dev/null || pwd)}/.monomind/dashboard-token" 2>/dev/null || true)" \
118
118
  -H "Content-Type: application/json" \
119
119
  -d "$(jq -cn \
120
120
  --arg session "$session_id" \
@@ -127,7 +127,7 @@ Invoke `Skill("mastermind-skills:runorg")` passing: brain_context, org_name: `$o
127
127
 
128
128
  After the skill spawns the boss agent and returns: note the status. Emit `session:complete`:
129
129
  ```bash
130
- curl -s -X POST "${CTRL_URL}/api/mastermind/event" \
130
+ curl -s -X POST "${CTRL_URL}/api/mastermind/event" -H "x-monomind-token: $(cat "${REPO_ROOT:-$(git rev-parse --show-toplevel 2>/dev/null || pwd)}/.monomind/dashboard-token" 2>/dev/null || true)" \
131
131
  -H "Content-Type: application/json" \
132
132
  -d "$(jq -cn \
133
133
  --arg session "$session_id" \
@@ -66,7 +66,7 @@ Invoke `Skill("mastermind-skills:stoporg")` passing: org_name: `$org_name`, sess
66
66
 
67
67
  After skill returns: emit `session:complete`:
68
68
  ```bash
69
- curl -s -X POST "${CTRL_URL}/api/mastermind/event" \
69
+ curl -s -X POST "${CTRL_URL}/api/mastermind/event" -H "x-monomind-token: $(cat "${REPO_ROOT:-$(git rev-parse --show-toplevel 2>/dev/null || pwd)}/.monomind/dashboard-token" 2>/dev/null || true)" \
70
70
  -H "Content-Type: application/json" \
71
71
  -d "$(jq -cn \
72
72
  --arg session "$session_id" \
@@ -172,11 +172,16 @@ async function main() {
172
172
  ? [...args, String(DEFAULT_PORT)]
173
173
  : [...args, 'ui', '--no-open', '--port', String(DEFAULT_PORT)];
174
174
 
175
+ // The child writes its ACTUAL bound port here — the only identity-proof
176
+ // signal. An HTTP probe alone can be answered by another project's server
177
+ // already holding the port (which then leaves control.json lying about
178
+ // where THIS project's events should go).
179
+ const BOUND_REPORT = path.join(CWD, '.monomind', `.bound-report-${Date.now()}.json`);
175
180
  const child = spawn(cmd, allArgs, {
176
181
  detached: true,
177
182
  stdio: 'ignore',
178
183
  cwd: CWD,
179
- env: { ...process.env, CLAUDE_PROJECT_DIR: CWD },
184
+ env: { ...process.env, CLAUDE_PROJECT_DIR: CWD, MONOMIND_BOUND_REPORT: BOUND_REPORT },
180
185
  });
181
186
 
182
187
  child.unref();
@@ -189,11 +194,20 @@ async function main() {
189
194
  // If port 4242 was in use, server.mjs auto-increments (up to +10).
190
195
  // Poll a few ports to find where it actually bound and update control.json.
191
196
  const http = require('http');
197
+ // Resolves to the responder's pid (number), null for "answers but pid
198
+ // unreadable" (auth-walled or old server), or false for "no answer".
192
199
  function probePort(p) {
193
200
  return new Promise((resolve) => {
194
201
  const req = http.get({ hostname: 'localhost', port: p, path: '/api/status', timeout: 1000 }, (res) => {
195
- res.resume();
196
- resolve(res.statusCode < 500);
202
+ let body = '';
203
+ res.on('data', (c) => { if (body.length < 4096) body += c; });
204
+ res.on('end', () => {
205
+ if (res.statusCode >= 500) return resolve(false);
206
+ try {
207
+ const pid = JSON.parse(body).pid;
208
+ resolve(typeof pid === 'number' ? pid : null);
209
+ } catch { resolve(null); }
210
+ });
197
211
  });
198
212
  req.on('error', () => resolve(false));
199
213
  req.on('timeout', () => { req.destroy(); resolve(false); });
@@ -201,20 +215,54 @@ async function main() {
201
215
  }
202
216
 
203
217
  // Give the server up to ~10 s to start, then confirm the actual port.
218
+ // Identity-first: the child's bound-report file (written by server.mjs) is
219
+ // authoritative; the HTTP probe only confirms a port when the responder's
220
+ // pid matches our child. A foreign server answering on DEFAULT_PORT must
221
+ // NOT be mistaken for ours — that lie misroutes every event emitter in
222
+ // this project (root cause of orgs running invisibly).
204
223
  async function confirmPort() {
224
+ let sawForeignOnDefault = false;
205
225
  for (let attempt = 0; attempt < 20; attempt++) {
206
226
  await new Promise(r => setTimeout(r, 500));
227
+ // 1) Authoritative: child self-reported its bound port
228
+ try {
229
+ const rep = JSON.parse(fs.readFileSync(BOUND_REPORT, 'utf8'));
230
+ if (rep && rep.pid === child.pid && typeof rep.port === 'number') {
231
+ try { fs.unlinkSync(BOUND_REPORT); } catch { /* ignore */ }
232
+ if (rep.port !== DEFAULT_PORT) {
233
+ writeStatus(child.pid, rep.port);
234
+ process.stdout.write(`[control] server bound to port ${rep.port} (updated control.json)\n`);
235
+ }
236
+ return;
237
+ }
238
+ } catch { /* not written yet or old server — fall through to probe */ }
239
+ // 2) Fallback: pid-matched HTTP probe (old servers without report support)
207
240
  for (let delta = 0; delta <= 10; delta++) {
208
241
  const p = DEFAULT_PORT + delta;
209
- if (await probePort(p)) {
242
+ const responderPid = await probePort(p);
243
+ if (responderPid === false) continue;
244
+ if (responderPid === child.pid) {
210
245
  if (p !== DEFAULT_PORT) {
211
246
  writeStatus(child.pid, p);
212
247
  process.stdout.write(`[control] server bound to port ${p} (updated control.json)\n`);
213
248
  }
214
249
  return;
215
250
  }
251
+ if (p === DEFAULT_PORT && typeof responderPid === 'number') sawForeignOnDefault = true;
252
+ // pid mismatch or unreadable — not provably ours, keep scanning
216
253
  }
217
254
  }
255
+ try { fs.unlinkSync(BOUND_REPORT); } catch { /* ignore */ }
256
+ if (sawForeignOnDefault) {
257
+ // Another project's server owns DEFAULT_PORT and our child never proved
258
+ // its own port — point control.json at the live server instead of lying,
259
+ // and kill our redundant child.
260
+ try { process.kill(child.pid, 'SIGTERM'); } catch { /* already gone */ }
261
+ process.stdout.write(`[control] port ${DEFAULT_PORT} is served by another project's control server — reusing it (killed redundant child)\n`);
262
+ const foreignPid = await probePort(DEFAULT_PORT);
263
+ writeStatus(typeof foreignPid === 'number' ? foreignPid : 0, DEFAULT_PORT);
264
+ return;
265
+ }
218
266
  // Server never became reachable on any expected port — kill the child
219
267
  // rather than leave an orphan bound to some port nothing will ever read.
220
268
  // The next session-start simply retries.
@@ -66,12 +66,20 @@ function forwardToDashboard(entry) {
66
66
  const rawPort = Number(ctrl.port);
67
67
  const port = (Number.isInteger(rawPort) && rawPort >= 1024 && rawPort <= 65535) ? rawPort : 4242;
68
68
  const body = JSON.stringify({ ...entry, hookCaptured: true });
69
+ // Ingest is default-deny: attach the dashboard credential (written by
70
+ // server.mjs next to control.json) or the POST is silently rejected.
71
+ let authHdr = '';
72
+ try { authHdr = fs.readFileSync(path.join(CWD, '.monomind', 'dashboard-token'), 'utf8').trim(); } catch {}
69
73
  const req = http.request({
70
74
  method: 'POST',
71
75
  hostname: 'localhost',
72
76
  port,
73
77
  path: '/api/mastermind/event',
74
- headers: { 'Content-Type': 'application/json', 'Content-Length': Buffer.byteLength(body) },
78
+ headers: {
79
+ 'Content-Type': 'application/json',
80
+ 'Content-Length': Buffer.byteLength(body),
81
+ ...(authHdr ? { 'x-monomind-token': authHdr } : {}),
82
+ },
75
83
  timeout: 400,
76
84
  });
77
85
  req.on('error', () => {});
@@ -201,12 +201,20 @@ function emitEvent(event) {
201
201
  }
202
202
  const u = new URL(baseUrl);
203
203
  const body = JSON.stringify(event);
204
+ // Ingest is default-deny: attach the dashboard credential (written by
205
+ // server.mjs next to control.json) or the POST is silently rejected.
206
+ let authHdr = '';
207
+ try { authHdr = fs.readFileSync(path.join(CWD, '.monomind', 'dashboard-token'), 'utf8').trim(); } catch {}
204
208
  const req = http.request({
205
209
  hostname: u.hostname,
206
210
  port: parseInt(u.port || '4242', 10),
207
211
  path: '/api/mastermind/event',
208
212
  method: 'POST',
209
- headers: { 'Content-Type': 'application/json', 'Content-Length': Buffer.byteLength(body) },
213
+ headers: {
214
+ 'Content-Type': 'application/json',
215
+ 'Content-Length': Buffer.byteLength(body),
216
+ ...(authHdr ? { 'x-monomind-token': authHdr } : {}),
217
+ },
210
218
  }, () => {
211
219
  try { fs.unlinkSync(spoolFile); } catch {}
212
220
  resolve();
@@ -319,32 +319,62 @@ module.exports = {
319
319
  // ── Second Brain: per-request knowledge injection ──────────────────
320
320
  // When the project has an indexed knowledge base, surface the most
321
321
  // relevant excerpts for THIS prompt so Claude has them without having
322
- // to decide to call knowledge_search. Keyword-scored over chunks.jsonl
323
- // (a hook subprocess can't afford a 1-3s embedding-model load per
324
- // prompt; full semantic search stays behind the knowledge_search MCP
325
- // tool / `monomind doc search`).
326
- // monolean: [keyword-only injection] upgrade path: warm control-server
327
- // endpoint holding the embedding model for semantic per-prompt retrieval.
322
+ // to decide to call knowledge_search. Semantic-first via the dashboard
323
+ // server's warm /api/knowledge/search (it holds the local embedding
324
+ // model hot a hook subprocess can't afford a 1-3s model load per
325
+ // prompt); tokenized keyword scoring over chunks.jsonl as the fallback
326
+ // when the server is down or still warming.
328
327
  try {
329
328
  var sbPrompt = String(prompt || '');
330
329
  // Skip slash commands and trivial prompts — injection would be noise.
331
330
  if (sbPrompt.length >= 12 && sbPrompt.charAt(0) !== '/') {
332
331
  var sbKnowledgeDir = path.join(CWD, '.monomind', 'knowledge');
333
332
  if (fs.existsSync(path.join(sbKnowledgeDir, 'chunks.jsonl'))) {
334
- var sbSearch = hCtx._buildKnowledgeSearchFn(sbKnowledgeDir);
335
- var sbHits = await hCtx.runWithTimeout(
336
- function() { return sbSearch(sbPrompt, { namespace: 'knowledge:shared', limit: 3, minScore: 0.45 }); },
337
- 'second-brain-inject'
338
- );
333
+ var sbHits = null;
334
+ var sbMethod = 'keyword';
335
+
336
+ // Semantic path: warm control-server endpoint (strictly local traffic;
337
+ // sbAuth is the local dashboard session value from .monomind, same one
338
+ // every other hook event POST attaches — not a checked-in secret).
339
+ try {
340
+ var sbCtrlUrl = 'http://localhost:4242';
341
+ try {
342
+ var sbCtl = JSON.parse(fs.readFileSync(path.join(CWD, '.monomind', 'control.json'), 'utf-8'));
343
+ if (sbCtl.url) sbCtrlUrl = sbCtl.url;
344
+ } catch (_) {}
345
+ var sbAuth = '';
346
+ try { sbAuth = fs.readFileSync(path.join(CWD, '.monomind', 'dashboard-token'), 'utf-8').trim(); } catch (_) {}
347
+ var sbResp = await fetch(sbCtrlUrl + '/api/knowledge/search', {
348
+ method: 'POST',
349
+ headers: { 'Content-Type': 'application/json', 'x-monomind-token': sbAuth },
350
+ body: JSON.stringify({ query: sbPrompt, namespace: 'knowledge:shared', limit: 3 }),
351
+ signal: AbortSignal.timeout(900),
352
+ });
353
+ if (sbResp.ok) {
354
+ var sbData = await sbResp.json();
355
+ if (sbData && Array.isArray(sbData.results) && sbData.results.length > 0) {
356
+ sbHits = sbData.results.map(function(r) { return { key: r.key, value: r.content, score: r.score, metadata: {} }; });
357
+ sbMethod = sbData.method === 'semantic' ? 'semantic' : 'keyword';
358
+ }
359
+ }
360
+ } catch (_) { /* server down or warming — fall back below */ }
361
+
362
+ if (!sbHits) {
363
+ var sbSearch = hCtx._buildKnowledgeSearchFn(sbKnowledgeDir);
364
+ sbHits = await hCtx.runWithTimeout(
365
+ function() { return sbSearch(sbPrompt, { namespace: 'knowledge:shared', limit: 3, minScore: 0.45 }); },
366
+ 'second-brain-inject'
367
+ );
368
+ }
339
369
  if (sbHits && sbHits.length > 0) {
340
- var sbLines = ['[SECOND_BRAIN] ' + sbHits.length + ' relevant excerpt(s) from the project knowledge base:'];
370
+ var sbLines = ['[SECOND_BRAIN] ' + sbHits.length + ' relevant excerpt(s) (' + sbMethod + ') from the project knowledge base:'];
341
371
  for (var sbI = 0; sbI < sbHits.length; sbI++) {
342
372
  var sbH = sbHits[sbI];
343
373
  var sbSrc = (sbH.metadata && sbH.metadata.filePath) ? String(sbH.metadata.filePath).split('/').slice(-2).join('/') : sbH.key;
344
374
  var sbText = String(sbH.value || '').replace(/\s+/g, ' ').slice(0, 240);
345
375
  sbLines.push(' • [' + sbSrc + '] ' + sbText);
346
376
  }
347
- sbLines.push(' (deeper/semantic lookup: mcp__monomind__knowledge_search or `monomind doc search -q "..."`)');
377
+ sbLines.push(' (deeper lookup: mcp__monomind__knowledge_search or `monomind doc search -q "..."`)');
348
378
  console.log(sbLines.join('\n'));
349
379
  }
350
380
  }
@@ -230,7 +230,7 @@ Resolve `CTRL_URL` at runtime: `jq -r '.url // "http://localhost:4242"' "$REPO_R
230
230
  ```bash
231
231
  REPO_ROOT=$(git rev-parse --show-toplevel 2>/dev/null || pwd)
232
232
  CTRL_URL=$(jq -r '.url // "http://localhost:4242"' "$REPO_ROOT/.monomind/control.json" 2>/dev/null || echo "http://localhost:4242")
233
- curl -s -o /dev/null -X POST "${CTRL_URL}/api/mastermind/event" \
233
+ curl -s -o /dev/null -X POST "${CTRL_URL}/api/mastermind/event" -H "x-monomind-token: $(cat "${REPO_ROOT:-$(git rev-parse --show-toplevel 2>/dev/null || pwd)}/.monomind/dashboard-token" 2>/dev/null || true)" \
234
234
  -H "Content-Type: application/json" \
235
235
  -d "$(jq -cn \
236
236
  --arg sid "$SESSION_ID" \
@@ -73,7 +73,7 @@ Set `TILLEND_EMPTY=true` **only if git shows no changes AND your self-assessment
73
73
  ```bash
74
74
  REPO_ROOT=$(git rev-parse --show-toplevel 2>/dev/null || pwd)
75
75
  CTRL_URL=$(jq -r '.url // "http://localhost:4242"' "$REPO_ROOT/.monomind/control.json" 2>/dev/null || echo "http://localhost:4242")
76
- curl -s -X POST "${CTRL_URL}/api/mastermind/event" \
76
+ curl -s -X POST "${CTRL_URL}/api/mastermind/event" -H "x-monomind-token: $(cat "${REPO_ROOT:-$(git rev-parse --show-toplevel 2>/dev/null || pwd)}/.monomind/dashboard-token" 2>/dev/null || true)" \
77
77
  -H "Content-Type: application/json" \
78
78
  -d "{\"type\":\"loop:complete\",\"loopId\":\"${LOOP_ID}\",\"command\":\"/<command>\",\"mode\":\"tillend\",\"ranReps\":<current_rep>,\"reason\":\"empty-round\",\"project\":\"${REPO_ROOT}\",\"ts\":$(date +%s)000}" || true
79
79
  ```
@@ -103,7 +103,7 @@ If `current_rep >= repeat_count`:
103
103
  ```bash
104
104
  REPO_ROOT=$(git rev-parse --show-toplevel 2>/dev/null || pwd)
105
105
  CTRL_URL=$(jq -r '.url // "http://localhost:4242"' "$REPO_ROOT/.monomind/control.json" 2>/dev/null || echo "http://localhost:4242")
106
- curl -s -X POST "${CTRL_URL}/api/mastermind/event" \
106
+ curl -s -X POST "${CTRL_URL}/api/mastermind/event" -H "x-monomind-token: $(cat "${REPO_ROOT:-$(git rev-parse --show-toplevel 2>/dev/null || pwd)}/.monomind/dashboard-token" 2>/dev/null || true)" \
107
107
  -H "Content-Type: application/json" \
108
108
  -d "{\"type\":\"loop:complete\",\"loopId\":\"${LOOP_ID}\",\"command\":\"/<command>\",\"ranReps\":<repeat_count>,\"project\":\"${REPO_ROOT}\",\"ts\":$(date +%s)000}" || true
109
109
  ```
@@ -151,7 +151,7 @@ Emit `loop:tick`:
151
151
  ```bash
152
152
  REPO_ROOT=$(git rev-parse --show-toplevel 2>/dev/null || pwd)
153
153
  CTRL_URL=$(jq -r '.url // "http://localhost:4242"' "$REPO_ROOT/.monomind/control.json" 2>/dev/null || echo "http://localhost:4242")
154
- curl -s -X POST "${CTRL_URL}/api/mastermind/event" \
154
+ curl -s -X POST "${CTRL_URL}/api/mastermind/event" -H "x-monomind-token: $(cat "${REPO_ROOT:-$(git rev-parse --show-toplevel 2>/dev/null || pwd)}/.monomind/dashboard-token" 2>/dev/null || true)" \
155
155
  -H "Content-Type: application/json" \
156
156
  -d "{\"type\":\"loop:tick\",\"loopId\":\"${LOOP_ID}\",\"command\":\"/<command>\",\"completedRep\":<current_rep>,\"nextRep\":<next_rep>,\"nextAt\":${NEXT_AT},\"project\":\"${REPO_ROOT}\",\"ts\":$(date +%s)000}" || true
157
157
  ```
@@ -139,7 +139,7 @@ Emit `org:adapter:installed` event:
139
139
  ```bash
140
140
  REPO_ROOT=$(git rev-parse --show-toplevel 2>/dev/null || pwd)
141
141
  CTRL_URL=$(jq -r '.url // "http://localhost:4242"' "$REPO_ROOT/.monomind/control.json" 2>/dev/null || echo "http://localhost:4242")
142
- curl -s -X POST "${CTRL_URL}/api/mastermind/event" \
142
+ curl -s -X POST "${CTRL_URL}/api/mastermind/event" -H "x-monomind-token: $(cat "${REPO_ROOT:-$(git rev-parse --show-toplevel 2>/dev/null || pwd)}/.monomind/dashboard-token" 2>/dev/null || true)" \
143
143
  -H "Content-Type: application/json" \
144
144
  -d "$(jq -cn --arg org "$org_name" --arg type "$adapter_type" --arg pkg "$package_name" \
145
145
  '{type:"org:adapter:installed",org:$org,adapter:$type,package:$pkg,ts:(now*1000|floor)}')" || true
@@ -126,7 +126,7 @@ Then emit `org:agent:hired` event to dashboard:
126
126
  ```bash
127
127
  REPO_ROOT=$(git rev-parse --show-toplevel 2>/dev/null || pwd)
128
128
  CTRL_URL=$(jq -r '.url // "http://localhost:4242"' "$REPO_ROOT/.monomind/control.json" 2>/dev/null || echo "http://localhost:4242")
129
- curl -s -X POST "${CTRL_URL}/api/mastermind/event" \
129
+ curl -s -X POST "${CTRL_URL}/api/mastermind/event" -H "x-monomind-token: $(cat "${REPO_ROOT:-$(git rev-parse --show-toplevel 2>/dev/null || pwd)}/.monomind/dashboard-token" 2>/dev/null || true)" \
130
130
  -H "Content-Type: application/json" \
131
131
  -d "$(jq -cn --arg org "$org_name" --arg role "$agent_id" --arg title "$title" \
132
132
  '{type:"org:agent:hired",org:$org,role:$role,title:$title,ts:(now*1000|floor)}')" || true
@@ -67,7 +67,7 @@ If this skill is invoked directly (not by master):
67
67
  ```bash
68
68
  REPO_ROOT=$(git rev-parse --show-toplevel 2>/dev/null || pwd)
69
69
  CTRL_URL=$(jq -r '.url // "http://localhost:4242"' "$REPO_ROOT/.monomind/control.json" 2>/dev/null || echo "http://localhost:4242")
70
- curl -s -X POST "${CTRL_URL}/api/mastermind/event" \
70
+ curl -s -X POST "${CTRL_URL}/api/mastermind/event" -H "x-monomind-token: $(cat "${REPO_ROOT:-$(git rev-parse --show-toplevel 2>/dev/null || pwd)}/.monomind/dashboard-token" 2>/dev/null || true)" \
71
71
  -H "Content-Type: application/json" \
72
72
  -d '{"type":"session:start","session":"<sessionId>","domain":"architect","ts":'"$(date +%s)"'000}' || true
73
73
  ```
@@ -104,7 +104,7 @@ If this skill is invoked directly (not by master):
104
104
  ```bash
105
105
  REPO_ROOT=$(git rev-parse --show-toplevel 2>/dev/null || pwd)
106
106
  CTRL_URL=$(jq -r '.url // "http://localhost:4242"' "$REPO_ROOT/.monomind/control.json" 2>/dev/null || echo "http://localhost:4242")
107
- curl -s -X POST "${CTRL_URL}/api/mastermind/event" \
107
+ curl -s -X POST "${CTRL_URL}/api/mastermind/event" -H "x-monomind-token: $(cat "${REPO_ROOT:-$(git rev-parse --show-toplevel 2>/dev/null || pwd)}/.monomind/dashboard-token" 2>/dev/null || true)" \
108
108
  -H "Content-Type: application/json" \
109
109
  -d '{"type":"session:complete","session":"<sessionId>","domain":"architect","ts":'"$(date +%s)"'000}' || true
110
110
  ```
@@ -294,7 +294,7 @@ Then emit `agent:spawn` for the manager and spawn it. Before executing the curl
294
294
  ```bash
295
295
  REPO_ROOT=$(git rev-parse --show-toplevel 2>/dev/null || pwd)
296
296
  CTRL_URL=$(jq -r '.url // "http://localhost:4242"' "$REPO_ROOT/.monomind/control.json" 2>/dev/null || echo "http://localhost:4242")
297
- curl -s -X POST "${CTRL_URL}/api/mastermind/event" \
297
+ curl -s -X POST "${CTRL_URL}/api/mastermind/event" -H "x-monomind-token: $(cat "${REPO_ROOT:-$(git rev-parse --show-toplevel 2>/dev/null || pwd)}/.monomind/dashboard-token" 2>/dev/null || true)" \
298
298
  -H "Content-Type: application/json" \
299
299
  -d '{"type":"agent:spawn","session":"<sessionId>","domain":"architect","agent":"<manager_agent_type lowercased and hyphenated, e.g. software-architect>","task":"coordinate architecture analysis","ts":'"$(date +%s)"'000}'
300
300
  ```
@@ -444,7 +444,7 @@ BEFORE spawning each agent, emit agent:spawn to the live dashboard. Before each
444
444
  \`\`\`bash
445
445
  REPO_ROOT=$(git rev-parse --show-toplevel 2>/dev/null || pwd)
446
446
  CTRL_URL=$(jq -r '.url // "http://localhost:4242"' "$REPO_ROOT/.monomind/control.json" 2>/dev/null || echo "http://localhost:4242")
447
- curl -s -X POST "${CTRL_URL}/api/mastermind/event" \
447
+ curl -s -X POST "${CTRL_URL}/api/mastermind/event" -H "x-monomind-token: $(cat "${REPO_ROOT:-$(git rev-parse --show-toplevel 2>/dev/null || pwd)}/.monomind/dashboard-token" 2>/dev/null || true)" \
448
448
  -H "Content-Type: application/json" \
449
449
  -d '{"type":"agent:spawn","session":"<sessionId>","domain":"architect","agent":"<subagent_type lowercased and hyphenated, e.g. software-architect>","task":"<stream-description>","ts":'"$(date +%s)"'000}'
450
450
  \`\`\`
@@ -453,7 +453,7 @@ If handing off artifacts to another domain (e.g. build for refactoring implement
453
453
  \`\`\`bash
454
454
  REPO_ROOT=$(git rev-parse --show-toplevel 2>/dev/null || pwd)
455
455
  CTRL_URL=$(jq -r '.url // "http://localhost:4242"' "$REPO_ROOT/.monomind/control.json" 2>/dev/null || echo "http://localhost:4242")
456
- curl -s -X POST "${CTRL_URL}/api/mastermind/event" \
456
+ curl -s -X POST "${CTRL_URL}/api/mastermind/event" -H "x-monomind-token: $(cat "${REPO_ROOT:-$(git rev-parse --show-toplevel 2>/dev/null || pwd)}/.monomind/dashboard-token" 2>/dev/null || true)" \
457
457
  -H "Content-Type: application/json" \
458
458
  -d '{"type":"intercom","session":"<sessionId>","from":"architect","to":"<domain>","msg":"<msg>","ts":'"$(date +%s)"'000}'
459
459
  \`\`\`
@@ -464,7 +464,7 @@ BEFORE returning, emit domain:complete to the live dashboard:
464
464
  \`\`\`bash
465
465
  REPO_ROOT=$(git rev-parse --show-toplevel 2>/dev/null || pwd)
466
466
  CTRL_URL=$(jq -r '.url // "http://localhost:4242"' "$REPO_ROOT/.monomind/control.json" 2>/dev/null || echo "http://localhost:4242")
467
- curl -s -X POST "${CTRL_URL}/api/mastermind/event" \
467
+ curl -s -X POST "${CTRL_URL}/api/mastermind/event" -H "x-monomind-token: $(cat "${REPO_ROOT:-$(git rev-parse --show-toplevel 2>/dev/null || pwd)}/.monomind/dashboard-token" 2>/dev/null || true)" \
468
468
  -H "Content-Type: application/json" \
469
469
  -d '{"type":"domain:complete","session":"<sessionId>","domain":"architect","status":"<choose: complete | partial | blocked>","artifacts":[],"decisions":[],"ts":'"$(date +%s)"'000}'
470
470
  \`\`\`
@@ -552,7 +552,7 @@ Before executing the curl blocks below and when constructing the Task() descript
552
552
  ```bash
553
553
  REPO_ROOT=$(git rev-parse --show-toplevel 2>/dev/null || pwd)
554
554
  CTRL_URL=$(jq -r '.url // "http://localhost:4242"' "$REPO_ROOT/.monomind/control.json" 2>/dev/null || echo "http://localhost:4242")
555
- curl -s -X POST "${CTRL_URL}/api/mastermind/event" \
555
+ curl -s -X POST "${CTRL_URL}/api/mastermind/event" -H "x-monomind-token: $(cat "${REPO_ROOT:-$(git rev-parse --show-toplevel 2>/dev/null || pwd)}/.monomind/dashboard-token" 2>/dev/null || true)" \
556
556
  -H "Content-Type: application/json" \
557
557
  -d '{"type":"agent:spawn","session":"<sessionId>","domain":"architect","agent":"<resolved agent slug, e.g. software-architect>","task":"<prompt>","ts":'"$(date +%s)"'000}'
558
558
  ```
@@ -568,7 +568,7 @@ Before executing the curl blocks below and when constructing the Task() descript
568
568
  ```bash
569
569
  REPO_ROOT=$(git rev-parse --show-toplevel 2>/dev/null || pwd)
570
570
  CTRL_URL=$(jq -r '.url // "http://localhost:4242"' "$REPO_ROOT/.monomind/control.json" 2>/dev/null || echo "http://localhost:4242")
571
- curl -s -X POST "${CTRL_URL}/api/mastermind/event" \
571
+ curl -s -X POST "${CTRL_URL}/api/mastermind/event" -H "x-monomind-token: $(cat "${REPO_ROOT:-$(git rev-parse --show-toplevel 2>/dev/null || pwd)}/.monomind/dashboard-token" 2>/dev/null || true)" \
572
572
  -H "Content-Type: application/json" \
573
573
  -d '{"type":"domain:complete","session":"<sessionId>","domain":"architect","status":"complete","artifacts":[],"decisions":[],"ts":'"$(date +%s)"'000}'
574
574
  ```
@@ -93,7 +93,7 @@ Emit `org:backup:created` event:
93
93
  ```bash
94
94
  REPO_ROOT=$(git rev-parse --show-toplevel 2>/dev/null || pwd)
95
95
  CTRL_URL=$(jq -r '.url // "http://localhost:4242"' "$REPO_ROOT/.monomind/control.json" 2>/dev/null || echo "http://localhost:4242")
96
- curl -s -X POST "${CTRL_URL}/api/mastermind/event" \
96
+ curl -s -X POST "${CTRL_URL}/api/mastermind/event" -H "x-monomind-token: $(cat "${REPO_ROOT:-$(git rev-parse --show-toplevel 2>/dev/null || pwd)}/.monomind/dashboard-token" 2>/dev/null || true)" \
97
97
  -H "Content-Type: application/json" \
98
98
  -d "$(jq -cn --arg org "$org_name" --arg file "$archiveName" \
99
99
  '{type:"org:backup:created",org:$org,file:$file,ts:(now*1000|floor)}')" || true
@@ -151,7 +151,7 @@ Emit `org:bootstrap:complete` event:
151
151
  ```bash
152
152
  REPO_ROOT=$(git rev-parse --show-toplevel 2>/dev/null || pwd)
153
153
  CTRL_URL=$(jq -r '.url // "http://localhost:4242"' "$REPO_ROOT/.monomind/control.json" 2>/dev/null || echo "http://localhost:4242")
154
- curl -s -X POST "${CTRL_URL}/api/mastermind/event" \
154
+ curl -s -X POST "${CTRL_URL}/api/mastermind/event" -H "x-monomind-token: $(cat "${REPO_ROOT:-$(git rev-parse --show-toplevel 2>/dev/null || pwd)}/.monomind/dashboard-token" 2>/dev/null || true)" \
155
155
  -H "Content-Type: application/json" \
156
156
  -d "$(jq -cn --arg org "$org_name" --arg boss "$boss_role_id" \
157
157
  '{type:"org:bootstrap:complete",org:$org,boss:$boss,ts:(now*1000|floor)}')" || true
@@ -122,7 +122,7 @@ if [ "$budget" -gt 0 ] && [ -f "$stateFile" ]; then
122
122
  echo "ALERT: Org $org_name has used $(awk -v t=$total -v b=$budget 'BEGIN{printf "%.1f", t/b*100}')% of budget"
123
123
  REPO_ROOT=$(git rev-parse --show-toplevel 2>/dev/null || pwd)
124
124
  CTRL_URL=$(jq -r '.url // "http://localhost:4242"' "$REPO_ROOT/.monomind/control.json" 2>/dev/null || echo "http://localhost:4242")
125
- curl -s -X POST "${CTRL_URL}/api/mastermind/event" \
125
+ curl -s -X POST "${CTRL_URL}/api/mastermind/event" -H "x-monomind-token: $(cat "${REPO_ROOT:-$(git rev-parse --show-toplevel 2>/dev/null || pwd)}/.monomind/dashboard-token" 2>/dev/null || true)" \
126
126
  -H "Content-Type: application/json" \
127
127
  -d "$(jq -cn --arg org "$org_name" --argjson total $total --argjson budget $budget \
128
128
  '{type:"org:budget:alert",org:$org,tokens_used:$total,budget:$budget,ts:(now*1000|floor)}')" || true
@@ -71,7 +71,7 @@ jq --arg id "$agent_id" --arg ts "$(date -u +%Y-%m-%dT%H:%M:%SZ)" --arg source "
71
71
 
72
72
  REPO_ROOT=$(git rev-parse --show-toplevel 2>/dev/null || pwd)
73
73
  CTRL_URL=$(jq -r '.url // "http://localhost:4242"' "$REPO_ROOT/.monomind/control.json" 2>/dev/null || echo "http://localhost:4242")
74
- curl -s -X POST "${CTRL_URL}/api/mastermind/event" \
74
+ curl -s -X POST "${CTRL_URL}/api/mastermind/event" -H "x-monomind-token: $(cat "${REPO_ROOT:-$(git rev-parse --show-toplevel 2>/dev/null || pwd)}/.monomind/dashboard-token" 2>/dev/null || true)" \
75
75
  -H "Content-Type: application/json" \
76
76
  -d "$(jq -cn \
77
77
  --arg org "$org_name" \
@@ -123,7 +123,7 @@ HEARTBEAT PROCEDURE:
123
123
 
124
124
  4. Report completion — emit heartbeat:complete event:
125
125
  CTRL_URL=$(jq -r '.url // "http://localhost:4242"' "$(git rev-parse --show-toplevel 2>/dev/null || pwd)/.monomind/control.json" 2>/dev/null || echo "http://localhost:4242")
126
- curl -s -X POST "${CTRL_URL}/api/mastermind/event" -H "Content-Type: application/json" \
126
+ curl -s -X POST "${CTRL_URL}/api/mastermind/event" -H "x-monomind-token: $(cat "${REPO_ROOT:-$(git rev-parse --show-toplevel 2>/dev/null || pwd)}/.monomind/dashboard-token" 2>/dev/null || true)" -H "Content-Type: application/json" \
127
127
  -d "$(jq -cn --arg org "${org_name}" --arg role "${agent_id}" --arg title "${agentTitle}" \
128
128
  '{type:"org:heartbeat:complete",org:$org,role:$role,title:$title,ts:(now*1000|floor)}')" || true
129
129
 
@@ -1089,7 +1089,7 @@ if [ -n "$SESSION_ID" ]; then
1089
1089
  --argjson next_actions '["<next_action_1>","<next_action_2>"]' \
1090
1090
  '{domain:$domain,status:$status,artifacts:$artifacts,next_actions:$next_actions}' \
1091
1091
  > "$MONO_DIR/sessions/${SESSION_ID}/idea.json"
1092
- curl -s -o /dev/null -X POST "${CTRL_URL}/api/mastermind/event" \
1092
+ curl -s -o /dev/null -X POST "${CTRL_URL}/api/mastermind/event" -H "x-monomind-token: $(cat "${REPO_ROOT:-$(git rev-parse --show-toplevel 2>/dev/null || pwd)}/.monomind/dashboard-token" 2>/dev/null || true)" \
1093
1093
  -H "Content-Type: application/json" \
1094
1094
  -d "$(jq -cn --arg sid "$SESSION_ID" --arg status "<status>" \
1095
1095
  '{type:"domain:complete",session:$sid,domain:"idea",status:$status,ts:(now*1000|floor)}')" || true
@@ -384,7 +384,7 @@ jq --arg ts "$(date -u +%Y-%m-%dT%H:%M:%SZ)" '.last_tick = $ts' "$cfg" > "$tmp"
384
384
  REPO_ROOT=$(git rev-parse --show-toplevel 2>/dev/null || pwd)
385
385
  CTRL_URL=$(jq -r '.url // "http://localhost:4242"' "$REPO_ROOT/.monomind/control.json" 2>/dev/null || echo "http://localhost:4242")
386
386
  SESSION_ID="monitor-${name}-$(date -u +%Y%m%dT%H%M%S)"
387
- curl -s -o /dev/null -X POST "${CTRL_URL}/api/mastermind/event" \
387
+ curl -s -o /dev/null -X POST "${CTRL_URL}/api/mastermind/event" -H "x-monomind-token: $(cat "${REPO_ROOT:-$(git rev-parse --show-toplevel 2>/dev/null || pwd)}/.monomind/dashboard-token" 2>/dev/null || true)" \
388
388
  -H "Content-Type: application/json" \
389
389
  -d "$(jq -cn --arg sid "$SESSION_ID" --arg name "$name" \
390
390
  '{type:"monitor:tick",session:$sid,monitor:$name,ts:(now*1000|floor)}')" || true
@@ -959,7 +959,7 @@ jq '.stats.done += 1' "$cfg" > "$tmp" && mv "$tmp" "$cfg"
959
959
 
960
960
  **Emit dashboard event:**
961
961
  ```bash
962
- curl -s -o /dev/null -X POST "${CTRL_URL}/api/mastermind/event" \
962
+ curl -s -o /dev/null -X POST "${CTRL_URL}/api/mastermind/event" -H "x-monomind-token: $(cat "${REPO_ROOT:-$(git rev-parse --show-toplevel 2>/dev/null || pwd)}/.monomind/dashboard-token" 2>/dev/null || true)" \
963
963
  -H "Content-Type: application/json" \
964
964
  -d "$(jq -cn --arg sid "$SESSION_ID" --arg name "$name" --arg title "$task_title" \
965
965
  '{type:"monitor:task:done",session:$sid,monitor:$name,task:$title,ts:(now*1000|floor)}')" || true
@@ -161,7 +161,7 @@ Emit `org:settings:updated` event:
161
161
  ```bash
162
162
  REPO_ROOT=$(git rev-parse --show-toplevel 2>/dev/null || pwd)
163
163
  CTRL_URL=$(jq -r '.url // "http://localhost:4242"' "$REPO_ROOT/.monomind/control.json" 2>/dev/null || echo "http://localhost:4242")
164
- curl -s -X POST "${CTRL_URL}/api/mastermind/event" \
164
+ curl -s -X POST "${CTRL_URL}/api/mastermind/event" -H "x-monomind-token: $(cat "${REPO_ROOT:-$(git rev-parse --show-toplevel 2>/dev/null || pwd)}/.monomind/dashboard-token" 2>/dev/null || true)" \
165
165
  -H "Content-Type: application/json" \
166
166
  -d "$(jq -cn --arg org "$org_name" --arg field "$field" --arg value "$value" \
167
167
  '{type:"org:settings:updated",org:$org,field:$field,value:$value,ts:(now*1000|floor)}')" || true
@@ -130,7 +130,7 @@ Emit `org:plugin:installed` event:
130
130
  ```bash
131
131
  REPO_ROOT=$(git rev-parse --show-toplevel 2>/dev/null || pwd)
132
132
  CTRL_URL=$(jq -r '.url // "http://localhost:4242"' "$REPO_ROOT/.monomind/control.json" 2>/dev/null || echo "http://localhost:4242")
133
- curl -s -X POST "${CTRL_URL}/api/mastermind/event" \
133
+ curl -s -X POST "${CTRL_URL}/api/mastermind/event" -H "x-monomind-token: $(cat "${REPO_ROOT:-$(git rev-parse --show-toplevel 2>/dev/null || pwd)}/.monomind/dashboard-token" 2>/dev/null || true)" \
134
134
  -H "Content-Type: application/json" \
135
135
  -d "$(jq -cn --arg org "${org_name:-global}" --arg id "$pluginId" --arg pkg "$package_name" \
136
136
  '{type:"org:plugin:installed",org:$org,plugin:$id,package:$pkg,ts:(now*1000|floor)}')" || true
@@ -117,7 +117,7 @@ CTRL_URL=$(jq -r '.url // "http://localhost:4242"' "$REPO_ROOT/.monomind/control
117
117
  ### 1.6.3 — Emit org:start event
118
118
 
119
119
  ```bash
120
- curl -s -X POST "${CTRL_URL}/api/mastermind/event" \
120
+ curl -s -X POST "${CTRL_URL}/api/mastermind/event" -H "x-monomind-token: $(cat "${REPO_ROOT:-$(git rev-parse --show-toplevel 2>/dev/null || pwd)}/.monomind/dashboard-token" 2>/dev/null || true)" \
121
121
  -H "Content-Type: application/json" \
122
122
  -d "$(jq -cn \
123
123
  --arg session "$sessionId" \
@@ -161,7 +161,7 @@ If `LOOP_STATUS == "active"` or `LOOP_STATUS == "paused"`:
161
161
 
162
162
  2. Emit `org:stop` to signal this iteration is pausing:
163
163
  ```bash
164
- curl -s -X POST "${CTRL_URL}/api/mastermind/event" \
164
+ curl -s -X POST "${CTRL_URL}/api/mastermind/event" -H "x-monomind-token: $(cat "${REPO_ROOT:-$(git rev-parse --show-toplevel 2>/dev/null || pwd)}/.monomind/dashboard-token" 2>/dev/null || true)" \
165
165
  -H "Content-Type: application/json" \
166
166
  -d "$(jq -cn \
167
167
  --arg org "$orgName" \
@@ -182,7 +182,7 @@ If `LOOP_STATUS == "active"` or `LOOP_STATUS == "paused"`:
182
182
  || python3 -c "import datetime; print(datetime.datetime.utcfromtimestamp($next_ts).strftime('%Y-%m-%dT%H:%M:%SZ'))")
183
183
  tmp="${orgFile}.tmp"
184
184
  jq --arg next "$next_iso" '.loop.next_run = $next' "$orgFile" > "$tmp" && mv "$tmp" "$orgFile"
185
- curl -s -X POST "${CTRL_URL}/api/mastermind/event" \
185
+ curl -s -X POST "${CTRL_URL}/api/mastermind/event" -H "x-monomind-token: $(cat "${REPO_ROOT:-$(git rev-parse --show-toplevel 2>/dev/null || pwd)}/.monomind/dashboard-token" 2>/dev/null || true)" \
186
186
  -H "Content-Type: application/json" \
187
187
  -d "$(jq -cn --arg org "$orgName" --arg next "$next_iso" --arg proj "$REPO_ROOT" \
188
188
  '{type:"org:loop:scheduled",org:$org,next_run:$next,project:$proj,ts:(now*1000|floor)}')" || true
@@ -312,10 +312,12 @@ fi
312
312
  # Resolve git-safe monomind directory
313
313
  REPO_ROOT=$(git rev-parse --show-toplevel 2>/dev/null || pwd)
314
314
  CTRL_URL=$(jq -r '.url // "http://localhost:4242"' "$REPO_ROOT/.monomind/control.json" 2>/dev/null || echo "http://localhost:4242")
315
- GIT_COMMON=$(git rev-parse --git-common-dir 2>/dev/null || echo ".git")
315
+ GIT_COMMON=$(git rev-parse --git-common-dir 2>/dev/null || true)
316
+ # Non-git project: never fabricate a .git/ dir — fall back to .monomind
317
+ [ -z "$GIT_COMMON" ] && GIT_COMMON="__NOGIT__"
316
318
  if [[ "$GIT_COMMON" != /* ]]; then GIT_COMMON="$REPO_ROOT/$GIT_COMMON"; fi
317
319
  GIT_COMMON="${GIT_COMMON%/}"
318
- MONO_DIR="${GIT_COMMON}/monomind"
320
+ if [ "$GIT_COMMON" = "__NOGIT__" ] || [ "${GIT_COMMON#*__NOGIT__}" != "$GIT_COMMON" ]; then MONO_DIR="$REPO_ROOT/.monomind"; else MONO_DIR="${GIT_COMMON}/monomind"; fi
319
321
 
320
322
  # Create run file and write run:start
321
323
  runDir="${MONO_DIR}/orgs/${orgName}/runs"
@@ -329,7 +331,7 @@ jq -cn \
329
331
 
330
332
  # Emit session:start first — creates the chat tab session record and writes active-session.json
331
333
  # so capture-handler can tag all subsequent agent:spawn / agent:complete events with this session
332
- curl -s -X POST "${CTRL_URL}/api/mastermind/event" \
334
+ curl -s -X POST "${CTRL_URL}/api/mastermind/event" -H "x-monomind-token: $(cat "${REPO_ROOT:-$(git rev-parse --show-toplevel 2>/dev/null || pwd)}/.monomind/dashboard-token" 2>/dev/null || true)" \
333
335
  -H "Content-Type: application/json" \
334
336
  -d "$(jq -cn \
335
337
  --arg session "$sessionId" \
@@ -338,7 +340,7 @@ curl -s -X POST "${CTRL_URL}/api/mastermind/event" \
338
340
  '{type:"session:start",session:$session,org:$org,prompt:$prompt,ts:(now*1000|floor)}')" || true
339
341
 
340
342
  # Emit org:start — must run here while CTRL_URL/runId/orgName are in scope
341
- curl -s -X POST "${CTRL_URL}/api/mastermind/event" \
343
+ curl -s -X POST "${CTRL_URL}/api/mastermind/event" -H "x-monomind-token: $(cat "${REPO_ROOT:-$(git rev-parse --show-toplevel 2>/dev/null || pwd)}/.monomind/dashboard-token" 2>/dev/null || true)" \
342
344
  -H "Content-Type: application/json" \
343
345
  -d "$(jq -cn \
344
346
  --arg session "$sessionId" \
@@ -457,7 +459,7 @@ APPROVAL GATE (when governance.policy is "board" or "strict"):
457
459
  '.approvals += [{"id":$id,"agent_id":$agent,"title":$title,"action":$action,"risk_level":$risk,"status":"pending","requested_at":(now|todate)}]' \
458
460
  "$approvalsFile" > "${approvalsFile}.tmp" && mv "${approvalsFile}.tmp" "$approvalsFile"
459
461
  # Emit approval request event so human sees it in dashboard
460
- curl -s -X POST "${CTRL_URL}/api/mastermind/event" -H "Content-Type: application/json" \
462
+ curl -s -X POST "${CTRL_URL}/api/mastermind/event" -H "x-monomind-token: $(cat "${REPO_ROOT:-$(git rev-parse --show-toplevel 2>/dev/null || pwd)}/.monomind/dashboard-token" 2>/dev/null || true)" -H "Content-Type: application/json" \
461
463
  -d "$(jq -cn --arg org "${orgName}" --arg id "$approval_id" --arg title "<title>" \
462
464
  '{type:"org:approval:requested",org:$org,approval_id:$id,title:$title,ts:(now*1000|floor)}')" || true
463
465
  # Poll until approved or rejected (max 30 min).
@@ -478,11 +480,13 @@ DASHBOARD EVENT HELPER — resolve once at startup, reuse in every step:
478
480
  REPO_ROOT=$(git rev-parse --show-toplevel 2>/dev/null || pwd)
479
481
  CTRL_URL=$(jq -r '.url // "http://localhost:4242"' "$REPO_ROOT/.monomind/control.json" 2>/dev/null || echo "http://localhost:4242")
480
482
  # Git-safe monomind dir — shared across all worktrees, survives branch switches:
481
- GIT_COMMON=$(git rev-parse --git-common-dir 2>/dev/null || echo ".git")
483
+ GIT_COMMON=$(git rev-parse --git-common-dir 2>/dev/null || true)
484
+ # Non-git project: never fabricate a .git/ dir — fall back to .monomind
485
+ [ -z "$GIT_COMMON" ] && GIT_COMMON="__NOGIT__"
482
486
  # Resolve to absolute path (git returns relative ".git" for main checkout)
483
487
  if [[ "$GIT_COMMON" != /* ]]; then GIT_COMMON="$REPO_ROOT/$GIT_COMMON"; fi
484
488
  GIT_COMMON="${GIT_COMMON%/}" # strip trailing slash if any
485
- MONO_DIR="${GIT_COMMON}/monomind"
489
+ if [ "$GIT_COMMON" = "__NOGIT__" ] || [ "${GIT_COMMON#*__NOGIT__}" != "$GIT_COMMON" ]; then MONO_DIR="$REPO_ROOT/.monomind"; else MONO_DIR="${GIT_COMMON}/monomind"; fi
486
490
  runFile="${MONO_DIR}/orgs/${orgName}/runs/${runId}.jsonl"
487
491
 
488
492
  ⚠️ DASHBOARD EVENTS ARE MANDATORY — run every curl below exactly as written.
@@ -497,7 +501,7 @@ If the file exists: write run:complete to run file, emit org:complete via curl,
497
501
  jq -cn --arg runId "${runId}" --arg org "${orgName}" \
498
502
  '{type:"run:complete",runId:$runId,org:$org,status:"stopped",ts:(now*1000|floor)}' >> "${runFile}" || true
499
503
  # REQUIRED — emit org:complete via curl (includes runId so it also gets appended):
500
- curl -s -X POST "${CTRL_URL}/api/mastermind/event" -H "Content-Type: application/json" \
504
+ curl -s -X POST "${CTRL_URL}/api/mastermind/event" -H "x-monomind-token: $(cat "${REPO_ROOT:-$(git rev-parse --show-toplevel 2>/dev/null || pwd)}/.monomind/dashboard-token" 2>/dev/null || true)" -H "Content-Type: application/json" \
501
505
  -d "$(jq -cn --arg s "${sessionId}" --arg o "${orgName}" --arg rid "${runId}" --arg p "$REPO_ROOT" \
502
506
  '{type:"org:complete",session:$s,org:$o,runId:$rid,project:$p,ts:(now*1000|floor)}')" || true
503
507
 
@@ -511,7 +515,7 @@ OPERATING LOOP:
511
515
  if [ "$(echo "$_pending" | jq 'length')" -gt 0 ]; then
512
516
  echo "$_pending" | jq -r '.[] | .text // .msg // ""'
513
517
  jq '[.[] | if .status == "pending" then .status = "processed" else . end]' "$_threads" > "${_threads}.tmp" && mv "${_threads}.tmp" "$_threads" || true
514
- curl -s -X POST "${CTRL_URL}/api/mastermind/event" -H "Content-Type: application/json" \
518
+ curl -s -X POST "${CTRL_URL}/api/mastermind/event" -H "x-monomind-token: $(cat "${REPO_ROOT:-$(git rev-parse --show-toplevel 2>/dev/null || pwd)}/.monomind/dashboard-token" 2>/dev/null || true)" -H "Content-Type: application/json" \
515
519
  -d "$(jq -cn --arg s "${sessionId}" --arg o "${orgName}" --arg rid "${runId}" \
516
520
  --arg msg "Received user message — adjusting plan if needed" \
517
521
  '{type:"org:comms",session:$s,org:$o,runId:$rid,from:"boss",to:"user",msg:$msg,ts:(now*1000|floor)}')" || true
@@ -529,12 +533,12 @@ OPERATING LOOP:
529
533
  monotask card move ${board_id} $CARD_ID ${doing_col}
530
534
  monotask card label add ${board_id} $CARD_ID "claimed"
531
535
  b) REQUIRED — emit org:comms to dashboard (include runId):
532
- curl -s -X POST "${CTRL_URL}/api/mastermind/event" -H "Content-Type: application/json" \
536
+ curl -s -X POST "${CTRL_URL}/api/mastermind/event" -H "x-monomind-token: $(cat "${REPO_ROOT:-$(git rev-parse --show-toplevel 2>/dev/null || pwd)}/.monomind/dashboard-token" 2>/dev/null || true)" -H "Content-Type: application/json" \
533
537
  -d "$(jq -cn --arg s "${sessionId}" --arg o "${orgName}" --arg rid "${runId}" --arg p "$REPO_ROOT" \
534
538
  --arg role "<role_id>" --arg task "<card title>" \
535
539
  '{type:"org:comms",session:$s,org:$o,runId:$rid,from:"boss",to:$role,msg:("Assigning: "+$task),project:$p,ts:(now*1000|floor)}')" || true
536
540
  c) REQUIRED — emit org:agent:online before spawning (include runId):
537
- curl -s -X POST "${CTRL_URL}/api/mastermind/event" -H "Content-Type: application/json" \
541
+ curl -s -X POST "${CTRL_URL}/api/mastermind/event" -H "x-monomind-token: $(cat "${REPO_ROOT:-$(git rev-parse --show-toplevel 2>/dev/null || pwd)}/.monomind/dashboard-token" 2>/dev/null || true)" -H "Content-Type: application/json" \
538
542
  -d "$(jq -cn --arg s "${sessionId}" --arg o "${orgName}" --arg rid "${runId}" --arg p "$REPO_ROOT" \
539
543
  --arg role "<role_id>" --arg title "<role title>" --arg at "<agent_type>" \
540
544
  '{type:"org:agent:online",session:$s,org:$o,runId:$rid,role:$role,title:$title,agent_type:$at,project:$p,ts:(now*1000|floor)}')" || true
@@ -549,23 +553,25 @@ OPERATING LOOP:
549
553
  DASHBOARD EVENTS — emit these at the start and end of your work (REQUIRED):
550
554
  REPO_ROOT=$(git rev-parse --show-toplevel 2>/dev/null || pwd)
551
555
  CTRL_URL=$(jq -r '.url // "http://localhost:4242"' "$REPO_ROOT/.monomind/control.json" 2>/dev/null || echo "http://localhost:4242")
552
- GIT_COMMON=$(git rev-parse --git-common-dir 2>/dev/null || echo ".git")
556
+ GIT_COMMON=$(git rev-parse --git-common-dir 2>/dev/null || true)
557
+ # Non-git project: never fabricate a .git/ dir — fall back to .monomind
558
+ [ -z "$GIT_COMMON" ] && GIT_COMMON="__NOGIT__"
553
559
  if [[ "$GIT_COMMON" != /* ]]; then GIT_COMMON="$REPO_ROOT/$GIT_COMMON"; fi
554
560
  GIT_COMMON="${GIT_COMMON%/}"
555
- MONO_DIR="${GIT_COMMON}/monomind"
561
+ if [ "$GIT_COMMON" = "__NOGIT__" ] || [ "${GIT_COMMON#*__NOGIT__}" != "$GIT_COMMON" ]; then MONO_DIR="$REPO_ROOT/.monomind"; else MONO_DIR="${GIT_COMMON}/monomind"; fi
556
562
  runFile="${MONO_DIR}/orgs/${orgName}/runs/${runId}.jsonl"
557
563
  # On start — announce you are working:
558
- curl -s -X POST "${CTRL_URL}/api/mastermind/event" -H "Content-Type: application/json" \
564
+ curl -s -X POST "${CTRL_URL}/api/mastermind/event" -H "x-monomind-token: $(cat "${REPO_ROOT:-$(git rev-parse --show-toplevel 2>/dev/null || pwd)}/.monomind/dashboard-token" 2>/dev/null || true)" -H "Content-Type: application/json" \
559
565
  -d "$(jq -cn --arg s "${sessionId}" --arg o "${orgName}" --arg rid "${runId}" \
560
566
  --arg from "<role_id>" --arg msg "Starting: <card title>" \
561
567
  '{type:"org:comms",session:$s,org:$o,runId:$rid,from:$from,to:"boss",msg:$msg,ts:(now*1000|floor)}')" || true
562
568
  # On completion — report back:
563
- curl -s -X POST "${CTRL_URL}/api/mastermind/event" -H "Content-Type: application/json" \
569
+ curl -s -X POST "${CTRL_URL}/api/mastermind/event" -H "x-monomind-token: $(cat "${REPO_ROOT:-$(git rev-parse --show-toplevel 2>/dev/null || pwd)}/.monomind/dashboard-token" 2>/dev/null || true)" -H "Content-Type: application/json" \
564
570
  -d "$(jq -cn --arg s "${sessionId}" --arg o "${orgName}" --arg rid "${runId}" \
565
571
  --arg from "<role_id>" --arg msg "Completed: <one-sentence summary of output>" \
566
572
  '{type:"org:comms",session:$s,org:$o,runId:$rid,from:$from,to:"boss",msg:$msg,ts:(now*1000|floor)}')" || true
567
573
  # When your task is fully complete — signal offline:
568
- curl -s -X POST "${CTRL_URL}/api/mastermind/event" -H "Content-Type: application/json" \
574
+ curl -s -X POST "${CTRL_URL}/api/mastermind/event" -H "x-monomind-token: $(cat "${REPO_ROOT:-$(git rev-parse --show-toplevel 2>/dev/null || pwd)}/.monomind/dashboard-token" 2>/dev/null || true)" -H "Content-Type: application/json" \
569
575
  -d "$(jq -cn --arg s "${sessionId}" --arg o "${orgName}" --arg rid "${runId}" \
570
576
  --arg from "<role_id>" \
571
577
  '{type:"org:agent:offline",session:$s,org:$o,runId:$rid,from:$from,ts:(now*1000|floor)}')" || true
@@ -588,7 +594,7 @@ OPERATING LOOP:
588
594
 
589
595
  6. Synthesize reports, make decisions, create new cards in Todo column based on progress toward goal.
590
596
  REQUIRED — after each decision, emit org:comms (include runId):
591
- curl -s -X POST "${CTRL_URL}/api/mastermind/event" -H "Content-Type: application/json" \
597
+ curl -s -X POST "${CTRL_URL}/api/mastermind/event" -H "x-monomind-token: $(cat "${REPO_ROOT:-$(git rev-parse --show-toplevel 2>/dev/null || pwd)}/.monomind/dashboard-token" 2>/dev/null || true)" -H "Content-Type: application/json" \
592
598
  -d "$(jq -cn --arg s "${sessionId}" --arg o "${orgName}" --arg rid "${runId}" --arg p "$REPO_ROOT" \
593
599
  --arg msg "<one-sentence summary of decision or finding>" \
594
600
  '{type:"org:comms",session:$s,org:$o,runId:$rid,from:"boss",to:"all",msg:$msg,project:$p,ts:(now*1000|floor)}')" || true
@@ -601,7 +607,7 @@ OPERATING LOOP:
601
607
  echo "{\"type\":\"run:cycle:complete\",\"org\":\"${orgName}\",\"runId\":\"${runId}\",\"ts\":\"$(date -u +%Y-%m-%dT%H:%M:%SZ)\",\"pending\":${pending_count:-0}}" >> "$activityFile" 2>/dev/null || true
602
608
 
603
609
  8. REQUIRED — emit org:checkpoint with a one-sentence progress summary (include runId):
604
- curl -s -X POST "${CTRL_URL}/api/mastermind/event" -H "Content-Type: application/json" \
610
+ curl -s -X POST "${CTRL_URL}/api/mastermind/event" -H "x-monomind-token: $(cat "${REPO_ROOT:-$(git rev-parse --show-toplevel 2>/dev/null || pwd)}/.monomind/dashboard-token" 2>/dev/null || true)" -H "Content-Type: application/json" \
605
611
  -d "$(jq -cn --arg s "${sessionId}" --arg o "${orgName}" --arg rid "${runId}" --arg p "$REPO_ROOT" \
606
612
  --arg prog "<one sentence: what was done this cycle and what is next>" \
607
613
  --argjson pend "${pending_count:-0}" \
@@ -705,7 +711,7 @@ If `caller` is not "command", follow _protocol.md Brain Write Procedure for doma
705
711
  When you create or modify a file that represents output of this org run, emit:
706
712
 
707
713
  ```bash
708
- curl -s -X POST "${CTRL_URL}/api/mastermind/event" \
714
+ curl -s -X POST "${CTRL_URL}/api/mastermind/event" -H "x-monomind-token: $(cat "${REPO_ROOT:-$(git rev-parse --show-toplevel 2>/dev/null || pwd)}/.monomind/dashboard-token" 2>/dev/null || true)" \
709
715
  -H "Content-Type: application/json" \
710
716
  -d "$(jq -cn \
711
717
  --arg s "${sessionId}" \
@@ -52,7 +52,7 @@ CTRL_URL=$(jq -r '.url // "http://localhost:4242"' "$REPO_ROOT/.monomind/control
52
52
  npx -y monomind@latest org stop "${org_name}" \
53
53
  || { mkdir -p ".monomind/orgs/${org_name}"; date -u +%Y-%m-%dT%H:%M:%SZ > ".monomind/orgs/${org_name}/stop"; }
54
54
  # Also POST to the control server in case a dashboard-started instance is running
55
- curl -s -X POST "${CTRL_URL}/api/orgs/${org_name}/stop" >/dev/null 2>&1 || true
55
+ curl -s -X POST -H "x-monomind-token: $(cat "${REPO_ROOT:-$(git rev-parse --show-toplevel 2>/dev/null || pwd)}/.monomind/dashboard-token" 2>/dev/null || true)" "${CTRL_URL}/api/orgs/${org_name}/stop" >/dev/null 2>&1 || true
56
56
  echo "Stop requested for org '${org_name}' (v2 daemon exits within 2s)."
57
57
  ```
58
58
  - Exit.
@@ -92,7 +92,7 @@ REPO_ROOT=$(git rev-parse --show-toplevel 2>/dev/null || pwd)
92
92
  CTRL_URL=$(jq -r '.url // "http://localhost:4242"' "$REPO_ROOT/.monomind/control.json" 2>/dev/null || echo "http://localhost:4242")
93
93
 
94
94
  # org:stop — signals dashboard to update status to stopped
95
- curl -s -X POST "${CTRL_URL}/api/mastermind/event" \
95
+ curl -s -X POST "${CTRL_URL}/api/mastermind/event" -H "x-monomind-token: $(cat "${REPO_ROOT:-$(git rev-parse --show-toplevel 2>/dev/null || pwd)}/.monomind/dashboard-token" 2>/dev/null || true)" \
96
96
  -H "Content-Type: application/json" \
97
97
  -d "$(jq -cn \
98
98
  --arg session "${session_id:-manual}" \
@@ -1013,6 +1013,31 @@ export async function startServer({ port = 4242, projectDir, openBrowser = true
1013
1013
  // (not per-request inside the request handler below) since both only
1014
1014
  // close over per-server-start state (dashboardAuthValue) plus their
1015
1015
  // explicit req/res/corsOrigin params. ──────────────────────────────────
1016
+ // ── Second Brain warm bridge: lazy singleton import of the compiled memory
1017
+ // bridge (loads the local embedding model once for the server's lifetime).
1018
+ // Boot-warmed below only when this project actually has a knowledge base.
1019
+ let _knowledgeBridgePromise = null;
1020
+ const _getKnowledgeBridge = () => {
1021
+ if (!_knowledgeBridgePromise) {
1022
+ _knowledgeBridgePromise = import('../memory/memory-bridge.js').catch((err) => {
1023
+ _knowledgeBridgePromise = null; // allow retry on next request
1024
+ if (process.env.MONOMIND_DEBUG) console.error('[knowledge] bridge import failed:', err.message);
1025
+ return null;
1026
+ });
1027
+ }
1028
+ return _knowledgeBridgePromise;
1029
+ };
1030
+ try {
1031
+ if (fs.existsSync(path.join(projectDir || process.cwd(), '.monomind', 'knowledge', 'chunks.jsonl'))) {
1032
+ // Warm off the startup path: first hook request should hit a hot model.
1033
+ const _warmTimer = setTimeout(() => {
1034
+ _getKnowledgeBridge().then(b => b?.bridgeSearchEntries?.({ query: 'warmup', namespace: 'knowledge:shared', limit: 1 }))
1035
+ .catch(() => { /* warm-up is best-effort */ });
1036
+ }, 3000);
1037
+ if (_warmTimer.unref) _warmTimer.unref();
1038
+ }
1039
+ } catch (_) { /* non-fatal */ }
1040
+
1016
1041
  const _checkAuth = (req) => {
1017
1042
  let _suppliedAuth = req.headers['x-monomind-token'] || '';
1018
1043
  if (!_suppliedAuth) {
@@ -5888,6 +5913,46 @@ new Sigma(g,document.getElementById('g'),{renderEdgeLabels:false,labelColor:{col
5888
5913
  return;
5889
5914
  }
5890
5915
 
5916
+ // POST /api/knowledge/search — warm semantic knowledge search for hooks.
5917
+ // The dashboard server is the one long-lived process on the machine, so it
5918
+ // holds the local embedding model warm; per-prompt hook subprocesses (which
5919
+ // cannot afford a model load) POST here and fall back to keyword scoring
5920
+ // when this endpoint is cold/absent. Fully local — model + store on disk.
5921
+ if (req.method === 'POST' && url === '/api/knowledge/search') {
5922
+ let body = '';
5923
+ req.on('data', c => { body += c; });
5924
+ req.on('end', async () => {
5925
+ try {
5926
+ const payload = JSON.parse(body || '{}');
5927
+ const query = String(payload.query || '').slice(0, 2000);
5928
+ const limit = Math.min(Math.max(parseInt(payload.limit, 10) || 3, 1), 10);
5929
+ const namespace = typeof payload.namespace === 'string' && /^[A-Za-z0-9:_-]{1,128}$/.test(payload.namespace)
5930
+ ? payload.namespace : 'knowledge:shared';
5931
+ if (!query) {
5932
+ res.writeHead(400, { 'Content-Type': 'application/json' });
5933
+ res.end('{"error":"query required"}');
5934
+ return;
5935
+ }
5936
+ const bridge = await _getKnowledgeBridge();
5937
+ if (!bridge) {
5938
+ res.writeHead(503, { 'Content-Type': 'application/json' });
5939
+ res.end('{"error":"knowledge bridge unavailable"}');
5940
+ return;
5941
+ }
5942
+ const out = await bridge.bridgeSearchEntries({ query, namespace, limit });
5943
+ res.writeHead(200, { 'Content-Type': 'application/json', ...(corsOrigin ? { 'Access-Control-Allow-Origin': corsOrigin } : {}) });
5944
+ res.end(JSON.stringify({
5945
+ method: out?.searchMethod || 'none',
5946
+ results: (out?.results || []).map(r => ({ key: r.key, content: String(r.content || '').slice(0, 2000), score: r.score })),
5947
+ }));
5948
+ } catch (err) {
5949
+ res.writeHead(500, { 'Content-Type': 'application/json' });
5950
+ res.end(JSON.stringify({ error: err.message }));
5951
+ }
5952
+ });
5953
+ return;
5954
+ }
5955
+
5891
5956
  // GET /api/mastermind/metrics — aggregate system metrics from token-summary and swarm-activity
5892
5957
  if (req.method === 'GET' && url === '/api/mastermind/metrics') {
5893
5958
  try {
@@ -6260,6 +6325,16 @@ new Sigma(g,document.getElementById('g'),{renderEdgeLabels:false,labelColor:{col
6260
6325
  const boundPort = await bindServer(server, port);
6261
6326
  const url = `http://localhost:${boundPort}`;
6262
6327
 
6328
+ // Self-report the ACTUAL bound port for the spawner (control-start.cjs).
6329
+ // An HTTP probe cannot distinguish this server from another project's server
6330
+ // already answering on the requested port — this file is identity-proof.
6331
+ if (process.env.MONOMIND_BOUND_REPORT) {
6332
+ try {
6333
+ fs.mkdirSync(path.dirname(process.env.MONOMIND_BOUND_REPORT), { recursive: true });
6334
+ fs.writeFileSync(process.env.MONOMIND_BOUND_REPORT, JSON.stringify({ pid: process.pid, port: boundPort, ts: Date.now() }));
6335
+ } catch (_) { /* non-fatal — spawner falls back to pid-matched HTTP probe */ }
6336
+ }
6337
+
6263
6338
  // ── One-time migration: mastermind-sessions.json → per-session JSONL ─────
6264
6339
  // Runs once on startup. Existing sessions in the old monolithic format are
6265
6340
  // split into individual JSONL files + _index.json for O(1) event writes.
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@monoes/monomindcli",
3
- "version": "2.3.2",
3
+ "version": "2.3.3",
4
4
  "type": "module",
5
5
  "description": "CLI engine for Monomind — an open-source MCP server that extends Claude Code with a codebase knowledge graph (tree-sitter + SQLite), persistent memory, multi-agent task coordination, and session hooks. MIT licensed, fully local.",
6
6
  "main": "dist/src/index.js",