agent-composer 0.1.0 → 0.1.2

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.
@@ -18,3 +18,25 @@ export interface InitResult {
18
18
  steps: InitStep[];
19
19
  }
20
20
  export declare function runInit(opts: InitOptions): InitResult;
21
+ export interface GlobalInitOptions {
22
+ /** Override the global config dir (tests inject a tmpdir). Defaults to ~/.config/composer. */
23
+ globalDir?: string;
24
+ /** Override the user's Claude Code home dir (tests inject a tmpdir). Defaults to ~/.claude. */
25
+ claudeHome?: string;
26
+ verbose?: boolean;
27
+ defaultBaseUrl?: string;
28
+ defaultAuthToken?: string;
29
+ /** Skip plugin asset install (default: false — assets ARE installed). */
30
+ skipPluginAssets?: boolean;
31
+ /** Override the plugin source directory (tests inject). */
32
+ pluginSourceDir?: string;
33
+ }
34
+ /**
35
+ * User-level (global) bootstrap. Writes composer.config.json and .env.json
36
+ * to ~/.config/composer/ and patches ~/.claude/settings.json with the
37
+ * mcpServers.composer entry so new projects work without per-project init.
38
+ *
39
+ * Runtime lookup chain (see src/config/paths.ts) makes the global files
40
+ * apply automatically when a project has no local copy.
41
+ */
42
+ export declare function runGlobalInit(opts?: GlobalInitOptions): InitResult;
package/dist/cli/init.js CHANGED
@@ -10,7 +10,10 @@
10
10
  // Idempotent: each step checks existing state and skips if already correct.
11
11
  // Never overwrites a present, non-default file (no --force flag in this slice).
12
12
  import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
13
+ import { homedir } from "node:os";
13
14
  import { join, resolve } from "node:path";
15
+ import { globalConfigDir } from "../config/paths.js";
16
+ import { installPluginAssets } from "./install-plugin.js";
14
17
  const DEFAULT_COMPOSER_CONFIG = {
15
18
  roles: {
16
19
  researcher: { provider: "cli", cli: ["agy", "--dangerously-skip-permissions", "-p"] },
@@ -63,6 +66,90 @@ export function runInit(opts) {
63
66
  log(" 4. Smoke-test the autoresearch loop: /evolve --eval-mode synthetic");
64
67
  return { steps };
65
68
  }
69
+ /**
70
+ * User-level (global) bootstrap. Writes composer.config.json and .env.json
71
+ * to ~/.config/composer/ and patches ~/.claude/settings.json with the
72
+ * mcpServers.composer entry so new projects work without per-project init.
73
+ *
74
+ * Runtime lookup chain (see src/config/paths.ts) makes the global files
75
+ * apply automatically when a project has no local copy.
76
+ */
77
+ export function runGlobalInit(opts = {}) {
78
+ const dir = opts.globalDir ?? globalConfigDir();
79
+ const claudeHome = opts.claudeHome ?? join(homedir(), ".claude");
80
+ const steps = [];
81
+ const log = (...args) => {
82
+ if (opts.verbose !== false)
83
+ process.stdout.write(args.map(String).join(" ") + "\n");
84
+ };
85
+ steps.push(ensureDir(dir, "global config dir"));
86
+ steps.push(writeGlobalComposerConfig(dir));
87
+ steps.push(writeGlobalEnvJson(dir, opts.defaultBaseUrl ?? DEFAULT_BASE_URL, opts.defaultAuthToken ?? DEFAULT_AUTH_TOKEN_PLACEHOLDER));
88
+ steps.push(ensureDir(claudeHome, "~/.claude directory"));
89
+ steps.push(wireGlobalMcpServer(claudeHome));
90
+ // Wave 4 0.1.2: drop plugin assets at user-level so the orchestrator
91
+ // skill + subagents + /evolve + boundary hook auto-load in every project.
92
+ if (!opts.skipPluginAssets) {
93
+ const pluginSteps = installPluginAssets({
94
+ claudeHome,
95
+ pluginSourceDir: opts.pluginSourceDir,
96
+ });
97
+ steps.push(...pluginSteps);
98
+ }
99
+ for (const s of steps) {
100
+ const tag = s.status === "created" ? "+" : s.status === "updated" ? "~" : "=";
101
+ log(` ${tag} ${s.name}${s.path ? ` (${s.path})` : ""}${s.reason ? ` — ${s.reason}` : ""}`);
102
+ }
103
+ log("");
104
+ log("composer init --global: done.");
105
+ log("");
106
+ log("Next steps:");
107
+ log(` 1. Fill ${join(dir, ".env.json")} with real ANTHROPIC_AUTH_TOKEN.`);
108
+ log(" 2. Launch Claude Code from ANY project: claude");
109
+ log(" (no per-project init required — runtime falls back to global config + env)");
110
+ log(" 3. Per-project overrides still work: drop composer.config.json or .env.json in cwd.");
111
+ return { steps };
112
+ }
113
+ function ensureDir(dirPath, label) {
114
+ if (existsSync(dirPath))
115
+ return { name: label, status: "skipped", path: dirPath, reason: "already exists" };
116
+ mkdirSync(dirPath, { recursive: true });
117
+ return { name: label, status: "created", path: dirPath };
118
+ }
119
+ function writeGlobalComposerConfig(dir) {
120
+ const path = join(dir, "composer.config.json");
121
+ if (existsSync(path)) {
122
+ return { name: "global composer.config.json", status: "skipped", path, reason: "already exists; not overwritten" };
123
+ }
124
+ writeFileSync(path, JSON.stringify(DEFAULT_COMPOSER_CONFIG, null, 2) + "\n", "utf8");
125
+ return { name: "global composer.config.json", status: "created", path };
126
+ }
127
+ function writeGlobalEnvJson(dir, baseUrl, token) {
128
+ const path = join(dir, ".env.json");
129
+ if (existsSync(path)) {
130
+ return { name: "global .env.json", status: "skipped", path, reason: "already exists; not overwritten" };
131
+ }
132
+ writeFileSync(path, JSON.stringify(DEFAULT_ENV_TEMPLATE(baseUrl, token), null, 2) + "\n", "utf8");
133
+ return { name: "global .env.json", status: "created", path, reason: "placeholder — fill with real token" };
134
+ }
135
+ function wireGlobalMcpServer(claudeHome) {
136
+ const path = join(claudeHome, "settings.json");
137
+ if (!existsSync(path)) {
138
+ writeFileSync(path, JSON.stringify(DEFAULT_MCP_SETTINGS, null, 2) + "\n", "utf8");
139
+ return { name: "~/.claude/settings.json", status: "created", path, reason: "mcpServers.composer wired (user-level)" };
140
+ }
141
+ const current = JSON.parse(readFileSync(path, "utf8"));
142
+ const mcpServers = current["mcpServers"] ?? {};
143
+ if (mcpServers["composer"]) {
144
+ return { name: "~/.claude/settings.json", status: "skipped", path, reason: "mcpServers.composer already wired" };
145
+ }
146
+ const merged = {
147
+ ...current,
148
+ mcpServers: { ...mcpServers, composer: DEFAULT_MCP_SETTINGS.mcpServers.composer },
149
+ };
150
+ writeFileSync(path, JSON.stringify(merged, null, 2) + "\n", "utf8");
151
+ return { name: "~/.claude/settings.json", status: "updated", path, reason: "mcpServers.composer wired (user-level)" };
152
+ }
66
153
  function ensureClaudeDir(cwd) {
67
154
  const path = join(cwd, ".claude");
68
155
  if (existsSync(path))
@@ -1 +1 @@
1
- {"version":3,"file":"init.js","sourceRoot":"","sources":["../../src/cli/init.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"init.js","sourceRoot":"","sources":["../../src/cli/init.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,24 @@
1
+ import type { InitStep } from "./init.js";
2
+ /**
3
+ * Resolve the plugin source directory shipped with this package.
4
+ * dist/cli/install-plugin.js (3 levels up) → package root → plugin/composer-mastermind/
5
+ */
6
+ export declare function defaultPluginSourceDir(): string;
7
+ export interface InstallPluginOptions {
8
+ /** Claude Code user home (defaults to $HOME/.claude). Tests inject a tmpdir. */
9
+ claudeHome: string;
10
+ /** Plugin source directory (defaults to defaultPluginSourceDir()). Tests inject. */
11
+ pluginSourceDir?: string;
12
+ }
13
+ /**
14
+ * Copy plugin assets into Claude Code user-level directories so they
15
+ * auto-load in every project. Idempotent — never overwrites a present file.
16
+ *
17
+ * Layout written:
18
+ * <claudeHome>/skills/composer-mastermind/SKILL.md
19
+ * <claudeHome>/agents/{coder,researcher,reviewer}.md
20
+ * <claudeHome>/commands/evolve.md
21
+ * <claudeHome>/hooks/composer-boundary_guard.sh
22
+ * <claudeHome>/settings.json — patched with PreToolUse entry
23
+ */
24
+ export declare function installPluginAssets(opts: InstallPluginOptions): InitStep[];
@@ -0,0 +1,124 @@
1
+ // Wave 4 0.1.2 — user-level plugin asset install.
2
+ //
3
+ // Drops composer-mastermind assets (SKILL.md, subagents, /evolve command,
4
+ // boundary_guard hook) into the user's ~/.claude/ tree so Claude Code
5
+ // auto-discovers them in every project. Companion to runGlobalInit().
6
+ //
7
+ // Source assets ship in the npm tarball under plugin/composer-mastermind/
8
+ // (added to package.json files whitelist in 0.1.2).
9
+ import { existsSync, mkdirSync, copyFileSync, chmodSync, readdirSync, readFileSync, writeFileSync } from "node:fs";
10
+ import { dirname, join, resolve } from "node:path";
11
+ import { fileURLToPath } from "node:url";
12
+ /**
13
+ * Resolve the plugin source directory shipped with this package.
14
+ * dist/cli/install-plugin.js (3 levels up) → package root → plugin/composer-mastermind/
15
+ */
16
+ export function defaultPluginSourceDir() {
17
+ const here = dirname(fileURLToPath(import.meta.url));
18
+ return resolve(here, "..", "..", "plugin", "composer-mastermind");
19
+ }
20
+ /**
21
+ * Copy plugin assets into Claude Code user-level directories so they
22
+ * auto-load in every project. Idempotent — never overwrites a present file.
23
+ *
24
+ * Layout written:
25
+ * <claudeHome>/skills/composer-mastermind/SKILL.md
26
+ * <claudeHome>/agents/{coder,researcher,reviewer}.md
27
+ * <claudeHome>/commands/evolve.md
28
+ * <claudeHome>/hooks/composer-boundary_guard.sh
29
+ * <claudeHome>/settings.json — patched with PreToolUse entry
30
+ */
31
+ export function installPluginAssets(opts) {
32
+ const src = opts.pluginSourceDir ?? defaultPluginSourceDir();
33
+ const claudeHome = opts.claudeHome;
34
+ const steps = [];
35
+ steps.push(copyOne(join(src, "skills/composer-mastermind/SKILL.md"), join(claudeHome, "skills/composer-mastermind/SKILL.md"), "composer-mastermind SKILL.md"));
36
+ const agentsSrc = join(src, "agents");
37
+ if (existsSync(agentsSrc)) {
38
+ for (const file of readdirSync(agentsSrc).sort()) {
39
+ if (!file.endsWith(".md"))
40
+ continue;
41
+ steps.push(copyOne(join(agentsSrc, file), join(claudeHome, "agents", file), `agent ${file}`));
42
+ }
43
+ }
44
+ const commandsSrc = join(src, "commands");
45
+ if (existsSync(commandsSrc)) {
46
+ for (const file of readdirSync(commandsSrc).sort()) {
47
+ if (!file.endsWith(".md"))
48
+ continue;
49
+ steps.push(copyOne(join(commandsSrc, file), join(claudeHome, "commands", file), `command /${file.replace(/\.md$/, "")}`));
50
+ }
51
+ }
52
+ // Boundary hook — copy script + register in settings.json
53
+ const hookSrc = join(src, "hooks", "boundary_guard.sh");
54
+ const hookDest = join(claudeHome, "hooks", "composer-boundary_guard.sh");
55
+ steps.push(copyOne(hookSrc, hookDest, "composer boundary_guard.sh hook script", { exec: true }));
56
+ steps.push(wireBoundaryHook(claudeHome, hookDest));
57
+ return steps;
58
+ }
59
+ function copyOne(srcPath, destPath, label, opts = {}) {
60
+ if (!existsSync(srcPath)) {
61
+ return { name: label, status: "skipped", reason: `source missing: ${srcPath}` };
62
+ }
63
+ if (existsSync(destPath)) {
64
+ return { name: label, status: "skipped", path: destPath, reason: "already present; not overwritten" };
65
+ }
66
+ mkdirSync(dirname(destPath), { recursive: true });
67
+ copyFileSync(srcPath, destPath);
68
+ if (opts.exec)
69
+ chmodSync(destPath, 0o755);
70
+ return { name: label, status: "created", path: destPath };
71
+ }
72
+ /**
73
+ * Patch <claudeHome>/settings.json hooks.PreToolUse with a composer
74
+ * boundary entry. Skip if an entry already references composer-boundary_guard.
75
+ */
76
+ function wireBoundaryHook(claudeHome, hookScriptPath) {
77
+ const settingsPath = join(claudeHome, "settings.json");
78
+ const matcher = "Bash|Edit|Write|NotebookEdit";
79
+ const entry = {
80
+ matcher,
81
+ hooks: [{ type: "command", command: hookScriptPath }],
82
+ };
83
+ let current;
84
+ if (existsSync(settingsPath)) {
85
+ try {
86
+ current = JSON.parse(readFileSync(settingsPath, "utf8"));
87
+ }
88
+ catch {
89
+ return {
90
+ name: "~/.claude/settings.json boundary hook",
91
+ status: "skipped",
92
+ path: settingsPath,
93
+ reason: "settings.json not valid JSON; refusing to patch",
94
+ };
95
+ }
96
+ }
97
+ else {
98
+ mkdirSync(dirname(settingsPath), { recursive: true });
99
+ current = {};
100
+ }
101
+ const hooks = current["hooks"] ?? {};
102
+ const preToolUse = hooks["PreToolUse"] ?? [];
103
+ // Idempotency: skip if any existing PreToolUse entry already references our script.
104
+ const alreadyWired = preToolUse.some((e) => e.hooks?.some((h) => h.command === hookScriptPath));
105
+ if (alreadyWired) {
106
+ return {
107
+ name: "~/.claude/settings.json boundary hook",
108
+ status: "skipped",
109
+ path: settingsPath,
110
+ reason: "composer-boundary_guard already registered",
111
+ };
112
+ }
113
+ const nextPreToolUse = [...preToolUse, entry];
114
+ const nextHooks = { ...hooks, PreToolUse: nextPreToolUse };
115
+ const next = { ...current, hooks: nextHooks };
116
+ writeFileSync(settingsPath, JSON.stringify(next, null, 2) + "\n", "utf8");
117
+ return {
118
+ name: "~/.claude/settings.json boundary hook",
119
+ status: "updated",
120
+ path: settingsPath,
121
+ reason: `appended PreToolUse entry → ${hookScriptPath}`,
122
+ };
123
+ }
124
+ //# sourceMappingURL=install-plugin.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"install-plugin.js","sourceRoot":"","sources":["../../src/cli/install-plugin.ts"],"names":[],"mappings":"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"}
@@ -8,6 +8,12 @@ export interface ComposerEnv {
8
8
  */
9
9
  ANTHROPIC_MODEL?: string;
10
10
  }
11
+ /**
12
+ * Reads `.env.json` via the path lookup chain (explicit > cwd > global).
13
+ * Returns `{}` if no file in the chain exists or any parse step fails — this
14
+ * loader is fail-silent by design (the registry surfaces missing-key errors
15
+ * later with better context).
16
+ */
11
17
  export declare function loadEnvJson(envPath?: string): ComposerEnv;
12
18
  export declare function applyEnvJson(envPath?: string): void;
13
19
  export declare function getEnv(): ComposerEnv;
@@ -7,10 +7,21 @@
7
7
  // loud later if a required key is missing.
8
8
  import fs from "node:fs";
9
9
  import path from "node:path";
10
+ import { resolveConfigPath } from "./paths.js";
10
11
  const DEFAULT_ENV_FILE = ".env.json";
11
- export function loadEnvJson(envPath = DEFAULT_ENV_FILE) {
12
- const resolved = path.resolve(envPath);
13
- if (!fs.existsSync(resolved))
12
+ /**
13
+ * Reads `.env.json` via the path lookup chain (explicit > cwd > global).
14
+ * Returns `{}` if no file in the chain exists or any parse step fails — this
15
+ * loader is fail-silent by design (the registry surfaces missing-key errors
16
+ * later with better context).
17
+ */
18
+ export function loadEnvJson(envPath) {
19
+ // If the caller passed an explicit path, use it directly (legacy behaviour
20
+ // for tests that pass a synthetic path). Otherwise resolve via the chain.
21
+ const resolved = envPath
22
+ ? path.resolve(envPath)
23
+ : resolveConfigPath(DEFAULT_ENV_FILE);
24
+ if (!resolved || !fs.existsSync(resolved))
14
25
  return {};
15
26
  let raw;
16
27
  try {
@@ -1 +1 @@
1
- {"version":3,"file":"env.js","sourceRoot":"","sources":["../../src/config/env.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"env.js","sourceRoot":"","sources":["../../src/config/env.ts"],"names":[],"mappings":"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"}
@@ -5,6 +5,7 @@
5
5
  import fs from "node:fs";
6
6
  import path from "node:path";
7
7
  import { ComposerConfigSchema } from "./schema.js";
8
+ import { resolveConfigPath, globalConfigDir } from "./paths.js";
8
9
  export function parseConfig(input) {
9
10
  const result = ComposerConfigSchema.safeParse(input);
10
11
  if (!result.success) {
@@ -16,9 +17,17 @@ export function parseConfig(input) {
16
17
  return result.data;
17
18
  }
18
19
  export function loadConfig(configPath) {
19
- const resolved = path.resolve(configPath);
20
- if (!fs.existsSync(resolved)) {
21
- throw new Error(`Composer config not found at ${resolved}`);
20
+ // Resolve via the lookup chain: explicit path > cwd > global config dir.
21
+ // Only throws when no file exists at any layer, so a user can drop
22
+ // composer.config.json at ~/.config/composer/ and have it apply everywhere.
23
+ const resolved = resolveConfigPath(configPath, configPath);
24
+ if (!resolved) {
25
+ const local = path.resolve(configPath);
26
+ const global = path.join(globalConfigDir(), configPath);
27
+ throw new Error(`Composer config not found. Looked in:\n` +
28
+ ` - ${local}\n` +
29
+ ` - ${global}\n` +
30
+ `Run \`agent-composer init\` (project) or \`agent-composer init --global\` (user-level).`);
22
31
  }
23
32
  const raw = fs.readFileSync(resolved, "utf8");
24
33
  let parsed;
@@ -1 +1 @@
1
- {"version":3,"file":"loader.js","sourceRoot":"","sources":["../../src/config/loader.ts"],"names":[],"mappings":"AAAA,kDAAkD;AAClD,uEAAuE;AACvE,qEAAqE;AACrE,+DAA+D;AAE/D,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,oBAAoB,EAAuB,MAAM,aAAa,CAAC;AAExE,MAAM,UAAU,WAAW,CAAC,KAAc;IACxC,MAAM,MAAM,GAAG,oBAAoB,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;IACrD,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;QACpB,MAAM,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,MAAM;aAC/B,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,QAAQ,KAAK,CAAC,CAAC,OAAO,EAAE,CAAC;aAC/D,IAAI,CAAC,IAAI,CAAC,CAAC;QACd,MAAM,IAAI,KAAK,CAAC,8CAA8C,MAAM,EAAE,CAAC,CAAC;IAC1E,CAAC;IACD,OAAO,MAAM,CAAC,IAAI,CAAC;AACrB,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,UAAkB;IAC3C,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;IAC1C,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC7B,MAAM,IAAI,KAAK,CAAC,gCAAgC,QAAQ,EAAE,CAAC,CAAC;IAC9D,CAAC;IACD,MAAM,GAAG,GAAG,EAAE,CAAC,YAAY,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;IAC9C,IAAI,MAAe,CAAC;IACpB,IAAI,CAAC;QACH,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAC3B,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,MAAM,MAAM,GAAG,CAAC,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;QAC1D,MAAM,IAAI,KAAK,CAAC,sBAAsB,QAAQ,uBAAuB,MAAM,EAAE,CAAC,CAAC;IACjF,CAAC;IACD,OAAO,WAAW,CAAC,MAAM,CAAC,CAAC;AAC7B,CAAC"}
1
+ {"version":3,"file":"loader.js","sourceRoot":"","sources":["../../src/config/loader.ts"],"names":[],"mappings":"AAAA,kDAAkD;AAClD,uEAAuE;AACvE,qEAAqE;AACrE,+DAA+D;AAE/D,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,oBAAoB,EAAuB,MAAM,aAAa,CAAC;AACxE,OAAO,EAAE,iBAAiB,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAEhE,MAAM,UAAU,WAAW,CAAC,KAAc;IACxC,MAAM,MAAM,GAAG,oBAAoB,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;IACrD,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;QACpB,MAAM,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,MAAM;aAC/B,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,QAAQ,KAAK,CAAC,CAAC,OAAO,EAAE,CAAC;aAC/D,IAAI,CAAC,IAAI,CAAC,CAAC;QACd,MAAM,IAAI,KAAK,CAAC,8CAA8C,MAAM,EAAE,CAAC,CAAC;IAC1E,CAAC;IACD,OAAO,MAAM,CAAC,IAAI,CAAC;AACrB,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,UAAkB;IAC3C,yEAAyE;IACzE,mEAAmE;IACnE,4EAA4E;IAC5E,MAAM,QAAQ,GAAG,iBAAiB,CAAC,UAAU,EAAE,UAAU,CAAC,CAAC;IAC3D,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;QACvC,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,eAAe,EAAE,EAAE,UAAU,CAAC,CAAC;QACxD,MAAM,IAAI,KAAK,CACb,yCAAyC;YACzC,OAAO,KAAK,IAAI;YAChB,OAAO,MAAM,IAAI;YACjB,yFAAyF,CAC1F,CAAC;IACJ,CAAC;IACD,MAAM,GAAG,GAAG,EAAE,CAAC,YAAY,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;IAC9C,IAAI,MAAe,CAAC;IACpB,IAAI,CAAC;QACH,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAC3B,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,MAAM,MAAM,GAAG,CAAC,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;QAC1D,MAAM,IAAI,KAAK,CAAC,sBAAsB,QAAQ,uBAAuB,MAAM,EAAE,CAAC,CAAC;IACjF,CAAC;IACD,OAAO,WAAW,CAAC,MAAM,CAAC,CAAC;AAC7B,CAAC"}
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Returns the directory where composer's user-level (global) config files live.
3
+ * Honours $XDG_CONFIG_HOME if set, otherwise defaults to ~/.config/composer.
4
+ */
5
+ export declare function globalConfigDir(): string;
6
+ /**
7
+ * Returns the first existing path from the lookup chain for a given filename
8
+ * (typically "composer.config.json" or ".env.json"). If an explicit path is
9
+ * provided AND it exists, that wins. Otherwise checks cwd, then global dir.
10
+ * Returns `null` if no file in the chain exists.
11
+ */
12
+ export declare function resolveConfigPath(filename: string, explicitPath?: string): string | null;
@@ -0,0 +1,42 @@
1
+ // Resolves global (user-home) and per-project paths for composer config + env.
2
+ //
3
+ // Lookup chain (in order):
4
+ // 1. Explicit path override (COMPOSER_CONFIG / COMPOSER_ENV env var, or CLI arg)
5
+ // 2. Per-project file in process.cwd()
6
+ // 3. Global file at $XDG_CONFIG_HOME/composer/ (default ~/.config/composer/)
7
+ //
8
+ // The first existing file wins; if none exist, callers decide how to handle
9
+ // (env loader returns {}, config loader throws).
10
+ import { existsSync } from "node:fs";
11
+ import { homedir } from "node:os";
12
+ import { resolve, join } from "node:path";
13
+ /**
14
+ * Returns the directory where composer's user-level (global) config files live.
15
+ * Honours $XDG_CONFIG_HOME if set, otherwise defaults to ~/.config/composer.
16
+ */
17
+ export function globalConfigDir() {
18
+ const xdg = process.env["XDG_CONFIG_HOME"];
19
+ const base = xdg && xdg.length > 0 ? xdg : join(homedir(), ".config");
20
+ return join(base, "composer");
21
+ }
22
+ /**
23
+ * Returns the first existing path from the lookup chain for a given filename
24
+ * (typically "composer.config.json" or ".env.json"). If an explicit path is
25
+ * provided AND it exists, that wins. Otherwise checks cwd, then global dir.
26
+ * Returns `null` if no file in the chain exists.
27
+ */
28
+ export function resolveConfigPath(filename, explicitPath) {
29
+ if (explicitPath) {
30
+ const r = resolve(explicitPath);
31
+ if (existsSync(r))
32
+ return r;
33
+ }
34
+ const local = resolve(process.cwd(), filename);
35
+ if (existsSync(local))
36
+ return local;
37
+ const global = join(globalConfigDir(), filename);
38
+ if (existsSync(global))
39
+ return global;
40
+ return null;
41
+ }
42
+ //# sourceMappingURL=paths.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"paths.js","sourceRoot":"","sources":["../../src/config/paths.ts"],"names":[],"mappings":"AAAA,+EAA+E;AAC/E,EAAE;AACF,2BAA2B;AAC3B,mFAAmF;AACnF,yCAAyC;AACzC,+EAA+E;AAC/E,EAAE;AACF,4EAA4E;AAC5E,iDAAiD;AAEjD,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAE1C;;;GAGG;AACH,MAAM,UAAU,eAAe;IAC7B,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAC;IAC3C,MAAM,IAAI,GAAG,GAAG,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,EAAE,EAAE,SAAS,CAAC,CAAC;IACtE,OAAO,IAAI,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC;AAChC,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,iBAAiB,CAAC,QAAgB,EAAE,YAAqB;IACvE,IAAI,YAAY,EAAE,CAAC;QACjB,MAAM,CAAC,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC;QAChC,IAAI,UAAU,CAAC,CAAC,CAAC;YAAE,OAAO,CAAC,CAAC;IAC9B,CAAC;IACD,MAAM,KAAK,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,QAAQ,CAAC,CAAC;IAC/C,IAAI,UAAU,CAAC,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC;IACpC,MAAM,MAAM,GAAG,IAAI,CAAC,eAAe,EAAE,EAAE,QAAQ,CAAC,CAAC;IACjD,IAAI,UAAU,CAAC,MAAM,CAAC;QAAE,OAAO,MAAM,CAAC;IACtC,OAAO,IAAI,CAAC;AACd,CAAC"}
package/dist/index.js CHANGED
@@ -9,13 +9,19 @@ import { loadConfig } from "./config/loader.js";
9
9
  import { applyEnvJson } from "./config/env.js";
10
10
  import { ProviderRegistry } from "./registry.js";
11
11
  import { createComposerServer } from "./server.js";
12
- import { runInit } from "./cli/init.js";
12
+ import { runInit, runGlobalInit } from "./cli/init.js";
13
13
  const CONFIG_PATH = process.env["COMPOSER_CONFIG"] ?? "composer.config.json";
14
14
  const ENV_PATH = process.env["COMPOSER_ENV"] ?? ".env.json";
15
15
  async function main() {
16
16
  const subcommand = process.argv[2];
17
+ const flag = process.argv[3];
17
18
  if (subcommand === "init") {
18
- runInit({ cwd: process.cwd() });
19
+ if (flag === "--global") {
20
+ runGlobalInit({});
21
+ }
22
+ else {
23
+ runInit({ cwd: process.cwd() });
24
+ }
19
25
  return;
20
26
  }
21
27
  applyEnvJson(ENV_PATH);
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA,2EAA2E;AAC3E,kEAAkE;AAClE,EAAE;AACF,oDAAoD;AACpD,2EAA2E;AAE3E,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAChD,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAC/C,OAAO,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AACjD,OAAO,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AACnD,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AAExC,MAAM,WAAW,GAAG,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAC,IAAI,sBAAsB,CAAC;AAC7E,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,IAAI,WAAW,CAAC;AAE5D,KAAK,UAAU,IAAI;IACjB,MAAM,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACnC,IAAI,UAAU,KAAK,MAAM,EAAE,CAAC;QAC1B,OAAO,CAAC,EAAE,GAAG,EAAE,OAAO,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;QAChC,OAAO;IACT,CAAC;IAED,YAAY,CAAC,QAAQ,CAAC,CAAC;IACvB,MAAM,MAAM,GAAG,UAAU,CAAC,WAAW,CAAC,CAAC;IACvC,MAAM,QAAQ,GAAG,IAAI,gBAAgB,CAAC,MAAM,CAAC,CAAC;IAC9C,MAAM,MAAM,GAAG,oBAAoB,CAAC,QAAQ,CAAC,CAAC;IAC9C,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;IAC7C,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IAChC,wEAAwE;IACxE,2BAA2B;IAC3B,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,mDAAmD,WAAW,IAAI,CACnE,CAAC;AACJ,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,GAAY,EAAE,EAAE;IAC5B,MAAM,GAAG,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IAC7D,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,uCAAuC,GAAG,IAAI,CAAC,CAAC;IACrE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA,2EAA2E;AAC3E,kEAAkE;AAClE,EAAE;AACF,oDAAoD;AACpD,2EAA2E;AAE3E,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAChD,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAC/C,OAAO,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AACjD,OAAO,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AACnD,OAAO,EAAE,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAEvD,MAAM,WAAW,GAAG,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAC,IAAI,sBAAsB,CAAC;AAC7E,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,IAAI,WAAW,CAAC;AAE5D,KAAK,UAAU,IAAI;IACjB,MAAM,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACnC,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAC7B,IAAI,UAAU,KAAK,MAAM,EAAE,CAAC;QAC1B,IAAI,IAAI,KAAK,UAAU,EAAE,CAAC;YACxB,aAAa,CAAC,EAAE,CAAC,CAAC;QACpB,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,EAAE,GAAG,EAAE,OAAO,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;QAClC,CAAC;QACD,OAAO;IACT,CAAC;IAED,YAAY,CAAC,QAAQ,CAAC,CAAC;IACvB,MAAM,MAAM,GAAG,UAAU,CAAC,WAAW,CAAC,CAAC;IACvC,MAAM,QAAQ,GAAG,IAAI,gBAAgB,CAAC,MAAM,CAAC,CAAC;IAC9C,MAAM,MAAM,GAAG,oBAAoB,CAAC,QAAQ,CAAC,CAAC;IAC9C,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;IAC7C,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IAChC,wEAAwE;IACxE,2BAA2B;IAC3B,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,mDAAmD,WAAW,IAAI,CACnE,CAAC;AACJ,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,GAAY,EAAE,EAAE;IAC5B,MAAM,GAAG,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IAC7D,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,uCAAuC,GAAG,IAAI,CAAC,CAAC;IACrE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agent-composer",
3
- "version": "0.1.0",
3
+ "version": "0.1.2",
4
4
  "type": "module",
5
5
  "description": "Multi-agent orchestration MCP server. Claude orchestrates; GLM and agy do the work.",
6
6
  "bin": {
@@ -8,6 +8,7 @@
8
8
  },
9
9
  "files": [
10
10
  "dist/",
11
+ "plugin/",
11
12
  "composer.config.schema.json",
12
13
  "README.md"
13
14
  ],
@@ -0,0 +1,50 @@
1
+ # composer-mastermind
2
+
3
+ > Multi-agent orchestrator plugin for Claude Code. Claude orchestrates; GLM and agy execute.
4
+
5
+ ## What it is
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:
8
+
9
+ | Subagent | Tool | Role |
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) |
13
+ | `reviewer` | `mcp__composer__composer_review` | Code review via `agy` CLI |
14
+
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.
16
+
17
+ ## What's inside
18
+
19
+ ```
20
+ composer-mastermind/
21
+ ├── plugin.json # this manifest
22
+ ├── skills/composer-mastermind/SKILL.md # the orchestrator brain
23
+ ├── agents/ # haiku-wrapped subagent defs
24
+ │ ├── coder.md
25
+ │ ├── researcher.md
26
+ │ └── reviewer.md
27
+ ├── commands/
28
+ │ └── evolve.md # /evolve slash command (GEPA loop)
29
+ └── hooks/
30
+ ├── boundary_guard.sh # PreToolUse fail-closed boundary
31
+ └── learn.sh # Stop hook — append user corrections
32
+ ```
33
+
34
+ ## Requires
35
+
36
+ - `agent-composer` (peer; install via `npx agent-composer` or global npm install)
37
+ - A `composer.config.json` + `.env.json` at the consumer project root (run `npx composer-mcp init` to scaffold; see ADR 0002 M0.3)
38
+ - Claude Code ≥4.6
39
+
40
+ ## Self-evolution surface
41
+
42
+ `/evolve --eval-mode real` mutates only the project-local copy of `SKILL.md` (`.claude/skills/composer-mastermind/SKILL.md`), never the plugin install. Plugin updates ship via npm; per-project skill drift is intentional. See ADR 0003 for the full mutation scope contract (S1 diff-path, S2 deny-list, S3 stat gate, S4 human-promote, S5 audit trail).
43
+
44
+ ## Source of truth
45
+
46
+ This is the **frozen v0.1.0 snapshot** of the composer-monorepo's canonical assets. The development instance lives at the upstream repo's `.claude/` tree; releases re-sync via M0.5 (see `scripts/release-sync.mjs`).
47
+
48
+ ## License
49
+
50
+ MIT.
@@ -0,0 +1,27 @@
1
+ ---
2
+ name: coder
3
+ description: Use when the orchestrator needs code written, refactored, debugged, or implemented. Delegates the actual coding to the composer_code MCP tool.
4
+ tools: mcp__composer__composer_code, Read, Glob
5
+ model: haiku
6
+ ---
7
+
8
+ You are the Composer **Coder** subagent. Your only job is to call the
9
+ `composer_code` MCP tool with the orchestrator's implementation request
10
+ and return its output.
11
+
12
+ # What you DO
13
+
14
+ - Receive the orchestrator's `{ prompt, context? }` brief.
15
+ - Use `Read` / `Glob` to pin exact file paths, surrounding code, and
16
+ imports into the `prompt` / `context` arguments — the coder provider
17
+ cannot see the repo itself.
18
+ - Call `mcp__composer__composer_code` once.
19
+ - Return the tool output verbatim (usually a diff or code block).
20
+
21
+ # What you DO NOT do
22
+
23
+ - DO NOT write code yourself.
24
+ - DO NOT edit files.
25
+ - DO NOT execute commands.
26
+ - DO NOT call any tool other than `composer_code`, `Read`, or `Glob`.
27
+ - DO NOT critique the returned code — that is the reviewer's job.
@@ -0,0 +1,27 @@
1
+ ---
2
+ name: researcher
3
+ description: Use when the orchestrator needs research, documentation lookup, web search, current API shape, or any external context. Delegates the actual research to the composer_research MCP tool.
4
+ tools: mcp__composer__composer_research, Read, Glob
5
+ model: haiku
6
+ ---
7
+
8
+ You are the Composer **Researcher** subagent. Your only job is to call
9
+ the `composer_research` MCP tool with the user's question and return its
10
+ output to the orchestrator.
11
+
12
+ # What you DO
13
+
14
+ - Read the orchestrator's research question.
15
+ - Optionally use `Read` or `Glob` to quote the relevant file path or
16
+ snippet into the `prompt` argument so the research provider has the
17
+ exact context.
18
+ - Call `mcp__composer__composer_research` once with `{ prompt, context? }`.
19
+ - Return the tool output verbatim. Do NOT paraphrase, summarize, or
20
+ augment with your own knowledge.
21
+
22
+ # What you DO NOT do
23
+
24
+ - DO NOT search the web yourself.
25
+ - DO NOT speculate when the tool returns "unknown" — pass that through.
26
+ - DO NOT call any tool other than `composer_research`, `Read`, or `Glob`.
27
+ - DO NOT write, edit, or execute anything.
@@ -0,0 +1,27 @@
1
+ ---
2
+ name: reviewer
3
+ description: Use when the orchestrator needs code review, diff critique, or bug-finding on a candidate patch before integration. Delegates the actual review to the composer_review MCP tool.
4
+ tools: mcp__composer__composer_review, Read, Glob
5
+ model: haiku
6
+ ---
7
+
8
+ You are the Composer **Reviewer** subagent. Your only job is to call
9
+ the `composer_review` 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 reviewer provider.
18
+ - Call `mcp__composer__composer_review` once.
19
+ - Return the tool output verbatim (a list of findings, severity, line refs).
20
+
21
+ # What you DO NOT do
22
+
23
+ - DO NOT propose fixes — only flag issues.
24
+ - DO NOT edit, write, or execute anything.
25
+ - DO NOT call any tool other than `composer_review`, `Read`, or `Glob`.
26
+ - DO NOT soften or rephrase the reviewer's output — the orchestrator
27
+ needs the raw verdict.
@@ -0,0 +1,62 @@
1
+ # /evolve — autoresearch loop for composer-mastermind
2
+
3
+ Kick off GEPA-lite autoresearch to evolve the orchestrator skill (`.claude/skills/composer-mastermind/SKILL.md`). Runs a synthetic v1 scorer to propose improvements; writes the candidate to `.claude/skills/composer-mastermind/SKILL.candidate.md` for manual review.
4
+
5
+ ## Usage
6
+
7
+ ```bash
8
+ /evolve
9
+ # Defaults: budget $2.00, max 10 rounds.
10
+
11
+ /evolve --budget-usd 1.00 --max-rounds 5
12
+ # Custom spend cap and round limit.
13
+ ```
14
+
15
+ ## What it runs
16
+
17
+ Invokes `./node_modules/.bin/tsx scripts/run-evolve.ts` with parsed CLI arguments. The driver wires real providers (GLM 5.1 for reflection, `agy` CLI for research) and a synthetic scorer into `runEvolve()`.
18
+
19
+ ## Winner
20
+
21
+ If the evolve loop finds an improvement, the candidate is written to:
22
+ ```
23
+ .claude/skills/composer-mastermind/SKILL.candidate.md
24
+ ```
25
+
26
+ Promote manually after review:
27
+ ```bash
28
+ mv .claude/skills/composer-mastermind/SKILL.candidate.md \
29
+ .claude/skills/composer-mastermind/SKILL.md
30
+ ```
31
+
32
+ If no improvement is detected, the file is not written; the original SKILL.md stands.
33
+
34
+ ## Cost
35
+
36
+ Each provider call costs ~$0.025 (GLM reflection). The default $2.00 budget covers ~80 calls. Real spend routes through GLM coder and `agy` CLI per `composer.config.json` spend authorization settings.
37
+
38
+ ## Output
39
+
40
+ The summary prints to stdout:
41
+
42
+ - Round history table: `| round | operator | parentScore | candidateScore | promoted | reason |`
43
+ - `stoppedAt: <plateau|budget|maxRounds>`
44
+ - `postflight: accept=<true|false> reason="..."`
45
+ - `budgetStats: calls=N usd=$X.XXXX`
46
+ - Parent vs. winner score improvement
47
+
48
+ ## Safety
49
+
50
+ - Respects `composer.config.json` `spendAuthorization.maxUsdPerSession`. If `--budget-usd` exceeds the cap, the script exits with an error message and exit code 1 before spending.
51
+ - Loop termination is governed by `runEvolve()` itself: whichever of budget, plateau, or `--max-rounds` hits first. To abort mid-loop, send SIGINT (Ctrl-C); the script exits without writing `SKILL.candidate.md` unless the write step already completed.
52
+ - Task descriptions in `evals/tasks.jsonl` are passed verbatim to the reflection provider — keep that file under version control to retain a clear trust boundary.
53
+ - **SKILL.md edits are safe during a real-mode run.** Each task eval runs in a throwaway `git worktree` at `/tmp/composer-eval-<pid>-<taskId>`. The candidate skill is written only into the worktree copy; the real repo's SKILL.md is never touched during evaluation. You can freely edit SKILL.md in your editor while `/evolve --eval-mode real` is running.
54
+
55
+ ## v1 caveat
56
+
57
+ The v1 scorer is synthetic (heuristic-based):
58
+ - 0.4 points for substring "dispatch" (case-insensitive)
59
+ - 0.2 points for substring "Read" (case-sensitive, the tool name)
60
+ - 0.4 points scaled by character count (peak at 4000 chars, linear falloff to 0 outside 2000–6000)
61
+
62
+ Real eval-against-eval-tasks lands in v2.
@@ -0,0 +1,72 @@
1
+ #!/usr/bin/env bash
2
+ # Wave 1 F1.5 — Composer boundary enforcement (PreToolUse hook).
3
+ # Contract per docs/adr/0001-contracts.md §C0.4:
4
+ # stdin: Anthropic PreToolUse JSON
5
+ # stdout: optional {"permissionDecision":"deny"|"allow"|"ask", ...}
6
+ # exit: always 0; semantics carried by JSON
7
+ # Fail-closed: any unexpected condition (missing jq / empty stdin /
8
+ # malformed JSON / absent tool_name) MUST emit a deny payload.
9
+
10
+ set -u
11
+
12
+ emit_deny() {
13
+ local reason="$1"
14
+ jq -nc --arg r "$reason" \
15
+ '{hookEventName:"PreToolUse", permissionDecision:"deny", permissionDecisionReason:$r}' 2>/dev/null \
16
+ || printf '{"hookEventName":"PreToolUse","permissionDecision":"deny","permissionDecisionReason":"%s"}\n' "$reason"
17
+ exit 0
18
+ }
19
+
20
+ # 1. Dependency: jq is mandatory for safe JSON parsing.
21
+ if ! command -v jq >/dev/null 2>&1; then
22
+ # Cannot use emit_deny (depends on jq); inline fallback.
23
+ printf '{"hookEventName":"PreToolUse","permissionDecision":"deny","permissionDecisionReason":"boundary_guard: jq missing, failing closed"}\n'
24
+ exit 0
25
+ fi
26
+
27
+ # 2. Read tool-call JSON from stdin.
28
+ INPUT="$(cat || true)"
29
+ if [[ -z "$INPUT" ]]; then
30
+ emit_deny "boundary_guard: empty stdin, failing closed"
31
+ fi
32
+
33
+ # 3. Parse tool_name. jq surfaces parse errors to stderr (suppressed) and
34
+ # returns empty on missing/null — both treated as malformed.
35
+ TOOL="$(jq -r '.tool_name // empty' <<<"$INPUT" 2>/dev/null)"
36
+ if [[ -z "$TOOL" ]]; then
37
+ emit_deny "boundary_guard: malformed JSON or missing tool_name, failing closed"
38
+ fi
39
+
40
+ # 3.5. COMPOSER_DANGEROUSLY_BYPASS_PERMISSIONS (dev-only escape hatch).
41
+ # When env var equals "1" or "true", allow every tool. Stderr-warns on
42
+ # every invocation so the bypass is visible in transcripts. Intended
43
+ # for bootstrap / dev sessions only. NEVER set in CI or runtime.
44
+ # See ADR 0001 amendment (2026-05-23, Wave-3 Step 1).
45
+ BYPASS="${COMPOSER_DANGEROUSLY_BYPASS_PERMISSIONS:-}"
46
+ if [[ "$BYPASS" == "1" || "$BYPASS" == "true" ]]; then
47
+ printf 'WARN boundary_guard: COMPOSER_DANGEROUSLY_BYPASS_PERMISSIONS=%s — boundary disabled, dev mode only\n' "$BYPASS" >&2
48
+ exit 0
49
+ fi
50
+
51
+ # 3.6. STOP_EVOLVE killswitch.
52
+ # If sentinel file exists AND the tool is a composer dispatch, deny.
53
+ # Sentinel path overridable via COMPOSER_STOP_EVOLVE_FILE (tests use
54
+ # a temp file); default "$CLAUDE_PROJECT_DIR/STOP_EVOLVE", falling
55
+ # back to "./STOP_EVOLVE" when CLAUDE_PROJECT_DIR is unset.
56
+ STOP_FILE="${COMPOSER_STOP_EVOLVE_FILE:-${CLAUDE_PROJECT_DIR:-.}/STOP_EVOLVE}"
57
+ if [[ -e "$STOP_FILE" ]] && [[ "$TOOL" == mcp__composer__* ]]; then
58
+ emit_deny "STOP_EVOLVE sentinel present at $STOP_FILE — Composer dispatches paused."
59
+ fi
60
+
61
+ # 4. Block list — native dangerous tools + MCP-prefixed variants.
62
+ case "$TOOL" in
63
+ Bash|Edit|Write|NotebookEdit \
64
+ | mcp__*__write_file | mcp__*__edit_file | mcp__*__bash \
65
+ | mcp__*__write | mcp__*__edit | mcp__*__exec)
66
+ emit_deny "Composer orchestrator forbids direct ${TOOL}. Delegate via Task to researcher / coder / reviewer."
67
+ ;;
68
+ esac
69
+
70
+ # 5. Pass-through. Emit nothing — Anthropic treats absent JSON + exit 0
71
+ # as implicit allow. (Explicit allow JSON is also valid but noisier.)
72
+ exit 0
@@ -0,0 +1,51 @@
1
+ #!/usr/bin/env bash
2
+ # Wave 1 F1.11 — passive learning log (T1 self-evolution tier).
3
+ # Runs as a Stop hook. Appends correction-shaped user messages from the
4
+ # current session transcript into .claude/learnings/<month>.md.
5
+ #
6
+ # Fail-safe: any missing dependency, missing transcript, or parse error
7
+ # results in a silent no-op (exit 0). This MUST NOT block session-end.
8
+
9
+ set -u
10
+
11
+ PROJECT_DIR="${CLAUDE_PROJECT_DIR:-$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)}"
12
+ LEARN_DIR="$PROJECT_DIR/.claude/learnings"
13
+ MONTH="$(date +%Y-%m)"
14
+ OUT="$LEARN_DIR/${MONTH}.md"
15
+
16
+ # Read JSON envelope from stdin (Anthropic Stop hook contract).
17
+ INPUT="$(cat || true)"
18
+ if [[ -z "$INPUT" ]]; then
19
+ exit 0
20
+ fi
21
+
22
+ if ! command -v jq >/dev/null 2>&1; then
23
+ exit 0
24
+ fi
25
+
26
+ TRANSCRIPT_PATH="$(jq -r '.transcript_path // empty' <<<"$INPUT" 2>/dev/null)"
27
+ if [[ -z "$TRANSCRIPT_PATH" || ! -f "$TRANSCRIPT_PATH" ]]; then
28
+ exit 0
29
+ fi
30
+
31
+ mkdir -p "$LEARN_DIR" 2>/dev/null || exit 0
32
+
33
+ # Trigger words for "correction-shaped" user messages.
34
+ # Conservative regex; expand from real data over time.
35
+ TRIGGER='(?i)\b(no|don.t|do not|wrong|stop|actually|instead|never|please don.t)\b'
36
+
37
+ # Anthropic transcripts are JSONL (one event per line). Filter user-role
38
+ # events whose content matches the trigger regex, then append a short
39
+ # bullet per match. Truncate to 240 chars to keep the log scannable.
40
+ {
41
+ printf '\n## Session ended %s\n\n' "$(date -u +%Y-%m-%dT%H:%M:%SZ)"
42
+ jq -r --arg trig "$TRIGGER" '
43
+ select(.role == "user" or .type == "user")
44
+ | (.content // .message // "") as $raw
45
+ | (if ($raw | type) == "array" then ($raw | map(.text // "") | join(" ")) else ($raw | tostring) end) as $text
46
+ | select($text | test($trig))
47
+ | "- " + ($text | gsub("\\s+"; " ") | .[0:240])
48
+ ' "$TRANSCRIPT_PATH" 2>/dev/null
49
+ } >> "$OUT" 2>/dev/null || true
50
+
51
+ exit 0
@@ -0,0 +1,19 @@
1
+ {
2
+ "name": "composer-mastermind",
3
+ "version": "0.1.0",
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.",
5
+ "claudeCodeVersion": ">=4.6",
6
+ "requires": ["agent-composer"],
7
+ "settings": {
8
+ "PreToolUse": ["bash:hooks/boundary_guard.sh"],
9
+ "Stop": ["bash:hooks/learn.sh"]
10
+ },
11
+ "skills": ["skills/composer-mastermind/SKILL.md"],
12
+ "agents": [
13
+ "agents/coder.md",
14
+ "agents/researcher.md",
15
+ "agents/reviewer.md"
16
+ ],
17
+ "commands": ["commands/evolve.md"],
18
+ "license": "MIT"
19
+ }
@@ -0,0 +1,85 @@
1
+ ---
2
+ name: composer-mastermind
3
+ description: Use when the user asks for code, research, documentation lookup, or code review. Routes the work to the matching subagent (researcher / coder / reviewer) and keeps plan/integration context in the main session. This skill defines an orchestration pattern — it is not a standalone library or external SDK.
4
+ ---
5
+
6
+ # Composer Mastermind
7
+
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
11
+ resource in the entire system — spend it on planning, not on raw worker
12
+ output.
13
+
14
+ > **Note:** This is an orchestration *pattern*, not an external SDK or
15
+ > published framework. There is no library to install, no package to
16
+ > version-check, and no upstream changelog to monitor. All guidance below
17
+ > is about local session behaviour.
18
+
19
+ # Hard prohibitions
20
+
21
+ - **DO NOT** use `Edit`, `Write`, `Bash`, or `NotebookEdit`. If you
22
+ need any of these, delegate to a subagent or ask the user.
23
+ - **DO NOT** call `mcp__composer__composer_research`, `composer_code`,
24
+ or `composer_review` directly from the main session. **ALWAYS**
25
+ dispatch via the `Task` tool to the matching subagent so the worker's
26
+ context window stays isolated and only the summary returns to you.
27
+ - **NEVER** write code in the main session — not even a one-liner. Delegate to `coder`.
28
+ - **NEVER** speculate when a fact is needed. Delegate to `researcher`.
29
+ - **NEVER** integrate a candidate patch without review. Delegate to
30
+ `reviewer` first.
31
+
32
+ # Delegation rules (hard)
33
+
34
+ | If the user (or your plan) needs… | Use the `Task` tool to dispatch to |
35
+ |---|---|
36
+ | Information, docs, web search, current API shape, "what's the X best practice" | `researcher` subagent |
37
+ | Writing new code, refactoring, debugging, fixing a bug | `coder` subagent |
38
+ | Reviewing a candidate patch / diff / implementation | `reviewer` subagent |
39
+ | Anything that mutates state outside the conversation (push, deploy, install) | Escalate to the user. Do not act. |
40
+
41
+ For multi-step requests, dispatch in order: `researcher` → plan →
42
+ `coder` → `reviewer` → integrate. Each `Task` call returns only the
43
+ subagent's summary; you hold the plan across the chain.
44
+
45
+ **Dispatch calibration:** dispatch costs ~1.5k cache tokens for
46
+ skill+agent registry plus one Task roundtrip. The split saves tokens
47
+ when the worker's expected output exceeds inline cost — roughly when
48
+ you'd emit >500 output tokens, or when work touches files you haven't
49
+ pinned. For tiny clarifications / refusals / one-line answers,
50
+ **inline is correct**. Heavy work (multi-file code, real research,
51
+ multi-step refactors) is where dispatch pays. Trust your
52
+ expected-output estimate; if under 5 lines, just answer.
53
+
54
+ # Spend authorization
55
+
56
+ Read `composer.config.json` `spendAuthorization.mode` before any
57
+ dispatch that hits a real-money provider (`anthropic`,
58
+ `openai_compatible`):
59
+
60
+ - `interactive` (default if field omitted): state the budget, show
61
+ the planned call, ask the user `go` before invoking the worker.
62
+ - `auto`: dispatch without asking. Respect `maxUsdPerCall` and
63
+ `maxUsdPerSession` caps; refuse with a short message if either would
64
+ be exceeded.
65
+ - `deny`: refuse all dispatches to priced providers. Tell the user
66
+ the config blocks real spend and suggest flipping to `mock` or
67
+ recording a fixture.
68
+
69
+ CLI providers (`agy`) are billed separately by the user's own auth
70
+ and do not count toward these caps. Mock providers are always free.
71
+
72
+ # Token discipline
73
+
74
+ - You hold context, plans, and integration. Workers hold execution.
75
+ - A worker returning >2k tokens is a smell — re-issue with a tighter
76
+ prompt or break the request into smaller steps.
77
+ - Use `Read` / `Glob` / `Grep` yourself ONLY to pin file paths and line
78
+ numbers into the worker's prompt. Never read a full file into your
79
+ own context.
80
+ - When reporting worker results, quote one key line or give a
81
+ one-sentence outcome — never paste the full worker output back.
82
+
83
+ # Prior learnings
84
+
85
+ @.claude/learnings/index.md