agent-composer 0.1.15 → 0.2.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 (42) hide show
  1. package/README.md +98 -15
  2. package/composer.config.schema.json +24 -1
  3. package/dist/cli/dispatch-hint.d.ts +2 -0
  4. package/dist/cli/dispatch-hint.js +63 -0
  5. package/dist/cli/dispatch-hint.js.map +1 -0
  6. package/dist/cli/init.js +41 -2
  7. package/dist/cli/init.js.map +1 -1
  8. package/dist/cli/install-plugin.d.ts +3 -2
  9. package/dist/cli/install-plugin.js +34 -10
  10. package/dist/cli/install-plugin.js.map +1 -1
  11. package/dist/config/schema.d.ts +44 -0
  12. package/dist/config/schema.js +12 -1
  13. package/dist/config/schema.js.map +1 -1
  14. package/dist/index.js +1 -1
  15. package/dist/index.js.map +1 -1
  16. package/dist/providers/CLIProvider.d.ts +16 -0
  17. package/dist/providers/CLIProvider.js +117 -3
  18. package/dist/providers/CLIProvider.js.map +1 -1
  19. package/dist/providers/IProvider.d.ts +1 -0
  20. package/dist/registry.js +4 -0
  21. package/dist/registry.js.map +1 -1
  22. package/dist/server.d.ts +6 -1
  23. package/dist/server.js +129 -15
  24. package/dist/server.js.map +1 -1
  25. package/dist/util/dispatchHint.d.ts +50 -0
  26. package/dist/util/dispatchHint.js +262 -0
  27. package/dist/util/dispatchHint.js.map +1 -0
  28. package/dist/util/handoff.d.ts +58 -0
  29. package/dist/util/handoff.js +107 -0
  30. package/dist/util/handoff.js.map +1 -0
  31. package/dist/util/projectToolResult.d.ts +13 -0
  32. package/dist/util/projectToolResult.js +169 -0
  33. package/dist/util/projectToolResult.js.map +1 -0
  34. package/package.json +3 -2
  35. package/plugin/composer-mastermind/README.md +24 -6
  36. package/plugin/composer-mastermind/agents/coder.md +7 -7
  37. package/plugin/composer-mastermind/agents/reviewer-claude.md +31 -0
  38. package/plugin/composer-mastermind/hooks/boundary_guard.sh +35 -5
  39. package/plugin/composer-mastermind/hooks/learn.sh +23 -0
  40. package/plugin/composer-mastermind/hooks/lint-on-save.sh +25 -1
  41. package/plugin/composer-mastermind/plugin.json +3 -2
  42. package/plugin/composer-mastermind/skills/composer-mastermind/SKILL.md +49 -19
@@ -0,0 +1,169 @@
1
+ const DEFAULT_MAX_CHARS = 16_000;
2
+ const PROJECTED_MARKER = /(?:^|\n)… \[elided \d+ chars \/ \d+ lines\] …(?:\n|$)/;
3
+ const JSON_PREFIX = "[projected JSON:";
4
+ const LOG_LINE = /^(?:\s*(?:PASS\b|FAIL\b|✓|✗|Error\b)|[^:\n]+:\d+:\d+\b|\s+at [^\n]+:\d+(?::\d+)?\b)/;
5
+ export function projectToolResult(input, opts = {}) {
6
+ if (typeof input !== "string") {
7
+ throw new Error("projectToolResult: input must be a string");
8
+ }
9
+ const options = normalizeOptions(opts);
10
+ const kind = detectKind(input);
11
+ if (input.length === 0 || input.length <= options.maxChars || isAlreadyProjected(input)) {
12
+ return {
13
+ text: input,
14
+ projected: false,
15
+ originalChars: input.length,
16
+ keptChars: input.length,
17
+ kind,
18
+ };
19
+ }
20
+ const text = kind === "json"
21
+ ? projectJson(input, options.maxChars)
22
+ : projectText(input, options.headChars, options.tailChars);
23
+ return {
24
+ text,
25
+ projected: true,
26
+ originalChars: input.length,
27
+ keptChars: text.length,
28
+ kind,
29
+ };
30
+ }
31
+ function normalizeOptions(opts) {
32
+ const maxChars = normalizeLimit("maxChars", opts.maxChars, DEFAULT_MAX_CHARS);
33
+ const defaultHeadChars = Math.round(maxChars * 0.6);
34
+ const defaultTailChars = Math.round(maxChars * 0.25);
35
+ const headChars = normalizeLimit("headChars", opts.headChars, defaultHeadChars, true);
36
+ const tailChars = normalizeLimit("tailChars", opts.tailChars, defaultTailChars, true);
37
+ return { maxChars, headChars, tailChars };
38
+ }
39
+ function normalizeLimit(name, value, fallback, allowZero = false) {
40
+ const raw = value ?? fallback;
41
+ if (raw === Number.POSITIVE_INFINITY)
42
+ return Number.MAX_SAFE_INTEGER;
43
+ if (!Number.isFinite(raw)) {
44
+ throw new Error(`projectToolResult: ${name} must be a finite number`);
45
+ }
46
+ const rounded = Math.round(raw);
47
+ if (rounded < 0 || (!allowZero && rounded === 0)) {
48
+ const expectation = allowZero ? "non-negative" : "positive";
49
+ throw new Error(`projectToolResult: ${name} must be ${expectation}`);
50
+ }
51
+ return rounded;
52
+ }
53
+ function isAlreadyProjected(input) {
54
+ return input.startsWith(JSON_PREFIX) || PROJECTED_MARKER.test(input);
55
+ }
56
+ function detectKind(input) {
57
+ const trimmed = input.trim();
58
+ if (trimmed.length > 0 && (trimmed.startsWith("{") || trimmed.startsWith("["))) {
59
+ try {
60
+ JSON.parse(trimmed);
61
+ return "json";
62
+ }
63
+ catch {
64
+ // Invalid JSON still falls through to text heuristics.
65
+ }
66
+ }
67
+ if (looksLikeDiff(input))
68
+ return "diff";
69
+ if (looksLikeLog(input))
70
+ return "log";
71
+ return "generic";
72
+ }
73
+ function looksLikeDiff(input) {
74
+ if (/^diff --git /m.test(input) || /^@@ /m.test(input))
75
+ return true;
76
+ const plusMinusLines = input
77
+ .split("\n")
78
+ .filter((line) => /^[+-]/.test(line)).length;
79
+ return plusMinusLines >= 6;
80
+ }
81
+ function looksLikeLog(input) {
82
+ return input.split("\n").some((line) => LOG_LINE.test(line));
83
+ }
84
+ function projectText(input, headChars, tailChars) {
85
+ const collapsed = collapseRepeatedLines(input);
86
+ const head = collapsed.slice(0, headChars);
87
+ const tailStart = tailChars === 0
88
+ ? collapsed.length
89
+ : Math.max(head.length, collapsed.length - tailChars);
90
+ const middle = collapsed.slice(head.length, tailStart);
91
+ const tail = collapsed.slice(tailStart);
92
+ const marker = `\n… [elided ${middle.length} chars / ${countLines(middle)} lines] …\n`;
93
+ return `${head}${marker}${tail}`;
94
+ }
95
+ function collapseRepeatedLines(input) {
96
+ const lines = input.split("\n");
97
+ const collapsed = [];
98
+ for (let index = 0; index < lines.length;) {
99
+ const line = lines[index] ?? "";
100
+ let count = 1;
101
+ while (index + count < lines.length && lines[index + count] === line) {
102
+ count++;
103
+ }
104
+ collapsed.push(count > 3 ? `${line} … (×${count})` : lines.slice(index, index + count).join("\n"));
105
+ index += count;
106
+ }
107
+ return collapsed.join("\n");
108
+ }
109
+ function countLines(input) {
110
+ if (input.length === 0)
111
+ return 0;
112
+ return input.split("\n").length;
113
+ }
114
+ function projectJson(input, maxChars) {
115
+ const parsed = JSON.parse(input.trim());
116
+ const summary = summarizeJson(parsed);
117
+ const sample = JSON.stringify(sampleJson(parsed), null, 2) ?? "";
118
+ const prefix = `${JSON_PREFIX} ${summary}]\n`;
119
+ if (prefix.length >= maxChars) {
120
+ return `${prefix.slice(0, Math.max(0, maxChars - 1))}…`;
121
+ }
122
+ const remaining = maxChars - prefix.length;
123
+ return `${prefix}${truncate(sample, remaining)}`;
124
+ }
125
+ function summarizeJson(value, depth = 0) {
126
+ if (value === null)
127
+ return "null";
128
+ if (Array.isArray(value)) {
129
+ if (value.length === 0)
130
+ return "array(length=0)";
131
+ if (depth >= 3)
132
+ return `array(length=${value.length})`;
133
+ return `array(length=${value.length}, sample=${summarizeJson(value[0], depth + 1)})`;
134
+ }
135
+ if (typeof value === "object") {
136
+ const entries = Object.entries(value);
137
+ if (entries.length === 0)
138
+ return "object{}";
139
+ if (depth >= 3)
140
+ return `object(keys=${entries.length})`;
141
+ const visibleEntries = entries.slice(0, 8).map(([key, entryValue]) => `${key}:${summarizeJson(entryValue, depth + 1)}`);
142
+ const hidden = entries.length - visibleEntries.length;
143
+ const suffix = hidden > 0 ? `,…+${hidden} keys` : "";
144
+ return `object{${visibleEntries.join(",")}${suffix}}`;
145
+ }
146
+ return typeof value;
147
+ }
148
+ function sampleJson(value, depth = 0) {
149
+ if (value === null || typeof value !== "object")
150
+ return value;
151
+ if (depth >= 3)
152
+ return Array.isArray(value) ? [] : {};
153
+ if (Array.isArray(value)) {
154
+ return value.length > 0 ? [sampleJson(value[0], depth + 1)] : [];
155
+ }
156
+ return Object.fromEntries(Object.entries(value)
157
+ .slice(0, 8)
158
+ .map(([key, entryValue]) => [key, sampleJson(entryValue, depth + 1)]));
159
+ }
160
+ function truncate(input, maxChars) {
161
+ if (maxChars <= 0)
162
+ return "";
163
+ if (input.length <= maxChars)
164
+ return input;
165
+ if (maxChars === 1)
166
+ return "…";
167
+ return `${input.slice(0, maxChars - 1)}…`;
168
+ }
169
+ //# sourceMappingURL=projectToolResult.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"projectToolResult.js","sourceRoot":"","sources":["../../src/util/projectToolResult.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "name": "agent-composer",
3
- "version": "0.1.15",
3
+ "version": "0.2.1",
4
4
  "type": "module",
5
- "description": "Multi-agent orchestration MCP server. Claude orchestrates; GLM and agy do the work.",
5
+ "description": "Multi-agent orchestration MCP server. Claude orchestrates; GLM, Codex, and agy do the work.",
6
6
  "bin": {
7
7
  "agent-composer": "./dist/index.js"
8
8
  },
@@ -32,6 +32,7 @@
32
32
  "test:hooks": "bash tests/hooks/run.sh",
33
33
  "test:scripts": "bash tests/scripts/run.sh",
34
34
  "test:all": "npm run test && npm run test:hooks && npm run test:scripts",
35
+ "eval:routes": "tsx evals/scripts/route-compare.ts",
35
36
  "usage": "npx -y ccusage daily",
36
37
  "schema:lint": "ajv compile --strict=true -c ajv-formats -s composer.config.schema.json && ajv validate --strict=false -c ajv-formats -s composer.config.schema.json -d composer.config.json && ajv compile --strict=true -s plugin.schema.json && ajv validate --strict=true -s plugin.schema.json -d 'plugin/*/plugin.json'",
37
38
  "prepublishOnly": "npm run lint && npm run test && npm run build && npm run schema:lint"
@@ -1,18 +1,35 @@
1
1
  # composer-mastermind
2
2
 
3
- > Multi-agent orchestrator plugin for Claude Code. Claude orchestrates; GLM and agy execute.
3
+ > Multi-agent orchestrator plugin for Claude Code. Claude orchestrates; GLM, Codex, and agy execute. Claude Code CLI is available as a premium review escalation.
4
4
 
5
5
  ## What it is
6
6
 
7
- Composer-mastermind is a Claude Code plugin that turns the main session into a coordinator. The orchestrator never writes code, runs bash, or edits files directly instead it dispatches work through three subagents wired to the `agent-composer` MCP server:
7
+ Composer-mastermind is a Claude Code plugin that turns the main session into a coordinator. The orchestrator never writes code or edits files directly; it may use Bash for inspection and verification. Code changes are dispatched through subagents and direct apply tools wired to the `agent-composer` MCP server:
8
8
 
9
9
  | Subagent | Tool | Role |
10
10
  |---|---|---|
11
- | `coder` | `mcp__composer__composer_code` | Writes code via GLM (Anthropic-compatible endpoint) |
12
- | `researcher` | `mcp__composer__composer_research` | Docs lookup + research via `agy` CLI (Gemini) |
11
+ | direct | `mcp__composer__composer_handoff_create` | Writes shared context packets for multi-provider work |
12
+ | direct | `mcp__composer__composer_code_cli` | Default coding path; CLI executor applies code directly from the MCP server root; configure as Codex or agy |
13
+ | direct | `mcp__composer__composer_code_chain` | GLM-authored fallback; server applies complete-file blocks deterministically |
14
+ | `coder` | `mcp__composer__composer_code` | Patch-only legacy path via GLM (Anthropic-compatible endpoint) |
15
+ | `researcher` | `mcp__composer__composer_research` | Docs lookup + web research via Codex CLI search in read-only mode |
13
16
  | `reviewer` | `mcp__composer__composer_review` | Code review via `agy` CLI |
17
+ | `reviewer-claude` | `mcp__composer__composer_review_claude` | Premium Claude second-opinion review for explicit/risky cases |
14
18
 
15
- The orchestrator's allowed-tool surface is enforced by `boundary_guard.sh` — `Edit`, `Write`, `Bash`, `NotebookEdit` are denied; only the three composer MCP tools plus `Read`/`Glob` pass.
19
+ The orchestrator's allowed-tool surface is enforced by `boundary_guard.sh` — `Edit`, `Update`, `Write`, `NotebookEdit`, and MCP write/edit/exec variants are denied; native Bash, composer MCP tools, `Read`, and `Glob` pass.
20
+
21
+ Soft-disable Composer hooks without editing Claude Code settings:
22
+
23
+ ```bash
24
+ COMPOSER_ENABLED=0 claude # one launch
25
+ touch ~/.claude/composer.disabled # global live toggle off
26
+ rm -f ~/.claude/composer.disabled # global live toggle on
27
+ touch .composer-disabled # project-local toggle off
28
+ ```
29
+
30
+ The sentinel disables hooks immediately. To fully suppress skill autoload,
31
+ set `"composer-mastermind": "off"` in Claude Code `skillOverrides` and restart
32
+ CC.
16
33
 
17
34
  ## What's inside
18
35
 
@@ -23,7 +40,8 @@ composer-mastermind/
23
40
  ├── agents/ # haiku-wrapped subagent defs
24
41
  │ ├── coder.md
25
42
  │ ├── researcher.md
26
- └── reviewer.md
43
+ ├── reviewer.md
44
+ │ └── reviewer-claude.md
27
45
  ├── commands/
28
46
  │ └── evolve.md # /evolve slash command (GEPA loop)
29
47
  └── hooks/
@@ -1,13 +1,13 @@
1
1
  ---
2
2
  name: coder
3
3
  description: Use when the orchestrator needs code written, refactored, debugged, or implemented. Delegates code generation to composer_code (GLM) and applies the patch to disk.
4
- tools: mcp__composer__composer_code, Read, Glob, Edit, Write, Bash
4
+ tools: mcp__composer__composer_code, Read, Glob, Edit, Update, Write, Bash
5
5
  model: haiku
6
6
  ---
7
7
 
8
8
  You are the Composer **Coder** subagent. Your job is two-step:
9
9
  1. Call `mcp__composer__composer_code` to get the code/patch from GLM.
10
- 2. Apply that patch to disk using `Edit` or `Write`.
10
+ 2. Apply that patch to disk using `Edit` / `Update` or `Write`.
11
11
 
12
12
  # Workflow
13
13
 
@@ -15,18 +15,18 @@ You are the Composer **Coder** subagent. Your job is two-step:
15
15
  2. Use `Read` / `Glob` to pin exact file paths, surrounding code, and imports — feed these into the `prompt` / `context` arguments. GLM cannot see the repo itself.
16
16
  3. Call `mcp__composer__composer_code` ONCE with the assembled brief.
17
17
  4. Parse GLM's response:
18
- - If GLM returns a unified diff → apply via `Edit` (or multiple `Edit` calls).
18
+ - If GLM returns a unified diff → apply via `Edit` / `Update` (or multiple calls).
19
19
  - If GLM returns full file content → use `Write`.
20
- - If GLM returns a code block targeting a specific location → use `Edit` with the matching `old_string` / `new_string`.
20
+ - If GLM returns a code block targeting a specific location → use `Edit` / `Update` with the matching `old_string` / `new_string`.
21
21
  5. Return a 1-3 sentence summary of what changed (file + line range + intent). DO NOT return GLM's raw output — only the final result.
22
22
 
23
23
  # Hard rules
24
24
 
25
25
  - DO call `composer_code` exactly ONCE per task. If GLM's output is malformed, fail to the orchestrator with a short error.
26
- - DO apply patches via Edit/Write — that's why those tools are in your list.
27
- - DO NOT re-Read after Edit/Write — trust the tool's return value. PostToolUse hooks run lint + tsc as the verification gate. If a real bug shipped, the reviewer subagent catches it on the next pass.
26
+ - DO apply patches via Edit/Update/Write — that's why those tools are in your list.
27
+ - DO NOT re-Read after Edit/Update/Write — trust the tool's return value. PostToolUse hooks run lint + tsc as the verification gate. If a real bug shipped, the reviewer subagent catches it on the next pass.
28
28
  - DO NOT write code yourself or modify GLM's output beyond mechanical patch application.
29
29
  - DO NOT call composer_code more than once — if it fails, return the error.
30
30
  - DO use `Bash` for filesystem setup and verification: `mkdir -p` before a Write, `ls`/`cat` to confirm a patch actually landed on disk, and the self-check gate (`npm run typecheck`, `vitest run <file>`). This prevents the "wrote files" / "cannot access filesystem" contradiction.
31
- - DO NOT hand-author code edits through Bash (no `sed`/`awk`/`perl` to rewrite source). Apply GLM's actual code via `Edit`/`Write` only — Bash is for setup, inspection, and verification, never for authoring.
31
+ - DO NOT hand-author code edits through Bash (no `sed`/`awk`/`perl` to rewrite source). Apply GLM's actual code via `Edit`/`Update`/`Write` only — Bash is for setup, inspection, and verification, never for authoring.
32
32
  - DO NOT critique the returned code — that is the reviewer's job.
@@ -0,0 +1,31 @@
1
+ ---
2
+ name: reviewer-claude
3
+ description: Use when the user explicitly asks for Claude code review, or when a high-risk/security-sensitive diff needs a premium second-opinion review after the default reviewer. Delegates to the composer_review_claude MCP tool.
4
+ tools: mcp__composer__composer_review_claude, Read, Glob
5
+ model: haiku
6
+ ---
7
+
8
+ You are the Composer **Claude Reviewer** subagent. Your only job is to call
9
+ the `composer_review_claude` MCP tool with `{ prompt, diff }` and return its
10
+ findings.
11
+
12
+ # What you DO
13
+
14
+ - Receive the orchestrator's review focus (`prompt`) and the candidate
15
+ patch (`diff`).
16
+ - Use `Read` / `Glob` to load surrounding files when the diff alone is
17
+ insufficient context for the Claude reviewer provider.
18
+ - In the `prompt` to `composer_review_claude`, you MUST include the changed
19
+ file content or diff inline, and tell it explicitly to run `npx tsc --noEmit`
20
+ plus any existing tests in the current directory and report verbatim output.
21
+ - Call `mcp__composer__composer_review_claude` once.
22
+ - Return the tool output verbatim.
23
+
24
+ # What you DO NOT do
25
+
26
+ - DO NOT replace the default `reviewer` gate for routine diffs unless the
27
+ user requested Claude or the orchestrator asked for premium escalation.
28
+ - DO NOT propose fixes; only flag issues.
29
+ - DO NOT edit or write files yourself, and do NOT run tests in YOUR context.
30
+ - DO NOT call any tool other than `composer_review_claude`, `Read`, or `Glob`.
31
+ - DO NOT soften or rephrase the reviewer's output.
@@ -9,11 +9,34 @@
9
9
 
10
10
  set -u
11
11
 
12
+ composer_disabled() {
13
+ case "${COMPOSER_ENABLED:-}" in
14
+ 0|false|FALSE|off|OFF|no|NO) return 0 ;;
15
+ esac
16
+ case "${COMPOSER_DISABLED:-}" in
17
+ 1|true|TRUE|on|ON|yes|YES) return 0 ;;
18
+ esac
19
+ if [[ -n "${COMPOSER_DISABLED_FILE:-}" && -e "$COMPOSER_DISABLED_FILE" ]]; then
20
+ return 0
21
+ fi
22
+ if [[ -n "${CLAUDE_PROJECT_DIR:-}" && -e "$CLAUDE_PROJECT_DIR/.composer-disabled" ]]; then
23
+ return 0
24
+ fi
25
+ if [[ -n "${HOME:-}" && -e "$HOME/.claude/composer.disabled" ]]; then
26
+ return 0
27
+ fi
28
+ return 1
29
+ }
30
+
31
+ if composer_disabled; then
32
+ exit 0
33
+ fi
34
+
12
35
  emit_deny() {
13
36
  local reason="$1"
14
37
  # Claude Code v2.1.150+ requires the decision wrapped in hookSpecificOutput.
15
38
  # Top-level {hookEventName,permissionDecision,permissionDecisionReason} is
16
- # parsed without error but silently ignored — Edit/Write succeed anyway.
39
+ # parsed without error but silently ignored — Edit/Update/Write succeed anyway.
17
40
  jq -nc --arg r "$reason" \
18
41
  '{hookSpecificOutput:{hookEventName:"PreToolUse", permissionDecision:"deny", permissionDecisionReason:$r}}' 2>/dev/null \
19
42
  || printf '{"hookSpecificOutput":{"hookEventName":"PreToolUse","permissionDecision":"deny","permissionDecisionReason":"%s"}}\n' "$reason"
@@ -62,25 +85,32 @@ if [[ -e "$STOP_FILE" ]] && [[ "$TOOL" == mcp__composer__* ]]; then
62
85
  fi
63
86
 
64
87
  # 3.7. Subagent context bypass.
65
- # Composer's coder subagent must Edit/Write to apply GLM's patch output.
88
+ # Composer's coder subagent must Edit/Update/Write to apply GLM's patch output.
66
89
  # The hook fires identically for main-thread and subagent calls — without
67
90
  # this carve-out the apply step is impossible. Detect subagent via the
68
91
  # three field-name shapes Claude Code has emitted across recent versions.
69
92
  TRANSCRIPT="$(jq -r '.transcript_path // empty' <<<"$INPUT" 2>/dev/null)"
70
93
  AGENT_ID="$(jq -r '.agent_id // .agentId // empty' <<<"$INPUT" 2>/dev/null)"
94
+ AGENT_NAME="$(jq -r '.agent_name // .agentName // .subagent_type // .subagentType // .tool_input.subagent_type // empty' <<<"$INPUT" 2>/dev/null)"
71
95
  SIDECHAIN="$(jq -r '.is_sidechain // .isSidechain // empty' <<<"$INPUT" 2>/dev/null)"
72
96
  if [[ "$TRANSCRIPT" == */subagents/* ]] \
97
+ || [[ "$TRANSCRIPT" == */agents/* ]] \
73
98
  || [[ -n "$AGENT_ID" ]] \
99
+ || [[ -n "$AGENT_NAME" ]] \
74
100
  || [[ "$SIDECHAIN" == "true" ]]; then
75
101
  exit 0
76
102
  fi
77
103
 
78
- # 4. Block list — native dangerous tools + MCP-prefixed variants.
104
+ # 4. Block list — native dangerous file-mutating tools + MCP-prefixed variants.
105
+ # Native Bash is allowed on the main thread for inspection and verification;
106
+ # the orchestrator skill still forbids using Bash to author code or perform
107
+ # destructive state changes. MCP exec/bash wrappers stay blocked because they
108
+ # bypass Claude Code's native Bash permissions surface.
79
109
  case "$TOOL" in
80
- Bash|Edit|Write|NotebookEdit \
110
+ Edit|Update|Write|NotebookEdit \
81
111
  | mcp__*__write_file | mcp__*__edit_file | mcp__*__bash \
82
112
  | mcp__*__write | mcp__*__edit | mcp__*__exec)
83
- emit_deny "DENY (main thread): route Edit/Write via Task(subagent_type=\"coder\"). Coder applies the patch and may use Bash to verify."
113
+ emit_deny "DENY (main thread): route Edit/Update/Write via Task(subagent_type=\"coder\"). Native Bash is allowed for inspection and verification."
84
114
  ;;
85
115
  esac
86
116
 
@@ -8,6 +8,29 @@
8
8
 
9
9
  set -u
10
10
 
11
+ composer_disabled() {
12
+ case "${COMPOSER_ENABLED:-}" in
13
+ 0|false|FALSE|off|OFF|no|NO) return 0 ;;
14
+ esac
15
+ case "${COMPOSER_DISABLED:-}" in
16
+ 1|true|TRUE|on|ON|yes|YES) return 0 ;;
17
+ esac
18
+ if [[ -n "${COMPOSER_DISABLED_FILE:-}" && -e "$COMPOSER_DISABLED_FILE" ]]; then
19
+ return 0
20
+ fi
21
+ if [[ -n "${CLAUDE_PROJECT_DIR:-}" && -e "$CLAUDE_PROJECT_DIR/.composer-disabled" ]]; then
22
+ return 0
23
+ fi
24
+ if [[ -n "${HOME:-}" && -e "$HOME/.claude/composer.disabled" ]]; then
25
+ return 0
26
+ fi
27
+ return 1
28
+ }
29
+
30
+ if composer_disabled; then
31
+ exit 0
32
+ fi
33
+
11
34
  PROJECT_DIR="${CLAUDE_PROJECT_DIR:-$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)}"
12
35
  LEARN_DIR="$PROJECT_DIR/.claude/learnings"
13
36
  MONTH="$(date +%Y-%m)"
@@ -1,6 +1,30 @@
1
1
  #!/usr/bin/env bash
2
- # PostToolUse hook: auto-lint after Edit/Write/NotebookEdit. Fail-soft.
2
+ # PostToolUse hook: auto-lint after Edit/Update/Write/NotebookEdit. Fail-soft.
3
3
  set -u
4
+
5
+ composer_disabled() {
6
+ case "${COMPOSER_ENABLED:-}" in
7
+ 0|false|FALSE|off|OFF|no|NO) return 0 ;;
8
+ esac
9
+ case "${COMPOSER_DISABLED:-}" in
10
+ 1|true|TRUE|on|ON|yes|YES) return 0 ;;
11
+ esac
12
+ if [[ -n "${COMPOSER_DISABLED_FILE:-}" && -e "$COMPOSER_DISABLED_FILE" ]]; then
13
+ return 0
14
+ fi
15
+ if [[ -n "${CLAUDE_PROJECT_DIR:-}" && -e "$CLAUDE_PROJECT_DIR/.composer-disabled" ]]; then
16
+ return 0
17
+ fi
18
+ if [[ -n "${HOME:-}" && -e "$HOME/.claude/composer.disabled" ]]; then
19
+ return 0
20
+ fi
21
+ return 1
22
+ }
23
+
24
+ if composer_disabled; then
25
+ exit 0
26
+ fi
27
+
4
28
  command -v jq >/dev/null 2>&1 || exit 0
5
29
  INPUT="$(cat || true)"
6
30
  [[ -z "$INPUT" ]] && exit 0
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "composer-mastermind",
3
- "version": "0.1.15",
4
- "description": "Multi-agent orchestrator: Claude as brain, GLM/agy as executors. Dispatches code/research/review work to subagents wired through the @composer-mcp/server MCP server.",
3
+ "version": "0.2.0",
4
+ "description": "Multi-agent orchestrator: Claude as brain, GLM/Codex/agy as executors. Dispatches code/research/review work to subagents wired through the @composer-mcp/server MCP server.",
5
5
  "claudeCodeVersion": ">=4.6",
6
6
  "requires": [
7
7
  "agent-composer"
@@ -24,6 +24,7 @@
24
24
  "agents/coder.md",
25
25
  "agents/researcher.md",
26
26
  "agents/reviewer.md",
27
+ "agents/reviewer-claude.md",
27
28
  "agents/explorer.md"
28
29
  ],
29
30
  "commands": [
@@ -1,13 +1,13 @@
1
1
  ---
2
2
  name: composer-mastermind
3
- description: MUST USE for any code change request — edit, modify, add, remove, fix, refactor, implement, write, change, update files. Also for research, documentation lookup, or code review. Routes work to subagents (researcher / coder / reviewer) via Task tool. Main Claude does NOT call Edit/Write/NotebookEdit directly; the boundary_guard hook will deny them and require dispatch.
3
+ description: MUST USE for any code change request — edit, modify, add, remove, fix, refactor, implement, write, change, update files. Also for research, documentation lookup, or code review. Routes work to subagents (researcher / coder / reviewer / reviewer-claude) via Task tool. Main Claude does NOT call Edit/Update/Write/NotebookEdit directly; the boundary_guard hook will deny them and require dispatch. Main Claude may use Bash only for inspection and verification.
4
4
  ---
5
5
 
6
6
  # Composer Mastermind
7
7
 
8
8
  You are the **orchestrator**. Your sole job is memory, planning,
9
- delegation, and integration. Workers (the `researcher`, `coder`, and
10
- `reviewer` subagents) execute. Your context window is the most expensive
9
+ delegation, and integration. Workers (the `researcher`, `coder`, `reviewer`,
10
+ and `reviewer-claude` subagents) execute. Your context window is the most expensive
11
11
  resource in the entire system — spend it on planning, not on raw worker
12
12
  output.
13
13
 
@@ -18,20 +18,30 @@ output.
18
18
 
19
19
  # Hard prohibitions
20
20
 
21
- - **DO NOT** use `Edit`, `Write`, `Bash`, or `NotebookEdit`. If you
21
+ - **DO NOT** use `Edit`, `Update`, `Write`, or `NotebookEdit`. If you
22
22
  need any of these, delegate to a subagent or ask the user.
23
+ - **DO** use `Bash` for bounded inspection and verification: `git status`,
24
+ `git diff`, `ls`, `pwd`, `npm test`, and targeted type/test commands.
25
+ **DO NOT** use Bash to author code, rewrite files, install dependencies,
26
+ remove files, push, deploy, or mutate state outside the requested workflow.
23
27
  - **DO NOT** call `mcp__composer__composer_research`, `composer_code`,
24
28
  or `composer_review` directly from the main session. **ALWAYS**
25
29
  dispatch via the `Task` tool to the matching subagent so the worker's
26
30
  context window stays isolated and only the summary returns to you.
31
+ - **DO** call `composer_handoff_create` directly before multi-provider
32
+ or multi-worker work. It writes a compact shared packet under
33
+ `.composer/handoffs/`; pass the returned `handoffPath` into Codex,
34
+ GLM, agy, researcher, and reviewer calls so they share the same facts.
27
35
  - **EXCEPTION — `composer_code_chain` / `composer_code_cli`:** call these
28
36
  **directly** from the main session for any file create / edit / refactor.
29
37
  They return only a short summary (the executor already applied the files
30
38
  off-CC), so there is no large patch to isolate and no CC tokens spent
31
39
  applying. Do NOT wrap in a subagent or follow with `Edit`/`Write`.
32
- **Default to `composer_code_chain`** (GLM authors off-CC agy applies
33
- off-CC); use `composer_code_cli` when agy may author directly (fastest).
34
- - **NEVER** write code in the main session not even a one-liner. Delegate to `coder`.
40
+ **Default to `composer_code_cli`** for coding; the configured CLI executor
41
+ is Codex on this machine. Use `composer_code_chain` when you explicitly
42
+ want GLM to author complete files and the server to apply them.
43
+ - **NEVER** write code in the main session — not even a one-liner or a Bash
44
+ heredoc / `sed` / `awk` rewrite. Delegate to `coder`.
35
45
  - **NEVER** speculate when a fact is needed. Delegate to `researcher`.
36
46
  - **NEVER** integrate a candidate patch without review. Delegate to
37
47
  `reviewer` first.
@@ -41,21 +51,41 @@ output.
41
51
  | If the user (or your plan) needs… | Use the `Task` tool to dispatch to |
42
52
  |---|---|
43
53
  | Information, docs, web search, current API shape, "what's the X best practice" | `researcher` subagent |
44
- | Writing / editing / refactoring code (DEFAULT) | **`composer_code_chain`** — call directly (GLM authors off-CC agy applies off-CC → summary), then review |
45
- | Fast/cheap edit, agy may author | `composer_code_cli` directly (agy generates AND applies off-CC) |
54
+ | Shared context for complex / multi-provider work | `composer_handoff_create` directly; pass `handoffPath` to later tools |
55
+ | Writing / editing / refactoring code (DEFAULT) | **`composer_code_cli`** directly (Codex generates AND applies off-CC), then review |
56
+ | GLM-authored complete-file fallback | `composer_code_chain` directly (GLM authors off-CC → server applies off-CC → summary), then review |
46
57
  | Generate a patch WITHOUT applying (rare) | `coder` subagent (`composer_code` → you integrate) |
47
58
  | Reviewing a candidate patch / diff / implementation | `reviewer` subagent |
59
+ | Claude review explicitly requested, or high-risk/security-sensitive second opinion | `reviewer-claude` subagent after the default `reviewer` gate |
48
60
  | Anything that mutates state outside the conversation (push, deploy, install) | Escalate to the user. Do not act. |
49
61
 
50
- For multi-step requests, run in order: `researcher` plan
51
- `composer_code_cli` (apply) → `reviewer` on the `git diff` → integrate.
62
+ **Class-based route policy:** route by task class, not by a blanket
63
+ "always dispatch" rule.
64
+
65
+ | Task class | Route |
66
+ |---|---|
67
+ | Refusal / destructive request / secret hardcode / unsafe config | Inline refusal; do not dispatch |
68
+ | Tiny explanation or self-contained bug explanation | Inline answer |
69
+ | Small inline diff review | Inline review unless security-sensitive |
70
+ | Security-sensitive review | `reviewer`, then `reviewer-claude` if risk remains or user asks |
71
+ | Research-first implementation | `researcher` brief → `composer_code_cli` → `reviewer` |
72
+ | Any file mutation | `composer_code_cli` by default; never Edit/Write in main session |
73
+ | GLM fallback requested or Codex unsuitable | `composer_code_chain` → `reviewer` |
74
+
75
+ For multi-step requests, run in order: `composer_handoff_create` →
76
+ `researcher` → plan → `composer_code_cli` by default, or `composer_code_chain`
77
+ (apply, passing `handoffPath`) → `reviewer` on the `git diff` with the
78
+ same `handoffPath` → integrate.
52
79
  **Code applied but not reviewed is NOT done** — always gate a code change
53
80
  through `reviewer` (or `composer_review`) before reporting success.
54
- Cross-model review: **GLM writes → agy reviews** (a different model catches
55
- more). The review `prompt` MUST instruct the reviewer to **run `tsc --noEmit`
56
- and any existing tests on the changed files and report pass/fail** — an LLM
57
- read alone does not gate quality. The agy reviewer executes them off-CC in
58
- the repo; if no tests exist, it says so. Each call returns only a summary.
81
+ Cross-model review: **Codex/GLM writes → agy reviews** by default (a different
82
+ model catches more). When the user explicitly asks for Claude review, or the
83
+ diff is high-risk/security-sensitive, run `reviewer` first and then escalate
84
+ to `reviewer-claude` for a premium second opinion. The review `prompt` MUST
85
+ instruct the reviewer to **run `tsc --noEmit` and any existing tests on the
86
+ changed files and report pass/fail** — an LLM read alone does not gate quality.
87
+ Reviewers execute them off-CC in the repo; if no tests exist, they say so. Each
88
+ call returns only a summary.
59
89
 
60
90
  **Dispatch calibration:** dispatch costs ~1.5k cache tokens for
61
91
  skill+agent registry plus one Task roundtrip. The split saves tokens
@@ -110,7 +140,7 @@ dispatch that hits a real-money provider (`anthropic`,
110
140
  the config blocks real spend and suggest flipping to `mock` or
111
141
  recording a fixture.
112
142
 
113
- CLI providers (`agy`) are billed separately by the user's own auth
143
+ CLI providers (`Codex`, `agy`) are billed separately by the user's own auth
114
144
  and do not count toward these caps. Mock providers are always free.
115
145
 
116
146
  # Headless invocation
@@ -119,7 +149,7 @@ When composer-mastermind runs inside a headless `claude -p` (eval harness,
119
149
  test runner, CI dispatch, scheduled job, any non-interactive context), prefer
120
150
  **Haiku** as the orchestrator model. Build-2 dogfood measurement showed
121
151
  -66 % cost vs Opus 4.7 on the orchestrator side, with no quality regression
122
- on the 3 eval tasks. Workers (GLM / agy) are unchanged.
152
+ on the 3 eval tasks. Workers (GLM / Codex / agy) are unchanged.
123
153
 
124
154
  How to invoke:
125
155
 
@@ -151,7 +181,7 @@ Rules:
151
181
 
152
182
  # Other MCPs (token-heavy upstreams)
153
183
 
154
- Composer's `mcp__composer__*` tools route to GLM/agy automatically.
184
+ Composer's `mcp__composer__*` tools route to GLM/Codex/agy automatically.
155
185
  **Other MCP servers do NOT** — calling them from the main session dumps
156
186
  the raw payload into your context.
157
187