kairn-cli 2.2.2 → 2.2.3
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.js +50 -4
- package/dist/cli.js.map +1 -1
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -4031,6 +4031,13 @@ async function snapshotBaseline(projectRoot, workspacePath) {
|
|
|
4031
4031
|
}
|
|
4032
4032
|
await copyDir(claudeDir, baselineDir);
|
|
4033
4033
|
await copyDir(claudeDir, iter0Dir);
|
|
4034
|
+
const mcpJsonPath = path16.join(projectRoot, ".mcp.json");
|
|
4035
|
+
try {
|
|
4036
|
+
await fs16.access(mcpJsonPath);
|
|
4037
|
+
await fs16.copyFile(mcpJsonPath, path16.join(baselineDir, ".mcp.json"));
|
|
4038
|
+
await fs16.copyFile(mcpJsonPath, path16.join(iter0Dir, ".mcp.json"));
|
|
4039
|
+
} catch {
|
|
4040
|
+
}
|
|
4034
4041
|
}
|
|
4035
4042
|
async function copyDir(src, dest) {
|
|
4036
4043
|
await fs16.mkdir(dest, { recursive: true });
|
|
@@ -4353,6 +4360,11 @@ async function scoreTask(task, workspacePath, stdout, stderr, config) {
|
|
|
4353
4360
|
// src/evolve/runner.ts
|
|
4354
4361
|
var execAsync2 = promisify2(exec2);
|
|
4355
4362
|
var COPY_SKIP_DIRS = /* @__PURE__ */ new Set([".git", "node_modules", ".kairn-evolve", ".claude"]);
|
|
4363
|
+
async function deployMcpJson(harnessPath, workDir) {
|
|
4364
|
+
const src = path18.join(harnessPath, ".mcp.json");
|
|
4365
|
+
await fs18.copyFile(src, path18.join(workDir, ".mcp.json")).catch(() => {
|
|
4366
|
+
});
|
|
4367
|
+
}
|
|
4356
4368
|
async function createIsolatedWorkspace(projectRoot, harnessPath) {
|
|
4357
4369
|
const suffix = `${Date.now()}-${Math.random().toString(36).slice(2)}`;
|
|
4358
4370
|
try {
|
|
@@ -4367,6 +4379,7 @@ async function createIsolatedWorkspace(projectRoot, harnessPath) {
|
|
|
4367
4379
|
});
|
|
4368
4380
|
await fs18.rm(path18.join(tmpDir2, ".claude"), { recursive: true, force: true });
|
|
4369
4381
|
await copyDir(harnessPath, path18.join(tmpDir2, ".claude"));
|
|
4382
|
+
await deployMcpJson(harnessPath, tmpDir2);
|
|
4370
4383
|
return { workDir: tmpDir2, isWorktree: true };
|
|
4371
4384
|
} catch {
|
|
4372
4385
|
}
|
|
@@ -4374,6 +4387,7 @@ async function createIsolatedWorkspace(projectRoot, harnessPath) {
|
|
|
4374
4387
|
await copyProjectDir(projectRoot, tmpDir);
|
|
4375
4388
|
await fs18.rm(path18.join(tmpDir, ".claude"), { recursive: true, force: true });
|
|
4376
4389
|
await copyDir(harnessPath, path18.join(tmpDir, ".claude"));
|
|
4390
|
+
await deployMcpJson(harnessPath, tmpDir);
|
|
4377
4391
|
return { workDir: tmpDir, isWorktree: false };
|
|
4378
4392
|
}
|
|
4379
4393
|
async function copyProjectDir(src, dest) {
|
|
@@ -4623,23 +4637,37 @@ minimal changes to the harness files that will fix those failures.
|
|
|
4623
4637
|
|
|
4624
4638
|
3. Check history for counterfactual evidence
|
|
4625
4639
|
|
|
4640
|
+
## Available Mutation Actions
|
|
4641
|
+
1. **replace** \u2014 Replace old_text with new_text in a file: { "file": "...", "action": "replace", "old_text": "...", "new_text": "...", "rationale": "..." }
|
|
4642
|
+
2. **add_section** \u2014 Append new content to a file (or create it): { "file": "...", "action": "add_section", "new_text": "...", "rationale": "..." }
|
|
4643
|
+
3. **create_file** \u2014 Create a new file: { "file": "...", "action": "create_file", "new_text": "...", "rationale": "..." }
|
|
4644
|
+
4. **delete_section** \u2014 Remove specific text from a file: { "file": "...", "action": "delete_section", "old_text": "...", "rationale": "..." }
|
|
4645
|
+
5. **delete_file** \u2014 Delete an entire file: { "file": "...", "action": "delete_file", "rationale": "..." }
|
|
4646
|
+
|
|
4626
4647
|
## Output Format
|
|
4627
4648
|
Return a JSON object:
|
|
4628
4649
|
{
|
|
4629
4650
|
"reasoning": "Your full causal analysis...",
|
|
4630
4651
|
"mutations": [
|
|
4631
4652
|
{ "file": "CLAUDE.md", "action": "replace", "old_text": "...", "new_text": "...", "rationale": "..." },
|
|
4632
|
-
{ "file": "commands/develop.md", "action": "add_section", "new_text": "...", "rationale": "..." }
|
|
4653
|
+
{ "file": "commands/develop.md", "action": "add_section", "new_text": "...", "rationale": "..." },
|
|
4654
|
+
{ "file": "rules/obsolete.md", "action": "delete_file", "rationale": "..." }
|
|
4633
4655
|
],
|
|
4634
4656
|
"expected_impact": { "task-id": "+15% \u2014 explanation" }
|
|
4635
4657
|
}
|
|
4636
4658
|
|
|
4659
|
+
## MCP Configuration
|
|
4660
|
+
You can also mutate .mcp.json to add, remove, or reconfigure MCP servers.
|
|
4661
|
+
Treat .mcp.json like any other harness file \u2014 propose changes when traces show
|
|
4662
|
+
the agent lacks a tool it needs, or has tools that add noise without benefit.
|
|
4663
|
+
|
|
4637
4664
|
## Rules
|
|
4638
4665
|
- MINIMAL changes only. Don't rewrite the entire CLAUDE.md.
|
|
4639
4666
|
- Each mutation must have a clear rationale tied to a specific trace observation.
|
|
4640
4667
|
- Never remove something that's working for another task.
|
|
4641
4668
|
- If a previous iteration's change caused a regression, REVERT it.
|
|
4642
|
-
-
|
|
4669
|
+
- Consider both additions AND removals. Remove sections that add noise without improving task performance.
|
|
4670
|
+
- Bloated harnesses hurt performance \u2014 trim what isn't earning its keep.
|
|
4643
4671
|
|
|
4644
4672
|
Return ONLY valid JSON.`;
|
|
4645
4673
|
var STDOUT_TRUNCATION_LIMIT = 1e3;
|
|
@@ -4830,10 +4858,11 @@ function parseProposerResponse(raw) {
|
|
|
4830
4858
|
if (file.includes("..")) {
|
|
4831
4859
|
continue;
|
|
4832
4860
|
}
|
|
4833
|
-
|
|
4861
|
+
const validActions = /* @__PURE__ */ new Set(["replace", "add_section", "create_file", "delete_section", "delete_file"]);
|
|
4862
|
+
if (!validActions.has(action)) {
|
|
4834
4863
|
continue;
|
|
4835
4864
|
}
|
|
4836
|
-
if (action === "replace" && !oldText) {
|
|
4865
|
+
if ((action === "replace" || action === "delete_section") && !oldText) {
|
|
4837
4866
|
continue;
|
|
4838
4867
|
}
|
|
4839
4868
|
const mutation = {
|
|
@@ -4912,6 +4941,23 @@ async function applyMutations(currentHarnessPath, nextIterationDir, mutations) {
|
|
|
4912
4941
|
} else if (mutation.action === "create_file") {
|
|
4913
4942
|
await fs20.mkdir(path20.dirname(filePath), { recursive: true });
|
|
4914
4943
|
await fs20.writeFile(filePath, mutation.newText, "utf-8");
|
|
4944
|
+
} else if (mutation.action === "delete_section") {
|
|
4945
|
+
if (!mutation.oldText) {
|
|
4946
|
+
continue;
|
|
4947
|
+
}
|
|
4948
|
+
let sectionContent;
|
|
4949
|
+
try {
|
|
4950
|
+
sectionContent = await fs20.readFile(filePath, "utf-8");
|
|
4951
|
+
} catch {
|
|
4952
|
+
continue;
|
|
4953
|
+
}
|
|
4954
|
+
if (!sectionContent.includes(mutation.oldText)) {
|
|
4955
|
+
continue;
|
|
4956
|
+
}
|
|
4957
|
+
await fs20.writeFile(filePath, sectionContent.replace(mutation.oldText, ""), "utf-8");
|
|
4958
|
+
} else if (mutation.action === "delete_file") {
|
|
4959
|
+
await fs20.unlink(filePath).catch(() => {
|
|
4960
|
+
});
|
|
4915
4961
|
}
|
|
4916
4962
|
}
|
|
4917
4963
|
const diffPatch = await generateDiff2(currentHarnessPath, newHarnessPath);
|