@monoes/monomindcli 1.13.0 → 1.14.1

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 (39) hide show
  1. package/.claude/agents/generated/churn-analyst.md +53 -0
  2. package/.claude/agents/generated/code-reviewer.md +55 -0
  3. package/.claude/agents/generated/code-validator.md +57 -0
  4. package/.claude/agents/generated/complexity-scanner.md +56 -0
  5. package/.claude/agents/generated/devbot-orchestrator.md +58 -0
  6. package/.claude/agents/generated/devbot-planner.md +63 -0
  7. package/.claude/agents/generated/impact-assessor.md +54 -0
  8. package/.claude/commands/mastermind/master.md +88 -24
  9. package/.claude/helpers/control-start.cjs +60 -1
  10. package/.claude/helpers/event-logger.cjs +43 -2
  11. package/.claude/helpers/handlers/capture-handler.cjs +336 -0
  12. package/.claude/helpers/handlers/route-handler.cjs +11 -11
  13. package/.claude/helpers/hook-handler.cjs +17 -1
  14. package/.claude/helpers/session.cjs +20 -2
  15. package/.claude/skills/mastermind/createorg.md +227 -16
  16. package/.claude/skills/mastermind/idea.md +15 -3
  17. package/.claude/skills/mastermind/runorg.md +2 -1
  18. package/dist/src/commands/index.js +2 -0
  19. package/dist/src/commands/org.d.ts +4 -0
  20. package/dist/src/commands/org.d.ts.map +1 -0
  21. package/dist/src/commands/org.js +93 -0
  22. package/dist/src/commands/org.js.map +1 -0
  23. package/dist/src/mcp-tools/memory-tools.js +6 -6
  24. package/dist/src/mcp-tools/memory-tools.js.map +1 -1
  25. package/dist/src/mcp-tools/session-tools.d.ts.map +1 -1
  26. package/dist/src/mcp-tools/session-tools.js +9 -10
  27. package/dist/src/mcp-tools/session-tools.js.map +1 -1
  28. package/dist/src/mcp-tools/task-tools.d.ts.map +1 -1
  29. package/dist/src/mcp-tools/task-tools.js +7 -8
  30. package/dist/src/mcp-tools/task-tools.js.map +1 -1
  31. package/dist/src/mcp-tools/types.d.ts +1 -0
  32. package/dist/src/mcp-tools/types.d.ts.map +1 -1
  33. package/dist/src/mcp-tools/types.js +49 -0
  34. package/dist/src/mcp-tools/types.js.map +1 -1
  35. package/dist/src/ui/dashboard.html +1639 -249
  36. package/dist/src/ui/orgs.html +1 -0
  37. package/dist/src/ui/server.mjs +402 -132
  38. package/dist/tsconfig.tsbuildinfo +1 -1
  39. package/package.json +1 -1
@@ -0,0 +1,53 @@
1
+ ---
2
+ name: churn-analyst
3
+ description: Script-only git log analyst that identifies high-churn problematic files from the last 6 months — no LLMs in this phase
4
+ capability:
5
+ role: churn-analyst
6
+ goal: Produce a ranked JSON list of files with the highest bug-fix commit frequency to feed Phase 2 triage
7
+ version: "1.0.0"
8
+ expertise:
9
+ - git log parsing and commit filtering
10
+ - churn score computation (frequency × recency weighting)
11
+ - JSON schema output formatting
12
+ - bash/python scripting for deterministic analysis
13
+ - commit message pattern matching (fix/bug/revert)
14
+ task_types:
15
+ - git-log-analysis
16
+ - churn-scoring
17
+ - blackboard-write
18
+ input_type: Git repository at cwd; trigger command from Orchestrator to start analysis
19
+ output_type: JSON payload written to blackboard — array of {file, churn_score, last_modified, commit_count_6m, status:"new"}
20
+ model_preference: haiku
21
+ termination: Blackboard updated with all files scoring above churn threshold; analysis complete message sent to Orchestrator
22
+ ---
23
+
24
+ # Churn Analyst
25
+
26
+ Deterministic Phase 1 sensor. Parses `git log` for the last 6 months, filters commits containing "fix", "bug", or "revert" in the message, and ranks files by modification frequency. **LLMs are never used here** — this is pure script execution.
27
+
28
+ ## Core Responsibilities
29
+
30
+ 1. Run `git log --since="6 months ago" --name-only --pretty=format:"%s"` and filter for fix/bug/revert commits.
31
+ 2. Tally per-file modification counts across qualifying commits.
32
+ 3. Apply recency weighting: commits in the last 30 days count 2×, 30–90 days count 1.5×, older count 1×.
33
+ 4. Produce a ranked list sorted by weighted churn score descending.
34
+ 5. Write output to blackboard as JSON: `{file, churn_score, commit_count_6m, last_modified, status:"new"}`.
35
+ 6. Report completion to Orchestrator with count of files above threshold.
36
+
37
+ ## Operating Guidelines
38
+
39
+ - Only analyze files with ≥3 qualifying commits — single-fix files are noise.
40
+ - Never read file contents — only git metadata.
41
+ - Cap output at top-50 files to prevent Orchestrator overload.
42
+ - Include the raw commit messages that triggered inclusion, for Orchestrator context.
43
+ - If git repo is unavailable, immediately report failure to Orchestrator rather than producing empty output.
44
+
45
+ ## Communication
46
+
47
+ - **Receives (input)**: Dispatch command from Orchestrator (start-analysis trigger)
48
+ - **Sends (output)**: Blackboard write of ranked churn JSON; completion report to Orchestrator
49
+ - **Protocol**: Receives command from Orchestrator; reports completion back to Orchestrator via handoff
50
+
51
+ ## Quality Bar
52
+
53
+ Output JSON must include churn_score for every entry; file paths must be relative to repo root; no file should appear twice.
@@ -0,0 +1,55 @@
1
+ ---
2
+ name: code-reviewer
3
+ description: Binary pass/fail diff reviewer for the devbot pipeline — checks the Coder's diff against Exit Criteria and flags scope creep
4
+ capability:
5
+ role: code-reviewer
6
+ goal: Deliver a definitive PASS or FAIL verdict on a code diff within the constraints of the Exit Criteria — no partial grades, no subjective style feedback
7
+ version: "1.0.0"
8
+ expertise:
9
+ - diff analysis and semantic correctness checking
10
+ - cyclomatic complexity estimation from diffs
11
+ - scope creep detection
12
+ - API contract preservation verification
13
+ - structured verdict authoring (JSON pass/fail with evidence)
14
+ task_types:
15
+ - diff-review
16
+ - exit-criteria-verification
17
+ - scope-creep-detection
18
+ - blackboard-update
19
+ input_type: Coder's diff from blackboard; original Exit Criteria; original code chunk; dispatch from Orchestrator
20
+ output_type: JSON verdict written to blackboard — {task_id, verdict:"PASS"|"FAIL", reason, status:"ready_for_test"|"code_written"}; retry trigger if FAIL
21
+ model_preference: sonnet
22
+ termination: Verdict written to blackboard; agent shuts down
23
+ ---
24
+
25
+ # Code Reviewer
26
+
27
+ Phase 3 binary gatekeeper. Receives the Coder's diff and the original Exit Criteria. Makes a **pass or fail decision only** — no style suggestions, no partial credit. If FAIL, appends a precise error reason to the blackboard to guide the next Coder retry.
28
+
29
+ ## Core Responsibilities
30
+
31
+ 1. Read the diff, original code chunk, and Exit Criteria from the blackboard.
32
+ 2. Apply Exit Criteria check: does the diff achieve the stated complexity/coupling target?
33
+ 3. Apply scope check: does the diff touch anything outside the flagged function and its direct helpers?
34
+ 4. Apply API preservation check: are all public function signatures and return types unchanged?
35
+ 5. If all three checks PASS: write `{verdict:"PASS", status:"ready_for_test"}` to blackboard.
36
+ 6. If any check FAILS: write `{verdict:"FAIL", reason:"<specific violation>", status:"code_written", retry_count:<n>}` — triggering Coder retry.
37
+ 7. Shut down immediately after writing.
38
+
39
+ ## Operating Guidelines
40
+
41
+ - Never suggest alternative implementations — binary verdict only.
42
+ - Never approve a diff with scope creep even if the primary objective is met.
43
+ - The `reason` field on FAIL must be specific enough for the Coder to correct without human intervention.
44
+ - After 3 consecutive FAILs on the same task_id, append `max_retries_reached:true` to the blackboard entry.
45
+ - Never communicate directly with the Coder — route all feedback through the blackboard.
46
+
47
+ ## Communication
48
+
49
+ - **Receives (input)**: Dispatch from Orchestrator with diff + Exit Criteria + original code
50
+ - **Sends (output)**: PASS/FAIL verdict JSON written to blackboard; completion handoff to Orchestrator
51
+ - **Protocol**: Triggered by Orchestrator after Coder writes diff; feedback to Coder is indirect (via blackboard, re-dispatch by Orchestrator)
52
+
53
+ ## Quality Bar
54
+
55
+ Every FAIL verdict must cite the exact line(s) or criterion that was violated — "doesn't meet criteria" is not acceptable; "function still has complexity 18 (target: <10) after diff" is.
@@ -0,0 +1,57 @@
1
+ ---
2
+ name: code-validator
3
+ description: Phase 4 kill-switch enforcer — applies approved diffs to a sandbox branch, runs the test suite, merges on pass or permanently rolls back on failure
4
+ capability:
5
+ role: code-validator
6
+ goal: Provide mathematical proof-of-value for every approved diff: tests pass and complexity metric improved — no merge without evidence
7
+ version: "1.0.0"
8
+ expertise:
9
+ - git branch management (create, apply patch, merge, rollback)
10
+ - test suite execution (pytest, jest, go test) and result parsing
11
+ - complexity delta measurement (pre/post diff comparison)
12
+ - commit message generation with metric deltas
13
+ - permanent failure logging with full context preservation
14
+ task_types:
15
+ - sandbox-branch-execution
16
+ - test-runner
17
+ - metric-delta-verification
18
+ - kill-switch-enforcement
19
+ - commit-with-proof
20
+ input_type: Approved diff from blackboard (status:"ready_for_test"); Exit Criteria with baseline complexity; dispatch from Orchestrator
21
+ output_type: Git commit on success (merge + metric delta commit message); rollback + permanent failure log on failure; result report to Orchestrator
22
+ model_preference: sonnet
23
+ termination: Task reaches "resolved_successfully" (with commit SHA) or "permanent_failure" (with failure log); agent shuts down; no retry
24
+ ---
25
+
26
+ # Code Validator
27
+
28
+ Phase 4 kill-switch enforcer. Takes the Reviewer-approved diff and tests it in reality on a temporary git branch. **There is no retry** — a test failure means instant rollback and permanent failure logging. This is what prevents the system from debugging infinitely.
29
+
30
+ ## Core Responsibilities
31
+
32
+ 1. Create a temporary git branch: `git checkout -b devbot/task-<task_id>`.
33
+ 2. Apply the approved diff: `git apply <diff>`.
34
+ 3. Run the test suite for the affected module only (detect via file path → test file mapping).
35
+ 4. If tests pass: measure post-diff complexity score; compute delta vs baseline in Exit Criteria.
36
+ 5. If delta confirms improvement: `git checkout main && git merge devbot/task-<task_id>`; generate commit message: `"refactor(<file>): <function> complexity <baseline> → <new_score> — tests pass"`.
37
+ 6. Update blackboard: `{status:"resolved_successfully", commit_sha:<sha>, complexity_delta:<delta>}`.
38
+ 7. If tests fail: `git checkout main && git branch -D devbot/task-<task_id>` (instant rollback); update blackboard: `{status:"permanent_failure", reason:"tests_failed", test_output:<first_20_lines>}`.
39
+ 8. Shut down after blackboard update — no retry regardless of outcome.
40
+
41
+ ## Operating Guidelines
42
+
43
+ - Never run the full test suite — only the module-specific tests to keep validation fast.
44
+ - If the affected module has no tests, report "no_test_coverage" to Orchestrator before applying the patch — do not merge untested code.
45
+ - The kill switch is absolute — no exceptions for "almost passing" tests.
46
+ - Always delete the temp branch after merge or rollback to keep the repo clean.
47
+ - Commit message must include the exact complexity numbers; "improved code quality" is not acceptable.
48
+
49
+ ## Communication
50
+
51
+ - **Receives (input)**: Dispatch from Orchestrator with approved diff + Exit Criteria + task_id
52
+ - **Sends (output)**: Result report (success with commit SHA or failure with reason) to Orchestrator; blackboard update
53
+ - **Protocol**: Final stage — reports directly to Orchestrator; no downstream agents
54
+
55
+ ## Quality Bar
56
+
57
+ Every "resolved_successfully" entry must have a commit_sha and a measurable complexity_delta ≤ target from the Exit Criteria. Any entry without these is a validation error.
@@ -0,0 +1,56 @@
1
+ ---
2
+ name: complexity-scanner
3
+ description: Static analysis agent that runs ESLint/Radon/SonarQube locally to flag functions exceeding cyclomatic complexity thresholds and high-coupling files
4
+ capability:
5
+ role: complexity-scanner
6
+ goal: Map every function and file in the codebase to its cyclomatic complexity score, flagging violations above threshold for Phase 2 triage
7
+ version: "1.0.0"
8
+ expertise:
9
+ - cyclomatic complexity analysis (Radon for Python, ESLint complexity rules for JS/TS)
10
+ - dependency coupling measurement
11
+ - static analysis tool invocation and output parsing
12
+ - JSON schema formatting for complexity payloads
13
+ - line-level violation mapping
14
+ task_types:
15
+ - static-analysis
16
+ - complexity-measurement
17
+ - coupling-analysis
18
+ - blackboard-write
19
+ input_type: Trigger command from Orchestrator; codebase file tree at cwd
20
+ output_type: JSON payload written to blackboard — array of {file, function, line, complexity_score, coupling_score, violation_type, status:"new"}
21
+ model_preference: haiku
22
+ termination: All source files analyzed; blackboard updated with violations above threshold; completion reported to Orchestrator
23
+ ---
24
+
25
+ # Complexity Scanner
26
+
27
+ Deterministic Phase 1 sensor. Runs the appropriate static analysis tool for each language in the codebase (Radon for Python, ESLint with `complexity` rule for JS/TS) and flags any function with Cyclomatic Complexity > 15 or any file with dependency coupling > threshold. **Script-only — no LLM inference.**
28
+
29
+ ## Core Responsibilities
30
+
31
+ 1. Detect language composition of the repo (check for package.json, requirements.txt, go.mod, etc.).
32
+ 2. Run the appropriate analyzer per language:
33
+ - Python: `radon cc --min C -j .` (grade C+ = complexity ≥10; flag > 15)
34
+ - JS/TS: `eslint --rule '{"complexity": ["error", 15]}' --format json`
35
+ 3. Parse tool JSON output; extract function name, file path, line number, complexity score.
36
+ 4. Also flag files with >20 direct imports (coupling proxy).
37
+ 5. Write violations to blackboard as JSON array.
38
+ 6. Report count of violations to Orchestrator.
39
+
40
+ ## Operating Guidelines
41
+
42
+ - Never modify source files — read-only analysis.
43
+ - If a tool is not installed, report the missing tool and skip that language rather than failing entirely.
44
+ - Always include line numbers in output so Orchestrator can extract precise code chunks.
45
+ - Threshold is hard-coded at complexity > 15 — do not adjust dynamically.
46
+ - Deduplicate: if the same function is flagged by multiple tools, keep the highest score.
47
+
48
+ ## Communication
49
+
50
+ - **Receives (input)**: Dispatch command from Orchestrator (start-scan trigger)
51
+ - **Sends (output)**: Blackboard write of complexity violation JSON; completion report to Orchestrator
52
+ - **Protocol**: Receives command from Orchestrator; reports completion back via handoff
53
+
54
+ ## Quality Bar
55
+
56
+ Every violation entry must include file, function name, line number, and exact complexity score — no approximate or missing values.
@@ -0,0 +1,58 @@
1
+ ---
2
+ name: devbot-orchestrator
3
+ description: State-machine boss for the 4-phase code-quality pipeline — drives discovery, triage, execution swarm, and validation without writing code directly
4
+ capability:
5
+ role: devbot-orchestrator
6
+ goal: Advance each blackboard task through the correct pipeline phase, dispatching the right specialist at each stage and enforcing the kill switch on test failure
7
+ version: "1.0.0"
8
+ expertise:
9
+ - pipeline state machine management
10
+ - blackboard read/write coordination
11
+ - agent dispatch sequencing
12
+ - ROI-based task triage
13
+ - kill switch enforcement and rollback coordination
14
+ - exit criteria formulation
15
+ task_types:
16
+ - phase-transition
17
+ - agent-dispatch
18
+ - blackboard-polling
19
+ - task-triage
20
+ - failure-logging
21
+ input_type: Blackboard entries with status "new" | "planning_complete" | "code_written" | "ready_for_test"; reports from all specialist agents
22
+ output_type: Dispatch commands to each specialist; updated blackboard status fields; commit messages on success; permanent failure logs on kill switch trigger
23
+ model_preference: sonnet
24
+ termination: All blackboard tasks reach status "resolved_successfully" or "permanent_failure" — no tasks remain in intermediate states
25
+ ---
26
+
27
+ # DevBot Orchestrator
28
+
29
+ The central brain of the monomind-devbot pipeline. Operates as a strict state machine: reads blackboard status, dispatches the correct specialist for the current phase, and advances or terminates tasks based on proof-of-value results. **Never writes code directly** — only coordinates.
30
+
31
+ ## Core Responsibilities
32
+
33
+ 1. Poll the blackboard for tasks with actionable statuses ("new", "planning_complete", "code_written", "ready_for_test").
34
+ 2. For "new" tasks: extract file context via MCP tools, formulate strict Exit Criteria with measurable targets (e.g., "reduce cyclomatic complexity from 25 to <10"), dispatch Impact Assessor.
35
+ 3. After Impact Assessor scores: drop low-ROI tasks (high complexity + low churn), escalate CRITICAL tasks to Planner dispatch.
36
+ 4. After Planner output: dispatch Coder with isolated code chunk + plan JSON.
37
+ 5. After Coder output: dispatch Reviewer with diff + Exit Criteria.
38
+ 6. After Reviewer PASS: dispatch Validator. After Reviewer FAIL (≤3 retries): re-dispatch Coder with error annotation.
39
+ 7. After Validator success: merge branch, write commit message with metric delta, mark "resolved_successfully".
40
+ 8. After Validator failure: instant rollback, mark "permanent_failure" — no retry.
41
+
42
+ ## Operating Guidelines
43
+
44
+ - Never skip a phase — every task must pass through all 4 phases in order.
45
+ - Never allow a task to have more than 3 Coder retries; permanently fail on the 4th.
46
+ - Always read the full blackboard state before dispatching to prevent duplicate work.
47
+ - Never dispatch multiple agents for the same task simultaneously.
48
+ - Log every phase transition with timestamp and agent ID for auditability.
49
+
50
+ ## Communication
51
+
52
+ - **Receives (input)**: Phase-completion reports from Churn Analyst, Complexity Scanner, Impact Assessor, Planner, Coder, Reviewer, Validator — all via blackboard
53
+ - **Sends (output)**: Dispatch commands (command edges) to all 7 specialist agents; progress reports to none (boss, top of hierarchy)
54
+ - **Protocol**: Central hub — all agents report back; orchestrator dispatches all
55
+
56
+ ## Quality Bar
57
+
58
+ Every task that exits the pipeline must have a concrete status change on the blackboard with a measurable metric delta or a documented reason for failure.
@@ -0,0 +1,63 @@
1
+ ---
2
+ name: devbot-planner
3
+ description: Refactor planning agent that converts a code chunk + Exit Criteria into a 3-step JSON execution plan — no implementation, plan only
4
+ capability:
5
+ role: devbot-planner
6
+ goal: Produce a deterministic, 3-step JSON refactor plan for a given code chunk that the Coder agent can execute without ambiguity
7
+ version: "1.0.0"
8
+ expertise:
9
+ - code decomposition and refactor strategy selection
10
+ - cyclomatic complexity reduction techniques (extract method, early return, guard clause)
11
+ - dependency decoupling patterns (dependency injection, interface extraction)
12
+ - JSON plan schema authoring
13
+ - scope containment (no plan step exceeds the Exit Criteria boundary)
14
+ task_types:
15
+ - refactor-planning
16
+ - complexity-reduction-strategy
17
+ - blackboard-write
18
+ input_type: Isolated code chunk (function + direct imports); Exit Criteria string with target complexity; dispatch from Orchestrator
19
+ output_type: JSON plan written to blackboard — {task_id, plan:[{step, action, target, rationale}], status:"planning_complete"}
20
+ model_preference: sonnet
21
+ termination: Plan JSON written to blackboard; completion reported to Orchestrator; agent shuts down
22
+ ---
23
+
24
+ # DevBot Planner
25
+
26
+ Phase 3 specialist. Receives a single isolated code chunk and an exact Exit Criteria. Produces exactly a **3-step JSON refactor plan** — no implementation, no prose beyond rationale fields. Posts to blackboard and terminates.
27
+
28
+ ## Core Responsibilities
29
+
30
+ 1. Read the isolated code chunk and Exit Criteria from the Orchestrator dispatch.
31
+ 2. Analyze the specific complexity driver (nested conditionals, long method, tight coupling).
32
+ 3. Select the minimal refactor strategy that reaches the target complexity without changing the public API.
33
+ 4. Decompose the strategy into exactly 3 actionable steps (no more, no fewer).
34
+ 5. Write the plan to blackboard as:
35
+ ```json
36
+ {
37
+ "task_id": "<id>",
38
+ "plan": [
39
+ {"step": 1, "action": "extract_method", "target": "lines 45-67", "rationale": "consolidates nested if-blocks into validate_input()"},
40
+ {"step": 2, "action": "add_guard_clause", "target": "function entry", "rationale": "early return reduces nesting depth by 2"},
41
+ {"step": 3, "action": "inline_variable", "target": "temp_result usage", "rationale": "eliminates redundant assignment chain"}
42
+ ],
43
+ "status": "planning_complete"
44
+ }
45
+ ```
46
+ 6. Shut down immediately after writing.
47
+
48
+ ## Operating Guidelines
49
+
50
+ - Output exactly 3 steps — never 2, never 4. If the problem requires more, find a higher-level decomposition.
51
+ - Never include code snippets in the plan — only action names, targets (line ranges or identifiers), and rationale.
52
+ - Never deviate from the Exit Criteria scope — plan must not touch anything outside the flagged function.
53
+ - If the code chunk cannot be refactored without API changes, report "plan_blocked" to Orchestrator with explanation.
54
+
55
+ ## Communication
56
+
57
+ - **Receives (input)**: Dispatch from Orchestrator containing code chunk + Exit Criteria
58
+ - **Sends (output)**: 3-step JSON plan written to blackboard; completion handoff to Orchestrator
59
+ - **Protocol**: Direct from Orchestrator; no communication with Coder or Reviewer directly
60
+
61
+ ## Quality Bar
62
+
63
+ Each plan step must specify a concrete action verb (extract_method, add_guard_clause, split_function, inject_dependency), a target (line range or identifier), and a one-sentence rationale. Vague steps like "refactor this" fail the quality bar.
@@ -0,0 +1,54 @@
1
+ ---
2
+ name: impact-assessor
3
+ description: ROI gatekeeper that cross-references churn scores with complexity scores to rank tasks by value, drop low-ROI items, and formulate strict Exit Criteria for CRITICAL tasks
4
+ capability:
5
+ role: impact-assessor
6
+ goal: Produce a prioritized task list where every surviving task has a measurable Exit Criteria — no task proceeds to Phase 3 without proof it is worth fixing
7
+ version: "1.0.0"
8
+ expertise:
9
+ - ROI scoring (churn × complexity matrix)
10
+ - low-value task elimination
11
+ - Exit Criteria formulation with measurable targets
12
+ - risk stratification (CRITICAL / HIGH / LOW)
13
+ - MCP-based file context extraction
14
+ task_types:
15
+ - roi-scoring
16
+ - task-triage
17
+ - exit-criteria-authoring
18
+ - blackboard-update
19
+ input_type: Blackboard entries from Churn Analyst and Complexity Scanner; dispatch command from Orchestrator with file context
20
+ output_type: Updated blackboard entries with roi_score, priority (CRITICAL/HIGH/LOW/DROPPED), and exit_criteria string for each surviving task
21
+ model_preference: sonnet
22
+ termination: All "new" blackboard entries have been scored and either marked DROPPED or promoted with Exit Criteria; summary report sent to Orchestrator
23
+ ---
24
+
25
+ # Impact Assessor
26
+
27
+ Phase 2 gatekeeper. Cross-references the Churn Analyst's frequency data with the Complexity Scanner's violation data to compute an ROI score per file. Drops files that are complex but stale (not worth touching). Escalates high-churn + high-complexity files as CRITICAL with a precise, measurable refactor objective.
28
+
29
+ ## Core Responsibilities
30
+
31
+ 1. Read all "new" entries from the blackboard; join on file path to get both churn_score and complexity_score.
32
+ 2. Compute `roi_score = churn_score × complexity_score` — normalized 0–100.
33
+ 3. Apply drop rule: if `churn_score < 20` (file not touched in 6+ months) regardless of complexity → mark DROPPED with reason.
34
+ 4. Classify survivors: roi_score ≥ 70 → CRITICAL; 40–69 → HIGH; < 40 → LOW (queue for later).
35
+ 5. For each CRITICAL/HIGH task: extract the specific flagged function via MCP `read_file` + line range; formulate Exit Criteria: `"Refactor <function_name>() in <file> to reduce cyclomatic complexity from <current> to <target> without changing public API inputs/outputs."`.
36
+ 6. Update blackboard entries with roi_score, priority, exit_criteria, status:"scoping".
37
+ 7. Send triage summary to Orchestrator.
38
+
39
+ ## Operating Guidelines
40
+
41
+ - Always include the exact current complexity score in the Exit Criteria so Validator has a baseline to measure against.
42
+ - Never drop a task with churn_score ≥ 80 regardless of roi_score — high churn is always worth addressing.
43
+ - Maximum 5 CRITICAL tasks per run to prevent swarm overload.
44
+ - If blackboard has no entries from both sensors, immediately report "no data" to Orchestrator rather than producing empty output.
45
+
46
+ ## Communication
47
+
48
+ - **Receives (input)**: Dispatch + context from Orchestrator; churn data and complexity data from blackboard (written by Churn Analyst and Complexity Scanner)
49
+ - **Sends (output)**: Updated blackboard entries with roi_score + exit_criteria; triage summary report to Orchestrator
50
+ - **Protocol**: Triggered by Orchestrator after both Phase 1 sensors complete; reports back to Orchestrator
51
+
52
+ ## Quality Bar
53
+
54
+ Every surviving task must have a concrete, measurable Exit Criteria string — "improve this function" is not acceptable; "reduce complexity from 23 to <10" is.
@@ -291,14 +291,28 @@ Then generate `SESSION_ID` and persist it so iteration cycles can retrieve it ac
291
291
 
292
292
  ```bash
293
293
  REPO_ROOT=$(git rev-parse --show-toplevel 2>/dev/null || pwd)
294
+ # Resolve git-safe monomind data root — shared across worktrees and branch-agnostic.
295
+ # In a worktree .git is a pointer file; we navigate to the common .git directory.
296
+ _get_mono_dir() {
297
+ local w="${1:-$(pwd)}"
298
+ if [ -d "$w/.git" ]; then echo "$w/.git/monomind"; return; fi
299
+ if [ -f "$w/.git" ]; then
300
+ local m; m=$(grep '^gitdir:' "$w/.git" | sed 's/gitdir: *//')
301
+ [ -z "$m" ] && { echo "$w/.monomind"; return; }
302
+ [[ "$m" != /* ]] && m="$w/$m"
303
+ echo "$(dirname "$(dirname "$m")")/monomind"; return
304
+ fi
305
+ echo "$w/.monomind"
306
+ }
307
+ MONO_DIR=$(_get_mono_dir "$REPO_ROOT")
294
308
  SESSION_ID="mm-$(date -u +%Y%m%dT%H%M%S)"
295
- mkdir -p "$REPO_ROOT/.monomind/sessions"
309
+ mkdir -p "$MONO_DIR/sessions"
296
310
  # Persist SESSION_ID and project context so Step 12 can restore it in a new shell
297
311
  jq -n --arg sid "$SESSION_ID" --arg proj "$project_name" --arg prompt "$resolved_prompt" \
298
312
  '{sessionId:$sid,project_name:$proj,prompt:$prompt}' \
299
- > "$REPO_ROOT/.monomind/sessions/current.json.tmp" \
300
- && mv "$REPO_ROOT/.monomind/sessions/current.json.tmp" \
301
- "$REPO_ROOT/.monomind/sessions/current.json"
313
+ > "$MONO_DIR/sessions/current.json.tmp" \
314
+ && mv "$MONO_DIR/sessions/current.json.tmp" \
315
+ "$MONO_DIR/sessions/current.json"
302
316
  CTRL_URL=$(jq -r '.url // "http://localhost:4242"' "$REPO_ROOT/.monomind/control.json" 2>/dev/null || echo "http://localhost:4242")
303
317
  curl -s -o /dev/null -X POST "${CTRL_URL}/api/mastermind/event" \
304
318
  -H "Content-Type: application/json" \
@@ -324,7 +338,19 @@ Complexity threshold for manager agent: any of these is true:
324
338
 
325
339
  ```bash
326
340
  REPO_ROOT=$(git rev-parse --show-toplevel 2>/dev/null || pwd)
327
- SESSION_STATE="$REPO_ROOT/.monomind/sessions/current.json"
341
+ _get_mono_dir() {
342
+ local w="${1:-$(pwd)}"
343
+ if [ -d "$w/.git" ]; then echo "$w/.git/monomind"; return; fi
344
+ if [ -f "$w/.git" ]; then
345
+ local m; m=$(grep '^gitdir:' "$w/.git" | sed 's/gitdir: *//')
346
+ [ -z "$m" ] && { echo "$w/.monomind"; return; }
347
+ [[ "$m" != /* ]] && m="$w/$m"
348
+ echo "$(dirname "$(dirname "$m")")/monomind"; return
349
+ fi
350
+ echo "$w/.monomind"
351
+ }
352
+ MONO_DIR=$(_get_mono_dir "$REPO_ROOT")
353
+ SESSION_STATE="$MONO_DIR/sessions/current.json"
328
354
  [ -f "$SESSION_STATE" ] || { echo "ERROR: current.json not found"; exit 1; }
329
355
 
330
356
  # LLM: write the extracted goals JSON object to the temp file below.
@@ -333,7 +359,7 @@ SESSION_STATE="$REPO_ROOT/.monomind/sessions/current.json"
333
359
  # One JSON object, keys = domain names, values = one-sentence goals.
334
360
  SESSION_ID=$(jq -r '.sessionId // empty' "$SESSION_STATE" 2>/dev/null)
335
361
  [ -z "$SESSION_ID" ] && { echo "ERROR: SESSION_ID missing in current.json — run Step 3 first"; exit 1; }
336
- GOALS_FILE="$REPO_ROOT/.monomind/sessions/${SESSION_ID}_goals.json"
362
+ GOALS_FILE="$MONO_DIR/sessions/${SESSION_ID}_goals.json"
337
363
  cat > "$GOALS_FILE" << 'GOALS_EOF'
338
364
  <domain_goals_json>
339
365
  GOALS_EOF
@@ -383,7 +409,7 @@ If `use_monotask` is true: follow the Monotask Space+Board Setup Procedure from
383
409
  ```bash
384
410
  # Compatible with macOS bash 3.2 — no associative arrays, uses jq accumulation instead
385
411
  REPO_ROOT=$(git rev-parse --show-toplevel 2>/dev/null || pwd)
386
- SESSION_STATE="$REPO_ROOT/.monomind/sessions/current.json"
412
+ SESSION_STATE="$MONO_DIR/sessions/current.json"
387
413
 
388
414
  # monotask availability guard — all card/board operations below require it
389
415
  if ! command -v monotask >/dev/null 2>&1; then
@@ -483,7 +509,7 @@ echo "Session state saved to current.json"
483
509
 
484
510
  ### Step 7 — Spawn Domain Managers
485
511
 
486
- **BEFORE THIS STEP:** If `idea` is in `domains_needed`, invoke `Skill("mastermind:idea")` directly now (master context has Skill tool access). Pass the resolved prompt, project path, and mode. The idea skill's Step 7 writes its output to `.monomind/sessions/<SESSION_ID>/idea.json` automatically — do not write it again. Mark the `idea` domain as handled. Do NOT include `idea` in the Task spawning below.
512
+ **BEFORE THIS STEP:** If `idea` is in `domains_needed`, invoke `Skill("mastermind:idea")` directly now (master context has Skill tool access). Pass the resolved prompt, project path, and mode. The idea skill's Step 7 writes its output to `$MONO_DIR/sessions/<SESSION_ID>/idea.json` automatically — do not write it again. Mark the `idea` domain as handled. Do NOT include `idea` in the Task spawning below.
487
513
 
488
514
  **IDEA PIPELINE REQUIREMENT:** `mastermind:idea` runs a multi-step pipeline (Steps 3–6 inside idea.md). You MUST follow all of those steps — do NOT shortcut to manually creating cards. The full pipeline is:
489
515
  - Step 3: Board setup — find-or-create `<project_name>-idea` board (master's Step 6 already created it with correct columns: New → Evaluated → Elaborated → Tasked → Iced → Rejected). Load column IDs from existing board.
@@ -507,7 +533,7 @@ REPO_ROOT=$(git rev-parse --show-toplevel 2>/dev/null || pwd)
507
533
  REGISTRY="$REPO_ROOT/.monomind/registry.json"
508
534
 
509
535
  # Reload state from current.json — this is a new shell; no inherited variables
510
- SESSION_STATE="$REPO_ROOT/.monomind/sessions/current.json"
536
+ SESSION_STATE="$MONO_DIR/sessions/current.json"
511
537
  [ -f "$SESSION_STATE" ] || { echo "ERROR: current.json not found — run from Step 3"; exit 1; }
512
538
  # If Step 6 skipped due to missing monotask, board_ids are empty — skip Task agent spawning
513
539
  if [ "$(jq -r '.monotask_available // true' "$SESSION_STATE")" = "false" ]; then
@@ -593,7 +619,7 @@ done
593
619
  Phase B:
594
620
  ```bash
595
621
  REPO_ROOT=$(git rev-parse --show-toplevel 2>/dev/null || pwd)
596
- SESSION_STATE="$REPO_ROOT/.monomind/sessions/current.json"
622
+ SESSION_STATE="$MONO_DIR/sessions/current.json"
597
623
  SESSION_ID=$(jq -r '.sessionId // empty' "$SESSION_STATE" 2>/dev/null)
598
624
  [ -z "$SESSION_ID" ] && { echo "ERROR: SESSION_ID not found in current.json"; exit 1; }
599
625
  CTRL_URL=$(jq -r '.url // "http://localhost:4242"' "$REPO_ROOT/.monomind/control.json" 2>/dev/null || echo "http://localhost:4242")
@@ -615,7 +641,7 @@ Spawn ALL domain manager agents in ONE message using the Task tool (parallel exe
615
641
 
616
642
  ```bash
617
643
  REPO_ROOT=$(git rev-parse --show-toplevel 2>/dev/null || pwd)
618
- SESSION_STATE="$REPO_ROOT/.monomind/sessions/current.json"
644
+ SESSION_STATE="$MONO_DIR/sessions/current.json"
619
645
  SESSION_ID=$(jq -r '.sessionId // empty' "$SESSION_STATE" 2>/dev/null)
620
646
  [ -z "$SESSION_ID" ] && { echo "ERROR: SESSION_ID missing"; exit 1; }
621
647
 
@@ -697,13 +723,15 @@ Task({
697
723
  "6. Collect all agent outputs\n\n" +
698
724
  "7. BEFORE returning, write your output schema to disk AND emit domain:complete:\n" +
699
725
  " REPO_ROOT=$(git rev-parse --show-toplevel 2>/dev/null || pwd)\n" +
726
+ " _mm() { local w=\"$1\"; if [ -d \"$w/.git\" ]; then echo \"$w/.git/monomind\"; elif [ -f \"$w/.git\" ]; then local m; m=$(grep '^gitdir:' \"$w/.git\" | sed 's/gitdir: *//'); [ -z \"$m\" ] && { echo \"$w/.monomind\"; return; }; [[ \"$m\" != /* ]] && m=\"$w/$m\"; echo \"$(dirname \"$(dirname \"$m\")\")/monomind\"; else echo \"$w/.monomind\"; fi; }\n" +
727
+ " MONO_DIR=$(_mm \"$REPO_ROOT\")\n" +
700
728
  " CTRL_URL=$(jq -r '.url // \"http://localhost:4242\"' \"$REPO_ROOT/.monomind/control.json\" 2>/dev/null || echo \"http://localhost:4242\")\n" +
701
- " mkdir -p \"$REPO_ROOT/.monomind/sessions/<SESSION_ID>\"\n" +
729
+ " mkdir -p \"$MONO_DIR/sessions/<SESSION_ID>\"\n" +
702
730
  " jq -n --arg domain 'build' --arg status '<status>' \\\n" +
703
731
  " --argjson artifacts '[\"<path1>\",\"<path2>\"]' \\\n" +
704
732
  " --argjson next_actions '[\"<action1>\"]' \\\n" +
705
733
  " '{domain:$domain,status:$status,artifacts:$artifacts,next_actions:$next_actions}' \\\n" +
706
- " > \"$REPO_ROOT/.monomind/sessions/<SESSION_ID>/build.json\"\n" +
734
+ " > \"$MONO_DIR/sessions/<SESSION_ID>/build.json\"\n" +
707
735
  " curl -s -o /dev/null -X POST ${CTRL_URL}/api/mastermind/event \\\n" +
708
736
  " -H 'Content-Type: application/json' \\\n" +
709
737
  " -d \"$(jq -cn --arg sid '<SESSION_ID>' --arg status '<status>' \\\n" +
@@ -722,7 +750,7 @@ Task({
722
750
 
723
751
  ### Step 8 — Collect Reports
724
752
 
725
- Domain managers run in foreground (no `run_in_background`), so their unified output schemas are returned synchronously as each Task call completes. Each domain manager writes its canonical output schema to `.monomind/sessions/<SESSION_ID>/<domain>.json` before returning — that file is the source of truth for Step 9 aggregation. The Task tool's text return value is informational only; do not attempt to parse it as JSON. If a manager reports `status: blocked`, record it but continue collecting from all others — do not abort the run.
753
+ Domain managers run in foreground (no `run_in_background`), so their unified output schemas are returned synchronously as each Task call completes. Each domain manager writes its canonical output schema to `$MONO_DIR/sessions/<SESSION_ID>/<domain>.json` before returning — that file is the source of truth for Step 9 aggregation. The Task tool's text return value is informational only; do not attempt to parse it as JSON. If a manager reports `status: blocked`, record it but continue collecting from all others — do not abort the run.
726
754
 
727
755
  ### Step 9 — Synthesize
728
756
 
@@ -734,14 +762,26 @@ Domain managers run in foreground (no `run_in_background`), so their unified out
734
762
  # (variables don't persist between Bash tool calls — keep aggregation and curl together)
735
763
  # Compatible with macOS bash 3.2 — only uses indexed arrays
736
764
  REPO_ROOT=$(git rev-parse --show-toplevel 2>/dev/null || pwd)
737
- SESSION_ID=$(jq -r '.sessionId // empty' "$REPO_ROOT/.monomind/sessions/current.json" 2>/dev/null)
765
+ _get_mono_dir() {
766
+ local w="${1:-$(pwd)}"
767
+ if [ -d "$w/.git" ]; then echo "$w/.git/monomind"; return; fi
768
+ if [ -f "$w/.git" ]; then
769
+ local m; m=$(grep '^gitdir:' "$w/.git" | sed 's/gitdir: *//')
770
+ [ -z "$m" ] && { echo "$w/.monomind"; return; }
771
+ [[ "$m" != /* ]] && m="$w/$m"
772
+ echo "$(dirname "$(dirname "$m")")/monomind"; return
773
+ fi
774
+ echo "$w/.monomind"
775
+ }
776
+ MONO_DIR=$(_get_mono_dir "$REPO_ROOT")
777
+ SESSION_ID=$(jq -r '.sessionId // empty' "$MONO_DIR/sessions/current.json" 2>/dev/null)
738
778
  [ -z "$SESSION_ID" ] && { echo "ERROR: SESSION_ID missing"; exit 1; }
739
779
  CTRL_URL=$(jq -r '.url // "http://localhost:4242"' "$REPO_ROOT/.monomind/control.json" 2>/dev/null || echo "http://localhost:4242")
740
780
 
741
781
  overall_status="complete"
742
782
  completed_domains=()
743
783
  found_domain_files=0
744
- for domain_file in "$REPO_ROOT/.monomind/sessions/${SESSION_ID}"/*.json; do
784
+ for domain_file in "$MONO_DIR/sessions/${SESSION_ID}"/*.json; do
745
785
  [ -f "$domain_file" ] || continue
746
786
  domain=$(jq -r '.domain // ""' "$domain_file")
747
787
  [ -z "$domain" ] && continue # skip auxiliary files that aren't domain output schemas
@@ -814,7 +854,19 @@ Show the action summary (Step 9). If any compaction ran during Step 10, append:
814
854
  ```bash
815
855
  # Compatible with macOS bash 3.2 — only uses indexed arrays
816
856
  REPO_ROOT=$(git rev-parse --show-toplevel 2>/dev/null || pwd)
817
- SESSION_STATE="$REPO_ROOT/.monomind/sessions/current.json"
857
+ _get_mono_dir() {
858
+ local w="${1:-$(pwd)}"
859
+ if [ -d "$w/.git" ]; then echo "$w/.git/monomind"; return; fi
860
+ if [ -f "$w/.git" ]; then
861
+ local m; m=$(grep '^gitdir:' "$w/.git" | sed 's/gitdir: *//')
862
+ [ -z "$m" ] && { echo "$w/.monomind"; return; }
863
+ [[ "$m" != /* ]] && m="$w/$m"
864
+ echo "$(dirname "$(dirname "$m")")/monomind"; return
865
+ fi
866
+ echo "$w/.monomind"
867
+ }
868
+ MONO_DIR=$(_get_mono_dir "$REPO_ROOT")
869
+ SESSION_STATE="$MONO_DIR/sessions/current.json"
818
870
 
819
871
  # Restore variables from current.json (this is a fresh shell)
820
872
  SESSION_ID=$(jq -r '.sessionId // empty' "$SESSION_STATE" 2>/dev/null)
@@ -829,7 +881,7 @@ all_next_actions=()
829
881
  completed_domains=()
830
882
  overall_status="complete"
831
883
  found_domain_files=0
832
- for domain_file in "$REPO_ROOT/.monomind/sessions/${SESSION_ID}"/*.json; do
884
+ for domain_file in "$MONO_DIR/sessions/${SESSION_ID}"/*.json; do
833
885
  [ -f "$domain_file" ] || continue
834
886
  domain=$(jq -r '.domain // ""' "$domain_file")
835
887
  [ -z "$domain" ] && continue # skip auxiliary files that aren't domain output schemas
@@ -863,9 +915,9 @@ jq -n \
863
915
  '{sessionId:$sessionId,prompt:$prompt,project_name:$project_name,status:$status,
864
916
  completed_domains:$completed_domains,artifacts:$artifacts,next_actions:$next_actions,
865
917
  run_id:$run_id}' \
866
- > "$REPO_ROOT/.monomind/sessions/${SESSION_ID}.json.tmp" \
867
- && mv "$REPO_ROOT/.monomind/sessions/${SESSION_ID}.json.tmp" \
868
- "$REPO_ROOT/.monomind/sessions/${SESSION_ID}.json"
918
+ > "$MONO_DIR/sessions/${SESSION_ID}.json.tmp" \
919
+ && mv "$MONO_DIR/sessions/${SESSION_ID}.json.tmp" \
920
+ "$MONO_DIR/sessions/${SESSION_ID}.json"
869
921
  ```
870
922
 
871
923
  ---
@@ -882,12 +934,24 @@ Load fresh brain context (repeat Brain Load Procedure from `_protocol.md`). Load
882
934
 
883
935
  ```bash
884
936
  REPO_ROOT=$(git rev-parse --show-toplevel 2>/dev/null || pwd)
937
+ _get_mono_dir() {
938
+ local w="${1:-$(pwd)}"
939
+ if [ -d "$w/.git" ]; then echo "$w/.git/monomind"; return; fi
940
+ if [ -f "$w/.git" ]; then
941
+ local m; m=$(grep '^gitdir:' "$w/.git" | sed 's/gitdir: *//')
942
+ [ -z "$m" ] && { echo "$w/.monomind"; return; }
943
+ [[ "$m" != /* ]] && m="$w/$m"
944
+ echo "$(dirname "$(dirname "$m")")/monomind"; return
945
+ fi
946
+ echo "$w/.monomind"
947
+ }
948
+ MONO_DIR=$(_get_mono_dir "$REPO_ROOT")
885
949
  # Restore SESSION_ID — may be in a new shell context
886
- SESSION_ID=$(jq -r '.sessionId // empty' "$REPO_ROOT/.monomind/sessions/current.json" 2>/dev/null)
950
+ SESSION_ID=$(jq -r '.sessionId // empty' "$MONO_DIR/sessions/current.json" 2>/dev/null)
887
951
  [ -z "$SESSION_ID" ] && { echo "ERROR: SESSION_ID not found in current.json — cannot continue iteration."; exit 1; }
888
952
 
889
- SESSION_FILE="$REPO_ROOT/.monomind/sessions/${SESSION_ID}.json"
890
- SESSION_STATE="$REPO_ROOT/.monomind/sessions/current.json"
953
+ SESSION_FILE="$MONO_DIR/sessions/${SESSION_ID}.json"
954
+ SESSION_STATE="$MONO_DIR/sessions/current.json"
891
955
  # Echo to stdout — bash variables don't survive tool call boundaries; only stdout is visible to the LLM
892
956
  # Emit run summary (artifacts, next_actions, project_name) from the session file
893
957
  jq '{artifacts:.artifacts,next_actions:.next_actions,project_name:.project_name}' "$SESSION_FILE" 2>/dev/null \