monomind 1.18.12 → 1.18.15

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 (46) hide show
  1. package/.claude/commands/mastermind/_repeat.md +22 -3
  2. package/.claude/commands/mastermind/architect.md +1 -1
  3. package/.claude/commands/mastermind/autodev.md +1 -1
  4. package/.claude/commands/mastermind/build.md +1 -1
  5. package/.claude/commands/mastermind/code-review.md +1 -1
  6. package/.claude/commands/mastermind/debug.md +1 -1
  7. package/.claude/commands/mastermind/idea.md +1 -1
  8. package/.claude/commands/mastermind/improve.md +1 -1
  9. package/.claude/commands/mastermind/plan.md +1 -1
  10. package/.claude/commands/mastermind/research.md +1 -1
  11. package/.claude/commands/mastermind/review.md +12 -1
  12. package/.claude/commands/mastermind/runorg.md +1 -1
  13. package/.claude/commands/mastermind/taskdev.md +1 -1
  14. package/.claude/commands/mastermind/tdd.md +1 -1
  15. package/.claude/commands/mastermind/verify.md +1 -1
  16. package/.claude/helpers/graphify-freshen.cjs +24 -0
  17. package/.claude/helpers/handlers/route-handler.cjs +7 -10
  18. package/.claude/helpers/hook-handler.cjs +5 -2
  19. package/.claude/helpers/utils/monograph.cjs +59 -16
  20. package/.claude/skills/mastermind-skills/_repeat.md +29 -4
  21. package/.claude/skills/mastermind-skills/review.md +17 -6
  22. package/package.json +1 -1
  23. package/packages/@monomind/cli/.claude/commands/mastermind/_repeat.md +22 -3
  24. package/packages/@monomind/cli/.claude/commands/mastermind/architect.md +1 -1
  25. package/packages/@monomind/cli/.claude/commands/mastermind/autodev.md +1 -1
  26. package/packages/@monomind/cli/.claude/commands/mastermind/build.md +1 -1
  27. package/packages/@monomind/cli/.claude/commands/mastermind/code-review.md +1 -1
  28. package/packages/@monomind/cli/.claude/commands/mastermind/debug.md +1 -1
  29. package/packages/@monomind/cli/.claude/commands/mastermind/idea.md +1 -1
  30. package/packages/@monomind/cli/.claude/commands/mastermind/improve.md +1 -1
  31. package/packages/@monomind/cli/.claude/commands/mastermind/plan.md +1 -1
  32. package/packages/@monomind/cli/.claude/commands/mastermind/research.md +1 -1
  33. package/packages/@monomind/cli/.claude/commands/mastermind/review.md +12 -1
  34. package/packages/@monomind/cli/.claude/commands/mastermind/runorg.md +1 -1
  35. package/packages/@monomind/cli/.claude/commands/mastermind/taskdev.md +1 -1
  36. package/packages/@monomind/cli/.claude/commands/mastermind/tdd.md +1 -1
  37. package/packages/@monomind/cli/.claude/commands/mastermind/verify.md +1 -1
  38. package/packages/@monomind/cli/.claude/helpers/graphify-freshen.cjs +24 -0
  39. package/packages/@monomind/cli/.claude/helpers/handlers/route-handler.cjs +7 -10
  40. package/packages/@monomind/cli/.claude/helpers/hook-handler.cjs +5 -2
  41. package/packages/@monomind/cli/.claude/helpers/utils/monograph.cjs +59 -16
  42. package/packages/@monomind/cli/.claude/skills/mastermind-skills/_repeat.md +29 -4
  43. package/packages/@monomind/cli/.claude/skills/mastermind-skills/review.md +17 -6
  44. package/packages/@monomind/cli/dist/src/mcp-tools/monograph-tools.js +40 -2
  45. package/packages/@monomind/cli/package.json +1 -1
  46. package/packages/@monomind/guidance/README.md +49 -1153
@@ -326,12 +326,31 @@ RECENT_HIL=$(find . -maxdepth 3 \( -name "humaninloop*.md" -o -name "humaninloop
326
326
 
327
327
  After each run in tillend mode, evaluate whether this run produced **zero findings and zero actions**. The loop stops only when a complete round finds nothing new and makes no changes — not when the AI predicts there is nothing left.
328
328
 
329
- **You (the AI running the loop) must now assess your own output from this run.** Answer these two questions:
329
+ <EXTREMELY-IMPORTANT>
330
+ **Anti-premature-stop rules:**
331
+ - "I think the work is done" is NOT a reason to stop. Only the checks below decide.
332
+ - "There's nothing more to find" is a PREDICTION, not an observation. Predictions do not stop loops.
333
+ - You MUST run the git verification command below. If git shows changes, the round is non-empty. Period.
334
+ - Only a round where git shows NO changes AND you confirm zero findings AND zero actions qualifies as empty.
335
+ </EXTREMELY-IMPORTANT>
336
+
337
+ **Step 4a — Machine verification (REQUIRED — run this command before any self-assessment):**
338
+
339
+ ```bash
340
+ GIT_CHANGES=$(git diff --stat HEAD 2>/dev/null; git diff --cached --stat 2>/dev/null; git status --porcelain 2>/dev/null | grep -v '^\?\?' | head -20)
341
+ echo "GIT_CHANGES_DURING_RUN: ${GIT_CHANGES:-NONE}"
342
+ ```
343
+
344
+ If `GIT_CHANGES` is non-empty, files were modified — `TILLEND_EMPTY=false` regardless of self-assessment. Skip directly to "Otherwise" below.
345
+
346
+ **Step 4b — Self-assessment (only if git shows no changes):**
347
+
348
+ Only if `GIT_CHANGES` was empty, answer these two questions about this run:
330
349
 
331
350
  1. **Were any findings produced?** — issues found, problems detected, items identified, things flagged, errors reported, tasks discovered, security vulnerabilities found, etc.
332
- 2. **Were any actions taken?** — files edited, code fixed, tasks created, cards moved, commits made, content written, configs changed, etc.
351
+ 2. **Were any actions taken?** — tasks created, content written, configs changed anything not captured by git diff.
333
352
 
334
- **Set `TILLEND_EMPTY=true` only if BOTH answers are "no" zero findings AND zero actions this round.**
353
+ **Set `TILLEND_EMPTY=true` only if git shows no changes AND BOTH answers are "no".**
335
354
 
336
355
  **Important:** If this round found things AND fixed them all, `TILLEND_EMPTY=false`. The loop must run once more to verify the fixes didn't introduce new issues. A "clean" prediction after a productive round is not enough — only an actually empty round stops the loop.
337
356
 
@@ -49,4 +49,4 @@ curl -s -X POST "${CTRL_URL}/api/mastermind/event" \
49
49
  -d '{"type":"session:complete","session":"<sessionId>","domain":"architect","status":"<status>","domains":["architect"],"ts":'"$(date +%s)"'000}' || true
50
50
  ```
51
51
 
52
- Invoke `Skill("mastermind-skills:_repeat")` now to execute the REPEAT POSTAMBLE. This is a required tool call do not skip it.
52
+ **MANDATORY — invoke `Skill("mastermind-skills:_repeat")` now.** This is required regardless of how the skill above completed, regardless of whether you think the work is done, regardless of whether you plan to end your response. For `--repeat N`: the count is non-negotiable — all N runs must happen. For `--tillend`: only a verified empty round (confirmed by git diff) stops the loop. Do not end your response without invoking this skill.
@@ -25,4 +25,4 @@ Invoke `Skill("mastermind-skills:autodev")` passing: brain_context, count, newfe
25
25
 
26
26
  After skill returns: follow _protocol.md Brain Write Procedure for domain `autodev`.
27
27
 
28
- Invoke `Skill("mastermind-skills:_repeat")` now to execute the REPEAT POSTAMBLE. This is a required tool call do not skip it.
28
+ **MANDATORY — invoke `Skill("mastermind-skills:_repeat")` now.** This is required regardless of how the skill above completed, regardless of whether you think the work is done, regardless of whether you plan to end your response. For `--repeat N`: the count is non-negotiable — all N runs must happen. For `--tillend`: only a verified empty round (confirmed by git diff) stops the loop. Do not end your response without invoking this skill.
@@ -20,4 +20,4 @@ Invoke `Skill("mastermind-skills:build")` passing: brain_context, prompt, projec
20
20
 
21
21
  After skill returns: follow _protocol.md Brain Write Procedure for domain `build`.
22
22
 
23
- Invoke `Skill("mastermind-skills:_repeat")` now to execute the REPEAT POSTAMBLE. This is a required tool call do not skip it.
23
+ **MANDATORY — invoke `Skill("mastermind-skills:_repeat")` now.** This is required regardless of how the skill above completed, regardless of whether you think the work is done, regardless of whether you plan to end your response. For `--repeat N`: the count is non-negotiable — all N runs must happen. For `--tillend`: only a verified empty round (confirmed by git diff) stops the loop. Do not end your response without invoking this skill.
@@ -311,4 +311,4 @@ If `ALL_HIL` is empty, omit the HIL section and congratulate:
311
311
 
312
312
  To repeat this command on a schedule, wrap it with `/mastermind:repeat` or use `--repeat N` / `--tillend` directly.
313
313
 
314
- Invoke `Skill("mastermind-skills:_repeat")` now to execute the REPEAT POSTAMBLE. This is a required tool call do not skip it.
314
+ **MANDATORY — invoke `Skill("mastermind-skills:_repeat")` now.** This is required regardless of how the skill above completed, regardless of whether you think the work is done, regardless of whether you plan to end your response. For `--repeat N`: the count is non-negotiable — all N runs must happen. For `--tillend`: only a verified empty round (confirmed by git diff) stops the loop. Do not end your response without invoking this skill.
@@ -16,4 +16,4 @@ Invoke `Skill("mastermind-skills:debug")` passing: brain_context, problem_descri
16
16
 
17
17
  After skill returns: follow `_protocol.md` Brain Write Procedure for domain `debug`.
18
18
 
19
- Invoke `Skill("mastermind-skills:_repeat")` now to execute the REPEAT POSTAMBLE. This is a required tool call do not skip it.
19
+ **MANDATORY — invoke `Skill("mastermind-skills:_repeat")` now.** This is required regardless of how the skill above completed, regardless of whether you think the work is done, regardless of whether you plan to end your response. For `--repeat N`: the count is non-negotiable — all N runs must happen. For `--tillend`: only a verified empty round (confirmed by git diff) stops the loop. Do not end your response without invoking this skill.
@@ -20,4 +20,4 @@ Invoke `Skill("mastermind-skills:idea")` passing: brain_context, prompt, project
20
20
 
21
21
  After skill returns: follow _protocol.md Brain Write Procedure for domain `idea`.
22
22
 
23
- Invoke `Skill("mastermind-skills:_repeat")` now to execute the REPEAT POSTAMBLE. This is a required tool call do not skip it.
23
+ **MANDATORY — invoke `Skill("mastermind-skills:_repeat")` now.** This is required regardless of how the skill above completed, regardless of whether you think the work is done, regardless of whether you plan to end your response. For `--repeat N`: the count is non-negotiable — all N runs must happen. For `--tillend`: only a verified empty round (confirmed by git diff) stops the loop. Do not end your response without invoking this skill.
@@ -339,4 +339,4 @@ Skill("mastermind-skills:do", "--monotask --space $SPACE_ID --board $TASK_BOARD_
339
339
 
340
340
  To repeat this command on a schedule, wrap it with `/mastermind:repeat` or use `--repeat N` / `--tillend` directly.
341
341
 
342
- Invoke `Skill("mastermind-skills:_repeat")` now to execute the REPEAT POSTAMBLE. This is a required tool call do not skip it.
342
+ **MANDATORY — invoke `Skill("mastermind-skills:_repeat")` now.** This is required regardless of how the skill above completed, regardless of whether you think the work is done, regardless of whether you plan to end your response. For `--repeat N`: the count is non-negotiable — all N runs must happen. For `--tillend`: only a verified empty round (confirmed by git diff) stops the loop. Do not end your response without invoking this skill.
@@ -20,4 +20,4 @@ Invoke `Skill("mastermind-skills:plan")` passing: brain_context, params, project
20
20
 
21
21
  After skill returns: follow `_protocol.md` Brain Write Procedure.
22
22
 
23
- Invoke `Skill("mastermind-skills:_repeat")` now to execute the REPEAT POSTAMBLE. This is a required tool call do not skip it.
23
+ **MANDATORY — invoke `Skill("mastermind-skills:_repeat")` now.** This is required regardless of how the skill above completed, regardless of whether you think the work is done, regardless of whether you plan to end your response. For `--repeat N`: the count is non-negotiable — all N runs must happen. For `--tillend`: only a verified empty round (confirmed by git diff) stops the loop. Do not end your response without invoking this skill.
@@ -20,4 +20,4 @@ Invoke `Skill("mastermind-skills:research")` passing: brain_context, prompt, pro
20
20
 
21
21
  After skill returns: follow _protocol.md Brain Write Procedure for domain `research`.
22
22
 
23
- Invoke `Skill("mastermind-skills:_repeat")` now to execute the REPEAT POSTAMBLE. This is a required tool call do not skip it.
23
+ **MANDATORY — invoke `Skill("mastermind-skills:_repeat")` now.** This is required regardless of how the skill above completed, regardless of whether you think the work is done, regardless of whether you plan to end your response. For `--repeat N`: the count is non-negotiable — all N runs must happen. For `--tillend`: only a verified empty round (confirmed by git diff) stops the loop. Do not end your response without invoking this skill.
@@ -18,6 +18,17 @@ Default mode for this command: **auto** (unless `--confirm` flag present or inta
18
18
 
19
19
  Invoke `Skill("mastermind-skills:review")` passing: brain_context, prompt, project_name, board_id (create if needed), mode.
20
20
 
21
+ **After review findings are collected — AUTO-FIX STEP (mode = auto only):**
22
+
23
+ When `mode = auto` (the default): if the review produced any fixable findings (code issues, bugs, style problems, security vulnerabilities with clear fixes), apply the fixes immediately in this same run. Do not ask the user whether to fix — auto mode means fix without asking. Specifically:
24
+ 1. For each fixable finding, edit the file directly to resolve it.
25
+ 2. After all fixes are applied, output a summary: `[review] Auto-fixed N issues. Remaining M issues require manual intervention.`
26
+ 3. Non-fixable findings (architectural concerns, design questions, trade-off decisions) are reported but not acted on.
27
+
28
+ When `mode = confirm`: present findings and ask the user which to fix. This is the ONLY mode where asking is appropriate.
29
+
30
+ **When `--tillend` is active:** auto-fix is especially critical. Without it, the loop finds the same unfixed issues every round and either loops forever or the AI falsely declares an empty round. The tillend contract is: find → fix → verify (next round) → stop when clean.
31
+
21
32
  After skill returns: follow _protocol.md Brain Write Procedure for domain `review`.
22
33
 
23
- Invoke `Skill("mastermind-skills:_repeat")` now to execute the REPEAT POSTAMBLE. This is a required tool call do not skip it.
34
+ **MANDATORY — invoke `Skill("mastermind-skills:_repeat")` now.** This is required regardless of how the skill above completed, regardless of whether you think the work is done, regardless of whether you plan to end your response. For `--repeat N`: the count is non-negotiable — all N runs must happen. For `--tillend`: only a verified empty round (confirmed by git diff) stops the loop. Do not end your response without invoking this skill.
@@ -133,7 +133,7 @@ curl -s -X POST "${CTRL_URL}/api/mastermind/event" \
133
133
  Follow _protocol.md Brain Write Procedure for domain `ops`.
134
134
 
135
135
 
136
- Invoke `Skill("mastermind-skills:_repeat")` now to execute the REPEAT POSTAMBLE. This is a required tool call do not skip it.
136
+ **MANDATORY — invoke `Skill("mastermind-skills:_repeat")` now.** This is required regardless of how the skill above completed, regardless of whether you think the work is done, regardless of whether you plan to end your response. For `--repeat N`: the count is non-negotiable — all N runs must happen. For `--tillend`: only a verified empty round (confirmed by git diff) stops the loop. Do not end your response without invoking this skill.
137
137
 
138
138
  After the REPEAT POSTAMBLE completes, if a loop was started or continued (LOOP_ID is set), write the org name into the loop state file so the dashboard can detect running status:
139
139
  ```bash
@@ -20,4 +20,4 @@ Invoke `Skill("mastermind-skills:taskdev")` passing: brain_context, plan_file, p
20
20
 
21
21
  After skill returns: follow `_protocol.md` Brain Write Procedure.
22
22
 
23
- Invoke `Skill("mastermind-skills:_repeat")` now to execute the REPEAT POSTAMBLE. This is a required tool call do not skip it.
23
+ **MANDATORY — invoke `Skill("mastermind-skills:_repeat")` now.** This is required regardless of how the skill above completed, regardless of whether you think the work is done, regardless of whether you plan to end your response. For `--repeat N`: the count is non-negotiable — all N runs must happen. For `--tillend`: only a verified empty round (confirmed by git diff) stops the loop. Do not end your response without invoking this skill.
@@ -16,4 +16,4 @@ Invoke `Skill("mastermind-skills:tdd")` passing: brain_context, feature_or_bug,
16
16
 
17
17
  After skill returns: follow `_protocol.md` Brain Write Procedure for domain `tdd`.
18
18
 
19
- Invoke `Skill("mastermind-skills:_repeat")` now to execute the REPEAT POSTAMBLE. This is a required tool call do not skip it.
19
+ **MANDATORY — invoke `Skill("mastermind-skills:_repeat")` now.** This is required regardless of how the skill above completed, regardless of whether you think the work is done, regardless of whether you plan to end your response. For `--repeat N`: the count is non-negotiable — all N runs must happen. For `--tillend`: only a verified empty round (confirmed by git diff) stops the loop. Do not end your response without invoking this skill.
@@ -16,4 +16,4 @@ Invoke `Skill("mastermind-skills:verify")` passing: brain_context, claim_or_task
16
16
 
17
17
  After skill returns: follow `_protocol.md` Brain Write Procedure for domain `verify`.
18
18
 
19
- Invoke `Skill("mastermind-skills:_repeat")` now to execute the REPEAT POSTAMBLE. This is a required tool call do not skip it.
19
+ **MANDATORY — invoke `Skill("mastermind-skills:_repeat")` now.** This is required regardless of how the skill above completed, regardless of whether you think the work is done, regardless of whether you plan to end your response. For `--repeat N`: the count is non-negotiable — all N runs must happen. For `--tillend`: only a verified empty round (confirmed by git diff) stops the loop. Do not end your response without invoking this skill.
@@ -66,6 +66,30 @@ if (!entryPoint) {
66
66
  process.exit(0);
67
67
  }
68
68
 
69
+ // Skip if index is already fresh — don't waste CPU on every session start
70
+ const dbPath = path.join(projectDir, '.monomind', 'monograph.db');
71
+ if (fs.existsSync(dbPath)) {
72
+ try {
73
+ const Database = require(require.resolve('better-sqlite3', { paths: [path.dirname(entryPoint)] }));
74
+ const db = new Database(dbPath, { readonly: true, timeout: 5000 });
75
+ try {
76
+ const row = db.prepare("SELECT value FROM index_meta WHERE key='last_commit_hash'").get();
77
+ if (row && row.value && /^[0-9a-f]{7,40}$/i.test(row.value)) {
78
+ const { execFileSync } = require('child_process');
79
+ const out = execFileSync('git', ['rev-list', '--count', row.value + '..HEAD'], {
80
+ cwd: projectDir, encoding: 'utf-8', timeout: 2000, stdio: ['pipe', 'pipe', 'pipe']
81
+ }).trim();
82
+ const behind = parseInt(out, 10);
83
+ if (behind === 0) {
84
+ console.log('[graph] index is fresh — skipping rebuild');
85
+ db.close();
86
+ process.exit(0);
87
+ }
88
+ }
89
+ } finally { try { db.close(); } catch {} }
90
+ } catch { /* can't check — proceed with build */ }
91
+ }
92
+
69
93
  // Skip if another build is already in progress (avoids SQLite BUSY on concurrent init + session-start)
70
94
  const lockPath = path.join(graphDir, 'build.lock');
71
95
  const now = Date.now();
@@ -361,17 +361,14 @@ module.exports = {
361
361
  // Source of truth is .monomind/monograph.db (SQLite). Legacy stats.json
362
362
  // is no longer written by the build, so it is checked only as a fallback.
363
363
  try {
364
- var monographDb = path.join(CWD, '.monomind', 'monograph.db');
365
364
  var legacyStats = path.join(CWD, '.monomind', 'graph', 'stats.json');
366
365
  var nodeCount = 0;
367
- if (fs.existsSync(monographDb)) {
368
- try {
369
- var hintDb = hCtx._openMonographDb();
370
- if (hintDb) {
371
- nodeCount = hintDb.prepare('SELECT COUNT(*) AS c FROM nodes').get().c;
372
- }
373
- } catch (e) { /* ignore — fall back to legacy */ }
374
- }
366
+ try {
367
+ var hintDb = hCtx._openMonographDb();
368
+ if (hintDb) {
369
+ nodeCount = hintDb.prepare('SELECT COUNT(*) AS c FROM nodes').get().c;
370
+ }
371
+ } catch (e) { /* ignore — fall back to legacy */ }
375
372
  if (nodeCount === 0 && fs.existsSync(legacyStats)) {
376
373
  try {
377
374
  var legacyStatsSt = fs.statSync(legacyStats);
@@ -381,7 +378,7 @@ module.exports = {
381
378
  }
382
379
  } catch (e) { /* ignore */ }
383
380
  }
384
- if (nodeCount > 100) {
381
+ if (nodeCount > 100 && hCtx._isGraphFresh()) {
385
382
  // Pre-resolve top-3 relevant files for the user's prompt — the LLM
386
383
  // sees the answer inline instead of being told to call a tool.
387
384
  // 3 is enough signal; more files inflate token cost on every prompt.
@@ -216,6 +216,7 @@ var hCtx = {
216
216
  _recordToolCall: _recordToolCall,
217
217
  _openMonographDb: _openMonographDb,
218
218
  _requireMonograph: _requireMonograph,
219
+ _isGraphFresh: _isGraphFresh,
219
220
  _triggerExtractYamlValue: _triggerExtractYamlValue,
220
221
  _triggerFinalize: _triggerFinalize,
221
222
  _triggerExtractFromFrontmatter: _triggerExtractFromFrontmatter,
@@ -312,7 +313,8 @@ const handlers = {
312
313
  if (db) {
313
314
  // Stop words: language keywords + generic single-word identifiers
314
315
  // that match Variable nodes in markdown/scripts (not real code symbols)
315
- var _grepStop = {import:1,export:1,from:1,require:1,return:1,function:1,const:1,let:1,var:1,class:1,interface:1,type:1,extends:1,implements:1,async:1,await:1,yield:1,throw:1,catch:1,finally:1,typeof:1,instanceof:1,void:1,null:1,undefined:1,true:1,false:1,this:1,super:1,new:1,delete:1,switch:1,case:1,break:1,continue:1,default:1,else:1,while:1,for:1,with:1,include:1,error:1,string:1,number:1,object:1,boolean:1,array:1,value:1,result:1,data:1,name:1,path:1,file:1,node:1,list:1,item:1,index:1,config:1,options:1,params:1,args:1,event:1,state:1,props:1,context:1,module:1,package:1,version:1,model:1,schema:1,table:1,query:1,response:1,request:1,handler:1,logger:1,graph:1,usage:1,storage:1,pipeline:1,service:1,utils:1,types:1,helpers:1,common:1,shared:1,server:1,client:1,source:1,output:1,input:1,stream:1,buffer:1,worker:1,plugin:1,format:1,render:1,update:1,create:1,remove:1,method:1,define:1,invoke:1,process:1,execute:1,resolve:1,reject:1,promise:1,callback:1,cursor:1,record:1,column:1,filter:1,reduce:1,status:1,action:1,commit:1,revert:1,publish:1,symbol:1,target:1,length:1,string:1,global:1,static:1,struct:1,select:1,insert:1,signal:1,socket:1,system:1,memory:1,parser:1,router:1,docker:1,script:1,bundle:1,deploy:1,search:1,prepare:1};
316
+ // monolean: only JS/TS reserved words — generic identifiers (handler, config, router, etc.) are valid symbol names
317
+ var _grepStop = {import:1,export:1,from:1,require:1,return:1,function:1,const:1,let:1,var:1,class:1,interface:1,type:1,extends:1,implements:1,async:1,await:1,yield:1,throw:1,catch:1,finally:1,typeof:1,instanceof:1,void:1,null:1,undefined:1,true:1,false:1,this:1,super:1,new:1,delete:1,switch:1,case:1,break:1,continue:1,default:1,else:1,while:1,for:1,with:1,static:1,enum:1,string:1,number:1,object:1,boolean:1};
316
318
 
317
319
  // --- Strategy 1: clean identifier → exact name match (case-sensitive) ---
318
320
  if (/^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(pattern) && pattern.length >= 4
@@ -479,7 +481,8 @@ const handlers = {
479
481
  var db = _openMonographDb();
480
482
  if (db) {
481
483
  try {
482
- var _searchStop = {import:1,export:1,from:1,require:1,return:1,function:1,const:1,let:1,var:1,class:1,interface:1,type:1,extends:1,implements:1,async:1,await:1,yield:1,throw:1,catch:1,finally:1,typeof:1,instanceof:1,void:1,null:1,undefined:1,true:1,false:1,this:1,super:1,new:1,delete:1,switch:1,case:1,break:1,continue:1,default:1,else:1,while:1,for:1,with:1,include:1,error:1,string:1,number:1,object:1,boolean:1,array:1,value:1,result:1,data:1,name:1,path:1,file:1,node:1,list:1,item:1,index:1,config:1,options:1,params:1,args:1,event:1,state:1,props:1,context:1,module:1,package:1,version:1,model:1,schema:1,table:1,query:1,response:1,request:1,handler:1,logger:1,graph:1,usage:1,storage:1,pipeline:1,service:1,utils:1,types:1,helpers:1,common:1,shared:1,server:1,client:1,source:1,output:1,input:1,stream:1,buffer:1,worker:1,plugin:1,format:1,render:1,update:1,create:1,remove:1,method:1,define:1,invoke:1,process:1,execute:1,resolve:1,reject:1,promise:1,callback:1,cursor:1,record:1,column:1,filter:1,reduce:1,status:1,action:1,commit:1,revert:1,publish:1,symbol:1,target:1,length:1,string:1,global:1,static:1,struct:1,select:1,insert:1,signal:1,socket:1,system:1,memory:1,parser:1,router:1,docker:1,script:1,bundle:1,deploy:1,search:1,prepare:1};
484
+ // monolean: only JS/TS reserved words — generic identifiers are valid symbol names
485
+ var _searchStop = {import:1,export:1,from:1,require:1,return:1,function:1,const:1,let:1,var:1,class:1,interface:1,type:1,extends:1,implements:1,async:1,await:1,yield:1,throw:1,catch:1,finally:1,typeof:1,instanceof:1,void:1,null:1,undefined:1,true:1,false:1,this:1,super:1,new:1,delete:1,switch:1,case:1,break:1,continue:1,default:1,else:1,while:1,for:1,with:1,static:1,enum:1,string:1,number:1,object:1,boolean:1};
483
486
 
484
487
  var isCleanSymbol = /^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(grepPattern);
485
488
 
@@ -49,11 +49,28 @@ function _suggestCacheSet(key, value) {
49
49
  }
50
50
  _suggestCache._map[key] = value;
51
51
  }
52
+ function _isValidDb(p) {
53
+ try { return fs.statSync(p).size >= 100; } catch (_) { return false; }
54
+ }
55
+
56
+ function _resolveDbPath() {
57
+ // monolean: try CWD first, then git root, so hooks work from any subdirectory
58
+ var candidate = path.join(CWD, '.monomind', 'monograph.db');
59
+ if (_isValidDb(candidate)) return candidate;
60
+ try {
61
+ var { execSync } = require('child_process');
62
+ var root = execSync('git rev-parse --show-toplevel', { cwd: CWD, encoding: 'utf-8', timeout: 2000 }).trim();
63
+ candidate = path.join(root, '.monomind', 'monograph.db');
64
+ if (_isValidDb(candidate)) return candidate;
65
+ } catch (_) {}
66
+ return null;
67
+ }
68
+
52
69
  function _openMonographDb() {
53
70
  if (_cachedMonographDb !== undefined) return _cachedMonographDb;
54
71
  try {
55
- var dbPath = path.join(CWD, '.monomind', 'monograph.db');
56
- if (!fs.existsSync(dbPath)) { _cachedMonographDb = null; return null; }
72
+ var dbPath = _resolveDbPath();
73
+ if (!dbPath) { _cachedMonographDb = null; return null; }
57
74
  var mod = _requireMonograph();
58
75
  if (!mod || !mod.openDb) { _cachedMonographDb = null; return null; }
59
76
  _cachedMonographDb = mod.openDb(dbPath);
@@ -183,21 +200,36 @@ function _getDollarRate() {
183
200
 
184
201
  // Staleness guard — skip graph DB lookups when the index is too far behind HEAD.
185
202
  // Returns true if it's safe to use the graph, false if stale.
203
+ // Uses last_commit_hash from the DB (not file mtime, which drifts from backups/WAL/VACUUM).
186
204
  var _graphFreshnessCache = undefined;
187
205
  function _isGraphFresh() {
188
206
  if (_graphFreshnessCache !== undefined) return _graphFreshnessCache;
189
207
  try {
190
- var dbPath = path.join(CWD, '.monomind', 'monograph.db');
191
- var dbStat = fs.statSync(dbPath);
192
- var { execSync } = require('child_process');
193
- var buildIso = new Date(dbStat.mtimeMs).toISOString();
194
- var out = execSync("git rev-list --count --since='" + buildIso + "' HEAD 2>/dev/null", {
195
- encoding: 'utf-8', timeout: 1500, stdio: ['pipe', 'pipe', 'pipe']
208
+ var db = _openMonographDb();
209
+ if (!db) { _graphFreshnessCache = false; return false; }
210
+ var row = null;
211
+ try {
212
+ row = db.prepare("SELECT value FROM index_meta WHERE key='last_commit_hash'").get() ||
213
+ db.prepare("SELECT value FROM index_meta WHERE key='lastCommit'").get();
214
+ } catch (_) {}
215
+ if (!row || !row.value) {
216
+ _graphFreshnessCache = false;
217
+ return false;
218
+ }
219
+ if (!/^[0-9a-f]{7,40}$/i.test(row.value)) {
220
+ _graphFreshnessCache = false;
221
+ return false;
222
+ }
223
+ var { execFileSync } = require('child_process');
224
+ var out = execFileSync('git', ['rev-list', '--count', row.value + '..HEAD'], {
225
+ encoding: 'utf-8', timeout: 1500, stdio: ['pipe', 'pipe', 'pipe'], cwd: CWD
196
226
  }).trim();
197
- var behind = parseInt(out, 10) || 0;
198
- _graphFreshnessCache = behind <= 50; // monolean: 50 commits is generous enough
227
+ var behind = parseInt(out, 10);
228
+ if (isNaN(behind)) { _graphFreshnessCache = false; return false; }
229
+ _graphFreshnessCache = behind <= 50;
199
230
  } catch(e) {
200
- _graphFreshnessCache = true; // can't check assume fresh
231
+ // Don't cache transient errors — let next call retry
232
+ return false;
201
233
  }
202
234
  return _graphFreshnessCache;
203
235
  }
@@ -354,14 +386,21 @@ function injectGodNodesContext(CWD) {
354
386
  try {
355
387
  var nodeCount = db.prepare('SELECT COUNT(*) AS c FROM nodes').get().c;
356
388
  var edgeCount = db.prepare('SELECT COUNT(*) AS c FROM edges').get().c;
389
+ // Precompute degree via indexed edge lookups to avoid O(N) correlated subquery
357
390
  var godNodes = db.prepare(
358
- "SELECT n.name, n.label, n.file_path, " +
359
- "(SELECT COUNT(*) FROM edges WHERE source_id=n.id OR target_id=n.id) AS deg " +
360
- "FROM nodes n " +
391
+ "WITH deg AS (" +
392
+ " SELECT id, SUM(cnt) AS deg FROM (" +
393
+ " SELECT source_id AS id, COUNT(*) AS cnt FROM edges GROUP BY source_id " +
394
+ " UNION ALL " +
395
+ " SELECT target_id AS id, COUNT(*) AS cnt FROM edges GROUP BY target_id" +
396
+ " ) GROUP BY id" +
397
+ ") " +
398
+ "SELECT n.name, n.label, n.file_path, d.deg " +
399
+ "FROM deg d JOIN nodes n ON n.id = d.id " +
361
400
  "WHERE n.label NOT IN ('Concept') " +
362
401
  "AND n.file_path IS NOT NULL AND n.file_path != '' " +
363
402
  "AND n.file_path NOT LIKE '%/node_modules/%' AND n.file_path NOT LIKE '%node_modules%' " +
364
- "ORDER BY deg DESC LIMIT 12"
403
+ "ORDER BY d.deg DESC LIMIT 12"
365
404
  ).all();
366
405
 
367
406
  // Staleness indicator: compare stored commit hash with current HEAD.
@@ -396,6 +435,7 @@ function injectGodNodesContext(CWD) {
396
435
  return n.name + ' (' + n.label + ', ' + n.deg + ' links)';
397
436
  }).join(', ');
398
437
  console.log('[MONOGRAPH_CONTEXT] ' + nodeCount + ' nodes · ' + edgeCount + ' edges. Key nodes: ' + godStr + staleIndicator);
438
+ console.log('[MONOGRAPH_ACTIVE] Indexed knowledge graph available — prefer monograph_query / monograph_suggest over grep/find for symbol and definition lookups.');
399
439
 
400
440
  // Write god nodes into knowledge/chunks.jsonl so semantic search finds them.
401
441
  var knowledgeDir = path.join(CWD, '.monomind', 'knowledge');
@@ -416,7 +456,10 @@ function injectGodNodesContext(CWD) {
416
456
  try { return JSON.parse(line).id !== 'monograph-god-nodes'; } catch(e) { return true; }
417
457
  });
418
458
  existing.push(godChunk);
419
- fs.writeFileSync(chunksFile, existing.join('\n') + '\n');
459
+ // Atomic write: tmp file + rename to avoid corruption on kill/timeout
460
+ var tmpChunks = chunksFile + '.tmp.' + process.pid;
461
+ fs.writeFileSync(tmpChunks, existing.join('\n') + '\n');
462
+ fs.renameSync(tmpChunks, chunksFile);
420
463
  } catch(e) {}
421
464
  }
422
465
  } catch(e) { /* non-fatal */ }
@@ -6,6 +6,21 @@ type: protocol-skill
6
6
 
7
7
  # REPEAT POSTAMBLE
8
8
 
9
+ <EXTREMELY-IMPORTANT>
10
+ ## MANDATORY EXECUTION — READ THIS FIRST
11
+
12
+ This postamble is **not optional**. You MUST execute every step below. You MUST call ScheduleWakeup unless a legitimate stop condition is met (stop file, empty round confirmed by git, or count reached).
13
+
14
+ **Anti-rationalization rules:**
15
+ - "I think the work is done" is NOT a reason to stop. Only the checks below decide.
16
+ - "The skill already handled everything" is NOT a reason to skip this postamble.
17
+ - "There's nothing more to do" is NOT your decision — the tillend check decides.
18
+ - For `--repeat N`: you MUST run all N iterations. The count is non-negotiable. You cannot stop at run 3 of 5 because you think 3 was enough.
19
+ - For `--tillend`: you MUST continue until git AND your assessment BOTH confirm an empty round. Your feeling that "it's probably clean" is not evidence.
20
+
21
+ If you are about to end your response without calling ScheduleWakeup and you have not hit a legitimate stop condition, **YOU ARE MAKING AN ERROR. Go back and call ScheduleWakeup.**
22
+ </EXTREMELY-IMPORTANT>
23
+
9
24
  **If neither `tillend_mode = true` nor `repeat_count ≥ 2` was active in this invocation, stop immediately — this skill is a no-op.**
10
25
 
11
26
  Otherwise execute all steps below before ending the response.
@@ -29,12 +44,22 @@ If the stop file exists:
29
44
 
30
45
  **`LOOP_ASYNC_PENDING` escape hatch:** If the calling skill set `LOOP_ASYNC_PENDING=true` before invoking this postamble (because it spawned background agents whose results have not yet arrived), skip the empty-round check and go directly to Step 4 to schedule the next run. Output: `[tillend] Async work in flight — deferring empty-round check to run <next_rep>.`
31
46
 
32
- Evaluate now whether this run produced **zero findings AND zero actions**:
47
+ **Step 2a Machine verification (REQUIRED before any self-assessment):**
48
+
49
+ Run this command to get an objective signal of whether files changed during this run:
50
+
51
+ ```bash
52
+ GIT_CHANGES=$(git diff --stat HEAD 2>/dev/null; git diff --cached --stat 2>/dev/null; git status --porcelain 2>/dev/null | grep -v '^\?\?' | head -20)
53
+ echo "GIT_CHANGES_DURING_RUN: ${GIT_CHANGES:-NONE}"
54
+ ```
55
+
56
+ If `GIT_CHANGES` is non-empty, files were modified — `TILLEND_EMPTY=false` regardless of your self-assessment. Skip to "Otherwise" below.
57
+
58
+ **Step 2b — Self-assessment (only if git shows no changes):**
33
59
 
34
- - **Findings**: issues found, problems detected, items flagged, security vulnerabilities, tasks discovered, errors reported
35
- - **Actions**: files edited, code fixed, commits made, tasks created, configs changed, content written
60
+ Only if `GIT_CHANGES` was empty, evaluate whether this run produced findings (issues identified, problems flagged) or actions (tasks created, content written, configs changed — anything not captured by git diff).
36
61
 
37
- Set `TILLEND_EMPTY=true` **only if BOTH are zero for this round**.
62
+ Set `TILLEND_EMPTY=true` **only if git shows no changes AND your self-assessment confirms zero findings and zero actions**.
38
63
 
39
64
  **Important**: If this round found things AND fixed them, `TILLEND_EMPTY=false` — the loop must continue to verify the fixes didn't introduce new issues.
40
65
 
@@ -171,8 +171,15 @@ Step 4 — Report:
171
171
 
172
172
  Also run /mastermind:do --board <board_id> to track execution.
173
173
 
174
- STEP 4 — COLLECT AND RETURN
175
- Synthesize all review findings. Return to caller:
174
+ STEP 4 — AUTO-FIX (mode = auto only, skip for mode = confirm)
175
+ When mode is auto: for each fixable finding from the review (code bugs, style issues, security vulnerabilities with clear fixes), apply the fix directly by editing the file. Do NOT ask the user for permission — auto mode means fix without asking. After fixing, output:
176
+ [review] Auto-fixed N issues. M issues remain (require manual intervention or are architectural).
177
+ Non-fixable findings (design questions, trade-offs, architectural concerns) are reported but left untouched.
178
+
179
+ When --tillend is active, this step is critical: without auto-fixing, the loop either finds the same issues every round (infinite loop) or falsely declares empty round. The tillend contract is: find → fix → verify (next round) → stop when clean.
180
+
181
+ STEP 5 — COLLECT AND RETURN
182
+ Synthesize all review findings and fixes applied. Return to caller:
176
183
 
177
184
  domain: review
178
185
  status: complete | partial | blocked
@@ -183,12 +190,14 @@ decisions:
183
190
  - what: [critical findings and recommended actions]
184
191
  why: [evidence from review]
185
192
  confidence: [0.0-1.0]
186
- outcome: pending
193
+ outcome: fixed | pending | manual
187
194
  lessons:
188
195
  - what_worked: [which review angles surfaced the most value]
189
196
  - what_didnt: [gaps in review coverage]
197
+ fixes_applied: [count of auto-fixed issues]
198
+ fixes_remaining: [count of issues needing manual intervention]
190
199
  next_actions:
191
- - [e.g. "run mastermind:build to fix critical issues found"]
200
+ - [e.g. "re-run review to verify fixes" if tillend is active]
192
201
  - [e.g. "run mastermind:release after fixes are confirmed"]
193
202
  board_url: monotask://<project_name>/review
194
203
  run_id: <ISO8601-timestamp>`,
@@ -203,8 +212,10 @@ run_id: <ISO8601-timestamp>`,
203
212
  For simple tasks (single reviewer, single artifact):
204
213
 
205
214
  1. Spawn one Task agent with the review request as a self-contained briefing
206
- 2. Collect output
207
- 3. Return unified output schema with `status: complete`
215
+ 2. Collect findings
216
+ 3. **If mode = auto**: apply fixes for all fixable findings directly (do NOT ask the user). Output: `[review] Auto-fixed N issues.`
217
+ 4. **If mode = confirm**: present findings and ask which to fix
218
+ 5. Return unified output schema with `status: complete`
208
219
 
209
220
  ---
210
221
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "monomind",
3
- "version": "1.18.12",
3
+ "version": "1.18.15",
4
4
  "description": "Monomind - Enterprise AI agent orchestration for Claude Code. Deploy 60+ specialized agents in coordinated swarms with self-learning, fault-tolerant consensus, vector memory, and MCP integration",
5
5
  "main": "dist/index.js",
6
6
  "type": "module",
@@ -326,12 +326,31 @@ RECENT_HIL=$(find . -maxdepth 3 \( -name "humaninloop*.md" -o -name "humaninloop
326
326
 
327
327
  After each run in tillend mode, evaluate whether this run produced **zero findings and zero actions**. The loop stops only when a complete round finds nothing new and makes no changes — not when the AI predicts there is nothing left.
328
328
 
329
- **You (the AI running the loop) must now assess your own output from this run.** Answer these two questions:
329
+ <EXTREMELY-IMPORTANT>
330
+ **Anti-premature-stop rules:**
331
+ - "I think the work is done" is NOT a reason to stop. Only the checks below decide.
332
+ - "There's nothing more to find" is a PREDICTION, not an observation. Predictions do not stop loops.
333
+ - You MUST run the git verification command below. If git shows changes, the round is non-empty. Period.
334
+ - Only a round where git shows NO changes AND you confirm zero findings AND zero actions qualifies as empty.
335
+ </EXTREMELY-IMPORTANT>
336
+
337
+ **Step 4a — Machine verification (REQUIRED — run this command before any self-assessment):**
338
+
339
+ ```bash
340
+ GIT_CHANGES=$(git diff --stat HEAD 2>/dev/null; git diff --cached --stat 2>/dev/null; git status --porcelain 2>/dev/null | grep -v '^\?\?' | head -20)
341
+ echo "GIT_CHANGES_DURING_RUN: ${GIT_CHANGES:-NONE}"
342
+ ```
343
+
344
+ If `GIT_CHANGES` is non-empty, files were modified — `TILLEND_EMPTY=false` regardless of self-assessment. Skip directly to "Otherwise" below.
345
+
346
+ **Step 4b — Self-assessment (only if git shows no changes):**
347
+
348
+ Only if `GIT_CHANGES` was empty, answer these two questions about this run:
330
349
 
331
350
  1. **Were any findings produced?** — issues found, problems detected, items identified, things flagged, errors reported, tasks discovered, security vulnerabilities found, etc.
332
- 2. **Were any actions taken?** — files edited, code fixed, tasks created, cards moved, commits made, content written, configs changed, etc.
351
+ 2. **Were any actions taken?** — tasks created, content written, configs changed anything not captured by git diff.
333
352
 
334
- **Set `TILLEND_EMPTY=true` only if BOTH answers are "no" zero findings AND zero actions this round.**
353
+ **Set `TILLEND_EMPTY=true` only if git shows no changes AND BOTH answers are "no".**
335
354
 
336
355
  **Important:** If this round found things AND fixed them all, `TILLEND_EMPTY=false`. The loop must run once more to verify the fixes didn't introduce new issues. A "clean" prediction after a productive round is not enough — only an actually empty round stops the loop.
337
356
 
@@ -49,4 +49,4 @@ curl -s -X POST "${CTRL_URL}/api/mastermind/event" \
49
49
  -d '{"type":"session:complete","session":"<sessionId>","domain":"architect","status":"<status>","domains":["architect"],"ts":'"$(date +%s)"'000}' || true
50
50
  ```
51
51
 
52
- Invoke `Skill("mastermind-skills:_repeat")` now to execute the REPEAT POSTAMBLE. This is a required tool call do not skip it.
52
+ **MANDATORY — invoke `Skill("mastermind-skills:_repeat")` now.** This is required regardless of how the skill above completed, regardless of whether you think the work is done, regardless of whether you plan to end your response. For `--repeat N`: the count is non-negotiable — all N runs must happen. For `--tillend`: only a verified empty round (confirmed by git diff) stops the loop. Do not end your response without invoking this skill.
@@ -25,4 +25,4 @@ Invoke `Skill("mastermind-skills:autodev")` passing: brain_context, count, newfe
25
25
 
26
26
  After skill returns: follow _protocol.md Brain Write Procedure for domain `autodev`.
27
27
 
28
- Invoke `Skill("mastermind-skills:_repeat")` now to execute the REPEAT POSTAMBLE. This is a required tool call do not skip it.
28
+ **MANDATORY — invoke `Skill("mastermind-skills:_repeat")` now.** This is required regardless of how the skill above completed, regardless of whether you think the work is done, regardless of whether you plan to end your response. For `--repeat N`: the count is non-negotiable — all N runs must happen. For `--tillend`: only a verified empty round (confirmed by git diff) stops the loop. Do not end your response without invoking this skill.
@@ -20,4 +20,4 @@ Invoke `Skill("mastermind-skills:build")` passing: brain_context, prompt, projec
20
20
 
21
21
  After skill returns: follow _protocol.md Brain Write Procedure for domain `build`.
22
22
 
23
- Invoke `Skill("mastermind-skills:_repeat")` now to execute the REPEAT POSTAMBLE. This is a required tool call do not skip it.
23
+ **MANDATORY — invoke `Skill("mastermind-skills:_repeat")` now.** This is required regardless of how the skill above completed, regardless of whether you think the work is done, regardless of whether you plan to end your response. For `--repeat N`: the count is non-negotiable — all N runs must happen. For `--tillend`: only a verified empty round (confirmed by git diff) stops the loop. Do not end your response without invoking this skill.
@@ -311,4 +311,4 @@ If `ALL_HIL` is empty, omit the HIL section and congratulate:
311
311
 
312
312
  To repeat this command on a schedule, wrap it with `/mastermind:repeat` or use `--repeat N` / `--tillend` directly.
313
313
 
314
- Invoke `Skill("mastermind-skills:_repeat")` now to execute the REPEAT POSTAMBLE. This is a required tool call do not skip it.
314
+ **MANDATORY — invoke `Skill("mastermind-skills:_repeat")` now.** This is required regardless of how the skill above completed, regardless of whether you think the work is done, regardless of whether you plan to end your response. For `--repeat N`: the count is non-negotiable — all N runs must happen. For `--tillend`: only a verified empty round (confirmed by git diff) stops the loop. Do not end your response without invoking this skill.
@@ -16,4 +16,4 @@ Invoke `Skill("mastermind-skills:debug")` passing: brain_context, problem_descri
16
16
 
17
17
  After skill returns: follow `_protocol.md` Brain Write Procedure for domain `debug`.
18
18
 
19
- Invoke `Skill("mastermind-skills:_repeat")` now to execute the REPEAT POSTAMBLE. This is a required tool call do not skip it.
19
+ **MANDATORY — invoke `Skill("mastermind-skills:_repeat")` now.** This is required regardless of how the skill above completed, regardless of whether you think the work is done, regardless of whether you plan to end your response. For `--repeat N`: the count is non-negotiable — all N runs must happen. For `--tillend`: only a verified empty round (confirmed by git diff) stops the loop. Do not end your response without invoking this skill.
@@ -20,4 +20,4 @@ Invoke `Skill("mastermind-skills:idea")` passing: brain_context, prompt, project
20
20
 
21
21
  After skill returns: follow _protocol.md Brain Write Procedure for domain `idea`.
22
22
 
23
- Invoke `Skill("mastermind-skills:_repeat")` now to execute the REPEAT POSTAMBLE. This is a required tool call do not skip it.
23
+ **MANDATORY — invoke `Skill("mastermind-skills:_repeat")` now.** This is required regardless of how the skill above completed, regardless of whether you think the work is done, regardless of whether you plan to end your response. For `--repeat N`: the count is non-negotiable — all N runs must happen. For `--tillend`: only a verified empty round (confirmed by git diff) stops the loop. Do not end your response without invoking this skill.
@@ -339,4 +339,4 @@ Skill("mastermind-skills:do", "--monotask --space $SPACE_ID --board $TASK_BOARD_
339
339
 
340
340
  To repeat this command on a schedule, wrap it with `/mastermind:repeat` or use `--repeat N` / `--tillend` directly.
341
341
 
342
- Invoke `Skill("mastermind-skills:_repeat")` now to execute the REPEAT POSTAMBLE. This is a required tool call do not skip it.
342
+ **MANDATORY — invoke `Skill("mastermind-skills:_repeat")` now.** This is required regardless of how the skill above completed, regardless of whether you think the work is done, regardless of whether you plan to end your response. For `--repeat N`: the count is non-negotiable — all N runs must happen. For `--tillend`: only a verified empty round (confirmed by git diff) stops the loop. Do not end your response without invoking this skill.
@@ -20,4 +20,4 @@ Invoke `Skill("mastermind-skills:plan")` passing: brain_context, params, project
20
20
 
21
21
  After skill returns: follow `_protocol.md` Brain Write Procedure.
22
22
 
23
- Invoke `Skill("mastermind-skills:_repeat")` now to execute the REPEAT POSTAMBLE. This is a required tool call do not skip it.
23
+ **MANDATORY — invoke `Skill("mastermind-skills:_repeat")` now.** This is required regardless of how the skill above completed, regardless of whether you think the work is done, regardless of whether you plan to end your response. For `--repeat N`: the count is non-negotiable — all N runs must happen. For `--tillend`: only a verified empty round (confirmed by git diff) stops the loop. Do not end your response without invoking this skill.