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.
- package/dist/cli/init.d.ts +22 -0
- package/dist/cli/init.js +87 -0
- package/dist/cli/init.js.map +1 -1
- package/dist/cli/install-plugin.d.ts +24 -0
- package/dist/cli/install-plugin.js +124 -0
- package/dist/cli/install-plugin.js.map +1 -0
- package/dist/config/env.d.ts +6 -0
- package/dist/config/env.js +14 -3
- package/dist/config/env.js.map +1 -1
- package/dist/config/loader.js +12 -3
- package/dist/config/loader.js.map +1 -1
- package/dist/config/paths.d.ts +12 -0
- package/dist/config/paths.js +42 -0
- package/dist/config/paths.js.map +1 -0
- package/dist/index.js +8 -2
- package/dist/index.js.map +1 -1
- package/package.json +2 -1
- package/plugin/composer-mastermind/README.md +50 -0
- package/plugin/composer-mastermind/agents/coder.md +27 -0
- package/plugin/composer-mastermind/agents/researcher.md +27 -0
- package/plugin/composer-mastermind/agents/reviewer.md +27 -0
- package/plugin/composer-mastermind/commands/evolve.md +62 -0
- package/plugin/composer-mastermind/hooks/boundary_guard.sh +72 -0
- package/plugin/composer-mastermind/hooks/learn.sh +51 -0
- package/plugin/composer-mastermind/plugin.json +19 -0
- package/plugin/composer-mastermind/skills/composer-mastermind/SKILL.md +85 -0
package/dist/cli/init.d.ts
CHANGED
|
@@ -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))
|
package/dist/cli/init.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"init.js","sourceRoot":"","sources":["../../src/cli/init.ts"],"names":[],"mappings":"AAAA,6CAA6C;AAC7C,EAAE;AACF,yEAAyE;AACzE,yBAAyB;AACzB,qEAAqE;AACrE,yCAAyC;AACzC,qCAAqC;AACrC,yDAAyD;AACzD,EAAE;AACF,4EAA4E;AAC5E,gFAAgF;AAEhF,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAC7E,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;
|
|
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":"AAAA,kDAAkD;AAClD,EAAE;AACF,0EAA0E;AAC1E,sEAAsE;AACtE,sEAAsE;AACtE,EAAE;AACF,0EAA0E;AAC1E,oDAAoD;AAEpD,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,YAAY,EAAE,SAAS,EAAE,WAAW,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AACnH,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACnD,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAGzC;;;GAGG;AACH,MAAM,UAAU,sBAAsB;IACpC,MAAM,IAAI,GAAG,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;IACrD,OAAO,OAAO,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,qBAAqB,CAAC,CAAC;AACpE,CAAC;AASD;;;;;;;;;;GAUG;AACH,MAAM,UAAU,mBAAmB,CAAC,IAA0B;IAC5D,MAAM,GAAG,GAAG,IAAI,CAAC,eAAe,IAAI,sBAAsB,EAAE,CAAC;IAC7D,MAAM,UAAU,GAAG,IAAI,CAAC,UAAU,CAAC;IACnC,MAAM,KAAK,GAAe,EAAE,CAAC;IAE7B,KAAK,CAAC,IAAI,CAAC,OAAO,CAChB,IAAI,CAAC,GAAG,EAAE,qCAAqC,CAAC,EAChD,IAAI,CAAC,UAAU,EAAE,qCAAqC,CAAC,EACvD,8BAA8B,CAC/B,CAAC,CAAC;IAEH,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC;IACtC,IAAI,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;QAC1B,KAAK,MAAM,IAAI,IAAI,WAAW,CAAC,SAAS,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC;YACjD,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC;gBAAE,SAAS;YACpC,KAAK,CAAC,IAAI,CAAC,OAAO,CAChB,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,EACrB,IAAI,CAAC,UAAU,EAAE,QAAQ,EAAE,IAAI,CAAC,EAChC,SAAS,IAAI,EAAE,CAChB,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED,MAAM,WAAW,GAAG,IAAI,CAAC,GAAG,EAAE,UAAU,CAAC,CAAC;IAC1C,IAAI,UAAU,CAAC,WAAW,CAAC,EAAE,CAAC;QAC5B,KAAK,MAAM,IAAI,IAAI,WAAW,CAAC,WAAW,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC;YACnD,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC;gBAAE,SAAS;YACpC,KAAK,CAAC,IAAI,CAAC,OAAO,CAChB,IAAI,CAAC,WAAW,EAAE,IAAI,CAAC,EACvB,IAAI,CAAC,UAAU,EAAE,UAAU,EAAE,IAAI,CAAC,EAClC,YAAY,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC,EAAE,CACxC,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED,0DAA0D;IAC1D,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,EAAE,OAAO,EAAE,mBAAmB,CAAC,CAAC;IACxD,MAAM,QAAQ,GAAG,IAAI,CAAC,UAAU,EAAE,OAAO,EAAE,4BAA4B,CAAC,CAAC;IACzE,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,QAAQ,EAAE,wCAAwC,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;IACjG,KAAK,CAAC,IAAI,CAAC,gBAAgB,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC,CAAC;IAEnD,OAAO,KAAK,CAAC;AACf,CAAC;AAID,SAAS,OAAO,CAAC,OAAe,EAAE,QAAgB,EAAE,KAAa,EAAE,OAAiB,EAAE;IACpF,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;QACzB,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,mBAAmB,OAAO,EAAE,EAAE,CAAC;IAClF,CAAC;IACD,IAAI,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;QACzB,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,kCAAkC,EAAE,CAAC;IACxG,CAAC;IACD,SAAS,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAClD,YAAY,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;IAChC,IAAI,IAAI,CAAC,IAAI;QAAE,SAAS,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;IAC1C,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC;AAC5D,CAAC;AAED;;;GAGG;AACH,SAAS,gBAAgB,CAAC,UAAkB,EAAE,cAAsB;IAClE,MAAM,YAAY,GAAG,IAAI,CAAC,UAAU,EAAE,eAAe,CAAC,CAAC;IACvD,MAAM,OAAO,GAAG,8BAA8B,CAAC;IAC/C,MAAM,KAAK,GAAG;QACZ,OAAO;QACP,KAAK,EAAE,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,cAAc,EAAE,CAAC;KACtD,CAAC;IAEF,IAAI,OAAgC,CAAC;IACrC,IAAI,UAAU,CAAC,YAAY,CAAC,EAAE,CAAC;QAC7B,IAAI,CAAC;YACH,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,YAAY,EAAE,MAAM,CAAC,CAA4B,CAAC;QACtF,CAAC;QAAC,MAAM,CAAC;YACP,OAAO;gBACL,IAAI,EAAE,uCAAuC;gBAC7C,MAAM,EAAE,SAAS;gBACjB,IAAI,EAAE,YAAY;gBAClB,MAAM,EAAE,iDAAiD;aAC1D,CAAC;QACJ,CAAC;IACH,CAAC;SAAM,CAAC;QACN,SAAS,CAAC,OAAO,CAAC,YAAY,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACtD,OAAO,GAAG,EAAE,CAAC;IACf,CAAC;IAED,MAAM,KAAK,GAAI,OAAO,CAAC,OAAO,CAAyC,IAAI,EAAE,CAAC;IAC9E,MAAM,UAAU,GAAI,KAAK,CAAC,YAAY,CAAkF,IAAI,EAAE,CAAC;IAE/H,oFAAoF;IACpF,MAAM,YAAY,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,KAAK,cAAc,CAAC,CAAC,CAAC;IAChG,IAAI,YAAY,EAAE,CAAC;QACjB,OAAO;YACL,IAAI,EAAE,uCAAuC;YAC7C,MAAM,EAAE,SAAS;YACjB,IAAI,EAAE,YAAY;YAClB,MAAM,EAAE,4CAA4C;SACrD,CAAC;IACJ,CAAC;IAED,MAAM,cAAc,GAAG,CAAC,GAAG,UAAU,EAAE,KAAK,CAAC,CAAC;IAC9C,MAAM,SAAS,GAAG,EAAE,GAAG,KAAK,EAAE,UAAU,EAAE,cAAc,EAAE,CAAC;IAC3D,MAAM,IAAI,GAAG,EAAE,GAAG,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC;IAC9C,aAAa,CAAC,YAAY,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,EAAE,MAAM,CAAC,CAAC;IAC1E,OAAO;QACL,IAAI,EAAE,uCAAuC;QAC7C,MAAM,EAAE,SAAS;QACjB,IAAI,EAAE,YAAY;QAClB,MAAM,EAAE,+BAA+B,cAAc,EAAE;KACxD,CAAC;AACJ,CAAC"}
|
package/dist/config/env.d.ts
CHANGED
|
@@ -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;
|
package/dist/config/env.js
CHANGED
|
@@ -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
|
-
|
|
12
|
-
|
|
13
|
-
|
|
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 {
|
package/dist/config/env.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"env.js","sourceRoot":"","sources":["../../src/config/env.ts"],"names":[],"mappings":"AAAA,mCAAmC;AACnC,EAAE;AACF,oEAAoE;AACpE,wEAAwE;AACxE,wEAAwE;AACxE,wEAAwE;AACxE,2CAA2C;AAE3C,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"env.js","sourceRoot":"","sources":["../../src/config/env.ts"],"names":[],"mappings":"AAAA,mCAAmC;AACnC,EAAE;AACF,oEAAoE;AACpE,wEAAwE;AACxE,wEAAwE;AACxE,wEAAwE;AACxE,2CAA2C;AAE3C,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAa/C,MAAM,gBAAgB,GAAG,WAAW,CAAC;AAErC;;;;;GAKG;AACH,MAAM,UAAU,WAAW,CAAC,OAAgB;IAC1C,2EAA2E;IAC3E,0EAA0E;IAC1E,MAAM,QAAQ,GAAG,OAAO;QACtB,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC;QACvB,CAAC,CAAC,iBAAiB,CAAC,gBAAgB,CAAC,CAAC;IACxC,IAAI,CAAC,QAAQ,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC;QAAE,OAAO,EAAE,CAAC;IACrD,IAAI,GAAW,CAAC;IAChB,IAAI,CAAC;QACH,GAAG,GAAG,EAAE,CAAC,YAAY,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;IAC1C,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;IACD,IAAI,MAAe,CAAC;IACpB,IAAI,CAAC;QACH,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAC3B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;IACD,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,MAAM,KAAK,IAAI;QAAE,OAAO,EAAE,CAAC;IAC7D,MAAM,GAAG,GAAG,MAAiC,CAAC;IAC9C,MAAM,MAAM,GAAgB,EAAE,CAAC;IAC/B,IAAI,OAAO,GAAG,CAAC,sBAAsB,CAAC,KAAK,QAAQ,EAAE,CAAC;QACpD,MAAM,CAAC,oBAAoB,GAAG,GAAG,CAAC,sBAAsB,CAAC,CAAC;IAC5D,CAAC;IACD,IAAI,OAAO,GAAG,CAAC,oBAAoB,CAAC,KAAK,QAAQ,EAAE,CAAC;QAClD,MAAM,CAAC,kBAAkB,GAAG,GAAG,CAAC,oBAAoB,CAAC,CAAC;IACxD,CAAC;IACD,IAAI,OAAO,GAAG,CAAC,iBAAiB,CAAC,KAAK,QAAQ,EAAE,CAAC;QAC/C,MAAM,CAAC,eAAe,GAAG,GAAG,CAAC,iBAAiB,CAAC,CAAC;IAClD,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,OAAgB;IAC3C,MAAM,GAAG,GAAG,WAAW,CAAC,OAAO,CAAC,CAAC;IACjC,KAAK,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;QACzC,IAAI,OAAO,CAAC,KAAK,QAAQ,IAAI,CAAC,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;YAC7D,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;QACrB,CAAC;IACH,CAAC;AACH,CAAC;AAED,MAAM,UAAU,MAAM;IACpB,MAAM,MAAM,GAAgB,EAAE,CAAC;IAC/B,MAAM,CAAC,GAAG,OAAO,CAAC,GAAG,CAAC,sBAAsB,CAAC,CAAC;IAC9C,MAAM,CAAC,GAAG,OAAO,CAAC,GAAG,CAAC,oBAAoB,CAAC,CAAC;IAC5C,MAAM,CAAC,GAAG,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAC;IACzC,IAAI,OAAO,CAAC,KAAK,QAAQ,IAAI,CAAC,CAAC,MAAM,GAAG,CAAC;QAAE,MAAM,CAAC,oBAAoB,GAAG,CAAC,CAAC;IAC3E,IAAI,OAAO,CAAC,KAAK,QAAQ,IAAI,CAAC,CAAC,MAAM,GAAG,CAAC;QAAE,MAAM,CAAC,kBAAkB,GAAG,CAAC,CAAC;IACzE,IAAI,OAAO,CAAC,KAAK,QAAQ,IAAI,CAAC,CAAC,MAAM,GAAG,CAAC;QAAE,MAAM,CAAC,eAAe,GAAG,CAAC,CAAC;IACtE,OAAO,MAAM,CAAC;AAChB,CAAC"}
|
package/dist/config/loader.js
CHANGED
|
@@ -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
|
-
|
|
20
|
-
|
|
21
|
-
|
|
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;
|
|
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
|
-
|
|
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;
|
|
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.
|
|
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
|