monomind 2.3.1 → 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.
- package/package.json +1 -1
- package/packages/@monomind/cli/.claude/commands/mastermind/_repeat.md +9 -9
- package/packages/@monomind/cli/.claude/commands/mastermind/approve.md +2 -2
- package/packages/@monomind/cli/.claude/commands/mastermind/architect.md +3 -3
- package/packages/@monomind/cli/.claude/commands/mastermind/createorg.md +4 -4
- package/packages/@monomind/cli/.claude/commands/mastermind/master.md +3 -3
- package/packages/@monomind/cli/.claude/commands/mastermind/repeat.md +5 -5
- package/packages/@monomind/cli/.claude/commands/mastermind/runorg.md +3 -3
- package/packages/@monomind/cli/.claude/commands/mastermind/stoporg.md +1 -1
- package/packages/@monomind/cli/.claude/helpers/control-start.cjs +52 -4
- package/packages/@monomind/cli/.claude/helpers/event-logger.cjs +9 -1
- package/packages/@monomind/cli/.claude/helpers/handlers/capture-handler.cjs +9 -1
- package/packages/@monomind/cli/.claude/helpers/handlers/route-handler.cjs +65 -0
- package/packages/@monomind/cli/.claude/helpers/handlers/session-restore-handler.cjs +59 -0
- package/packages/@monomind/cli/.claude/skills/mastermind-skills/_protocol.md +1 -1
- package/packages/@monomind/cli/.claude/skills/mastermind-skills/_repeat.md +3 -3
- package/packages/@monomind/cli/.claude/skills/mastermind-skills/adapters.md +1 -1
- package/packages/@monomind/cli/.claude/skills/mastermind-skills/agents.md +1 -1
- package/packages/@monomind/cli/.claude/skills/mastermind-skills/architect.md +8 -8
- package/packages/@monomind/cli/.claude/skills/mastermind-skills/backup.md +1 -1
- package/packages/@monomind/cli/.claude/skills/mastermind-skills/bootstrap.md +1 -1
- package/packages/@monomind/cli/.claude/skills/mastermind-skills/costs.md +1 -1
- package/packages/@monomind/cli/.claude/skills/mastermind-skills/heartbeat.md +2 -2
- package/packages/@monomind/cli/.claude/skills/mastermind-skills/idea.md +1 -1
- package/packages/@monomind/cli/.claude/skills/mastermind-skills/monitor.md +2 -2
- package/packages/@monomind/cli/.claude/skills/mastermind-skills/org-settings.md +1 -1
- package/packages/@monomind/cli/.claude/skills/mastermind-skills/plugins.md +1 -1
- package/packages/@monomind/cli/.claude/skills/mastermind-skills/runorg.md +28 -22
- package/packages/@monomind/cli/.claude/skills/mastermind-skills/stoporg.md +2 -2
- package/packages/@monomind/cli/dist/src/commands/cleanup.d.ts +14 -0
- package/packages/@monomind/cli/dist/src/commands/cleanup.js +99 -0
- package/packages/@monomind/cli/dist/src/commands/doctor-project-checks.d.ts +4 -0
- package/packages/@monomind/cli/dist/src/commands/doctor-project-checks.js +25 -0
- package/packages/@monomind/cli/dist/src/commands/doctor.js +3 -1
- package/packages/@monomind/cli/dist/src/knowledge/document-pipeline.js +39 -5
- package/packages/@monomind/cli/dist/src/memory/memory-bridge.js +11 -1
- package/packages/@monomind/cli/dist/src/orgrt/daemon.d.ts +17 -0
- package/packages/@monomind/cli/dist/src/orgrt/daemon.js +90 -1
- package/packages/@monomind/cli/dist/src/orgrt/session.d.ts +2 -0
- package/packages/@monomind/cli/dist/src/orgrt/session.js +5 -0
- package/packages/@monomind/cli/dist/src/ui/server.mjs +75 -0
- package/packages/@monomind/cli/package.json +2 -2
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "monomind",
|
|
3
|
-
"version": "2.3.
|
|
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
|
-
|
|
196
|
-
|
|
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
|
-
|
|
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: {
|
|
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: {
|
|
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();
|
|
@@ -316,6 +316,71 @@ module.exports = {
|
|
|
316
316
|
|
|
317
317
|
if (output.length > 0) console.log(output.join('\n'));
|
|
318
318
|
|
|
319
|
+
// ── Second Brain: per-request knowledge injection ──────────────────
|
|
320
|
+
// When the project has an indexed knowledge base, surface the most
|
|
321
|
+
// relevant excerpts for THIS prompt so Claude has them without having
|
|
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.
|
|
327
|
+
try {
|
|
328
|
+
var sbPrompt = String(prompt || '');
|
|
329
|
+
// Skip slash commands and trivial prompts — injection would be noise.
|
|
330
|
+
if (sbPrompt.length >= 12 && sbPrompt.charAt(0) !== '/') {
|
|
331
|
+
var sbKnowledgeDir = path.join(CWD, '.monomind', 'knowledge');
|
|
332
|
+
if (fs.existsSync(path.join(sbKnowledgeDir, 'chunks.jsonl'))) {
|
|
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
|
+
}
|
|
369
|
+
if (sbHits && sbHits.length > 0) {
|
|
370
|
+
var sbLines = ['[SECOND_BRAIN] ' + sbHits.length + ' relevant excerpt(s) (' + sbMethod + ') from the project knowledge base:'];
|
|
371
|
+
for (var sbI = 0; sbI < sbHits.length; sbI++) {
|
|
372
|
+
var sbH = sbHits[sbI];
|
|
373
|
+
var sbSrc = (sbH.metadata && sbH.metadata.filePath) ? String(sbH.metadata.filePath).split('/').slice(-2).join('/') : sbH.key;
|
|
374
|
+
var sbText = String(sbH.value || '').replace(/\s+/g, ' ').slice(0, 240);
|
|
375
|
+
sbLines.push(' • [' + sbSrc + '] ' + sbText);
|
|
376
|
+
}
|
|
377
|
+
sbLines.push(' (deeper lookup: mcp__monomind__knowledge_search or `monomind doc search -q "..."`)');
|
|
378
|
+
console.log(sbLines.join('\n'));
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
} catch (e) { /* non-fatal — knowledge injection must never block a prompt */ }
|
|
383
|
+
|
|
319
384
|
// Record any decision markers in this prompt (auto-ADR pipeline).
|
|
320
385
|
try { hCtx._recordDecisionMarkers(prompt); } catch (e) {}
|
|
321
386
|
|
|
@@ -344,6 +344,65 @@ module.exports = {
|
|
|
344
344
|
}
|
|
345
345
|
} catch (e) { /* non-fatal */ }
|
|
346
346
|
|
|
347
|
+
// Second Brain continuous ingestion — the generated CLAUDE.md promises
|
|
348
|
+
// "re-indexing happens automatically on session start"; make that true for
|
|
349
|
+
// user documents, not just the 3 fixed files above. Gated on (a) an active
|
|
350
|
+
// knowledge base, (b) at least one document newer than the last ingest,
|
|
351
|
+
// (c) a 30-min rate limit. Detached+unref spawn (same pattern as the
|
|
352
|
+
// helper-heal block below) — session start never waits on model loading.
|
|
353
|
+
try {
|
|
354
|
+
var _kbMetaPath = path.join(CWD, '.monomind', 'knowledge', 'doc-metadata.jsonl');
|
|
355
|
+
if (fs.existsSync(_kbMetaPath)) {
|
|
356
|
+
var _kbMetaMtime = fs.statSync(_kbMetaPath).mtimeMs;
|
|
357
|
+
var _kbMarkerPath = path.join(CWD, '.monomind', 'knowledge', 'reindex-check.json');
|
|
358
|
+
var _kbLastCheck = 0;
|
|
359
|
+
try { _kbLastCheck = JSON.parse(fs.readFileSync(_kbMarkerPath, 'utf-8')).ts || 0; } catch (_) {}
|
|
360
|
+
if (Date.now() - _kbLastCheck > 30 * 60 * 1000) {
|
|
361
|
+
// Cheap bounded scan: any document changed since the last ingest?
|
|
362
|
+
var _DOC_EXT = { '.md': 1, '.txt': 1, '.pdf': 1, '.docx': 1 };
|
|
363
|
+
var _kbDirty = false;
|
|
364
|
+
var _kbScanned = 0;
|
|
365
|
+
var _kbWalk = function(dir, depth) {
|
|
366
|
+
if (_kbDirty || depth > 3 || _kbScanned > 2000) return;
|
|
367
|
+
var names;
|
|
368
|
+
try { names = fs.readdirSync(dir); } catch (_) { return; }
|
|
369
|
+
for (var ni = 0; ni < names.length && !_kbDirty; ni++) {
|
|
370
|
+
var n = names[ni];
|
|
371
|
+
if (n.charAt(0) === '.' || n === 'node_modules' || n === 'dist') continue;
|
|
372
|
+
var p = path.join(dir, n);
|
|
373
|
+
var st;
|
|
374
|
+
try { st = fs.statSync(p); } catch (_) { continue; }
|
|
375
|
+
_kbScanned++;
|
|
376
|
+
if (st.isDirectory()) { _kbWalk(p, depth + 1); continue; }
|
|
377
|
+
var ext = path.extname(n).toLowerCase();
|
|
378
|
+
if (_DOC_EXT[ext] && st.mtimeMs > _kbMetaMtime) _kbDirty = true;
|
|
379
|
+
}
|
|
380
|
+
};
|
|
381
|
+
_kbWalk(CWD, 0);
|
|
382
|
+
if (_kbDirty) {
|
|
383
|
+
var _kbMarkerOk = false;
|
|
384
|
+
try {
|
|
385
|
+
fs.writeFileSync(_kbMarkerPath, JSON.stringify({ ts: Date.now() }), 'utf-8');
|
|
386
|
+
_kbMarkerOk = true;
|
|
387
|
+
} catch (_) {}
|
|
388
|
+
if (_kbMarkerOk) {
|
|
389
|
+
var _kbSpawn = require('child_process').spawn;
|
|
390
|
+
var _kbChild = _kbSpawn('npx', ['-y', 'monomind@latest', 'doc', 'ingest', '.'], {
|
|
391
|
+
cwd: CWD,
|
|
392
|
+
detached: true,
|
|
393
|
+
stdio: 'ignore',
|
|
394
|
+
env: process.env,
|
|
395
|
+
shell: process.platform === 'win32',
|
|
396
|
+
windowsHide: true,
|
|
397
|
+
});
|
|
398
|
+
_kbChild.unref();
|
|
399
|
+
console.log('[KNOWLEDGE_REINDEX] changed documents detected — re-ingesting in background');
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
} catch (e) { /* non-fatal — reindex must never block session start */ }
|
|
405
|
+
|
|
347
406
|
// Monograph Context Injection — delegates to shared helper in utils/monograph.cjs.
|
|
348
407
|
injectGodNodesContext(CWD);
|
|
349
408
|
|
|
@@ -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
|
```
|