opencode-swarm 7.107.1 → 7.107.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/{curator-np2ky29t.js → curator-6zvpn7fs.js} +2 -2
- package/dist/cli/{curator-llm-factory-gdhtm1hh.js → curator-llm-factory-r3m5e7n8.js} +2 -2
- package/dist/cli/{evidence-summary-service-dh44gevz.js → evidence-summary-service-7nwhd8s4.js} +1 -1
- package/dist/cli/{guardrail-explain-414smfg4.js → guardrail-explain-zajegz3a.js} +3 -3
- package/dist/cli/{hive-promoter-y9r8d315.js → hive-promoter-nwcsha2j.js} +2 -2
- package/dist/cli/{index-gt514nt1.js → index-168p3bfr.js} +541 -420
- package/dist/cli/{index-jjp5qrjv.js → index-f12bmedv.js} +10 -9
- package/dist/cli/{index-7v734syt.js → index-jr54w7pb.js} +1 -1
- package/dist/cli/{index-87d4wsv9.js → index-r87xhtmx.js} +3 -3
- package/dist/cli/index.js +2 -2
- package/dist/commands/handoff.d.ts +2 -1
- package/dist/commands/registry.d.ts +4 -4
- package/dist/config/bundled-skills.d.ts +3 -5
- package/dist/index.js +269 -260
- package/dist/session/snapshot-writer.d.ts +4 -0
- package/dist/tools/external-skill-discover.d.ts +11 -0
- package/dist/tools/pre-check-batch.d.ts +4 -0
- package/dist/turbo/lean/evidence.d.ts +22 -0
- package/dist/turbo/lean/integration.d.ts +6 -1
- package/dist/turbo/lean/reviewer.d.ts +6 -1
- package/dist/turbo/lean/runner.d.ts +10 -1
- package/dist/utils/untrusted-markdown.d.ts +1 -0
- package/dist/worktree/merge.d.ts +1 -0
- package/package.json +1 -1
|
@@ -44,7 +44,7 @@ import {
|
|
|
44
44
|
savePlan,
|
|
45
45
|
transientBackoff,
|
|
46
46
|
validateProjectRoot
|
|
47
|
-
} from "./index-
|
|
47
|
+
} from "./index-f12bmedv.js";
|
|
48
48
|
import {
|
|
49
49
|
_internals as _internals2,
|
|
50
50
|
_internals1 as _internals3,
|
|
@@ -724,7 +724,7 @@ var init_restricted_environment_executor = __esm(() => {
|
|
|
724
724
|
|
|
725
725
|
// src/sandbox/win32/native-sandbox-executor.ts
|
|
726
726
|
import * as crypto3 from "crypto";
|
|
727
|
-
import * as
|
|
727
|
+
import * as fs12 from "fs";
|
|
728
728
|
import * as os10 from "os";
|
|
729
729
|
import * as path36 from "path";
|
|
730
730
|
|
|
@@ -790,10 +790,10 @@ class NativeWindowsSandboxExecutor {
|
|
|
790
790
|
const policyJson = JSON.stringify(policy);
|
|
791
791
|
const policyDir = path36.join(os10.tmpdir(), "swarm-sandbox-policies");
|
|
792
792
|
try {
|
|
793
|
-
|
|
793
|
+
fs12.mkdirSync(policyDir, { recursive: true });
|
|
794
794
|
} catch {}
|
|
795
795
|
const policyFile = path36.join(policyDir, `${runId}.json`);
|
|
796
|
-
|
|
796
|
+
fs12.writeFileSync(policyFile, policyJson, "utf-8");
|
|
797
797
|
const mode = this._probeResult.mode === "none" ? "auto" : this._probeResult.mode;
|
|
798
798
|
const escapedBinary = binary.includes(" ") ? `"${binary}"` : binary;
|
|
799
799
|
const escapedPolicyFile = policyFile.includes(" ") ? `"${policyFile}"` : policyFile;
|
|
@@ -924,7 +924,7 @@ var init_executor = __esm(() => {
|
|
|
924
924
|
});
|
|
925
925
|
|
|
926
926
|
// src/state.ts
|
|
927
|
-
import * as
|
|
927
|
+
import * as fs32 from "fs/promises";
|
|
928
928
|
import * as path68 from "path";
|
|
929
929
|
|
|
930
930
|
// src/db/qa-gate-profile.ts
|
|
@@ -5646,7 +5646,7 @@ function getDeferredWarnings() {
|
|
|
5646
5646
|
}
|
|
5647
5647
|
|
|
5648
5648
|
// src/config/bundled-skills.ts
|
|
5649
|
-
import
|
|
5649
|
+
import { randomUUID as randomUUID3 } from "crypto";
|
|
5650
5650
|
import * as fsp from "fs/promises";
|
|
5651
5651
|
import * as path8 from "path";
|
|
5652
5652
|
var BUNDLED_PROJECT_SKILLS = [
|
|
@@ -5679,10 +5679,6 @@ var BUNDLED_PROJECT_SKILLS = [
|
|
|
5679
5679
|
];
|
|
5680
5680
|
var MAX_SKILL_FILES = 64;
|
|
5681
5681
|
var MAX_SKILL_BYTES = 512000;
|
|
5682
|
-
var syncedProjectSkillTargets = new Set;
|
|
5683
|
-
function getSyncCacheKey(projectDirectory, packageRoot) {
|
|
5684
|
-
return `${path8.resolve(projectDirectory)}\x00${path8.resolve(packageRoot)}`;
|
|
5685
|
-
}
|
|
5686
5682
|
function warnBundledSkillSyncFailure(err) {
|
|
5687
5683
|
const message = err instanceof Error ? err.message : String(err);
|
|
5688
5684
|
console.warn(`[opencode-swarm] Could not install bundled project skills; continuing without sync: ${message}`);
|
|
@@ -5737,7 +5733,7 @@ async function collectBundledSkillFilesBoundedAsync(sourceDir, state, relativeDi
|
|
|
5737
5733
|
}
|
|
5738
5734
|
return files;
|
|
5739
5735
|
}
|
|
5740
|
-
async function rollbackCopiedFilesAsync(copiedFiles, destDir) {
|
|
5736
|
+
async function rollbackCopiedFilesAsync(copiedFiles, destDir, overwrittenFiles = []) {
|
|
5741
5737
|
const safeDestDir = path8.resolve(destDir);
|
|
5742
5738
|
const dirs = new Set;
|
|
5743
5739
|
for (const copiedFile of copiedFiles) {
|
|
@@ -5750,6 +5746,15 @@ async function rollbackCopiedFilesAsync(copiedFiles, destDir) {
|
|
|
5750
5746
|
} catch {}
|
|
5751
5747
|
dirs.add(path8.dirname(resolvedFile));
|
|
5752
5748
|
}
|
|
5749
|
+
for (const overwritten of overwrittenFiles.reverse()) {
|
|
5750
|
+
const resolvedFile = path8.resolve(overwritten.path);
|
|
5751
|
+
const relative2 = path8.relative(safeDestDir, resolvedFile);
|
|
5752
|
+
if (relative2.startsWith("..") || path8.isAbsolute(relative2))
|
|
5753
|
+
continue;
|
|
5754
|
+
try {
|
|
5755
|
+
await fsp.writeFile(resolvedFile, overwritten.contents);
|
|
5756
|
+
} catch {}
|
|
5757
|
+
}
|
|
5753
5758
|
for (const dir of [...dirs].sort((a, b) => b.length - a.length)) {
|
|
5754
5759
|
const relative2 = path8.relative(safeDestDir, path8.resolve(dir));
|
|
5755
5760
|
if (relative2.startsWith("..") || path8.isAbsolute(relative2))
|
|
@@ -5759,39 +5764,58 @@ async function rollbackCopiedFilesAsync(copiedFiles, destDir) {
|
|
|
5759
5764
|
} catch {}
|
|
5760
5765
|
}
|
|
5761
5766
|
}
|
|
5767
|
+
async function copyFileAtomicAsync(sourcePath, destPath) {
|
|
5768
|
+
const tempPath = path8.join(path8.dirname(destPath), `.${path8.basename(destPath)}.tmp.${randomUUID3()}`);
|
|
5769
|
+
try {
|
|
5770
|
+
await fsp.copyFile(sourcePath, tempPath);
|
|
5771
|
+
await fsp.rename(tempPath, destPath);
|
|
5772
|
+
} catch (err) {
|
|
5773
|
+
try {
|
|
5774
|
+
await fsp.rm(tempPath, { force: true });
|
|
5775
|
+
} catch {}
|
|
5776
|
+
throw err;
|
|
5777
|
+
}
|
|
5778
|
+
}
|
|
5762
5779
|
async function copyBundledDirectoryBoundedAsync(sourceDir, destDir) {
|
|
5763
5780
|
const files = await collectBundledSkillFilesBoundedAsync(sourceDir, {
|
|
5764
5781
|
files: 0,
|
|
5765
5782
|
bytes: 0
|
|
5766
5783
|
});
|
|
5767
5784
|
const copiedFiles = [];
|
|
5785
|
+
const overwrittenFiles = [];
|
|
5768
5786
|
try {
|
|
5769
5787
|
for (const file of files) {
|
|
5770
5788
|
const sourcePath = path8.join(sourceDir, file.relativePath);
|
|
5771
5789
|
const destPath = path8.join(destDir, file.relativePath);
|
|
5772
5790
|
await fsp.mkdir(path8.dirname(destPath), { recursive: true });
|
|
5773
|
-
|
|
5774
|
-
await
|
|
5791
|
+
if (await pathExistsAsync(destPath)) {
|
|
5792
|
+
if (await isSymbolicLinkAsync(destPath)) {
|
|
5793
|
+
throw new Error("refusing to overwrite symlinked bundled skill file");
|
|
5794
|
+
}
|
|
5795
|
+
const [sourceContents, destContents] = await Promise.all([
|
|
5796
|
+
fsp.readFile(sourcePath),
|
|
5797
|
+
fsp.readFile(destPath)
|
|
5798
|
+
]);
|
|
5799
|
+
if (sourceContents.equals(destContents)) {
|
|
5800
|
+
continue;
|
|
5801
|
+
}
|
|
5802
|
+
overwrittenFiles.push({ path: destPath, contents: destContents });
|
|
5803
|
+
await copyFileAtomicAsync(sourcePath, destPath);
|
|
5804
|
+
} else {
|
|
5805
|
+
await copyFileAtomicAsync(sourcePath, destPath);
|
|
5775
5806
|
copiedFiles.push(destPath);
|
|
5776
|
-
} catch (err) {
|
|
5777
|
-
if (err.code !== "EEXIST")
|
|
5778
|
-
throw err;
|
|
5779
5807
|
}
|
|
5780
5808
|
}
|
|
5781
5809
|
} catch (err) {
|
|
5782
|
-
await rollbackCopiedFilesAsync(copiedFiles, destDir);
|
|
5810
|
+
await rollbackCopiedFilesAsync(copiedFiles, destDir, overwrittenFiles);
|
|
5783
5811
|
throw err;
|
|
5784
5812
|
}
|
|
5785
5813
|
}
|
|
5786
5814
|
async function syncBundledProjectSkillsIfMissingAsync(projectDirectory, packageRoot, quiet = false) {
|
|
5787
5815
|
try {
|
|
5788
|
-
const cacheKey = getSyncCacheKey(projectDirectory, packageRoot);
|
|
5789
|
-
if (syncedProjectSkillTargets.has(cacheKey))
|
|
5790
|
-
return;
|
|
5791
5816
|
const sourceRoot = path8.join(packageRoot, ".opencode", "skills");
|
|
5792
5817
|
const opencodeDir = path8.join(projectDirectory, ".opencode");
|
|
5793
5818
|
const skillsDir = path8.join(opencodeDir, "skills");
|
|
5794
|
-
let sawBundledSource = false;
|
|
5795
5819
|
if (!await ensureNotSymlinkedDirectoryAsync(opencodeDir))
|
|
5796
5820
|
return;
|
|
5797
5821
|
if (!await ensureNotSymlinkedDirectoryAsync(skillsDir))
|
|
@@ -5800,21 +5824,15 @@ async function syncBundledProjectSkillsIfMissingAsync(projectDirectory, packageR
|
|
|
5800
5824
|
const sourceDir = path8.join(sourceRoot, slug);
|
|
5801
5825
|
const sourceSkill = path8.join(sourceDir, "SKILL.md");
|
|
5802
5826
|
const destDir = path8.join(skillsDir, slug);
|
|
5803
|
-
const destSkill = path8.join(destDir, "SKILL.md");
|
|
5804
5827
|
if (!await pathExistsAsync(sourceSkill))
|
|
5805
5828
|
continue;
|
|
5806
|
-
sawBundledSource = true;
|
|
5807
|
-
if (await pathExistsAsync(destSkill))
|
|
5808
|
-
continue;
|
|
5809
5829
|
if (!await ensureNotSymlinkedDirectoryAsync(destDir))
|
|
5810
5830
|
continue;
|
|
5811
5831
|
await copyBundledDirectoryBoundedAsync(sourceDir, destDir);
|
|
5812
5832
|
if (!quiet) {
|
|
5813
|
-
console.warn(`[opencode-swarm]
|
|
5833
|
+
console.warn(`[opencode-swarm] Synchronized bundled skill .opencode/skills/${slug}/SKILL.md for first-class /swarm command support`);
|
|
5814
5834
|
}
|
|
5815
5835
|
}
|
|
5816
|
-
if (sawBundledSource)
|
|
5817
|
-
syncedProjectSkillTargets.add(cacheKey);
|
|
5818
5836
|
} catch (err) {
|
|
5819
5837
|
if (!quiet)
|
|
5820
5838
|
warnBundledSkillSyncFailure(err);
|
|
@@ -6092,7 +6110,7 @@ async function handleAutoProceedCommand(_directory, args, sessionID) {
|
|
|
6092
6110
|
}
|
|
6093
6111
|
|
|
6094
6112
|
// src/services/cost-accounting.ts
|
|
6095
|
-
import * as
|
|
6113
|
+
import * as fs2 from "fs";
|
|
6096
6114
|
import * as os5 from "os";
|
|
6097
6115
|
import * as path10 from "path";
|
|
6098
6116
|
function summarizeTelemetryCosts(directory) {
|
|
@@ -6110,15 +6128,15 @@ function readTelemetryEvents(directory) {
|
|
|
6110
6128
|
path10.join(swarmDir, "telemetry.jsonl.1"),
|
|
6111
6129
|
path10.join(swarmDir, "telemetry.jsonl")
|
|
6112
6130
|
];
|
|
6113
|
-
const tmpDir =
|
|
6131
|
+
const tmpDir = fs2.mkdtempSync(path10.join(os5.tmpdir(), "telemetry-snapshot-"));
|
|
6114
6132
|
const snapshotFiles = [];
|
|
6115
6133
|
try {
|
|
6116
6134
|
for (const file of files) {
|
|
6117
|
-
if (!
|
|
6135
|
+
if (!fs2.existsSync(file))
|
|
6118
6136
|
continue;
|
|
6119
6137
|
const snap = path10.join(tmpDir, path10.basename(file));
|
|
6120
6138
|
try {
|
|
6121
|
-
|
|
6139
|
+
fs2.copyFileSync(file, snap);
|
|
6122
6140
|
snapshotFiles.push(snap);
|
|
6123
6141
|
} catch {}
|
|
6124
6142
|
}
|
|
@@ -6127,7 +6145,7 @@ function readTelemetryEvents(directory) {
|
|
|
6127
6145
|
for (const file of snapshotFiles) {
|
|
6128
6146
|
let content = "";
|
|
6129
6147
|
try {
|
|
6130
|
-
content =
|
|
6148
|
+
content = fs2.readFileSync(file, "utf-8");
|
|
6131
6149
|
} catch {
|
|
6132
6150
|
continue;
|
|
6133
6151
|
}
|
|
@@ -6145,10 +6163,10 @@ function readTelemetryEvents(directory) {
|
|
|
6145
6163
|
try {
|
|
6146
6164
|
for (const f of snapshotFiles) {
|
|
6147
6165
|
try {
|
|
6148
|
-
|
|
6166
|
+
fs2.unlinkSync(f);
|
|
6149
6167
|
} catch {}
|
|
6150
6168
|
}
|
|
6151
|
-
|
|
6169
|
+
fs2.rmdirSync(tmpDir);
|
|
6152
6170
|
} catch {}
|
|
6153
6171
|
return events;
|
|
6154
6172
|
}
|
|
@@ -6672,7 +6690,7 @@ async function handleBrainstormCommand(_directory, args) {
|
|
|
6672
6690
|
|
|
6673
6691
|
// src/tools/checkpoint.ts
|
|
6674
6692
|
import * as child_process from "child_process";
|
|
6675
|
-
import * as
|
|
6693
|
+
import * as fs3 from "fs";
|
|
6676
6694
|
import * as path11 from "path";
|
|
6677
6695
|
|
|
6678
6696
|
// src/tools/create-tool.ts
|
|
@@ -6765,8 +6783,8 @@ function getCheckpointLogPath(directory) {
|
|
|
6765
6783
|
function readCheckpointLog(directory) {
|
|
6766
6784
|
const logPath = getCheckpointLogPath(directory);
|
|
6767
6785
|
try {
|
|
6768
|
-
if (
|
|
6769
|
-
const content =
|
|
6786
|
+
if (fs3.existsSync(logPath)) {
|
|
6787
|
+
const content = fs3.readFileSync(logPath, "utf-8");
|
|
6770
6788
|
const parsed = JSON.parse(content);
|
|
6771
6789
|
if (!parsed.checkpoints || !Array.isArray(parsed.checkpoints)) {
|
|
6772
6790
|
return { version: 1, checkpoints: [] };
|
|
@@ -6779,12 +6797,12 @@ function readCheckpointLog(directory) {
|
|
|
6779
6797
|
function writeCheckpointLog(log2, directory) {
|
|
6780
6798
|
const logPath = getCheckpointLogPath(directory);
|
|
6781
6799
|
const dir = path11.dirname(logPath);
|
|
6782
|
-
if (!
|
|
6783
|
-
|
|
6800
|
+
if (!fs3.existsSync(dir)) {
|
|
6801
|
+
fs3.mkdirSync(dir, { recursive: true });
|
|
6784
6802
|
}
|
|
6785
6803
|
const tempPath = `${logPath}.tmp`;
|
|
6786
|
-
|
|
6787
|
-
|
|
6804
|
+
fs3.writeFileSync(tempPath, JSON.stringify(log2, null, 2), "utf-8");
|
|
6805
|
+
fs3.renameSync(tempPath, logPath);
|
|
6788
6806
|
}
|
|
6789
6807
|
function gitExec(args, cwd) {
|
|
6790
6808
|
for (let attempt = 0;attempt < MAX_TRANSIENT_RETRIES; attempt++) {
|
|
@@ -6818,7 +6836,7 @@ function appendRetentionEvent(directory, event) {
|
|
|
6818
6836
|
const eventsPath = path11.join(directory, ".swarm", "events.jsonl");
|
|
6819
6837
|
const line = `${JSON.stringify({ ...event, timestamp: new Date().toISOString() })}
|
|
6820
6838
|
`;
|
|
6821
|
-
|
|
6839
|
+
fs3.appendFileSync(eventsPath, line);
|
|
6822
6840
|
} catch {}
|
|
6823
6841
|
}
|
|
6824
6842
|
function getCurrentSha(directory) {
|
|
@@ -6922,13 +6940,13 @@ function handleRestore(label, directory) {
|
|
|
6922
6940
|
error: `checkpoint not found: "${label}"`
|
|
6923
6941
|
}, null, 2);
|
|
6924
6942
|
}
|
|
6925
|
-
gitExec(["reset", "--
|
|
6943
|
+
gitExec(["reset", "--hard", checkpoint.sha], directory);
|
|
6926
6944
|
return JSON.stringify({
|
|
6927
6945
|
action: "restore",
|
|
6928
6946
|
success: true,
|
|
6929
6947
|
label,
|
|
6930
6948
|
sha: checkpoint.sha,
|
|
6931
|
-
message: `Restored to checkpoint: "${label}" (
|
|
6949
|
+
message: `Restored to checkpoint: "${label}" (hard reset)`
|
|
6932
6950
|
}, null, 2);
|
|
6933
6951
|
} catch (e) {
|
|
6934
6952
|
const errorMessage = e instanceof Error ? `restore failed: ${e.message}` : "restore failed: unknown error";
|
|
@@ -6978,7 +6996,7 @@ function handleDelete(label, directory) {
|
|
|
6978
6996
|
}
|
|
6979
6997
|
}
|
|
6980
6998
|
var checkpoint = createSwarmTool({
|
|
6981
|
-
description: "Save, restore, list, and delete git checkpoints. " + "Use save to create a named snapshot, restore to return to a checkpoint
|
|
6999
|
+
description: "Save, restore, list, and delete git checkpoints. " + "Use save to create a named snapshot, restore to return tracked files to a checkpoint, " + "list to see all checkpoints, and delete to remove a checkpoint from the log. " + "Git commits are preserved on delete.",
|
|
6982
7000
|
args: {
|
|
6983
7001
|
action: exports_external.string().describe("Action to perform: save, restore, list, or delete"),
|
|
6984
7002
|
label: exports_external.string().optional().describe("Checkpoint label (required for save, restore, delete)")
|
|
@@ -7180,7 +7198,7 @@ async function handleClarifyCommand(_directory, args) {
|
|
|
7180
7198
|
// src/commands/close.ts
|
|
7181
7199
|
import { spawnSync as spawnSync2 } from "child_process";
|
|
7182
7200
|
import * as fsSync from "fs";
|
|
7183
|
-
import { promises as
|
|
7201
|
+
import { promises as fs10 } from "fs";
|
|
7184
7202
|
import path27 from "path";
|
|
7185
7203
|
|
|
7186
7204
|
// src/hooks/curator-postmortem.ts
|
|
@@ -7900,11 +7918,11 @@ var _internals8 = {
|
|
|
7900
7918
|
return KnowledgeConfigSchema2.parse({});
|
|
7901
7919
|
},
|
|
7902
7920
|
applyCuratorKnowledgeUpdates: async (directory, recommendations, knowledgeConfig) => {
|
|
7903
|
-
const { applyCuratorKnowledgeUpdates } = await import("./curator-
|
|
7921
|
+
const { applyCuratorKnowledgeUpdates } = await import("./curator-6zvpn7fs.js");
|
|
7904
7922
|
return applyCuratorKnowledgeUpdates(directory, recommendations, knowledgeConfig);
|
|
7905
7923
|
},
|
|
7906
7924
|
checkHivePromotions: async (entries, knowledgeConfig) => {
|
|
7907
|
-
const { checkHivePromotions } = await import("./hive-promoter-
|
|
7925
|
+
const { checkHivePromotions } = await import("./hive-promoter-nwcsha2j.js");
|
|
7908
7926
|
return checkHivePromotions(entries, knowledgeConfig);
|
|
7909
7927
|
},
|
|
7910
7928
|
applyProposalTriage: async (directory, triage) => {
|
|
@@ -7964,8 +7982,8 @@ var _internals8 = {
|
|
|
7964
7982
|
import path16 from "path";
|
|
7965
7983
|
|
|
7966
7984
|
// src/hooks/curator.ts
|
|
7967
|
-
import { randomUUID as
|
|
7968
|
-
import * as
|
|
7985
|
+
import { randomUUID as randomUUID5 } from "crypto";
|
|
7986
|
+
import * as fs5 from "fs";
|
|
7969
7987
|
import * as path15 from "path";
|
|
7970
7988
|
|
|
7971
7989
|
// src/hooks/knowledge-escalator.ts
|
|
@@ -8403,12 +8421,12 @@ function formatLearningSummary(metrics) {
|
|
|
8403
8421
|
|
|
8404
8422
|
// src/services/skill-reviser.ts
|
|
8405
8423
|
init_logger();
|
|
8406
|
-
import { readFile as
|
|
8424
|
+
import { readFile as readFile5, rename as rename4, writeFile as writeFile5 } from "fs/promises";
|
|
8407
8425
|
|
|
8408
8426
|
// src/services/skill-improver-quota.ts
|
|
8409
8427
|
var import_proper_lockfile = __toESM(require_proper_lockfile(), 1);
|
|
8410
8428
|
import { existsSync as existsSync8 } from "fs";
|
|
8411
|
-
import { mkdir as mkdir4, readFile as
|
|
8429
|
+
import { mkdir as mkdir4, readFile as readFile4, rename as rename3, writeFile as writeFile4 } from "fs/promises";
|
|
8412
8430
|
import * as path13 from "path";
|
|
8413
8431
|
var LOCK_ACQUIRE_TIMEOUT_MS = 1e4;
|
|
8414
8432
|
var LOCK_RETRY_OPTS = {
|
|
@@ -8453,7 +8471,7 @@ async function readState(filePath) {
|
|
|
8453
8471
|
if (!existsSync8(filePath))
|
|
8454
8472
|
return null;
|
|
8455
8473
|
try {
|
|
8456
|
-
const raw = await
|
|
8474
|
+
const raw = await readFile4(filePath, "utf-8");
|
|
8457
8475
|
const parsed = JSON.parse(raw);
|
|
8458
8476
|
if (typeof parsed.date !== "string" || typeof parsed.calls_used !== "number" || typeof parsed.max_calls !== "number" || parsed.window !== "utc" && parsed.window !== "local") {
|
|
8459
8477
|
return null;
|
|
@@ -8466,8 +8484,8 @@ async function readState(filePath) {
|
|
|
8466
8484
|
async function writeState(filePath, state) {
|
|
8467
8485
|
await mkdir4(path13.dirname(filePath), { recursive: true });
|
|
8468
8486
|
const tmp = `${filePath}.tmp-${process.pid}`;
|
|
8469
|
-
await
|
|
8470
|
-
await
|
|
8487
|
+
await writeFile4(tmp, JSON.stringify(state, null, 2), "utf-8");
|
|
8488
|
+
await rename3(tmp, filePath);
|
|
8471
8489
|
}
|
|
8472
8490
|
async function getQuotaState(directory, opts) {
|
|
8473
8491
|
const filePath = resolveQuotaPath(directory, opts.scope);
|
|
@@ -8544,7 +8562,7 @@ var MAX_REVISION_CALLS_PER_PHASE = 3;
|
|
|
8544
8562
|
var DEFAULT_MAX_CALLS = 10;
|
|
8545
8563
|
async function getSkillVersion(skillPath) {
|
|
8546
8564
|
try {
|
|
8547
|
-
const content = await
|
|
8565
|
+
const content = await readFile5(skillPath, "utf-8");
|
|
8548
8566
|
const match = content.match(/^version:\s*(\d+)\s*$/m);
|
|
8549
8567
|
return match ? parseInt(match[1], 10) : 1;
|
|
8550
8568
|
} catch {
|
|
@@ -8681,8 +8699,8 @@ async function reviseSkill(params) {
|
|
|
8681
8699
|
};
|
|
8682
8700
|
}
|
|
8683
8701
|
const tmpPath = `${params.skillPath}.tmp-${process.pid}-${Date.now()}`;
|
|
8684
|
-
await
|
|
8685
|
-
await
|
|
8702
|
+
await writeFile5(tmpPath, revised, "utf-8");
|
|
8703
|
+
await rename4(tmpPath, params.skillPath);
|
|
8686
8704
|
const newVersion = params.currentVersion + 1;
|
|
8687
8705
|
const entry = {
|
|
8688
8706
|
version: newVersion,
|
|
@@ -8758,9 +8776,9 @@ async function reviseSkill(params) {
|
|
|
8758
8776
|
};
|
|
8759
8777
|
}
|
|
8760
8778
|
const tmpPath = `${params.skillPath}.tmp-${process.pid}-${Date.now()}`;
|
|
8761
|
-
await
|
|
8779
|
+
await writeFile5(tmpPath, `${finalOutput}
|
|
8762
8780
|
`, "utf-8");
|
|
8763
|
-
await
|
|
8781
|
+
await rename4(tmpPath, params.skillPath);
|
|
8764
8782
|
const newVersion = expectedVersion;
|
|
8765
8783
|
const entry = {
|
|
8766
8784
|
version: newVersion,
|
|
@@ -8814,7 +8832,7 @@ init_logger();
|
|
|
8814
8832
|
|
|
8815
8833
|
// src/hooks/skill-usage-log.ts
|
|
8816
8834
|
import * as crypto2 from "crypto";
|
|
8817
|
-
import * as
|
|
8835
|
+
import * as fs4 from "fs";
|
|
8818
8836
|
import * as path14 from "path";
|
|
8819
8837
|
function resolveLogPath(directory) {
|
|
8820
8838
|
return validateSwarmPath(directory, "skill-usage.jsonl");
|
|
@@ -8824,16 +8842,16 @@ function normalizeComplianceVerdict(verdict) {
|
|
|
8824
8842
|
}
|
|
8825
8843
|
var _internals10 = {
|
|
8826
8844
|
generateId: () => crypto2.randomUUID(),
|
|
8827
|
-
appendFileSync:
|
|
8828
|
-
readFileSync:
|
|
8829
|
-
writeFileSync:
|
|
8830
|
-
renameSync:
|
|
8831
|
-
mkdirSync:
|
|
8832
|
-
existsSync:
|
|
8833
|
-
statSync:
|
|
8834
|
-
openSync:
|
|
8835
|
-
readSync:
|
|
8836
|
-
closeSync:
|
|
8845
|
+
appendFileSync: fs4.appendFileSync.bind(fs4),
|
|
8846
|
+
readFileSync: fs4.readFileSync.bind(fs4),
|
|
8847
|
+
writeFileSync: fs4.writeFileSync.bind(fs4),
|
|
8848
|
+
renameSync: fs4.renameSync.bind(fs4),
|
|
8849
|
+
mkdirSync: fs4.mkdirSync.bind(fs4),
|
|
8850
|
+
existsSync: fs4.existsSync.bind(fs4),
|
|
8851
|
+
statSync: fs4.statSync.bind(fs4),
|
|
8852
|
+
openSync: fs4.openSync.bind(fs4),
|
|
8853
|
+
readSync: fs4.readSync.bind(fs4),
|
|
8854
|
+
closeSync: fs4.closeSync.bind(fs4),
|
|
8837
8855
|
pruneSkillUsageLog,
|
|
8838
8856
|
resolveSourceKnowledgeIds,
|
|
8839
8857
|
applySkillUsageFeedback,
|
|
@@ -9340,7 +9358,7 @@ var _internals11 = {
|
|
|
9340
9358
|
retireOrMarkStale,
|
|
9341
9359
|
retireSkill,
|
|
9342
9360
|
getArchivedKnowledgeIds,
|
|
9343
|
-
readFileAsync: (filePath, encoding) => import("fs/promises").then((
|
|
9361
|
+
readFileAsync: (filePath, encoding) => import("fs/promises").then((fs6) => fs6.readFile(filePath, encoding)),
|
|
9344
9362
|
readKnowledge,
|
|
9345
9363
|
reviseSkill,
|
|
9346
9364
|
getSkillVersion,
|
|
@@ -9567,16 +9585,16 @@ function arrayOfStrings(v) {
|
|
|
9567
9585
|
function readLatestPostMortemDigest(directory) {
|
|
9568
9586
|
try {
|
|
9569
9587
|
const swarmDir = path15.join(directory, ".swarm");
|
|
9570
|
-
if (!
|
|
9588
|
+
if (!fs5.existsSync(swarmDir))
|
|
9571
9589
|
return null;
|
|
9572
|
-
const candidates =
|
|
9590
|
+
const candidates = fs5.readdirSync(swarmDir).filter((name) => /^post-mortem-[^/\\]+\.md$/.test(name)).map((name) => {
|
|
9573
9591
|
const filePath = path15.join(swarmDir, name);
|
|
9574
|
-
return { name, filePath, mtimeMs:
|
|
9592
|
+
return { name, filePath, mtimeMs: fs5.statSync(filePath).mtimeMs };
|
|
9575
9593
|
}).sort((a, b) => b.mtimeMs - a.mtimeMs);
|
|
9576
9594
|
const latest = candidates[0];
|
|
9577
9595
|
if (!latest)
|
|
9578
9596
|
return null;
|
|
9579
|
-
const content =
|
|
9597
|
+
const content = fs5.readFileSync(latest.filePath, "utf-8");
|
|
9580
9598
|
const summary = content.match(/SUMMARY:\s*\n([\s\S]*?)(?:\n[A-Z_]+:|\n##|$)/);
|
|
9581
9599
|
const body = (summary?.[1]?.trim() || content.slice(0, 1500)).slice(0, 1500);
|
|
9582
9600
|
return `${latest.name}
|
|
@@ -9613,7 +9631,7 @@ async function readCuratorSummary(directory) {
|
|
|
9613
9631
|
}
|
|
9614
9632
|
async function writeCuratorSummary(directory, summary) {
|
|
9615
9633
|
const resolvedPath = validateSwarmPath(directory, "curator-summary.json");
|
|
9616
|
-
|
|
9634
|
+
fs5.mkdirSync(path15.dirname(resolvedPath), { recursive: true });
|
|
9617
9635
|
await bunWrite(resolvedPath, JSON.stringify(summary, null, 2));
|
|
9618
9636
|
}
|
|
9619
9637
|
function normalizeAgentName(name) {
|
|
@@ -10054,7 +10072,7 @@ async function runCuratorPhase(directory, phase, agentsDispatched, config, knowl
|
|
|
10054
10072
|
if (knowledgeApplicationFindings.length > 0) {
|
|
10055
10073
|
try {
|
|
10056
10074
|
const evidenceDir = path15.join(directory, ".swarm", "evidence", String(phase));
|
|
10057
|
-
|
|
10075
|
+
fs5.mkdirSync(evidenceDir, { recursive: true });
|
|
10058
10076
|
const findingsPath = path15.join(evidenceDir, "curator-findings.json");
|
|
10059
10077
|
await bunWrite(findingsPath, JSON.stringify({ findings: knowledgeApplicationFindings }, null, 2));
|
|
10060
10078
|
} catch (err) {
|
|
@@ -10357,7 +10375,7 @@ async function applyCuratorKnowledgeUpdates(directory, recommendations, knowledg
|
|
|
10357
10375
|
}
|
|
10358
10376
|
const now = new Date().toISOString();
|
|
10359
10377
|
const newEntry = {
|
|
10360
|
-
id:
|
|
10378
|
+
id: randomUUID5(),
|
|
10361
10379
|
tier: "swarm",
|
|
10362
10380
|
lesson,
|
|
10363
10381
|
category: rec.category ?? "other",
|
|
@@ -10674,18 +10692,18 @@ async function promoteFromSwarm(directory, lessonId) {
|
|
|
10674
10692
|
// src/hooks/knowledge-curator.ts
|
|
10675
10693
|
import { createHash as createHash4 } from "crypto";
|
|
10676
10694
|
import { existsSync as existsSync13 } from "fs";
|
|
10677
|
-
import { appendFile as appendFile2, mkdir as mkdir6, readFile as
|
|
10695
|
+
import { appendFile as appendFile2, mkdir as mkdir6, readFile as readFile8, writeFile as writeFile8 } from "fs/promises";
|
|
10678
10696
|
import * as path21 from "path";
|
|
10679
10697
|
|
|
10680
10698
|
// src/services/synonym-map.ts
|
|
10681
10699
|
var import_proper_lockfile2 = __toESM(require_proper_lockfile(), 1);
|
|
10682
10700
|
import {
|
|
10683
10701
|
mkdir as mkdir5,
|
|
10684
|
-
readFile as
|
|
10685
|
-
rename as
|
|
10702
|
+
readFile as readFile6,
|
|
10703
|
+
rename as rename5,
|
|
10686
10704
|
stat as stat3,
|
|
10687
10705
|
unlink,
|
|
10688
|
-
writeFile as
|
|
10706
|
+
writeFile as writeFile6
|
|
10689
10707
|
} from "fs/promises";
|
|
10690
10708
|
import * as path17 from "path";
|
|
10691
10709
|
var SYNONYM_MAP_FILENAME = "synonym-map.json";
|
|
@@ -10835,7 +10853,7 @@ async function readSynonymMap(directory, maxPairs = DEFAULT_MAX_PAIRS) {
|
|
|
10835
10853
|
const st = await stat3(filePath);
|
|
10836
10854
|
if (st.size > ceiling)
|
|
10837
10855
|
return emptySynonymMap();
|
|
10838
|
-
const raw = await
|
|
10856
|
+
const raw = await readFile6(filePath, "utf-8");
|
|
10839
10857
|
return coerceSynonymMap(JSON.parse(raw), maxPairs);
|
|
10840
10858
|
} catch {
|
|
10841
10859
|
return emptySynonymMap();
|
|
@@ -10845,8 +10863,8 @@ async function writeSynonymMapAtomic(filePath, map) {
|
|
|
10845
10863
|
await mkdir5(path17.dirname(filePath), { recursive: true });
|
|
10846
10864
|
const tmp = `${filePath}.tmp.${Date.now()}.${Math.floor(Math.random() * 1e9)}`;
|
|
10847
10865
|
try {
|
|
10848
|
-
await
|
|
10849
|
-
await
|
|
10866
|
+
await writeFile6(tmp, JSON.stringify(map, null, 2), "utf-8");
|
|
10867
|
+
await rename5(tmp, filePath);
|
|
10850
10868
|
} finally {
|
|
10851
10869
|
try {
|
|
10852
10870
|
await unlink(tmp);
|
|
@@ -10919,17 +10937,17 @@ function reinforceSwarmKnowledgeEntry(entry, confirmation) {
|
|
|
10919
10937
|
|
|
10920
10938
|
// src/hooks/micro-reflector.ts
|
|
10921
10939
|
import { existsSync as existsSync12 } from "fs";
|
|
10922
|
-
import { readFile as
|
|
10940
|
+
import { readFile as readFile7, writeFile as writeFile7 } from "fs/promises";
|
|
10923
10941
|
import * as path20 from "path";
|
|
10924
10942
|
init_logger();
|
|
10925
10943
|
|
|
10926
10944
|
// src/hooks/skill-propagation-gate.ts
|
|
10927
|
-
import * as
|
|
10945
|
+
import * as fs7 from "fs";
|
|
10928
10946
|
import * as path19 from "path";
|
|
10929
10947
|
init_logger();
|
|
10930
10948
|
|
|
10931
10949
|
// src/hooks/skill-scoring.ts
|
|
10932
|
-
import * as
|
|
10950
|
+
import * as fs6 from "fs";
|
|
10933
10951
|
import * as path18 from "path";
|
|
10934
10952
|
var FREQUENCY_CAP = 10;
|
|
10935
10953
|
var FREQUENCY_WEIGHT = 0.3;
|
|
@@ -11103,13 +11121,13 @@ function parseSkillFrontmatter(content, skillPath) {
|
|
|
11103
11121
|
return meta;
|
|
11104
11122
|
}
|
|
11105
11123
|
function readFilePrefix(filePath) {
|
|
11106
|
-
const fd =
|
|
11124
|
+
const fd = fs6.openSync(filePath, "r");
|
|
11107
11125
|
try {
|
|
11108
11126
|
const buffer = Buffer.alloc(SKILL_FRONTMATTER_READ_BYTES);
|
|
11109
|
-
const bytesRead =
|
|
11127
|
+
const bytesRead = fs6.readSync(fd, buffer, 0, SKILL_FRONTMATTER_READ_BYTES, 0);
|
|
11110
11128
|
return buffer.toString("utf-8", 0, bytesRead);
|
|
11111
11129
|
} finally {
|
|
11112
|
-
|
|
11130
|
+
fs6.closeSync(fd);
|
|
11113
11131
|
}
|
|
11114
11132
|
}
|
|
11115
11133
|
function readSkillMetadata(skillPath, directory) {
|
|
@@ -11258,7 +11276,7 @@ function formatSkillIndexWithContext(skills, directory) {
|
|
|
11258
11276
|
const usageLogPath = path18.join(directory, ".swarm", "skill-usage.jsonl");
|
|
11259
11277
|
let hasHistory = false;
|
|
11260
11278
|
try {
|
|
11261
|
-
const stat4 =
|
|
11279
|
+
const stat4 = fs6.statSync(usageLogPath);
|
|
11262
11280
|
hasHistory = stat4.size > 0;
|
|
11263
11281
|
} catch {}
|
|
11264
11282
|
if (!hasHistory) {
|
|
@@ -11421,13 +11439,13 @@ var SKILL_SEARCH_ROOTS = [
|
|
|
11421
11439
|
];
|
|
11422
11440
|
var MAX_SCORING_SESSION_ENTRIES = 500;
|
|
11423
11441
|
var _internals13 = {
|
|
11424
|
-
readdirSync:
|
|
11425
|
-
existsSync:
|
|
11426
|
-
statSync:
|
|
11427
|
-
mkdirSync:
|
|
11428
|
-
appendFileSync:
|
|
11429
|
-
readFileSync:
|
|
11430
|
-
writeFileSync:
|
|
11442
|
+
readdirSync: fs7.readdirSync.bind(fs7),
|
|
11443
|
+
existsSync: fs7.existsSync.bind(fs7),
|
|
11444
|
+
statSync: fs7.statSync.bind(fs7),
|
|
11445
|
+
mkdirSync: fs7.mkdirSync.bind(fs7),
|
|
11446
|
+
appendFileSync: fs7.appendFileSync.bind(fs7),
|
|
11447
|
+
readFileSync: fs7.readFileSync.bind(fs7),
|
|
11448
|
+
writeFileSync: fs7.writeFileSync.bind(fs7),
|
|
11431
11449
|
skillPropagationGateBefore: null,
|
|
11432
11450
|
skillPropagationTransformScan: null,
|
|
11433
11451
|
SKILL_CAPABLE_AGENTS,
|
|
@@ -11948,7 +11966,7 @@ async function readTaskTrajectory(directory, taskId) {
|
|
|
11948
11966
|
const filePath = validateSwarmPath(directory, rel);
|
|
11949
11967
|
if (!existsSync12(filePath))
|
|
11950
11968
|
return [];
|
|
11951
|
-
const content = await
|
|
11969
|
+
const content = await readFile7(filePath, "utf-8");
|
|
11952
11970
|
const out = [];
|
|
11953
11971
|
for (const line of content.split(`
|
|
11954
11972
|
`)) {
|
|
@@ -12418,11 +12436,11 @@ async function consumeInsightCandidates(directory, batchLimit = MESO_INSIGHT_BAT
|
|
|
12418
12436
|
if (!existsSync13(filePath))
|
|
12419
12437
|
return [];
|
|
12420
12438
|
const consumed = [];
|
|
12421
|
-
await transactFile(filePath, async (p) => readInsightJsonl(await
|
|
12439
|
+
await transactFile(filePath, async (p) => readInsightJsonl(await readFile8(p, "utf-8").catch(() => "")), async (p, data) => {
|
|
12422
12440
|
const body = data.length === 0 ? "" : `${data.map((c) => JSON.stringify(c)).join(`
|
|
12423
12441
|
`)}
|
|
12424
12442
|
`;
|
|
12425
|
-
await
|
|
12443
|
+
await writeFile8(p, body, "utf-8");
|
|
12426
12444
|
}, (all) => {
|
|
12427
12445
|
if (all.length === 0)
|
|
12428
12446
|
return null;
|
|
@@ -12902,7 +12920,7 @@ var _internals15 = {
|
|
|
12902
12920
|
|
|
12903
12921
|
// src/scope/scope-persistence.ts
|
|
12904
12922
|
var import_proper_lockfile3 = __toESM(require_proper_lockfile(), 1);
|
|
12905
|
-
import * as
|
|
12923
|
+
import * as fs8 from "fs";
|
|
12906
12924
|
import * as path22 from "path";
|
|
12907
12925
|
var DEFAULT_TTL_MS = 24 * 60 * 60 * 1000;
|
|
12908
12926
|
var LOCK_STALE_MS = 30 * 1000;
|
|
@@ -12938,12 +12956,12 @@ function getScopesDir(directory) {
|
|
|
12938
12956
|
}
|
|
12939
12957
|
function clearAllScopes(directory) {
|
|
12940
12958
|
try {
|
|
12941
|
-
|
|
12959
|
+
fs8.rmSync(getScopesDir(directory), { recursive: true, force: true });
|
|
12942
12960
|
} catch {}
|
|
12943
12961
|
}
|
|
12944
12962
|
|
|
12945
12963
|
// src/services/session-reflection.ts
|
|
12946
|
-
import { promises as
|
|
12964
|
+
import { promises as fs9 } from "fs";
|
|
12947
12965
|
import * as path23 from "path";
|
|
12948
12966
|
|
|
12949
12967
|
// src/hooks/abort-utils.ts
|
|
@@ -13106,12 +13124,12 @@ async function gatherRetroLessonsAndTaxonomy(directory) {
|
|
|
13106
13124
|
const taxonomy = {};
|
|
13107
13125
|
try {
|
|
13108
13126
|
const evidenceDir = path23.join(directory, ".swarm", "evidence");
|
|
13109
|
-
const entries = await
|
|
13127
|
+
const entries = await fs9.readdir(evidenceDir);
|
|
13110
13128
|
const retroDirs = entries.filter((e) => e.startsWith("retro-")).sort((a, b) => a.localeCompare(b, undefined, { numeric: true }));
|
|
13111
13129
|
for (const retroDir of retroDirs) {
|
|
13112
13130
|
const evidencePath = path23.join(evidenceDir, retroDir, "evidence.json");
|
|
13113
13131
|
try {
|
|
13114
|
-
const content = await
|
|
13132
|
+
const content = await fs9.readFile(evidencePath, "utf-8");
|
|
13115
13133
|
const parsed = JSON.parse(content);
|
|
13116
13134
|
const bundleEntries = parsed.entries ?? [parsed];
|
|
13117
13135
|
for (const entry of bundleEntries) {
|
|
@@ -13139,13 +13157,13 @@ async function gatherGateFailures(directory) {
|
|
|
13139
13157
|
const failures = new Map;
|
|
13140
13158
|
try {
|
|
13141
13159
|
const evidenceDir = path23.join(directory, ".swarm", "evidence");
|
|
13142
|
-
const entries = await
|
|
13160
|
+
const entries = await fs9.readdir(evidenceDir);
|
|
13143
13161
|
for (const entry of entries) {
|
|
13144
13162
|
if (entry.startsWith("retro-"))
|
|
13145
13163
|
continue;
|
|
13146
13164
|
const evidencePath = path23.join(evidenceDir, entry, "evidence.json");
|
|
13147
13165
|
try {
|
|
13148
|
-
const content = await
|
|
13166
|
+
const content = await fs9.readFile(evidencePath, "utf-8");
|
|
13149
13167
|
const parsed = JSON.parse(content);
|
|
13150
13168
|
const bundleEntries = parsed.entries ?? [parsed];
|
|
13151
13169
|
for (const e of bundleEntries) {
|
|
@@ -13337,18 +13355,18 @@ async function writeSessionReflection(directory, result) {
|
|
|
13337
13355
|
lines.push(result.architectReport);
|
|
13338
13356
|
const content = lines.join(`
|
|
13339
13357
|
`);
|
|
13340
|
-
await
|
|
13358
|
+
await fs9.writeFile(reflectionPath, content, "utf-8");
|
|
13341
13359
|
return reflectionPath;
|
|
13342
13360
|
}
|
|
13343
13361
|
|
|
13344
13362
|
// src/services/skill-improver.ts
|
|
13345
13363
|
import { existsSync as existsSync15 } from "fs";
|
|
13346
|
-
import { mkdir as mkdir8, readFile as
|
|
13364
|
+
import { mkdir as mkdir8, readFile as readFile9, rename as rename6, writeFile as writeFile10 } from "fs/promises";
|
|
13347
13365
|
import * as path25 from "path";
|
|
13348
13366
|
init_logger();
|
|
13349
13367
|
|
|
13350
13368
|
// src/services/trajectory-cluster.ts
|
|
13351
|
-
import { mkdir as mkdir7, writeFile as
|
|
13369
|
+
import { mkdir as mkdir7, writeFile as writeFile9 } from "fs/promises";
|
|
13352
13370
|
import * as path24 from "path";
|
|
13353
13371
|
init_logger();
|
|
13354
13372
|
var MACRO_TRAJECTORY_WINDOW = 200;
|
|
@@ -13486,7 +13504,7 @@ async function writeMotifProposals(directory, opts = {}) {
|
|
|
13486
13504
|
for (const motif of motifs.slice(0, max)) {
|
|
13487
13505
|
const slug = `motif-${slugify(motif.signature)}`;
|
|
13488
13506
|
const filePath = path24.join(proposalsDir, `${slug}.md`);
|
|
13489
|
-
await
|
|
13507
|
+
await writeFile9(filePath, buildMotifProposal(motif), "utf-8");
|
|
13490
13508
|
result.proposalsWritten.push(filePath);
|
|
13491
13509
|
}
|
|
13492
13510
|
return result;
|
|
@@ -13631,7 +13649,7 @@ async function writeSuccessMotifProposals(directory, opts = {}) {
|
|
|
13631
13649
|
for (const motif of motifs.slice(0, max)) {
|
|
13632
13650
|
const slug = workflowSlug(motif.signature);
|
|
13633
13651
|
const filePath = path24.join(proposalsDir, `${slug}.md`);
|
|
13634
|
-
await
|
|
13652
|
+
await writeFile9(filePath, buildWorkflowProposal(motif), "utf-8");
|
|
13635
13653
|
result.proposalsWritten.push(filePath);
|
|
13636
13654
|
}
|
|
13637
13655
|
return result;
|
|
@@ -13755,8 +13773,8 @@ function timestampSlug(d) {
|
|
|
13755
13773
|
async function atomicWrite(p, content) {
|
|
13756
13774
|
await mkdir8(path25.dirname(p), { recursive: true });
|
|
13757
13775
|
const tmp = `${p}.tmp-${process.pid}-${Date.now()}`;
|
|
13758
|
-
await
|
|
13759
|
-
await
|
|
13776
|
+
await writeFile10(tmp, content, "utf-8");
|
|
13777
|
+
await rename6(tmp, p);
|
|
13760
13778
|
}
|
|
13761
13779
|
async function gatherInventory(directory) {
|
|
13762
13780
|
const swarm = await readKnowledge(resolveSwarmKnowledgePath(directory));
|
|
@@ -13770,7 +13788,7 @@ async function gatherInventory(directory) {
|
|
|
13770
13788
|
for (const skill of skills.active) {
|
|
13771
13789
|
let content;
|
|
13772
13790
|
try {
|
|
13773
|
-
content = await
|
|
13791
|
+
content = await readFile9(skill.path, "utf-8");
|
|
13774
13792
|
} catch {
|
|
13775
13793
|
continue;
|
|
13776
13794
|
}
|
|
@@ -13946,7 +13964,7 @@ async function reconcileStaleActiveSkills(directory, options = {}) {
|
|
|
13946
13964
|
for (const skill of skills.active) {
|
|
13947
13965
|
let content;
|
|
13948
13966
|
try {
|
|
13949
|
-
content = await
|
|
13967
|
+
content = await readFile9(skill.path, "utf-8");
|
|
13950
13968
|
} catch {
|
|
13951
13969
|
continue;
|
|
13952
13970
|
}
|
|
@@ -14682,20 +14700,20 @@ function countSessionKnowledgeEntries(entries, sessionStart, fallbackCount) {
|
|
|
14682
14700
|
async function copyDirRecursiveWithFailures(src, dest) {
|
|
14683
14701
|
let count = 0;
|
|
14684
14702
|
const failures = [];
|
|
14685
|
-
const entries = await
|
|
14686
|
-
await
|
|
14703
|
+
const entries = await fs10.readdir(src);
|
|
14704
|
+
await fs10.mkdir(dest, { recursive: true });
|
|
14687
14705
|
for (const entry of entries) {
|
|
14688
14706
|
const srcEntry = path27.join(src, entry);
|
|
14689
14707
|
const destEntry = path27.join(dest, entry);
|
|
14690
14708
|
try {
|
|
14691
|
-
const stat4 = await
|
|
14709
|
+
const stat4 = await fs10.stat(srcEntry);
|
|
14692
14710
|
if (stat4.isDirectory()) {
|
|
14693
14711
|
const subResult = await copyDirRecursiveWithFailures(srcEntry, destEntry);
|
|
14694
14712
|
count += subResult.copied;
|
|
14695
14713
|
failures.push(...subResult.failures);
|
|
14696
14714
|
} else {
|
|
14697
14715
|
try {
|
|
14698
|
-
await
|
|
14716
|
+
await fs10.copyFile(srcEntry, destEntry);
|
|
14699
14717
|
count++;
|
|
14700
14718
|
} catch (err) {
|
|
14701
14719
|
const errno = err?.code;
|
|
@@ -14873,18 +14891,18 @@ async function runFinalizeStage(ctx) {
|
|
|
14873
14891
|
}
|
|
14874
14892
|
const lessonsFilePath = path27.join(ctx.swarmDir, "close-lessons.md");
|
|
14875
14893
|
try {
|
|
14876
|
-
const lessonsText = await
|
|
14894
|
+
const lessonsText = await fs10.readFile(lessonsFilePath, "utf-8");
|
|
14877
14895
|
ctx.explicitLessons = lessonsText.split(`
|
|
14878
14896
|
`).map((line) => line.trim()).filter((line) => line.length > 0 && !line.startsWith("#"));
|
|
14879
14897
|
} catch {}
|
|
14880
14898
|
try {
|
|
14881
14899
|
const evidenceDir = path27.join(ctx.swarmDir, "evidence");
|
|
14882
|
-
const evidenceEntries = await
|
|
14900
|
+
const evidenceEntries = await fs10.readdir(evidenceDir);
|
|
14883
14901
|
const retroDirs = evidenceEntries.filter((e) => e.startsWith("retro-")).sort((a, b) => a.localeCompare(b, undefined, { numeric: true }));
|
|
14884
14902
|
for (const retroDir of retroDirs) {
|
|
14885
14903
|
const evidencePath = path27.join(evidenceDir, retroDir, "evidence.json");
|
|
14886
14904
|
try {
|
|
14887
|
-
const content = await
|
|
14905
|
+
const content = await fs10.readFile(evidencePath, "utf-8");
|
|
14888
14906
|
const parsed = JSON.parse(content);
|
|
14889
14907
|
const entries = parsed.entries ?? [parsed];
|
|
14890
14908
|
for (const entry of entries) {
|
|
@@ -14928,7 +14946,7 @@ async function runFinalizeStage(ctx) {
|
|
|
14928
14946
|
console.warn("[close-command] curateAndStoreSwarm error:", error2);
|
|
14929
14947
|
}
|
|
14930
14948
|
if (ctx.curationSucceeded && ctx.allLessons.length > 0) {
|
|
14931
|
-
await
|
|
14949
|
+
await fs10.unlink(lessonsFilePath).catch(() => {});
|
|
14932
14950
|
}
|
|
14933
14951
|
if (ctx.curationSucceeded) {
|
|
14934
14952
|
if (ctx.config.hive_enabled === false) {} else {
|
|
@@ -15077,7 +15095,7 @@ async function copySqliteSafe(srcPath, destPath) {
|
|
|
15077
15095
|
const code = result.error.code;
|
|
15078
15096
|
if (code === "ENOENT") {
|
|
15079
15097
|
try {
|
|
15080
|
-
await
|
|
15098
|
+
await fs10.copyFile(srcPath, destPath);
|
|
15081
15099
|
return {
|
|
15082
15100
|
success: true,
|
|
15083
15101
|
reason: "copied without WAL checkpoint (sqlite3 CLI unavailable)"
|
|
@@ -15116,7 +15134,7 @@ async function copySqliteSafe(srcPath, destPath) {
|
|
|
15116
15134
|
};
|
|
15117
15135
|
}
|
|
15118
15136
|
try {
|
|
15119
|
-
await
|
|
15137
|
+
await fs10.copyFile(srcPath, destPath);
|
|
15120
15138
|
if (checkpointVerified) {
|
|
15121
15139
|
return { success: true };
|
|
15122
15140
|
}
|
|
@@ -15136,7 +15154,7 @@ async function runArchiveStage(ctx) {
|
|
|
15136
15154
|
ctx.archiveSuffix = Math.random().toString(36).slice(2, 8);
|
|
15137
15155
|
ctx.archiveDir = path27.join(ctx.swarmDir, "archive", `swarm-${ctx.timestamp}-${ctx.archiveSuffix}`);
|
|
15138
15156
|
try {
|
|
15139
|
-
await
|
|
15157
|
+
await fs10.mkdir(ctx.archiveDir, { recursive: true });
|
|
15140
15158
|
const WAL_SIDECAR_FILES = new Set(["swarm.db-shm", "swarm.db-wal"]);
|
|
15141
15159
|
const linkedKnowledgeShared = isLinked(ctx.directory);
|
|
15142
15160
|
if (linkedKnowledgeShared) {
|
|
@@ -15166,7 +15184,7 @@ async function runArchiveStage(ctx) {
|
|
|
15166
15184
|
}
|
|
15167
15185
|
} else {
|
|
15168
15186
|
try {
|
|
15169
|
-
await
|
|
15187
|
+
await fs10.copyFile(srcPath, destPath);
|
|
15170
15188
|
ctx.archivedFileCount++;
|
|
15171
15189
|
if (ACTIVE_STATE_TO_CLEAN.includes(artifact)) {
|
|
15172
15190
|
ctx.archivedActiveStateFiles.add(artifact);
|
|
@@ -15181,12 +15199,12 @@ async function runArchiveStage(ctx) {
|
|
|
15181
15199
|
}
|
|
15182
15200
|
}
|
|
15183
15201
|
}
|
|
15184
|
-
const dynamicArchiveArtifacts = (await
|
|
15202
|
+
const dynamicArchiveArtifacts = (await fs10.readdir(ctx.swarmDir).catch(() => [])).filter((name) => /^post-mortem-[^/\\]+\.md$/.test(name) || /^drift-report-phase-\d+\.json$/.test(name));
|
|
15185
15203
|
for (const artifact of dynamicArchiveArtifacts) {
|
|
15186
15204
|
const srcPath = path27.join(ctx.swarmDir, artifact);
|
|
15187
15205
|
const destPath = path27.join(ctx.archiveDir, artifact);
|
|
15188
15206
|
try {
|
|
15189
|
-
await
|
|
15207
|
+
await fs10.copyFile(srcPath, destPath);
|
|
15190
15208
|
ctx.archivedFileCount++;
|
|
15191
15209
|
ctx.archivedActiveStateFiles.add(artifact);
|
|
15192
15210
|
} catch (err) {
|
|
@@ -15279,7 +15297,7 @@ async function runCleanStage(ctx) {
|
|
|
15279
15297
|
}
|
|
15280
15298
|
const filePath = path27.join(ctx.swarmDir, artifact);
|
|
15281
15299
|
try {
|
|
15282
|
-
await
|
|
15300
|
+
await fs10.unlink(filePath);
|
|
15283
15301
|
cleanedFiles.push(artifact);
|
|
15284
15302
|
} catch (err) {
|
|
15285
15303
|
const errno = err?.code;
|
|
@@ -15297,7 +15315,7 @@ async function runCleanStage(ctx) {
|
|
|
15297
15315
|
continue;
|
|
15298
15316
|
}
|
|
15299
15317
|
try {
|
|
15300
|
-
await
|
|
15318
|
+
await fs10.unlink(path27.join(ctx.swarmDir, artifact));
|
|
15301
15319
|
cleanedFiles.push(artifact);
|
|
15302
15320
|
} catch (err) {
|
|
15303
15321
|
const errno = err?.code;
|
|
@@ -15313,16 +15331,16 @@ async function runCleanStage(ctx) {
|
|
|
15313
15331
|
}
|
|
15314
15332
|
const dirPath = path27.join(ctx.swarmDir, dirName);
|
|
15315
15333
|
try {
|
|
15316
|
-
await
|
|
15334
|
+
await fs10.rm(dirPath, { recursive: true, force: true });
|
|
15317
15335
|
cleanedFiles.push(`${dirName}/`);
|
|
15318
15336
|
} catch {}
|
|
15319
15337
|
}
|
|
15320
15338
|
try {
|
|
15321
|
-
const swarmFiles = await
|
|
15339
|
+
const swarmFiles = await fs10.readdir(ctx.swarmDir);
|
|
15322
15340
|
const configBackups = swarmFiles.filter((f) => f.startsWith("config-backup-") && f.endsWith(".json"));
|
|
15323
15341
|
for (const backup of configBackups) {
|
|
15324
15342
|
try {
|
|
15325
|
-
await
|
|
15343
|
+
await fs10.unlink(path27.join(ctx.swarmDir, backup));
|
|
15326
15344
|
configBackupsRemoved++;
|
|
15327
15345
|
} catch (err) {
|
|
15328
15346
|
const errno = err?.code;
|
|
@@ -15335,7 +15353,7 @@ async function runCleanStage(ctx) {
|
|
|
15335
15353
|
const ledgerSiblings = swarmFiles.filter((f) => (f.startsWith("plan-ledger.archived-") || f.startsWith("plan-ledger.backup-")) && f.endsWith(".jsonl"));
|
|
15336
15354
|
for (const sibling of ledgerSiblings) {
|
|
15337
15355
|
try {
|
|
15338
|
-
await
|
|
15356
|
+
await fs10.unlink(path27.join(ctx.swarmDir, sibling));
|
|
15339
15357
|
} catch (err) {
|
|
15340
15358
|
const errno = err?.code;
|
|
15341
15359
|
if (errno === "ENOENT") {} else {
|
|
@@ -15362,7 +15380,7 @@ async function runCleanStage(ctx) {
|
|
|
15362
15380
|
];
|
|
15363
15381
|
for (const candidate of candidates) {
|
|
15364
15382
|
try {
|
|
15365
|
-
await
|
|
15383
|
+
await fs10.unlink(candidate);
|
|
15366
15384
|
swarmPlanFilesRemoved++;
|
|
15367
15385
|
} catch (err) {
|
|
15368
15386
|
if (err?.code !== "ENOENT") {
|
|
@@ -15372,11 +15390,11 @@ async function runCleanStage(ctx) {
|
|
|
15372
15390
|
}
|
|
15373
15391
|
let tmpFilesRemoved = 0;
|
|
15374
15392
|
try {
|
|
15375
|
-
const swarmFiles = await
|
|
15393
|
+
const swarmFiles = await fs10.readdir(ctx.swarmDir);
|
|
15376
15394
|
const tmpFiles = swarmFiles.filter((f) => f.startsWith(".tmp."));
|
|
15377
15395
|
for (const tmp of tmpFiles) {
|
|
15378
15396
|
try {
|
|
15379
|
-
await
|
|
15397
|
+
await fs10.unlink(path27.join(ctx.swarmDir, tmp));
|
|
15380
15398
|
tmpFilesRemoved++;
|
|
15381
15399
|
} catch (err) {
|
|
15382
15400
|
const errno = err?.code;
|
|
@@ -15398,7 +15416,7 @@ async function runCleanStage(ctx) {
|
|
|
15398
15416
|
}
|
|
15399
15417
|
for (const terminalFile of TERMINAL_STATE_FILES) {
|
|
15400
15418
|
try {
|
|
15401
|
-
await
|
|
15419
|
+
await fs10.unlink(path27.join(ctx.swarmDir, terminalFile));
|
|
15402
15420
|
if (!cleanedFiles.includes(terminalFile)) {
|
|
15403
15421
|
cleanedFiles.push(terminalFile);
|
|
15404
15422
|
}
|
|
@@ -15425,7 +15443,7 @@ async function runCleanStage(ctx) {
|
|
|
15425
15443
|
`);
|
|
15426
15444
|
const contextTempPath = path27.join(path27.dirname(contextPath), `${path27.basename(contextPath)}.tmp.${Date.now()}.${Math.floor(Math.random() * 1e9)}`);
|
|
15427
15445
|
try {
|
|
15428
|
-
await
|
|
15446
|
+
await fs10.writeFile(contextTempPath, contextContent, "utf-8");
|
|
15429
15447
|
fsSync.renameSync(contextTempPath, contextPath);
|
|
15430
15448
|
} catch (error2) {
|
|
15431
15449
|
try {
|
|
@@ -15505,14 +15523,14 @@ async function handleCloseCommand(directory, args, options = {}) {
|
|
|
15505
15523
|
phases: []
|
|
15506
15524
|
};
|
|
15507
15525
|
try {
|
|
15508
|
-
const content = await
|
|
15526
|
+
const content = await fs10.readFile(planPath, "utf-8");
|
|
15509
15527
|
planData = JSON.parse(content);
|
|
15510
15528
|
planExists = true;
|
|
15511
15529
|
} catch (error2) {
|
|
15512
15530
|
if (error2?.code !== "ENOENT") {
|
|
15513
15531
|
return `\u274C Failed to read plan.json: ${error2 instanceof Error ? error2.message : String(error2)}`;
|
|
15514
15532
|
}
|
|
15515
|
-
const swarmDirExists = await
|
|
15533
|
+
const swarmDirExists = await fs10.access(swarmDir).then(() => true).catch(() => false);
|
|
15516
15534
|
if (!swarmDirExists) {
|
|
15517
15535
|
return `\u274C No .swarm/ directory found in ${directory}. Run /swarm close from the project root, or run /swarm plan first.`;
|
|
15518
15536
|
}
|
|
@@ -15528,7 +15546,7 @@ async function handleCloseCommand(directory, args, options = {}) {
|
|
|
15528
15546
|
if (!planExists) {
|
|
15529
15547
|
const archiveDir = path27.join(swarmDir, "archive");
|
|
15530
15548
|
try {
|
|
15531
|
-
const archiveEntries = await
|
|
15549
|
+
const archiveEntries = await fs10.readdir(archiveDir);
|
|
15532
15550
|
const hasArchiveBundle = archiveEntries.some((entry) => entry.startsWith("swarm-"));
|
|
15533
15551
|
if (hasArchiveBundle) {
|
|
15534
15552
|
const hasActiveState = [
|
|
@@ -15664,7 +15682,7 @@ This project was already finalized in a previous /swarm close run. The plan has
|
|
|
15664
15682
|
`);
|
|
15665
15683
|
const closeSummaryTempPath = path27.join(path27.dirname(closeSummaryPath), `${path27.basename(closeSummaryPath)}.tmp.${Date.now()}.${Math.floor(Math.random() * 1e9)}`);
|
|
15666
15684
|
try {
|
|
15667
|
-
await
|
|
15685
|
+
await fs10.writeFile(closeSummaryTempPath, summaryContent, "utf-8");
|
|
15668
15686
|
fsSync.renameSync(closeSummaryTempPath, closeSummaryPath);
|
|
15669
15687
|
} catch (error2) {
|
|
15670
15688
|
try {
|
|
@@ -16032,7 +16050,7 @@ async function handleConfigCommand(directory, _args) {
|
|
|
16032
16050
|
|
|
16033
16051
|
// src/services/skill-consolidation.ts
|
|
16034
16052
|
import { existsSync as existsSync18 } from "fs";
|
|
16035
|
-
import { mkdir as mkdir9, readFile as
|
|
16053
|
+
import { mkdir as mkdir9, readFile as readFile10, rename as rename7, writeFile as writeFile11 } from "fs/promises";
|
|
16036
16054
|
import * as path29 from "path";
|
|
16037
16055
|
|
|
16038
16056
|
// src/utils/timeout.ts
|
|
@@ -16065,7 +16083,7 @@ async function readState2(directory) {
|
|
|
16065
16083
|
if (!existsSync18(filePath))
|
|
16066
16084
|
return {};
|
|
16067
16085
|
try {
|
|
16068
|
-
const parsed = JSON.parse(await
|
|
16086
|
+
const parsed = JSON.parse(await readFile10(filePath, "utf-8"));
|
|
16069
16087
|
if (!parsed || typeof parsed !== "object")
|
|
16070
16088
|
return {};
|
|
16071
16089
|
return parsed;
|
|
@@ -16076,8 +16094,8 @@ async function readState2(directory) {
|
|
|
16076
16094
|
async function atomicWrite2(filePath, content) {
|
|
16077
16095
|
await mkdir9(path29.dirname(filePath), { recursive: true });
|
|
16078
16096
|
const tmp = `${filePath}.tmp-${process.pid}-${Date.now()}`;
|
|
16079
|
-
await
|
|
16080
|
-
await
|
|
16097
|
+
await writeFile11(tmp, content, "utf-8");
|
|
16098
|
+
await rename7(tmp, filePath);
|
|
16081
16099
|
}
|
|
16082
16100
|
async function writeState2(directory, state) {
|
|
16083
16101
|
await atomicWrite2(consolidationStatePath(directory), `${JSON.stringify(state, null, 2)}
|
|
@@ -16355,7 +16373,7 @@ async function handleCouncilCommand(_directory, args) {
|
|
|
16355
16373
|
|
|
16356
16374
|
// src/commands/coupling.ts
|
|
16357
16375
|
import { randomBytes } from "crypto";
|
|
16358
|
-
import * as
|
|
16376
|
+
import * as fs11 from "fs";
|
|
16359
16377
|
import * as path31 from "path";
|
|
16360
16378
|
|
|
16361
16379
|
// src/turbo/epic/cochange-source.ts
|
|
@@ -16364,8 +16382,8 @@ import { promisify as promisify2 } from "util";
|
|
|
16364
16382
|
|
|
16365
16383
|
// src/tools/co-change-analyzer.ts
|
|
16366
16384
|
import * as child_process2 from "child_process";
|
|
16367
|
-
import { randomUUID as
|
|
16368
|
-
import { readdir as readdir2, readFile as
|
|
16385
|
+
import { randomUUID as randomUUID6 } from "crypto";
|
|
16386
|
+
import { readdir as readdir2, readFile as readFile11, stat as stat4 } from "fs/promises";
|
|
16369
16387
|
import * as path30 from "path";
|
|
16370
16388
|
import { promisify } from "util";
|
|
16371
16389
|
function getExecFileAsync() {
|
|
@@ -16492,7 +16510,7 @@ async function getStaticEdges(directory) {
|
|
|
16492
16510
|
const sourceFiles = await scanSourceFiles(directory);
|
|
16493
16511
|
for (const sourceFile of sourceFiles) {
|
|
16494
16512
|
try {
|
|
16495
|
-
const content = await
|
|
16513
|
+
const content = await readFile11(sourceFile, "utf-8");
|
|
16496
16514
|
const importRegex = /(?:import|require)\s*(?:\(?\s*['"`]|.*?from\s+['"`])([^'"`]+)['"`]/g;
|
|
16497
16515
|
for (let match = importRegex.exec(content);match !== null; match = importRegex.exec(content)) {
|
|
16498
16516
|
const importPath = match[1].trim();
|
|
@@ -16627,7 +16645,7 @@ function darkMatterToKnowledgeEntries(pairs, projectName) {
|
|
|
16627
16645
|
}
|
|
16628
16646
|
const confidence = Math.min(0.3 + 0.2 * Math.min(pair.coChangeCount / 10, 1), 0.5);
|
|
16629
16647
|
entries.push({
|
|
16630
|
-
id:
|
|
16648
|
+
id: randomUUID6(),
|
|
16631
16649
|
tier: "swarm",
|
|
16632
16650
|
lesson,
|
|
16633
16651
|
category: "architecture",
|
|
@@ -17041,16 +17059,16 @@ function parseArgs3(args) {
|
|
|
17041
17059
|
}
|
|
17042
17060
|
function persistReportJson(directory, report) {
|
|
17043
17061
|
const epicDir = path31.join(directory, ".swarm", "epic");
|
|
17044
|
-
|
|
17062
|
+
fs11.mkdirSync(epicDir, { recursive: true });
|
|
17045
17063
|
const filePath = path31.join(epicDir, "coupling-report.json");
|
|
17046
17064
|
const tmpPath = `${filePath}.tmp.${randomBytes(8).toString("hex")}`;
|
|
17047
|
-
|
|
17065
|
+
fs11.writeFileSync(tmpPath, `${JSON.stringify(report, null, 2)}
|
|
17048
17066
|
`, "utf-8");
|
|
17049
17067
|
try {
|
|
17050
|
-
|
|
17068
|
+
fs11.renameSync(tmpPath, filePath);
|
|
17051
17069
|
} catch (err) {
|
|
17052
17070
|
try {
|
|
17053
|
-
|
|
17071
|
+
fs11.unlinkSync(tmpPath);
|
|
17054
17072
|
} catch {}
|
|
17055
17073
|
throw err;
|
|
17056
17074
|
}
|
|
@@ -17140,8 +17158,8 @@ var _internals22 = {
|
|
|
17140
17158
|
loadCuratorDeps: async () => {
|
|
17141
17159
|
const [{ CuratorConfigSchema }, curator, { createCuratorLLMDelegate: createCuratorLLMDelegate2 }] = await Promise.all([
|
|
17142
17160
|
import("./schema-vw2ffhe9.js"),
|
|
17143
|
-
import("./curator-
|
|
17144
|
-
import("./curator-llm-factory-
|
|
17161
|
+
import("./curator-6zvpn7fs.js"),
|
|
17162
|
+
import("./curator-llm-factory-r3m5e7n8.js")
|
|
17145
17163
|
]);
|
|
17146
17164
|
return { CuratorConfigSchema, curator, createCuratorLLMDelegate: createCuratorLLMDelegate2 };
|
|
17147
17165
|
}
|
|
@@ -17637,7 +17655,7 @@ import { fileURLToPath } from "url";
|
|
|
17637
17655
|
// package.json
|
|
17638
17656
|
var package_default = {
|
|
17639
17657
|
name: "opencode-swarm",
|
|
17640
|
-
version: "7.107.
|
|
17658
|
+
version: "7.107.2",
|
|
17641
17659
|
description: "Architect-centric agentic swarm plugin for OpenCode - hub-and-spoke orchestration with SME consultation, code generation, and QA review",
|
|
17642
17660
|
main: "dist/index.js",
|
|
17643
17661
|
types: "dist/index.d.ts",
|
|
@@ -17793,7 +17811,7 @@ init_executor();
|
|
|
17793
17811
|
|
|
17794
17812
|
// src/services/knowledge-diagnostics.ts
|
|
17795
17813
|
import { existsSync as existsSync20 } from "fs";
|
|
17796
|
-
import { readFile as
|
|
17814
|
+
import { readFile as readFile12 } from "fs/promises";
|
|
17797
17815
|
|
|
17798
17816
|
// src/services/version-check.ts
|
|
17799
17817
|
import { existsSync as existsSync19, mkdirSync as mkdirSync13, readFileSync as readFileSync10, writeFileSync as writeFileSync8 } from "fs";
|
|
@@ -17869,7 +17887,7 @@ var INSIGHT_BACKLOG_WARN = 50;
|
|
|
17869
17887
|
async function readRawLines(filePath) {
|
|
17870
17888
|
if (!existsSync20(filePath))
|
|
17871
17889
|
return { entries: [], corrupt: 0 };
|
|
17872
|
-
const content = await
|
|
17890
|
+
const content = await readFile12(filePath, "utf-8");
|
|
17873
17891
|
const entries = [];
|
|
17874
17892
|
let corrupt = 0;
|
|
17875
17893
|
for (const line of content.split(`
|
|
@@ -17995,7 +18013,7 @@ async function safeJsonlCount(filePath) {
|
|
|
17995
18013
|
if (!filePath || !existsSync20(filePath))
|
|
17996
18014
|
return 0;
|
|
17997
18015
|
try {
|
|
17998
|
-
const content = await
|
|
18016
|
+
const content = await readFile12(filePath, "utf-8");
|
|
17999
18017
|
let n = 0;
|
|
18000
18018
|
for (const line of content.split(`
|
|
18001
18019
|
`)) {
|
|
@@ -19231,7 +19249,7 @@ function decideEpicActivation(tasks, cochangePairs, commitsObserved, options) {
|
|
|
19231
19249
|
|
|
19232
19250
|
// src/turbo/epic/calibration.ts
|
|
19233
19251
|
init_logger();
|
|
19234
|
-
import * as
|
|
19252
|
+
import * as fs13 from "fs";
|
|
19235
19253
|
import * as path38 from "path";
|
|
19236
19254
|
var STATE_FILE = "calibration.json";
|
|
19237
19255
|
var STATE_REL_DIR = path38.join(".swarm", "epic");
|
|
@@ -19257,12 +19275,12 @@ function markUnreadable(directory, reason) {
|
|
|
19257
19275
|
}
|
|
19258
19276
|
function repairCalibrationUnreadable(directory) {
|
|
19259
19277
|
const filePath = path38.join(directory, STATE_REL_DIR, STATE_FILE);
|
|
19260
|
-
if (!
|
|
19278
|
+
if (!fs13.existsSync(filePath)) {
|
|
19261
19279
|
stateUnreadableMap.delete(directory);
|
|
19262
19280
|
return;
|
|
19263
19281
|
}
|
|
19264
19282
|
try {
|
|
19265
|
-
const raw =
|
|
19283
|
+
const raw = fs13.readFileSync(filePath, "utf-8");
|
|
19266
19284
|
const parsed = JSON.parse(raw);
|
|
19267
19285
|
if (!isValidCalibrationShape(parsed)) {
|
|
19268
19286
|
stateUnreadableMap.set(directory, true);
|
|
@@ -19289,8 +19307,8 @@ function isValidCalibrationShape(candidate) {
|
|
|
19289
19307
|
}
|
|
19290
19308
|
function ensureSwarmEpicDir(directory) {
|
|
19291
19309
|
const dir = path38.resolve(directory, STATE_REL_DIR);
|
|
19292
|
-
if (!
|
|
19293
|
-
|
|
19310
|
+
if (!fs13.existsSync(dir)) {
|
|
19311
|
+
fs13.mkdirSync(dir, { recursive: true });
|
|
19294
19312
|
}
|
|
19295
19313
|
return dir;
|
|
19296
19314
|
}
|
|
@@ -19302,16 +19320,16 @@ function loadCalibrationState(directory) {
|
|
|
19302
19320
|
}
|
|
19303
19321
|
const filePath = path38.join(directory, STATE_REL_DIR, STATE_FILE);
|
|
19304
19322
|
try {
|
|
19305
|
-
if (!
|
|
19323
|
+
if (!fs13.existsSync(filePath)) {
|
|
19306
19324
|
const seed = emptyCalibrationState();
|
|
19307
19325
|
try {
|
|
19308
19326
|
ensureSwarmEpicDir(directory);
|
|
19309
|
-
|
|
19327
|
+
fs13.writeFileSync(filePath, `${JSON.stringify(seed, null, 2)}
|
|
19310
19328
|
`, "utf-8");
|
|
19311
19329
|
} catch {}
|
|
19312
19330
|
return seed;
|
|
19313
19331
|
}
|
|
19314
|
-
const raw =
|
|
19332
|
+
const raw = fs13.readFileSync(filePath, "utf-8");
|
|
19315
19333
|
const parsed = JSON.parse(raw);
|
|
19316
19334
|
if (!isValidCalibrationShape(parsed)) {
|
|
19317
19335
|
markUnreadable(directory, `malformed shape (version=${parsed?.version}, hotModuleAdditions type=${Array.isArray(parsed?.hotModuleAdditions) ? "array" : typeof parsed?.hotModuleAdditions})`);
|
|
@@ -19326,36 +19344,36 @@ function loadCalibrationState(directory) {
|
|
|
19326
19344
|
|
|
19327
19345
|
// src/turbo/epic/divergence-recorder.ts
|
|
19328
19346
|
init_logger();
|
|
19329
|
-
import * as
|
|
19347
|
+
import * as fs14 from "fs";
|
|
19330
19348
|
import * as path39 from "path";
|
|
19331
19349
|
var EVIDENCE_REL_DIR = path39.join(".swarm", "epic");
|
|
19332
19350
|
var EVIDENCE_FILE = "divergence.jsonl";
|
|
19333
19351
|
var MAX_TAIL_BYTES2 = 16 * 1024 * 1024;
|
|
19334
19352
|
function readDivergenceHistory(directory, options) {
|
|
19335
19353
|
const filePath = path39.join(directory, EVIDENCE_REL_DIR, EVIDENCE_FILE);
|
|
19336
|
-
if (!
|
|
19354
|
+
if (!fs14.existsSync(filePath)) {
|
|
19337
19355
|
return [];
|
|
19338
19356
|
}
|
|
19339
19357
|
const maxBytes = options?.maxBytes ?? MAX_TAIL_BYTES2;
|
|
19340
19358
|
let raw;
|
|
19341
19359
|
let tailTruncated = false;
|
|
19342
19360
|
try {
|
|
19343
|
-
const stat5 =
|
|
19361
|
+
const stat5 = fs14.statSync(filePath);
|
|
19344
19362
|
if (Number.isFinite(maxBytes) && stat5.size > maxBytes) {
|
|
19345
|
-
const fd =
|
|
19363
|
+
const fd = fs14.openSync(filePath, "r");
|
|
19346
19364
|
try {
|
|
19347
19365
|
const buf = Buffer.alloc(maxBytes);
|
|
19348
19366
|
const offset = stat5.size - maxBytes;
|
|
19349
|
-
|
|
19367
|
+
fs14.readSync(fd, buf, 0, maxBytes, offset);
|
|
19350
19368
|
raw = buf.toString("utf-8");
|
|
19351
19369
|
tailTruncated = true;
|
|
19352
19370
|
} finally {
|
|
19353
19371
|
try {
|
|
19354
|
-
|
|
19372
|
+
fs14.closeSync(fd);
|
|
19355
19373
|
} catch {}
|
|
19356
19374
|
}
|
|
19357
19375
|
} else {
|
|
19358
|
-
raw =
|
|
19376
|
+
raw = fs14.readFileSync(filePath, "utf-8");
|
|
19359
19377
|
}
|
|
19360
19378
|
} catch {
|
|
19361
19379
|
return [];
|
|
@@ -19380,16 +19398,16 @@ function readDivergenceHistory(directory, options) {
|
|
|
19380
19398
|
}
|
|
19381
19399
|
|
|
19382
19400
|
// src/turbo/epic/promotion-evidence.ts
|
|
19383
|
-
import * as
|
|
19401
|
+
import * as fs15 from "fs";
|
|
19384
19402
|
import * as path40 from "path";
|
|
19385
19403
|
var EVIDENCE_REL_DIR2 = path40.join(".swarm", "evidence");
|
|
19386
19404
|
var EVIDENCE_FILE2 = "epic-promotions.jsonl";
|
|
19387
19405
|
function readPromotionEvidence(directory) {
|
|
19388
19406
|
const filePath = path40.join(directory, EVIDENCE_REL_DIR2, EVIDENCE_FILE2);
|
|
19389
|
-
if (!
|
|
19407
|
+
if (!fs15.existsSync(filePath)) {
|
|
19390
19408
|
return [];
|
|
19391
19409
|
}
|
|
19392
|
-
const raw =
|
|
19410
|
+
const raw = fs15.readFileSync(filePath, "utf-8");
|
|
19393
19411
|
const lines = raw.split(`
|
|
19394
19412
|
`).filter((l) => l.trim().length > 0);
|
|
19395
19413
|
const records = [];
|
|
@@ -19894,7 +19912,7 @@ async function handleEvidenceCommand(directory, args) {
|
|
|
19894
19912
|
return formatTaskEvidenceMarkdown(evidenceData);
|
|
19895
19913
|
}
|
|
19896
19914
|
async function handleEvidenceSummaryCommand(directory) {
|
|
19897
|
-
const { buildEvidenceSummary } = await import("./evidence-summary-service-
|
|
19915
|
+
const { buildEvidenceSummary } = await import("./evidence-summary-service-7nwhd8s4.js");
|
|
19898
19916
|
const artifact = await buildEvidenceSummary(directory);
|
|
19899
19917
|
if (!artifact) {
|
|
19900
19918
|
return "No plan found. Run `/swarm plan` to check plan status.";
|
|
@@ -19958,7 +19976,7 @@ async function handleExportCommand(directory, _args) {
|
|
|
19958
19976
|
}
|
|
19959
19977
|
// src/full-auto/state.ts
|
|
19960
19978
|
var import_proper_lockfile4 = __toESM(require_proper_lockfile(), 1);
|
|
19961
|
-
import * as
|
|
19979
|
+
import * as fs16 from "fs";
|
|
19962
19980
|
import * as path41 from "path";
|
|
19963
19981
|
init_logger();
|
|
19964
19982
|
var lockfile4 = import_proper_lockfile4.default;
|
|
@@ -19968,8 +19986,8 @@ function nowISO2() {
|
|
|
19968
19986
|
}
|
|
19969
19987
|
function ensureSwarmDir(directory) {
|
|
19970
19988
|
const swarmDir = path41.resolve(directory, ".swarm");
|
|
19971
|
-
if (!
|
|
19972
|
-
|
|
19989
|
+
if (!fs16.existsSync(swarmDir)) {
|
|
19990
|
+
fs16.mkdirSync(swarmDir, { recursive: true });
|
|
19973
19991
|
}
|
|
19974
19992
|
return swarmDir;
|
|
19975
19993
|
}
|
|
@@ -20027,7 +20045,7 @@ function withStateLock(directory, fn) {
|
|
|
20027
20045
|
let release;
|
|
20028
20046
|
try {
|
|
20029
20047
|
const lockTarget = validateSwarmPath(directory, STATE_FILE2);
|
|
20030
|
-
if (!
|
|
20048
|
+
if (!fs16.existsSync(lockTarget)) {
|
|
20031
20049
|
ensureSwarmDir(directory);
|
|
20032
20050
|
const seed = {
|
|
20033
20051
|
version: 2,
|
|
@@ -20035,7 +20053,7 @@ function withStateLock(directory, fn) {
|
|
|
20035
20053
|
oversightSequence: 0,
|
|
20036
20054
|
sessions: {}
|
|
20037
20055
|
};
|
|
20038
|
-
|
|
20056
|
+
fs16.writeFileSync(lockTarget, `${JSON.stringify(seed, null, 2)}
|
|
20039
20057
|
`, "utf-8");
|
|
20040
20058
|
}
|
|
20041
20059
|
release = lockfile4.lockSync(lockTarget, {
|
|
@@ -20085,7 +20103,7 @@ function readPersisted(directory) {
|
|
|
20085
20103
|
const filePath = validateSwarmPath(directory, STATE_FILE2);
|
|
20086
20104
|
let stats;
|
|
20087
20105
|
try {
|
|
20088
|
-
stats =
|
|
20106
|
+
stats = fs16.statSync(filePath);
|
|
20089
20107
|
} catch {
|
|
20090
20108
|
clearStateUnreadable();
|
|
20091
20109
|
readCache.delete(filePath);
|
|
@@ -20096,7 +20114,7 @@ function readPersisted(directory) {
|
|
|
20096
20114
|
clearStateUnreadable();
|
|
20097
20115
|
return structuredClone(cached.state);
|
|
20098
20116
|
}
|
|
20099
|
-
const raw =
|
|
20117
|
+
const raw = fs16.readFileSync(filePath, "utf-8");
|
|
20100
20118
|
const parsed = JSON.parse(raw);
|
|
20101
20119
|
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed) || parsed.version !== 2 || !parsed.sessions || typeof parsed.sessions !== "object" || Array.isArray(parsed.sessions)) {
|
|
20102
20120
|
markStateUnreadable(`malformed shape (version=${parsed?.version}, sessions type=${Array.isArray(parsed?.sessions) ? "array" : typeof parsed?.sessions})`);
|
|
@@ -20121,8 +20139,8 @@ function readPersisted(directory) {
|
|
|
20121
20139
|
error(`[full-auto/state] Failed to read ${STATE_FILE2}: ${reason} \u2014 attempting .bak recovery`);
|
|
20122
20140
|
try {
|
|
20123
20141
|
const bakPath = validateSwarmPath(directory, `${STATE_FILE2}.bak`);
|
|
20124
|
-
if (
|
|
20125
|
-
const raw =
|
|
20142
|
+
if (fs16.existsSync(bakPath)) {
|
|
20143
|
+
const raw = fs16.readFileSync(bakPath, "utf-8");
|
|
20126
20144
|
const parsed = JSON.parse(raw);
|
|
20127
20145
|
if (parsed?.version === 2 && parsed.sessions && !Array.isArray(parsed.sessions)) {
|
|
20128
20146
|
warn(`[full-auto/state] Recovered from ${STATE_FILE2}.bak`);
|
|
@@ -20162,23 +20180,23 @@ function writePersisted(directory, persisted) {
|
|
|
20162
20180
|
throw new Error(`Full-Auto state persistence prepare failed: ${msg}`);
|
|
20163
20181
|
}
|
|
20164
20182
|
try {
|
|
20165
|
-
if (
|
|
20166
|
-
|
|
20183
|
+
if (fs16.existsSync(filePath)) {
|
|
20184
|
+
fs16.copyFileSync(filePath, bakPath);
|
|
20167
20185
|
}
|
|
20168
20186
|
} catch {}
|
|
20169
20187
|
try {
|
|
20170
|
-
|
|
20188
|
+
fs16.writeFileSync(tmpPath, payload, "utf-8");
|
|
20171
20189
|
try {
|
|
20172
|
-
const fd =
|
|
20190
|
+
const fd = fs16.openSync(tmpPath, "r+");
|
|
20173
20191
|
try {
|
|
20174
|
-
|
|
20192
|
+
fs16.fsyncSync(fd);
|
|
20175
20193
|
} finally {
|
|
20176
|
-
|
|
20194
|
+
fs16.closeSync(fd);
|
|
20177
20195
|
}
|
|
20178
20196
|
} catch {}
|
|
20179
|
-
|
|
20197
|
+
fs16.renameSync(tmpPath, filePath);
|
|
20180
20198
|
readCache.delete(filePath);
|
|
20181
|
-
const readback =
|
|
20199
|
+
const readback = fs16.readFileSync(filePath, "utf-8");
|
|
20182
20200
|
const parsed = JSON.parse(readback);
|
|
20183
20201
|
if (parsed?.version !== 2) {
|
|
20184
20202
|
throw new Error("Round-trip readback returned wrong version");
|
|
@@ -20832,6 +20850,12 @@ function serializeAgentSession(s) {
|
|
|
20832
20850
|
lastCoderDelegationTaskId: s.lastCoderDelegationTaskId ?? null,
|
|
20833
20851
|
currentTaskId: s.currentTaskId ?? null,
|
|
20834
20852
|
turboMode: s.turboMode ?? false,
|
|
20853
|
+
...s.turboStrategy !== undefined && { turboStrategy: s.turboStrategy },
|
|
20854
|
+
leanTurboActive: s.leanTurboActive ?? false,
|
|
20855
|
+
...s.leanTurboCurrentPhase !== undefined && {
|
|
20856
|
+
leanTurboCurrentPhase: s.leanTurboCurrentPhase
|
|
20857
|
+
},
|
|
20858
|
+
epicModeActive: s.epicModeActive ?? false,
|
|
20835
20859
|
gateLog,
|
|
20836
20860
|
reviewerCallCount,
|
|
20837
20861
|
lastGateFailure: s.lastGateFailure ?? null,
|
|
@@ -20922,13 +20946,21 @@ var _internals30 = {
|
|
|
20922
20946
|
};
|
|
20923
20947
|
|
|
20924
20948
|
// src/commands/handoff.ts
|
|
20925
|
-
|
|
20949
|
+
var HANDOFF_SOURCE_SESSION_PREFIX = "<!-- opencode-swarm-handoff-source-session:";
|
|
20950
|
+
function formatSessionScopedHandoffMarkdown(markdown, sessionID) {
|
|
20951
|
+
if (!sessionID) {
|
|
20952
|
+
return markdown;
|
|
20953
|
+
}
|
|
20954
|
+
return `${HANDOFF_SOURCE_SESSION_PREFIX} ${encodeURIComponent(sessionID)} -->
|
|
20955
|
+
${markdown}`;
|
|
20956
|
+
}
|
|
20957
|
+
async function handleHandoffCommand(directory, _args, sessionID) {
|
|
20926
20958
|
const handoffData = await getHandoffData(directory);
|
|
20927
20959
|
const markdown = formatHandoffMarkdown(handoffData);
|
|
20928
20960
|
try {
|
|
20929
20961
|
const resolvedPath = validateSwarmPath(directory, "handoff.md");
|
|
20930
20962
|
const tempPath = `${resolvedPath}.tmp.${crypto4.randomUUID()}`;
|
|
20931
|
-
await bunWrite(tempPath, markdown);
|
|
20963
|
+
await bunWrite(tempPath, formatSessionScopedHandoffMarkdown(markdown, sessionID));
|
|
20932
20964
|
try {
|
|
20933
20965
|
renameSync10(tempPath, resolvedPath);
|
|
20934
20966
|
} catch (renameErr) {
|
|
@@ -21393,9 +21425,9 @@ import { join as join37 } from "path";
|
|
|
21393
21425
|
|
|
21394
21426
|
// src/hooks/knowledge-migrator.ts
|
|
21395
21427
|
init_logger();
|
|
21396
|
-
import { randomUUID as
|
|
21428
|
+
import { randomUUID as randomUUID8 } from "crypto";
|
|
21397
21429
|
import { existsSync as existsSync26, readFileSync as readFileSync16 } from "fs";
|
|
21398
|
-
import { mkdir as mkdir10, readFile as
|
|
21430
|
+
import { mkdir as mkdir10, readFile as readFile13, writeFile as writeFile12 } from "fs/promises";
|
|
21399
21431
|
import * as os11 from "os";
|
|
21400
21432
|
import * as path43 from "path";
|
|
21401
21433
|
|
|
@@ -21465,9 +21497,9 @@ var _internals32 = {
|
|
|
21465
21497
|
resolveLegacyHiveKnowledgePath,
|
|
21466
21498
|
existsSync: existsSync26,
|
|
21467
21499
|
readFileSync: readFileSync16,
|
|
21468
|
-
readFile:
|
|
21500
|
+
readFile: readFile13,
|
|
21469
21501
|
mkdir: mkdir10,
|
|
21470
|
-
writeFile:
|
|
21502
|
+
writeFile: writeFile12
|
|
21471
21503
|
};
|
|
21472
21504
|
async function migrateContextToKnowledge(directory, config) {
|
|
21473
21505
|
const sentinelPath = path43.join(directory, ".swarm", ".knowledge-migrated");
|
|
@@ -21491,7 +21523,7 @@ async function migrateContextToKnowledge(directory, config) {
|
|
|
21491
21523
|
skippedReason: "no-context-file"
|
|
21492
21524
|
};
|
|
21493
21525
|
}
|
|
21494
|
-
const contextContent = await
|
|
21526
|
+
const contextContent = await readFile13(contextPath, "utf-8");
|
|
21495
21527
|
if (contextContent.trim().length === 0) {
|
|
21496
21528
|
return {
|
|
21497
21529
|
migrated: false,
|
|
@@ -21535,7 +21567,7 @@ async function migrateContextToKnowledge(directory, config) {
|
|
|
21535
21567
|
}
|
|
21536
21568
|
const inferredTags = inferTags(raw.text);
|
|
21537
21569
|
const entry = {
|
|
21538
|
-
id:
|
|
21570
|
+
id: randomUUID8(),
|
|
21539
21571
|
tier: "swarm",
|
|
21540
21572
|
lesson: _internals32.truncateLesson(raw.text),
|
|
21541
21573
|
category: raw.categoryHint ?? _internals32.inferCategoryFromText(raw.text),
|
|
@@ -21635,7 +21667,7 @@ async function migrateHiveKnowledgeLegacy(config) {
|
|
|
21635
21667
|
const scopeTag = legacyEntry.scope_tag || "global";
|
|
21636
21668
|
const legacyId = legacyEntry.id;
|
|
21637
21669
|
const existingIds = new Set(existingHiveEntries.map((e) => e.id));
|
|
21638
|
-
const resolvedId = legacyId && existingIds.has(legacyId) ?
|
|
21670
|
+
const resolvedId = legacyId && existingIds.has(legacyId) ? randomUUID8() : legacyId || randomUUID8();
|
|
21639
21671
|
if (legacyId && existingIds.has(legacyId)) {
|
|
21640
21672
|
warn(`[knowledge-migrator] Legacy entry ID collision for "${legacyId}", generating new UUID`);
|
|
21641
21673
|
}
|
|
@@ -22451,7 +22483,7 @@ import { existsSync as existsSync28 } from "fs";
|
|
|
22451
22483
|
import * as path48 from "path";
|
|
22452
22484
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
22453
22485
|
// src/memory/evaluation.ts
|
|
22454
|
-
import * as
|
|
22486
|
+
import * as fs17 from "fs/promises";
|
|
22455
22487
|
import * as os12 from "os";
|
|
22456
22488
|
import * as path46 from "path";
|
|
22457
22489
|
var DEFAULT_PROVIDERS = [
|
|
@@ -22474,7 +22506,7 @@ async function evaluateMemoryRecallFixtures(options) {
|
|
|
22474
22506
|
for (const fixture of fixtures) {
|
|
22475
22507
|
const materialized = materializeFixture(fixture);
|
|
22476
22508
|
for (const providerName of providers) {
|
|
22477
|
-
const tempRoot = await
|
|
22509
|
+
const tempRoot = await fs17.realpath(await fs17.mkdtemp(path46.join(os12.tmpdir(), "swarm-memory-eval-")));
|
|
22478
22510
|
const provider = createEvaluationProvider(providerName, tempRoot);
|
|
22479
22511
|
try {
|
|
22480
22512
|
await provider.initialize?.();
|
|
@@ -22517,7 +22549,7 @@ async function evaluateMemoryRecallFixtures(options) {
|
|
|
22517
22549
|
async function rmTempRoot(tempRoot) {
|
|
22518
22550
|
for (let attempt = 0;attempt < 10; attempt++) {
|
|
22519
22551
|
try {
|
|
22520
|
-
await
|
|
22552
|
+
await fs17.rm(tempRoot, { recursive: true, force: true });
|
|
22521
22553
|
return;
|
|
22522
22554
|
} catch (err) {
|
|
22523
22555
|
if (attempt === 9)
|
|
@@ -22527,11 +22559,11 @@ async function rmTempRoot(tempRoot) {
|
|
|
22527
22559
|
}
|
|
22528
22560
|
}
|
|
22529
22561
|
async function loadRecallEvaluationFixtures(fixtureDirectory) {
|
|
22530
|
-
const entries = await
|
|
22562
|
+
const entries = await fs17.readdir(fixtureDirectory, { withFileTypes: true });
|
|
22531
22563
|
const files = entries.filter((entry) => entry.isFile() && entry.name.endsWith(".json")).map((entry) => entry.name).sort((a, b) => a.localeCompare(b));
|
|
22532
22564
|
const fixtures = [];
|
|
22533
22565
|
for (const file of files) {
|
|
22534
|
-
const raw = await
|
|
22566
|
+
const raw = await fs17.readFile(path46.join(fixtureDirectory, file), "utf-8");
|
|
22535
22567
|
fixtures.push(validateFixture(JSON.parse(raw), file));
|
|
22536
22568
|
}
|
|
22537
22569
|
return fixtures;
|
|
@@ -22807,14 +22839,14 @@ var CuratorOutputMemoryDecisionSchema = exports_external.object({
|
|
|
22807
22839
|
curatorMemoryDecisions: exports_external.array(CuratorMemoryDecisionSchema).max(20).optional()
|
|
22808
22840
|
}).passthrough();
|
|
22809
22841
|
// src/memory/consolidation-log.ts
|
|
22810
|
-
import { appendFile as appendFile3, mkdir as mkdir11, readFile as
|
|
22842
|
+
import { appendFile as appendFile3, mkdir as mkdir11, readFile as readFile15 } from "fs/promises";
|
|
22811
22843
|
import * as path47 from "path";
|
|
22812
22844
|
var LOG_RELATIVE_PATH = path47.join("memory", "consolidation-log.jsonl");
|
|
22813
22845
|
async function readConsolidationLog(directory) {
|
|
22814
22846
|
const filePath = validateSwarmPath(directory, LOG_RELATIVE_PATH);
|
|
22815
22847
|
let raw;
|
|
22816
22848
|
try {
|
|
22817
|
-
raw = await
|
|
22849
|
+
raw = await readFile15(filePath, "utf-8");
|
|
22818
22850
|
} catch {
|
|
22819
22851
|
return [];
|
|
22820
22852
|
}
|
|
@@ -23987,11 +24019,11 @@ var _internals39 = {
|
|
|
23987
24019
|
};
|
|
23988
24020
|
|
|
23989
24021
|
// src/services/preflight-service.ts
|
|
23990
|
-
import * as
|
|
24022
|
+
import * as fs24 from "fs";
|
|
23991
24023
|
import * as path55 from "path";
|
|
23992
24024
|
|
|
23993
24025
|
// src/tools/lint.ts
|
|
23994
|
-
import * as
|
|
24026
|
+
import * as fs18 from "fs";
|
|
23995
24027
|
import * as path49 from "path";
|
|
23996
24028
|
|
|
23997
24029
|
// src/utils/path-security.ts
|
|
@@ -24066,7 +24098,7 @@ function getLinterCommand(linter, mode, projectDir) {
|
|
|
24066
24098
|
}
|
|
24067
24099
|
function getAdditionalLinterCommand(linter, mode, cwd) {
|
|
24068
24100
|
const gradlewName = process.platform === "win32" ? "gradlew.bat" : "gradlew";
|
|
24069
|
-
const gradlew =
|
|
24101
|
+
const gradlew = fs18.existsSync(path49.join(cwd, gradlewName)) ? path49.join(cwd, gradlewName) : null;
|
|
24070
24102
|
switch (linter) {
|
|
24071
24103
|
case "ruff":
|
|
24072
24104
|
return mode === "fix" ? ["ruff", "check", "--fix", "."] : ["ruff", "check", "."];
|
|
@@ -24100,12 +24132,12 @@ function getAdditionalLinterCommand(linter, mode, cwd) {
|
|
|
24100
24132
|
}
|
|
24101
24133
|
}
|
|
24102
24134
|
function detectRuff(cwd) {
|
|
24103
|
-
if (
|
|
24135
|
+
if (fs18.existsSync(path49.join(cwd, "ruff.toml")))
|
|
24104
24136
|
return isCommandAvailable("ruff");
|
|
24105
24137
|
try {
|
|
24106
24138
|
const pyproject = path49.join(cwd, "pyproject.toml");
|
|
24107
|
-
if (
|
|
24108
|
-
const content =
|
|
24139
|
+
if (fs18.existsSync(pyproject)) {
|
|
24140
|
+
const content = fs18.readFileSync(pyproject, "utf-8");
|
|
24109
24141
|
if (content.includes("[tool.ruff]"))
|
|
24110
24142
|
return isCommandAvailable("ruff");
|
|
24111
24143
|
}
|
|
@@ -24113,21 +24145,21 @@ function detectRuff(cwd) {
|
|
|
24113
24145
|
return false;
|
|
24114
24146
|
}
|
|
24115
24147
|
function detectClippy(cwd) {
|
|
24116
|
-
return
|
|
24148
|
+
return fs18.existsSync(path49.join(cwd, "Cargo.toml")) && isCommandAvailable("cargo");
|
|
24117
24149
|
}
|
|
24118
24150
|
function detectGolangciLint(cwd) {
|
|
24119
|
-
return
|
|
24151
|
+
return fs18.existsSync(path49.join(cwd, "go.mod")) && isCommandAvailable("golangci-lint");
|
|
24120
24152
|
}
|
|
24121
24153
|
function detectCheckstyle(cwd) {
|
|
24122
|
-
const hasMaven =
|
|
24123
|
-
const hasGradle =
|
|
24124
|
-
const hasBinary = hasMaven && isCommandAvailable("mvn") || hasGradle && (
|
|
24154
|
+
const hasMaven = fs18.existsSync(path49.join(cwd, "pom.xml"));
|
|
24155
|
+
const hasGradle = fs18.existsSync(path49.join(cwd, "build.gradle")) || fs18.existsSync(path49.join(cwd, "build.gradle.kts"));
|
|
24156
|
+
const hasBinary = hasMaven && isCommandAvailable("mvn") || hasGradle && (fs18.existsSync(path49.join(cwd, "gradlew")) || isCommandAvailable("gradle"));
|
|
24125
24157
|
return (hasMaven || hasGradle) && hasBinary;
|
|
24126
24158
|
}
|
|
24127
24159
|
function detectKtlint(cwd) {
|
|
24128
|
-
const hasKotlin =
|
|
24160
|
+
const hasKotlin = fs18.existsSync(path49.join(cwd, "build.gradle.kts")) || fs18.existsSync(path49.join(cwd, "build.gradle")) || (() => {
|
|
24129
24161
|
try {
|
|
24130
|
-
return
|
|
24162
|
+
return fs18.readdirSync(cwd).some((f) => f.endsWith(".kt") || f.endsWith(".kts"));
|
|
24131
24163
|
} catch {
|
|
24132
24164
|
return false;
|
|
24133
24165
|
}
|
|
@@ -24136,7 +24168,7 @@ function detectKtlint(cwd) {
|
|
|
24136
24168
|
}
|
|
24137
24169
|
function detectDotnetFormat(cwd) {
|
|
24138
24170
|
try {
|
|
24139
|
-
const files =
|
|
24171
|
+
const files = fs18.readdirSync(cwd);
|
|
24140
24172
|
const hasCsproj = files.some((f) => f.endsWith(".csproj") || f.endsWith(".sln"));
|
|
24141
24173
|
return hasCsproj && isCommandAvailable("dotnet");
|
|
24142
24174
|
} catch {
|
|
@@ -24144,14 +24176,14 @@ function detectDotnetFormat(cwd) {
|
|
|
24144
24176
|
}
|
|
24145
24177
|
}
|
|
24146
24178
|
function detectCppcheck(cwd) {
|
|
24147
|
-
if (
|
|
24179
|
+
if (fs18.existsSync(path49.join(cwd, "CMakeLists.txt"))) {
|
|
24148
24180
|
return isCommandAvailable("cppcheck");
|
|
24149
24181
|
}
|
|
24150
24182
|
try {
|
|
24151
24183
|
const dirsToCheck = [cwd, path49.join(cwd, "src")];
|
|
24152
24184
|
const hasCpp = dirsToCheck.some((dir) => {
|
|
24153
24185
|
try {
|
|
24154
|
-
return
|
|
24186
|
+
return fs18.readdirSync(dir).some((f) => /\.(c|cpp|cc|cxx|h|hpp)$/.test(f));
|
|
24155
24187
|
} catch {
|
|
24156
24188
|
return false;
|
|
24157
24189
|
}
|
|
@@ -24162,13 +24194,13 @@ function detectCppcheck(cwd) {
|
|
|
24162
24194
|
}
|
|
24163
24195
|
}
|
|
24164
24196
|
function detectSwiftlint(cwd) {
|
|
24165
|
-
return
|
|
24197
|
+
return fs18.existsSync(path49.join(cwd, "Package.swift")) && isCommandAvailable("swiftlint");
|
|
24166
24198
|
}
|
|
24167
24199
|
function detectDartAnalyze(cwd) {
|
|
24168
|
-
return
|
|
24200
|
+
return fs18.existsSync(path49.join(cwd, "pubspec.yaml")) && (isCommandAvailable("dart") || isCommandAvailable("flutter"));
|
|
24169
24201
|
}
|
|
24170
24202
|
function detectRubocop(cwd) {
|
|
24171
|
-
return (
|
|
24203
|
+
return (fs18.existsSync(path49.join(cwd, "Gemfile")) || fs18.existsSync(path49.join(cwd, "gems.rb")) || fs18.existsSync(path49.join(cwd, ".rubocop.yml"))) && (isCommandAvailable("rubocop") || isCommandAvailable("bundle"));
|
|
24172
24204
|
}
|
|
24173
24205
|
function detectAdditionalLinter(cwd) {
|
|
24174
24206
|
if (detectRuff(cwd))
|
|
@@ -24197,7 +24229,7 @@ function findBinInAncestors(startDir, binName) {
|
|
|
24197
24229
|
let dir = startDir;
|
|
24198
24230
|
while (true) {
|
|
24199
24231
|
const candidate = path49.join(dir, "node_modules", ".bin", binName);
|
|
24200
|
-
if (
|
|
24232
|
+
if (fs18.existsSync(candidate))
|
|
24201
24233
|
return candidate;
|
|
24202
24234
|
const parent = path49.dirname(dir);
|
|
24203
24235
|
if (parent === dir)
|
|
@@ -24212,7 +24244,7 @@ function findBinInEnvPath(binName) {
|
|
|
24212
24244
|
if (!dir)
|
|
24213
24245
|
continue;
|
|
24214
24246
|
const candidate = path49.join(dir, binName);
|
|
24215
|
-
if (
|
|
24247
|
+
if (fs18.existsSync(candidate))
|
|
24216
24248
|
return candidate;
|
|
24217
24249
|
}
|
|
24218
24250
|
return null;
|
|
@@ -24220,7 +24252,7 @@ function findBinInEnvPath(binName) {
|
|
|
24220
24252
|
async function detectAvailableLinter(directory) {
|
|
24221
24253
|
if (!directory)
|
|
24222
24254
|
return null;
|
|
24223
|
-
if (!
|
|
24255
|
+
if (!fs18.existsSync(directory))
|
|
24224
24256
|
return null;
|
|
24225
24257
|
const projectDir = directory;
|
|
24226
24258
|
const isWindows = process.platform === "win32";
|
|
@@ -24253,7 +24285,7 @@ async function _detectAvailableLinter(_projectDir, biomeBin, eslintBin) {
|
|
|
24253
24285
|
const result = await Promise.race([biomeExit, timeout]);
|
|
24254
24286
|
if (result === "timeout") {
|
|
24255
24287
|
biomeProc.kill();
|
|
24256
|
-
} else if (biomeProc.exitCode === 0 &&
|
|
24288
|
+
} else if (biomeProc.exitCode === 0 && fs18.existsSync(biomeBin)) {
|
|
24257
24289
|
return "biome";
|
|
24258
24290
|
}
|
|
24259
24291
|
} catch {}
|
|
@@ -24267,7 +24299,7 @@ async function _detectAvailableLinter(_projectDir, biomeBin, eslintBin) {
|
|
|
24267
24299
|
const result = await Promise.race([eslintExit, timeout]);
|
|
24268
24300
|
if (result === "timeout") {
|
|
24269
24301
|
eslintProc.kill();
|
|
24270
|
-
} else if (eslintProc.exitCode === 0 &&
|
|
24302
|
+
} else if (eslintProc.exitCode === 0 && fs18.existsSync(eslintBin)) {
|
|
24271
24303
|
return "eslint";
|
|
24272
24304
|
}
|
|
24273
24305
|
} catch {}
|
|
@@ -24443,7 +24475,7 @@ var _internals40 = {
|
|
|
24443
24475
|
};
|
|
24444
24476
|
|
|
24445
24477
|
// src/tools/secretscan.ts
|
|
24446
|
-
import * as
|
|
24478
|
+
import * as fs19 from "fs";
|
|
24447
24479
|
import * as path50 from "path";
|
|
24448
24480
|
var MAX_FILE_PATH_LENGTH = 500;
|
|
24449
24481
|
var MAX_FILE_SIZE_BYTES = 512 * 1024;
|
|
@@ -24673,9 +24705,9 @@ function isGlobOrPathPattern(pattern) {
|
|
|
24673
24705
|
function loadSecretScanIgnore(scanDir) {
|
|
24674
24706
|
const ignorePath = path50.join(scanDir, ".secretscanignore");
|
|
24675
24707
|
try {
|
|
24676
|
-
if (!
|
|
24708
|
+
if (!fs19.existsSync(ignorePath))
|
|
24677
24709
|
return [];
|
|
24678
|
-
const content =
|
|
24710
|
+
const content = fs19.readFileSync(ignorePath, "utf8");
|
|
24679
24711
|
const patterns = [];
|
|
24680
24712
|
for (const rawLine of content.split(/\r?\n/)) {
|
|
24681
24713
|
const line = rawLine.trim();
|
|
@@ -24790,11 +24822,11 @@ function createRedactedContext(line, findings) {
|
|
|
24790
24822
|
result += line.slice(lastEnd);
|
|
24791
24823
|
return result;
|
|
24792
24824
|
}
|
|
24793
|
-
var O_NOFOLLOW = process.platform !== "win32" ?
|
|
24825
|
+
var O_NOFOLLOW = process.platform !== "win32" ? fs19.constants.O_NOFOLLOW : undefined;
|
|
24794
24826
|
function scanFileForSecrets(filePath) {
|
|
24795
24827
|
const findings = [];
|
|
24796
24828
|
try {
|
|
24797
|
-
const lstat2 =
|
|
24829
|
+
const lstat2 = fs19.lstatSync(filePath);
|
|
24798
24830
|
if (lstat2.isSymbolicLink()) {
|
|
24799
24831
|
return findings;
|
|
24800
24832
|
}
|
|
@@ -24803,14 +24835,14 @@ function scanFileForSecrets(filePath) {
|
|
|
24803
24835
|
}
|
|
24804
24836
|
let buffer;
|
|
24805
24837
|
if (O_NOFOLLOW !== undefined) {
|
|
24806
|
-
const fd =
|
|
24838
|
+
const fd = fs19.openSync(filePath, "r", O_NOFOLLOW);
|
|
24807
24839
|
try {
|
|
24808
|
-
buffer =
|
|
24840
|
+
buffer = fs19.readFileSync(fd);
|
|
24809
24841
|
} finally {
|
|
24810
|
-
|
|
24842
|
+
fs19.closeSync(fd);
|
|
24811
24843
|
}
|
|
24812
24844
|
} else {
|
|
24813
|
-
buffer =
|
|
24845
|
+
buffer = fs19.readFileSync(filePath);
|
|
24814
24846
|
}
|
|
24815
24847
|
if (isBinaryFile(filePath, buffer)) {
|
|
24816
24848
|
return findings;
|
|
@@ -24865,7 +24897,7 @@ function findScannableFiles(dir, excludeExact, excludeGlobs, scanDir, visited, s
|
|
|
24865
24897
|
const files = [];
|
|
24866
24898
|
let entries;
|
|
24867
24899
|
try {
|
|
24868
|
-
entries =
|
|
24900
|
+
entries = fs19.readdirSync(dir);
|
|
24869
24901
|
} catch {
|
|
24870
24902
|
stats.fileErrors++;
|
|
24871
24903
|
return files;
|
|
@@ -24888,7 +24920,7 @@ function findScannableFiles(dir, excludeExact, excludeGlobs, scanDir, visited, s
|
|
|
24888
24920
|
}
|
|
24889
24921
|
let lstat2;
|
|
24890
24922
|
try {
|
|
24891
|
-
lstat2 =
|
|
24923
|
+
lstat2 = fs19.lstatSync(fullPath);
|
|
24892
24924
|
} catch {
|
|
24893
24925
|
stats.fileErrors++;
|
|
24894
24926
|
continue;
|
|
@@ -24900,7 +24932,7 @@ function findScannableFiles(dir, excludeExact, excludeGlobs, scanDir, visited, s
|
|
|
24900
24932
|
if (lstat2.isDirectory()) {
|
|
24901
24933
|
let realPath;
|
|
24902
24934
|
try {
|
|
24903
|
-
realPath =
|
|
24935
|
+
realPath = fs19.realpathSync(fullPath);
|
|
24904
24936
|
} catch {
|
|
24905
24937
|
stats.fileErrors++;
|
|
24906
24938
|
continue;
|
|
@@ -24985,12 +25017,12 @@ var secretscan = createSwarmTool({
|
|
|
24985
25017
|
const _scanDirRaw = path50.resolve(directory);
|
|
24986
25018
|
const scanDir = (() => {
|
|
24987
25019
|
try {
|
|
24988
|
-
return
|
|
25020
|
+
return fs19.realpathSync(_scanDirRaw);
|
|
24989
25021
|
} catch {
|
|
24990
25022
|
return _scanDirRaw;
|
|
24991
25023
|
}
|
|
24992
25024
|
})();
|
|
24993
|
-
if (!
|
|
25025
|
+
if (!fs19.existsSync(scanDir)) {
|
|
24994
25026
|
const errorResult = {
|
|
24995
25027
|
error: "directory not found",
|
|
24996
25028
|
scan_dir: directory,
|
|
@@ -25001,7 +25033,7 @@ var secretscan = createSwarmTool({
|
|
|
25001
25033
|
};
|
|
25002
25034
|
return JSON.stringify(errorResult, null, 2);
|
|
25003
25035
|
}
|
|
25004
|
-
const dirStat =
|
|
25036
|
+
const dirStat = fs19.statSync(scanDir);
|
|
25005
25037
|
if (!dirStat.isDirectory()) {
|
|
25006
25038
|
const errorResult = {
|
|
25007
25039
|
error: "target must be a directory, not a file",
|
|
@@ -25052,7 +25084,7 @@ var secretscan = createSwarmTool({
|
|
|
25052
25084
|
break;
|
|
25053
25085
|
const fileFindings = scanFileForSecrets(filePath);
|
|
25054
25086
|
try {
|
|
25055
|
-
const stat5 =
|
|
25087
|
+
const stat5 = fs19.statSync(filePath);
|
|
25056
25088
|
if (stat5.size > MAX_FILE_SIZE_BYTES) {
|
|
25057
25089
|
skippedFiles++;
|
|
25058
25090
|
continue;
|
|
@@ -25144,11 +25176,11 @@ var _internals41 = {
|
|
|
25144
25176
|
};
|
|
25145
25177
|
|
|
25146
25178
|
// src/tools/test-runner.ts
|
|
25147
|
-
import * as
|
|
25179
|
+
import * as fs23 from "fs";
|
|
25148
25180
|
import * as path54 from "path";
|
|
25149
25181
|
|
|
25150
25182
|
// src/test-impact/analyzer.ts
|
|
25151
|
-
import
|
|
25183
|
+
import fs20 from "fs";
|
|
25152
25184
|
import path51 from "path";
|
|
25153
25185
|
var IMPORT_REGEX_ES = /import\s+[\s\S]*?\s+from\s+['"]([^'"]+)['"]/g;
|
|
25154
25186
|
var IMPORT_REGEX_REQUIRE = /require\s*\(\s*['"]([^'"]+)['"]\s*\)/g;
|
|
@@ -25176,7 +25208,7 @@ function sharedTrailingSegments(a, b) {
|
|
|
25176
25208
|
function isCacheStale(impactMap, generatedAtMs) {
|
|
25177
25209
|
for (const sourcePath of Object.keys(impactMap)) {
|
|
25178
25210
|
try {
|
|
25179
|
-
const stat5 =
|
|
25211
|
+
const stat5 = fs20.statSync(sourcePath);
|
|
25180
25212
|
if (stat5.mtimeMs > generatedAtMs) {
|
|
25181
25213
|
return true;
|
|
25182
25214
|
}
|
|
@@ -25192,13 +25224,13 @@ function resolveRelativeImport(fromDir, importPath) {
|
|
|
25192
25224
|
}
|
|
25193
25225
|
const resolved = path51.resolve(fromDir, importPath);
|
|
25194
25226
|
if (path51.extname(resolved)) {
|
|
25195
|
-
if (
|
|
25227
|
+
if (fs20.existsSync(resolved) && fs20.statSync(resolved).isFile()) {
|
|
25196
25228
|
return normalizePath2(resolved);
|
|
25197
25229
|
}
|
|
25198
25230
|
} else {
|
|
25199
25231
|
for (const ext of EXTENSIONS_TO_TRY) {
|
|
25200
25232
|
const withExt = resolved + ext;
|
|
25201
|
-
if (
|
|
25233
|
+
if (fs20.existsSync(withExt) && fs20.statSync(withExt).isFile()) {
|
|
25202
25234
|
return normalizePath2(withExt);
|
|
25203
25235
|
}
|
|
25204
25236
|
}
|
|
@@ -25216,7 +25248,7 @@ function resolvePythonImport(fromDir, module) {
|
|
|
25216
25248
|
const rest = module.slice(leadingDots);
|
|
25217
25249
|
if (rest.length === 0) {
|
|
25218
25250
|
const initPath = path51.join(baseDir, "__init__.py");
|
|
25219
|
-
if (
|
|
25251
|
+
if (fs20.existsSync(initPath) && fs20.statSync(initPath).isFile()) {
|
|
25220
25252
|
return normalizePath2(initPath);
|
|
25221
25253
|
}
|
|
25222
25254
|
return null;
|
|
@@ -25227,7 +25259,7 @@ function resolvePythonImport(fromDir, module) {
|
|
|
25227
25259
|
path51.join(baseDir, subpath, "__init__.py")
|
|
25228
25260
|
];
|
|
25229
25261
|
for (const c of candidates) {
|
|
25230
|
-
if (
|
|
25262
|
+
if (fs20.existsSync(c) && fs20.statSync(c).isFile())
|
|
25231
25263
|
return normalizePath2(c);
|
|
25232
25264
|
}
|
|
25233
25265
|
return null;
|
|
@@ -25247,7 +25279,7 @@ function findGoModule(fromDir) {
|
|
|
25247
25279
|
walked.push(cur);
|
|
25248
25280
|
try {
|
|
25249
25281
|
const goMod = path51.join(cur, "go.mod");
|
|
25250
|
-
const content =
|
|
25282
|
+
const content = fs20.readFileSync(goMod, "utf-8");
|
|
25251
25283
|
const moduleMatch = content.match(/^\s*module\s+"?([^"\s/]+(?:\/[^"\s]+)*)"?/m);
|
|
25252
25284
|
if (moduleMatch) {
|
|
25253
25285
|
const result = { moduleRoot: cur, modulePath: moduleMatch[1] };
|
|
@@ -25257,7 +25289,7 @@ function findGoModule(fromDir) {
|
|
|
25257
25289
|
}
|
|
25258
25290
|
} catch {}
|
|
25259
25291
|
try {
|
|
25260
|
-
|
|
25292
|
+
fs20.accessSync(path51.join(cur, ".git"));
|
|
25261
25293
|
break;
|
|
25262
25294
|
} catch {}
|
|
25263
25295
|
const parent = path51.dirname(cur);
|
|
@@ -25282,10 +25314,10 @@ function resolveGoImport(fromDir, importPath) {
|
|
|
25282
25314
|
}
|
|
25283
25315
|
if (dir === null)
|
|
25284
25316
|
return [];
|
|
25285
|
-
if (!
|
|
25317
|
+
if (!fs20.existsSync(dir) || !fs20.statSync(dir).isDirectory())
|
|
25286
25318
|
return [];
|
|
25287
25319
|
try {
|
|
25288
|
-
return
|
|
25320
|
+
return fs20.readdirSync(dir).filter((f) => f.endsWith(".go") && !f.endsWith("_test.go")).map((f) => normalizePath2(path51.join(dir, f)));
|
|
25289
25321
|
} catch {
|
|
25290
25322
|
return [];
|
|
25291
25323
|
}
|
|
@@ -25305,13 +25337,13 @@ function findTestFilesSync(cwd) {
|
|
|
25305
25337
|
function walk(dir, visitedInodes) {
|
|
25306
25338
|
let entries;
|
|
25307
25339
|
try {
|
|
25308
|
-
entries =
|
|
25340
|
+
entries = fs20.readdirSync(dir, { withFileTypes: true });
|
|
25309
25341
|
} catch {
|
|
25310
25342
|
return;
|
|
25311
25343
|
}
|
|
25312
25344
|
let dirInode;
|
|
25313
25345
|
try {
|
|
25314
|
-
dirInode =
|
|
25346
|
+
dirInode = fs20.statSync(dir).ino;
|
|
25315
25347
|
} catch {
|
|
25316
25348
|
return;
|
|
25317
25349
|
}
|
|
@@ -25400,7 +25432,7 @@ async function buildImpactMapInternal(cwd) {
|
|
|
25400
25432
|
for (const testFile of testFiles) {
|
|
25401
25433
|
let content;
|
|
25402
25434
|
try {
|
|
25403
|
-
content =
|
|
25435
|
+
content = fs20.readFileSync(testFile, "utf-8");
|
|
25404
25436
|
} catch {
|
|
25405
25437
|
continue;
|
|
25406
25438
|
}
|
|
@@ -25432,9 +25464,9 @@ async function buildImpactMap(cwd) {
|
|
|
25432
25464
|
}
|
|
25433
25465
|
async function loadImpactMap(cwd, options) {
|
|
25434
25466
|
const cachePath = path51.join(cwd, ".swarm", "cache", "impact-map.json");
|
|
25435
|
-
if (
|
|
25467
|
+
if (fs20.existsSync(cachePath)) {
|
|
25436
25468
|
try {
|
|
25437
|
-
const content =
|
|
25469
|
+
const content = fs20.readFileSync(cachePath, "utf-8");
|
|
25438
25470
|
const data = JSON.parse(content);
|
|
25439
25471
|
if (data.map !== null && typeof data.map === "object" && !Array.isArray(data.map)) {
|
|
25440
25472
|
const map = data.map;
|
|
@@ -25470,15 +25502,15 @@ async function saveImpactMap(cwd, impactMap) {
|
|
|
25470
25502
|
_internals42.validateProjectRoot(cwd);
|
|
25471
25503
|
const cacheDir2 = path51.join(cwd, ".swarm", "cache");
|
|
25472
25504
|
const cachePath = path51.join(cacheDir2, "impact-map.json");
|
|
25473
|
-
if (!
|
|
25474
|
-
|
|
25505
|
+
if (!fs20.existsSync(cacheDir2)) {
|
|
25506
|
+
fs20.mkdirSync(cacheDir2, { recursive: true });
|
|
25475
25507
|
}
|
|
25476
25508
|
const data = {
|
|
25477
25509
|
generatedAt: new Date().toISOString(),
|
|
25478
25510
|
fileCount: Object.keys(impactMap).length,
|
|
25479
25511
|
map: impactMap
|
|
25480
25512
|
};
|
|
25481
|
-
|
|
25513
|
+
fs20.writeFileSync(cachePath, JSON.stringify(data, null, 2), "utf-8");
|
|
25482
25514
|
}
|
|
25483
25515
|
async function analyzeImpact(changedFiles, cwd, budget) {
|
|
25484
25516
|
if (!Array.isArray(changedFiles)) {
|
|
@@ -25847,7 +25879,7 @@ function detectFlakyTests(allHistory) {
|
|
|
25847
25879
|
}
|
|
25848
25880
|
|
|
25849
25881
|
// src/test-impact/history-store.ts
|
|
25850
|
-
import
|
|
25882
|
+
import fs21 from "fs";
|
|
25851
25883
|
import path52 from "path";
|
|
25852
25884
|
var MAX_HISTORY_PER_TEST = 20;
|
|
25853
25885
|
var MAX_ERROR_LENGTH = 500;
|
|
@@ -25957,8 +25989,8 @@ function batchAppendTestRuns(records, workingDir) {
|
|
|
25957
25989
|
const historyPath = getHistoryPath(workingDir);
|
|
25958
25990
|
const historyDir = path52.dirname(historyPath);
|
|
25959
25991
|
_internals43.validateProjectRoot(workingDir);
|
|
25960
|
-
if (!
|
|
25961
|
-
|
|
25992
|
+
if (!fs21.existsSync(historyDir)) {
|
|
25993
|
+
fs21.mkdirSync(historyDir, { recursive: true });
|
|
25962
25994
|
}
|
|
25963
25995
|
withHistoryWriteLock(historyPath, () => {
|
|
25964
25996
|
const existingRecords = readAllRecords(historyPath);
|
|
@@ -25992,13 +26024,13 @@ function batchAppendTestRuns(records, workingDir) {
|
|
|
25992
26024
|
`)}
|
|
25993
26025
|
`;
|
|
25994
26026
|
const tempPath = `${historyPath}.tmp`;
|
|
25995
|
-
|
|
25996
|
-
|
|
26027
|
+
fs21.writeFileSync(tempPath, content, "utf-8");
|
|
26028
|
+
fs21.renameSync(tempPath, historyPath);
|
|
25997
26029
|
} catch (err) {
|
|
25998
26030
|
try {
|
|
25999
26031
|
const tempPath = `${historyPath}.tmp`;
|
|
26000
|
-
if (
|
|
26001
|
-
|
|
26032
|
+
if (fs21.existsSync(tempPath)) {
|
|
26033
|
+
fs21.unlinkSync(tempPath);
|
|
26002
26034
|
}
|
|
26003
26035
|
} catch {}
|
|
26004
26036
|
throw new Error(`Failed to write test history: ${err instanceof Error ? err.message : String(err)}`);
|
|
@@ -26010,7 +26042,7 @@ function withHistoryWriteLock(historyPath, fn) {
|
|
|
26010
26042
|
const deadline = Date.now() + HISTORY_WRITE_LOCK_TIMEOUT_MS;
|
|
26011
26043
|
while (true) {
|
|
26012
26044
|
try {
|
|
26013
|
-
|
|
26045
|
+
fs21.mkdirSync(lockPath);
|
|
26014
26046
|
break;
|
|
26015
26047
|
} catch (error2) {
|
|
26016
26048
|
const code = error2 instanceof Error && "code" in error2 ? error2.code : undefined;
|
|
@@ -26021,9 +26053,9 @@ function withHistoryWriteLock(historyPath, fn) {
|
|
|
26021
26053
|
throw new Error(`Timed out waiting for test history lock: ${historyPath}`);
|
|
26022
26054
|
}
|
|
26023
26055
|
try {
|
|
26024
|
-
const lockStat =
|
|
26056
|
+
const lockStat = fs21.statSync(lockPath);
|
|
26025
26057
|
if (Date.now() - lockStat.mtimeMs >= HISTORY_WRITE_LOCK_STALE_MS) {
|
|
26026
|
-
|
|
26058
|
+
fs21.rmSync(lockPath, { recursive: true, force: true });
|
|
26027
26059
|
continue;
|
|
26028
26060
|
}
|
|
26029
26061
|
} catch {}
|
|
@@ -26038,7 +26070,7 @@ function withHistoryWriteLock(historyPath, fn) {
|
|
|
26038
26070
|
return fn();
|
|
26039
26071
|
} finally {
|
|
26040
26072
|
try {
|
|
26041
|
-
|
|
26073
|
+
fs21.rmSync(lockPath, { recursive: true, force: true });
|
|
26042
26074
|
} catch {}
|
|
26043
26075
|
}
|
|
26044
26076
|
function sleepSync(ms) {
|
|
@@ -26047,11 +26079,11 @@ function withHistoryWriteLock(historyPath, fn) {
|
|
|
26047
26079
|
}
|
|
26048
26080
|
}
|
|
26049
26081
|
function readAllRecords(historyPath) {
|
|
26050
|
-
if (!
|
|
26082
|
+
if (!fs21.existsSync(historyPath)) {
|
|
26051
26083
|
return [];
|
|
26052
26084
|
}
|
|
26053
26085
|
try {
|
|
26054
|
-
const content =
|
|
26086
|
+
const content = fs21.readFileSync(historyPath, "utf-8");
|
|
26055
26087
|
const lines = content.split(`
|
|
26056
26088
|
`);
|
|
26057
26089
|
const records = [];
|
|
@@ -26084,7 +26116,7 @@ var _internals43 = {
|
|
|
26084
26116
|
};
|
|
26085
26117
|
|
|
26086
26118
|
// src/tools/resolve-working-directory.ts
|
|
26087
|
-
import * as
|
|
26119
|
+
import * as fs22 from "fs";
|
|
26088
26120
|
import * as path53 from "path";
|
|
26089
26121
|
function resolveWorkingDirectory(workingDirectory, fallbackDirectory) {
|
|
26090
26122
|
if (workingDirectory == null || workingDirectory === "") {
|
|
@@ -26128,7 +26160,7 @@ function resolveWorkingDirectory(workingDirectory, fallbackDirectory) {
|
|
|
26128
26160
|
const resolvedDir = path53.resolve(normalizedDir);
|
|
26129
26161
|
let statResult;
|
|
26130
26162
|
try {
|
|
26131
|
-
statResult =
|
|
26163
|
+
statResult = fs22.statSync(resolvedDir);
|
|
26132
26164
|
} catch {
|
|
26133
26165
|
return {
|
|
26134
26166
|
success: false,
|
|
@@ -26147,7 +26179,7 @@ function resolveWorkingDirectory(workingDirectory, fallbackDirectory) {
|
|
|
26147
26179
|
const resolvedFallback = path53.resolve(fallbackDirectory);
|
|
26148
26180
|
let fallbackExists = false;
|
|
26149
26181
|
try {
|
|
26150
|
-
|
|
26182
|
+
fs22.statSync(resolvedFallback);
|
|
26151
26183
|
fallbackExists = true;
|
|
26152
26184
|
} catch {
|
|
26153
26185
|
fallbackExists = false;
|
|
@@ -26261,19 +26293,19 @@ function hasDevDependency(devDeps, ...patterns) {
|
|
|
26261
26293
|
return hasPackageJsonDependency(devDeps, ...patterns);
|
|
26262
26294
|
}
|
|
26263
26295
|
function detectGoTest(cwd) {
|
|
26264
|
-
return
|
|
26296
|
+
return fs23.existsSync(path54.join(cwd, "go.mod")) && isCommandAvailable("go");
|
|
26265
26297
|
}
|
|
26266
26298
|
function detectJavaMaven(cwd) {
|
|
26267
|
-
return
|
|
26299
|
+
return fs23.existsSync(path54.join(cwd, "pom.xml")) && isCommandAvailable("mvn");
|
|
26268
26300
|
}
|
|
26269
26301
|
function detectGradle(cwd) {
|
|
26270
|
-
const hasBuildFile =
|
|
26271
|
-
const hasGradlew =
|
|
26302
|
+
const hasBuildFile = fs23.existsSync(path54.join(cwd, "build.gradle")) || fs23.existsSync(path54.join(cwd, "build.gradle.kts"));
|
|
26303
|
+
const hasGradlew = fs23.existsSync(path54.join(cwd, "gradlew")) || fs23.existsSync(path54.join(cwd, "gradlew.bat"));
|
|
26272
26304
|
return hasBuildFile && (hasGradlew || isCommandAvailable("gradle"));
|
|
26273
26305
|
}
|
|
26274
26306
|
function detectDotnetTest(cwd) {
|
|
26275
26307
|
try {
|
|
26276
|
-
const files =
|
|
26308
|
+
const files = fs23.readdirSync(cwd);
|
|
26277
26309
|
const hasCsproj = files.some((f) => f.endsWith(".csproj"));
|
|
26278
26310
|
return hasCsproj && isCommandAvailable("dotnet");
|
|
26279
26311
|
} catch {
|
|
@@ -26281,25 +26313,25 @@ function detectDotnetTest(cwd) {
|
|
|
26281
26313
|
}
|
|
26282
26314
|
}
|
|
26283
26315
|
function detectCTest(cwd) {
|
|
26284
|
-
const hasSource =
|
|
26285
|
-
const hasBuildCache =
|
|
26316
|
+
const hasSource = fs23.existsSync(path54.join(cwd, "CMakeLists.txt"));
|
|
26317
|
+
const hasBuildCache = fs23.existsSync(path54.join(cwd, "CMakeCache.txt")) || fs23.existsSync(path54.join(cwd, "build", "CMakeCache.txt"));
|
|
26286
26318
|
return (hasSource || hasBuildCache) && isCommandAvailable("ctest");
|
|
26287
26319
|
}
|
|
26288
26320
|
function detectSwiftTest(cwd) {
|
|
26289
|
-
return
|
|
26321
|
+
return fs23.existsSync(path54.join(cwd, "Package.swift")) && isCommandAvailable("swift");
|
|
26290
26322
|
}
|
|
26291
26323
|
function detectDartTest(cwd) {
|
|
26292
|
-
return
|
|
26324
|
+
return fs23.existsSync(path54.join(cwd, "pubspec.yaml")) && (isCommandAvailable("dart") || isCommandAvailable("flutter"));
|
|
26293
26325
|
}
|
|
26294
26326
|
function detectRSpec(cwd) {
|
|
26295
|
-
const hasRSpecFile =
|
|
26296
|
-
const hasGemfile =
|
|
26297
|
-
const hasSpecDir =
|
|
26327
|
+
const hasRSpecFile = fs23.existsSync(path54.join(cwd, ".rspec"));
|
|
26328
|
+
const hasGemfile = fs23.existsSync(path54.join(cwd, "Gemfile"));
|
|
26329
|
+
const hasSpecDir = fs23.existsSync(path54.join(cwd, "spec"));
|
|
26298
26330
|
const hasRSpec = hasRSpecFile || hasGemfile && hasSpecDir;
|
|
26299
26331
|
return hasRSpec && (isCommandAvailable("bundle") || isCommandAvailable("rspec"));
|
|
26300
26332
|
}
|
|
26301
26333
|
function detectMinitest(cwd) {
|
|
26302
|
-
return
|
|
26334
|
+
return fs23.existsSync(path54.join(cwd, "test")) && (fs23.existsSync(path54.join(cwd, "Gemfile")) || fs23.existsSync(path54.join(cwd, "Rakefile"))) && isCommandAvailable("ruby");
|
|
26303
26335
|
}
|
|
26304
26336
|
var DISPATCH_FRAMEWORK_MAP = {
|
|
26305
26337
|
bun: "bun",
|
|
@@ -26385,8 +26417,8 @@ async function detectTestFramework(cwd) {
|
|
|
26385
26417
|
const baseDir = cwd;
|
|
26386
26418
|
try {
|
|
26387
26419
|
const packageJsonPath = path54.join(baseDir, "package.json");
|
|
26388
|
-
if (
|
|
26389
|
-
const content =
|
|
26420
|
+
if (fs23.existsSync(packageJsonPath)) {
|
|
26421
|
+
const content = fs23.readFileSync(packageJsonPath, "utf-8");
|
|
26390
26422
|
const pkg = JSON.parse(content);
|
|
26391
26423
|
const _deps = pkg.dependencies || {};
|
|
26392
26424
|
const devDeps = pkg.devDependencies || {};
|
|
@@ -26405,7 +26437,7 @@ async function detectTestFramework(cwd) {
|
|
|
26405
26437
|
return "jest";
|
|
26406
26438
|
if (hasDevDependency(devDeps, "mocha", "@types/mocha"))
|
|
26407
26439
|
return "mocha";
|
|
26408
|
-
if (
|
|
26440
|
+
if (fs23.existsSync(path54.join(baseDir, "bun.lockb")) || fs23.existsSync(path54.join(baseDir, "bun.lock"))) {
|
|
26409
26441
|
if (scripts.test?.includes("bun"))
|
|
26410
26442
|
return "bun";
|
|
26411
26443
|
}
|
|
@@ -26415,28 +26447,28 @@ async function detectTestFramework(cwd) {
|
|
|
26415
26447
|
const pyprojectTomlPath = path54.join(baseDir, "pyproject.toml");
|
|
26416
26448
|
const setupCfgPath = path54.join(baseDir, "setup.cfg");
|
|
26417
26449
|
const requirementsTxtPath = path54.join(baseDir, "requirements.txt");
|
|
26418
|
-
if (
|
|
26419
|
-
const content =
|
|
26450
|
+
if (fs23.existsSync(pyprojectTomlPath)) {
|
|
26451
|
+
const content = fs23.readFileSync(pyprojectTomlPath, "utf-8");
|
|
26420
26452
|
if (content.includes("[tool.pytest"))
|
|
26421
26453
|
return "pytest";
|
|
26422
26454
|
if (content.includes("pytest"))
|
|
26423
26455
|
return "pytest";
|
|
26424
26456
|
}
|
|
26425
|
-
if (
|
|
26426
|
-
const content =
|
|
26457
|
+
if (fs23.existsSync(setupCfgPath)) {
|
|
26458
|
+
const content = fs23.readFileSync(setupCfgPath, "utf-8");
|
|
26427
26459
|
if (content.includes("[pytest]"))
|
|
26428
26460
|
return "pytest";
|
|
26429
26461
|
}
|
|
26430
|
-
if (
|
|
26431
|
-
const content =
|
|
26462
|
+
if (fs23.existsSync(requirementsTxtPath)) {
|
|
26463
|
+
const content = fs23.readFileSync(requirementsTxtPath, "utf-8");
|
|
26432
26464
|
if (content.includes("pytest"))
|
|
26433
26465
|
return "pytest";
|
|
26434
26466
|
}
|
|
26435
26467
|
} catch {}
|
|
26436
26468
|
try {
|
|
26437
26469
|
const cargoTomlPath = path54.join(baseDir, "Cargo.toml");
|
|
26438
|
-
if (
|
|
26439
|
-
const content =
|
|
26470
|
+
if (fs23.existsSync(cargoTomlPath)) {
|
|
26471
|
+
const content = fs23.readFileSync(cargoTomlPath, "utf-8");
|
|
26440
26472
|
if (content.includes("[dev-dependencies]")) {
|
|
26441
26473
|
if (content.includes("tokio") || content.includes("mockall") || content.includes("pretty_assertions")) {
|
|
26442
26474
|
return "cargo";
|
|
@@ -26448,7 +26480,7 @@ async function detectTestFramework(cwd) {
|
|
|
26448
26480
|
const pesterConfigPath = path54.join(baseDir, "pester.config.ps1");
|
|
26449
26481
|
const pesterConfigJsonPath = path54.join(baseDir, "pester.config.ps1.json");
|
|
26450
26482
|
const pesterPs1Path = path54.join(baseDir, "tests.ps1");
|
|
26451
|
-
if (
|
|
26483
|
+
if (fs23.existsSync(pesterConfigPath) || fs23.existsSync(pesterConfigJsonPath) || fs23.existsSync(pesterPs1Path)) {
|
|
26452
26484
|
return "pester";
|
|
26453
26485
|
}
|
|
26454
26486
|
} catch {}
|
|
@@ -26551,19 +26583,19 @@ function hasCompoundTestExtension(filename) {
|
|
|
26551
26583
|
const lower = filename.toLowerCase();
|
|
26552
26584
|
return COMPOUND_TEST_EXTENSIONS.some((ext) => lower.endsWith(ext));
|
|
26553
26585
|
}
|
|
26554
|
-
function isLanguageSpecificTestFile(
|
|
26555
|
-
const lower =
|
|
26586
|
+
function isLanguageSpecificTestFile(basename11) {
|
|
26587
|
+
const lower = basename11.toLowerCase();
|
|
26556
26588
|
if (lower.endsWith("_test.go"))
|
|
26557
26589
|
return true;
|
|
26558
26590
|
if (lower.endsWith(".py") && (lower.startsWith("test_") || lower.endsWith("_test.py")))
|
|
26559
26591
|
return true;
|
|
26560
26592
|
if (lower.endsWith("_spec.rb"))
|
|
26561
26593
|
return true;
|
|
26562
|
-
if (lower.endsWith(".java") && (/^Test[A-Z]/.test(
|
|
26594
|
+
if (lower.endsWith(".java") && (/^Test[A-Z]/.test(basename11) || basename11.endsWith("Test.java") || basename11.endsWith("Tests.java") || lower.endsWith("it.java")))
|
|
26563
26595
|
return true;
|
|
26564
26596
|
if (lower.endsWith(".cs") && (lower.endsWith("test.cs") || lower.endsWith("tests.cs")))
|
|
26565
26597
|
return true;
|
|
26566
|
-
if (lower.endsWith(".kt") && (/^Test[A-Z]/.test(
|
|
26598
|
+
if (lower.endsWith(".kt") && (/^Test[A-Z]/.test(basename11) || lower.endsWith("test.kt") || lower.endsWith("tests.kt")))
|
|
26567
26599
|
return true;
|
|
26568
26600
|
if (lower.endsWith(".tests.ps1"))
|
|
26569
26601
|
return true;
|
|
@@ -26571,23 +26603,23 @@ function isLanguageSpecificTestFile(basename10) {
|
|
|
26571
26603
|
}
|
|
26572
26604
|
function isConventionTestFilePath(filePath) {
|
|
26573
26605
|
const normalizedPath = filePath.replace(/\\/g, "/");
|
|
26574
|
-
const
|
|
26575
|
-
return hasCompoundTestExtension(
|
|
26606
|
+
const basename11 = path54.basename(filePath);
|
|
26607
|
+
return hasCompoundTestExtension(basename11) || basename11.includes(".spec.") || basename11.includes(".test.") || isLanguageSpecificTestFile(basename11) || isTestDirectoryPath(normalizedPath);
|
|
26576
26608
|
}
|
|
26577
26609
|
function getTestFilesFromConvention(sourceFiles, workingDir = process.cwd()) {
|
|
26578
26610
|
const testFiles = [];
|
|
26579
26611
|
for (const file of sourceFiles) {
|
|
26580
26612
|
const absoluteFile = resolveWorkspacePath(file, workingDir);
|
|
26581
26613
|
const relativeFile = path54.relative(workingDir, absoluteFile);
|
|
26582
|
-
const
|
|
26614
|
+
const basename11 = path54.basename(absoluteFile);
|
|
26583
26615
|
const dirname24 = path54.dirname(absoluteFile);
|
|
26584
26616
|
const preferRelativeOutput = !path54.isAbsolute(file);
|
|
26585
26617
|
if (isConventionTestFilePath(relativeFile) || isConventionTestFilePath(file)) {
|
|
26586
26618
|
dedupePush(testFiles, toWorkspaceOutputPath(absoluteFile, workingDir, preferRelativeOutput));
|
|
26587
26619
|
continue;
|
|
26588
26620
|
}
|
|
26589
|
-
const nameWithoutExt =
|
|
26590
|
-
const ext = path54.extname(
|
|
26621
|
+
const nameWithoutExt = basename11.replace(/\.[^.]+$/, "");
|
|
26622
|
+
const ext = path54.extname(basename11);
|
|
26591
26623
|
const genericTestNames = [
|
|
26592
26624
|
`${nameWithoutExt}.spec${ext}`,
|
|
26593
26625
|
`${nameWithoutExt}.test${ext}`
|
|
@@ -26598,7 +26630,7 @@ function getTestFilesFromConvention(sourceFiles, workingDir = process.cwd()) {
|
|
|
26598
26630
|
...languageSpecificTestNames
|
|
26599
26631
|
].map((candidateName) => path54.join(dirname24, candidateName));
|
|
26600
26632
|
const testDirectoryNames = [
|
|
26601
|
-
|
|
26633
|
+
basename11,
|
|
26602
26634
|
...genericTestNames,
|
|
26603
26635
|
...languageSpecificTestNames
|
|
26604
26636
|
];
|
|
@@ -26609,7 +26641,7 @@ function getTestFilesFromConvention(sourceFiles, workingDir = process.cwd()) {
|
|
|
26609
26641
|
...repoLevelDirectories.flatMap((candidateDir) => testDirectoryNames.map((candidateName) => path54.join(candidateDir, candidateName)))
|
|
26610
26642
|
];
|
|
26611
26643
|
for (const testFile of possibleTestFiles) {
|
|
26612
|
-
if (
|
|
26644
|
+
if (fs23.existsSync(testFile)) {
|
|
26613
26645
|
dedupePush(testFiles, toWorkspaceOutputPath(testFile, workingDir, preferRelativeOutput));
|
|
26614
26646
|
}
|
|
26615
26647
|
}
|
|
@@ -26626,7 +26658,7 @@ async function getTestFilesFromGraph(sourceFiles, workingDir) {
|
|
|
26626
26658
|
for (const testFile of candidateTestFiles) {
|
|
26627
26659
|
try {
|
|
26628
26660
|
const absoluteTestFile = resolveWorkspacePath(testFile, workingDir);
|
|
26629
|
-
const content =
|
|
26661
|
+
const content = fs23.readFileSync(absoluteTestFile, "utf-8");
|
|
26630
26662
|
const testDir = path54.dirname(absoluteTestFile);
|
|
26631
26663
|
const importRegex = /import\s+.*?\s+from\s+['"]([^'"]+)['"]/g;
|
|
26632
26664
|
let match;
|
|
@@ -26647,7 +26679,7 @@ async function getTestFilesFromGraph(sourceFiles, workingDir) {
|
|
|
26647
26679
|
".cjs"
|
|
26648
26680
|
]) {
|
|
26649
26681
|
const withExt = resolvedImport + extToTry;
|
|
26650
|
-
if (absoluteSourceFiles.includes(withExt) ||
|
|
26682
|
+
if (absoluteSourceFiles.includes(withExt) || fs23.existsSync(withExt)) {
|
|
26651
26683
|
resolvedImport = withExt;
|
|
26652
26684
|
break;
|
|
26653
26685
|
}
|
|
@@ -26686,7 +26718,7 @@ async function getTestFilesFromGraph(sourceFiles, workingDir) {
|
|
|
26686
26718
|
".cjs"
|
|
26687
26719
|
]) {
|
|
26688
26720
|
const withExt = resolvedImport + extToTry;
|
|
26689
|
-
if (absoluteSourceFiles.includes(withExt) ||
|
|
26721
|
+
if (absoluteSourceFiles.includes(withExt) || fs23.existsSync(withExt)) {
|
|
26690
26722
|
resolvedImport = withExt;
|
|
26691
26723
|
break;
|
|
26692
26724
|
}
|
|
@@ -26817,8 +26849,8 @@ function buildTestCommand(framework, scope, files, coverage, baseDir, bail) {
|
|
|
26817
26849
|
return ["mvn", "test"];
|
|
26818
26850
|
case "gradle": {
|
|
26819
26851
|
const isWindows = process.platform === "win32";
|
|
26820
|
-
const hasGradlewBat =
|
|
26821
|
-
const hasGradlew =
|
|
26852
|
+
const hasGradlewBat = fs23.existsSync(path54.join(baseDir, "gradlew.bat"));
|
|
26853
|
+
const hasGradlew = fs23.existsSync(path54.join(baseDir, "gradlew"));
|
|
26822
26854
|
if (hasGradlewBat && isWindows)
|
|
26823
26855
|
return ["gradlew.bat", "test"];
|
|
26824
26856
|
if (hasGradlew)
|
|
@@ -26835,7 +26867,7 @@ function buildTestCommand(framework, scope, files, coverage, baseDir, bail) {
|
|
|
26835
26867
|
"cmake-build-release",
|
|
26836
26868
|
"out"
|
|
26837
26869
|
];
|
|
26838
|
-
const actualBuildDir = buildDirCandidates.find((d) =>
|
|
26870
|
+
const actualBuildDir = buildDirCandidates.find((d) => fs23.existsSync(path54.join(baseDir, d, "CMakeCache.txt"))) ?? "build";
|
|
26839
26871
|
return ["ctest", "--test-dir", actualBuildDir];
|
|
26840
26872
|
}
|
|
26841
26873
|
case "swift-test":
|
|
@@ -27273,9 +27305,9 @@ async function runTests(framework, scope, files, coverage, timeout_ms, cwd, bail
|
|
|
27273
27305
|
try {
|
|
27274
27306
|
if (vitestJsonOutputPath) {
|
|
27275
27307
|
try {
|
|
27276
|
-
|
|
27277
|
-
if (
|
|
27278
|
-
|
|
27308
|
+
fs23.mkdirSync(path54.dirname(vitestJsonOutputPath), { recursive: true });
|
|
27309
|
+
if (fs23.existsSync(vitestJsonOutputPath)) {
|
|
27310
|
+
fs23.unlinkSync(vitestJsonOutputPath);
|
|
27279
27311
|
}
|
|
27280
27312
|
} catch {}
|
|
27281
27313
|
}
|
|
@@ -27301,8 +27333,8 @@ async function runTests(framework, scope, files, coverage, timeout_ms, cwd, bail
|
|
|
27301
27333
|
}
|
|
27302
27334
|
if (vitestJsonOutputPath) {
|
|
27303
27335
|
try {
|
|
27304
|
-
if (
|
|
27305
|
-
const vitestJsonOutput =
|
|
27336
|
+
if (fs23.existsSync(vitestJsonOutputPath)) {
|
|
27337
|
+
const vitestJsonOutput = fs23.readFileSync(vitestJsonOutputPath, "utf-8");
|
|
27306
27338
|
if (vitestJsonOutput.trim().length > 0) {
|
|
27307
27339
|
output += (output ? `
|
|
27308
27340
|
` : "") + vitestJsonOutput;
|
|
@@ -27952,8 +27984,8 @@ function validateTimeout(timeoutMs, defaultValue) {
|
|
|
27952
27984
|
function getPackageVersion(dir) {
|
|
27953
27985
|
try {
|
|
27954
27986
|
const packagePath = path55.join(dir, "package.json");
|
|
27955
|
-
if (
|
|
27956
|
-
const content =
|
|
27987
|
+
if (fs24.existsSync(packagePath)) {
|
|
27988
|
+
const content = fs24.readFileSync(packagePath, "utf-8");
|
|
27957
27989
|
const pkg = JSON.parse(content);
|
|
27958
27990
|
return pkg.version ?? null;
|
|
27959
27991
|
}
|
|
@@ -27963,8 +27995,8 @@ function getPackageVersion(dir) {
|
|
|
27963
27995
|
function getChangelogVersion(dir) {
|
|
27964
27996
|
try {
|
|
27965
27997
|
const changelogPath = path55.join(dir, "CHANGELOG.md");
|
|
27966
|
-
if (
|
|
27967
|
-
const content =
|
|
27998
|
+
if (fs24.existsSync(changelogPath)) {
|
|
27999
|
+
const content = fs24.readFileSync(changelogPath, "utf-8");
|
|
27968
28000
|
const match = content.match(/^##\s*\[?(\d+\.\d+\.\d+)\]?/m);
|
|
27969
28001
|
if (match) {
|
|
27970
28002
|
return match[1];
|
|
@@ -27977,9 +28009,9 @@ function getVersionFileVersion(dir) {
|
|
|
27977
28009
|
const possibleFiles = ["VERSION.txt", "version.txt", "VERSION", "version"];
|
|
27978
28010
|
for (const file of possibleFiles) {
|
|
27979
28011
|
const filePath = path55.join(dir, file);
|
|
27980
|
-
if (
|
|
28012
|
+
if (fs24.existsSync(filePath)) {
|
|
27981
28013
|
try {
|
|
27982
|
-
const content =
|
|
28014
|
+
const content = fs24.readFileSync(filePath, "utf-8").trim();
|
|
27983
28015
|
const match = content.match(/(\d+\.\d+\.\d+)/);
|
|
27984
28016
|
if (match) {
|
|
27985
28017
|
return match[1];
|
|
@@ -28713,7 +28745,7 @@ async function handleQaGatesCommand(directory, args, sessionID) {
|
|
|
28713
28745
|
}
|
|
28714
28746
|
|
|
28715
28747
|
// src/commands/reset.ts
|
|
28716
|
-
import * as
|
|
28748
|
+
import * as fs25 from "fs";
|
|
28717
28749
|
import * as path56 from "path";
|
|
28718
28750
|
|
|
28719
28751
|
// src/background/circuit-breaker.ts
|
|
@@ -29421,8 +29453,8 @@ async function handleResetCommand(directory, args) {
|
|
|
29421
29453
|
for (const filename of filesToReset) {
|
|
29422
29454
|
try {
|
|
29423
29455
|
const resolvedPath = validateSwarmPath(directory, filename);
|
|
29424
|
-
if (
|
|
29425
|
-
|
|
29456
|
+
if (fs25.existsSync(resolvedPath)) {
|
|
29457
|
+
fs25.unlinkSync(resolvedPath);
|
|
29426
29458
|
results.push(`- \u2705 Deleted ${filename}`);
|
|
29427
29459
|
} else {
|
|
29428
29460
|
results.push(`- \u23ED\uFE0F ${filename} not found (skipped)`);
|
|
@@ -29434,8 +29466,8 @@ async function handleResetCommand(directory, args) {
|
|
|
29434
29466
|
for (const filename of ["SWARM_PLAN.md", "SWARM_PLAN.json"]) {
|
|
29435
29467
|
try {
|
|
29436
29468
|
const rootPath = path56.join(directory, filename);
|
|
29437
|
-
if (
|
|
29438
|
-
|
|
29469
|
+
if (fs25.existsSync(rootPath)) {
|
|
29470
|
+
fs25.unlinkSync(rootPath);
|
|
29439
29471
|
results.push(`- \u2705 Deleted ${filename} (root)`);
|
|
29440
29472
|
}
|
|
29441
29473
|
} catch (err) {
|
|
@@ -29450,8 +29482,8 @@ async function handleResetCommand(directory, args) {
|
|
|
29450
29482
|
}
|
|
29451
29483
|
try {
|
|
29452
29484
|
const summariesPath = validateSwarmPath(directory, "summaries");
|
|
29453
|
-
if (
|
|
29454
|
-
|
|
29485
|
+
if (fs25.existsSync(summariesPath)) {
|
|
29486
|
+
fs25.rmSync(summariesPath, { recursive: true, force: true });
|
|
29455
29487
|
results.push("- \u2705 Deleted summaries/ directory");
|
|
29456
29488
|
} else {
|
|
29457
29489
|
results.push("- \u23ED\uFE0F summaries/ not found (skipped)");
|
|
@@ -29470,11 +29502,11 @@ async function handleResetCommand(directory, args) {
|
|
|
29470
29502
|
}
|
|
29471
29503
|
|
|
29472
29504
|
// src/commands/reset-session.ts
|
|
29473
|
-
import * as
|
|
29505
|
+
import * as fs28 from "fs";
|
|
29474
29506
|
import * as path59 from "path";
|
|
29475
29507
|
|
|
29476
29508
|
// src/prm/trajectory-store.ts
|
|
29477
|
-
import * as
|
|
29509
|
+
import * as fs26 from "fs/promises";
|
|
29478
29510
|
import * as path57 from "path";
|
|
29479
29511
|
var MAX_TRACKED_TRAJECTORY_SESSIONS = 500;
|
|
29480
29512
|
function getTrajectoryPath(sessionId, directory) {
|
|
@@ -29508,7 +29540,7 @@ function clearTrajectoryCache(sessionId) {
|
|
|
29508
29540
|
async function readTrajectory(sessionId, directory) {
|
|
29509
29541
|
try {
|
|
29510
29542
|
const trajectoryPath = getTrajectoryPath(sessionId, directory);
|
|
29511
|
-
const content = await
|
|
29543
|
+
const content = await fs26.readFile(trajectoryPath, "utf-8");
|
|
29512
29544
|
const lines = content.split(`
|
|
29513
29545
|
`).filter((line) => line.trim().length > 0);
|
|
29514
29546
|
const entries = [];
|
|
@@ -29533,15 +29565,15 @@ async function cleanupOldTrajectoryFiles(directory, maxAgeDays = 7) {
|
|
|
29533
29565
|
for (const subdir of ["trajectories", "replays"]) {
|
|
29534
29566
|
try {
|
|
29535
29567
|
const dirPath = validateSwarmPath(directory, subdir);
|
|
29536
|
-
const entries = await
|
|
29568
|
+
const entries = await fs26.readdir(dirPath, { withFileTypes: true });
|
|
29537
29569
|
for (const entry of entries) {
|
|
29538
29570
|
if (!entry.isFile())
|
|
29539
29571
|
continue;
|
|
29540
29572
|
const filePath = path57.join(dirPath, entry.name);
|
|
29541
29573
|
try {
|
|
29542
|
-
const stat6 = await
|
|
29574
|
+
const stat6 = await fs26.stat(filePath);
|
|
29543
29575
|
if (now - stat6.mtimeMs > cutoffMs) {
|
|
29544
|
-
await
|
|
29576
|
+
await fs26.unlink(filePath);
|
|
29545
29577
|
}
|
|
29546
29578
|
} catch {}
|
|
29547
29579
|
}
|
|
@@ -29963,7 +29995,7 @@ function detectPatterns(trajectory, config, lastProcessedStep = 0) {
|
|
|
29963
29995
|
};
|
|
29964
29996
|
}
|
|
29965
29997
|
// src/prm/replay.ts
|
|
29966
|
-
import { promises as
|
|
29998
|
+
import { promises as fs27 } from "fs";
|
|
29967
29999
|
import path58 from "path";
|
|
29968
30000
|
function isPathSafe(targetPath, basePath) {
|
|
29969
30001
|
const resolvedTarget = path58.resolve(targetPath);
|
|
@@ -29994,7 +30026,7 @@ async function startReplayRecording(sessionID, directory) {
|
|
|
29994
30026
|
console.warn(`[replay] Invalid path detected - path traversal attempt blocked for session ${sessionID}`);
|
|
29995
30027
|
return null;
|
|
29996
30028
|
}
|
|
29997
|
-
await
|
|
30029
|
+
await fs27.mkdir(replayDir, { recursive: true });
|
|
29998
30030
|
return filepath;
|
|
29999
30031
|
} catch (err) {
|
|
30000
30032
|
console.warn(`[replay] Failed to start recording for session ${sessionID}: ${err}`);
|
|
@@ -30014,7 +30046,7 @@ async function recordReplayEntry(artifactPath, sessionID, entry) {
|
|
|
30014
30046
|
};
|
|
30015
30047
|
const line = `${JSON.stringify(fullEntry)}
|
|
30016
30048
|
`;
|
|
30017
|
-
await
|
|
30049
|
+
await fs27.appendFile(artifactPath, line, "utf-8");
|
|
30018
30050
|
} catch (err) {
|
|
30019
30051
|
console.warn(`[replay] Failed to record entry: ${err}`);
|
|
30020
30052
|
}
|
|
@@ -30061,8 +30093,8 @@ async function handleResetSessionCommand(directory, _args) {
|
|
|
30061
30093
|
const results = [];
|
|
30062
30094
|
try {
|
|
30063
30095
|
const statePath = validateSwarmPath(directory, "session/state.json");
|
|
30064
|
-
if (
|
|
30065
|
-
|
|
30096
|
+
if (fs28.existsSync(statePath)) {
|
|
30097
|
+
fs28.unlinkSync(statePath);
|
|
30066
30098
|
results.push("\u2705 Deleted .swarm/session/state.json");
|
|
30067
30099
|
} else {
|
|
30068
30100
|
results.push("\u23ED\uFE0F state.json not found (already clean)");
|
|
@@ -30072,9 +30104,9 @@ async function handleResetSessionCommand(directory, _args) {
|
|
|
30072
30104
|
}
|
|
30073
30105
|
const sessionDir = path59.dirname(validateSwarmPath(directory, "session/state.json"));
|
|
30074
30106
|
let sessionFiles = [];
|
|
30075
|
-
if (
|
|
30107
|
+
if (fs28.existsSync(sessionDir)) {
|
|
30076
30108
|
try {
|
|
30077
|
-
sessionFiles =
|
|
30109
|
+
sessionFiles = fs28.readdirSync(sessionDir);
|
|
30078
30110
|
} catch (err) {
|
|
30079
30111
|
results.push(`\u274C Failed to read session directory: ${errorMessage(err)}`);
|
|
30080
30112
|
}
|
|
@@ -30084,11 +30116,11 @@ async function handleResetSessionCommand(directory, _args) {
|
|
|
30084
30116
|
continue;
|
|
30085
30117
|
const filePath = path59.join(sessionDir, file);
|
|
30086
30118
|
try {
|
|
30087
|
-
if (!
|
|
30119
|
+
if (!fs28.existsSync(filePath))
|
|
30088
30120
|
continue;
|
|
30089
|
-
if (!
|
|
30121
|
+
if (!fs28.lstatSync(filePath).isFile())
|
|
30090
30122
|
continue;
|
|
30091
|
-
|
|
30123
|
+
fs28.unlinkSync(filePath);
|
|
30092
30124
|
results.push(`\u2713 Deleted ${file}`);
|
|
30093
30125
|
} catch (err) {
|
|
30094
30126
|
results.push(`\u274C Failed to delete ${file}: ${errorMessage(err)}`);
|
|
@@ -30106,8 +30138,8 @@ async function handleResetSessionCommand(directory, _args) {
|
|
|
30106
30138
|
results.push(`\u2705 Cleared ${chainCount} delegation chain(s)`);
|
|
30107
30139
|
const worktreesDir = path59.resolve(path59.dirname(directory), ".swarm-worktrees");
|
|
30108
30140
|
try {
|
|
30109
|
-
if (
|
|
30110
|
-
|
|
30141
|
+
if (fs28.existsSync(worktreesDir)) {
|
|
30142
|
+
fs28.rmSync(worktreesDir, { recursive: true, force: true });
|
|
30111
30143
|
results.push("\u2705 Removed .swarm-worktrees/ directory");
|
|
30112
30144
|
}
|
|
30113
30145
|
} catch (err) {
|
|
@@ -30213,18 +30245,91 @@ ${error2 instanceof Error ? error2.message : String(error2)}`;
|
|
|
30213
30245
|
}
|
|
30214
30246
|
|
|
30215
30247
|
// src/commands/rollback.ts
|
|
30216
|
-
import * as
|
|
30248
|
+
import * as fs29 from "fs";
|
|
30217
30249
|
import * as path61 from "path";
|
|
30250
|
+
function safeParseToolJson(result) {
|
|
30251
|
+
try {
|
|
30252
|
+
const jsonStr = typeof result === "string" ? result : result.output;
|
|
30253
|
+
return JSON.parse(jsonStr);
|
|
30254
|
+
} catch {
|
|
30255
|
+
return null;
|
|
30256
|
+
}
|
|
30257
|
+
}
|
|
30258
|
+
async function listGitCheckpoints(directory) {
|
|
30259
|
+
try {
|
|
30260
|
+
const result = await checkpoint.execute({ action: "list" }, {
|
|
30261
|
+
directory
|
|
30262
|
+
});
|
|
30263
|
+
const parsed = safeParseToolJson(result);
|
|
30264
|
+
if (!parsed)
|
|
30265
|
+
return null;
|
|
30266
|
+
if (parsed.success !== true || !Array.isArray(parsed.checkpoints)) {
|
|
30267
|
+
return null;
|
|
30268
|
+
}
|
|
30269
|
+
return parsed.checkpoints;
|
|
30270
|
+
} catch {
|
|
30271
|
+
return null;
|
|
30272
|
+
}
|
|
30273
|
+
}
|
|
30274
|
+
function formatGitCheckpointList(checkpoints) {
|
|
30275
|
+
if (checkpoints.length === 0) {
|
|
30276
|
+
return "No checkpoints found. Create one with `/swarm checkpoint save <label>`";
|
|
30277
|
+
}
|
|
30278
|
+
return [
|
|
30279
|
+
"## Available Checkpoints",
|
|
30280
|
+
"",
|
|
30281
|
+
...checkpoints.map((c, index) => `- ${index + 1}. "${c.label}" - ${new Date(c.timestamp).toLocaleString()} (${c.sha.slice(0, 12)})`),
|
|
30282
|
+
"",
|
|
30283
|
+
"Run `/swarm rollback <label-or-number>` to restore to a checkpoint."
|
|
30284
|
+
].join(`
|
|
30285
|
+
`);
|
|
30286
|
+
}
|
|
30287
|
+
function resolveGitCheckpoint(checkpoints, selector) {
|
|
30288
|
+
const index = Number.parseInt(selector, 10);
|
|
30289
|
+
if (/^\d+$/.test(selector) && index >= 1 && index <= checkpoints.length) {
|
|
30290
|
+
return checkpoints[index - 1] ?? null;
|
|
30291
|
+
}
|
|
30292
|
+
return checkpoints.find((c) => c.label === selector) ?? null;
|
|
30293
|
+
}
|
|
30294
|
+
async function restoreGitCheckpoint(directory, selected) {
|
|
30295
|
+
const result = await checkpoint.execute({ action: "restore", label: selected.label }, { directory });
|
|
30296
|
+
const parsed = safeParseToolJson(result);
|
|
30297
|
+
if (!parsed) {
|
|
30298
|
+
return `Error: Failed to parse checkpoint response for "${selected.label}"`;
|
|
30299
|
+
}
|
|
30300
|
+
if (parsed.success !== true) {
|
|
30301
|
+
return `Error: ${parsed.error || `Failed to restore checkpoint "${selected.label}"`}`;
|
|
30302
|
+
}
|
|
30303
|
+
const eventsPath = validateSwarmPath(directory, "events.jsonl");
|
|
30304
|
+
const rollbackEvent = {
|
|
30305
|
+
type: "rollback",
|
|
30306
|
+
label: selected.label,
|
|
30307
|
+
sha: selected.sha,
|
|
30308
|
+
timestamp: new Date().toISOString(),
|
|
30309
|
+
source: "checkpoints.json"
|
|
30310
|
+
};
|
|
30311
|
+
try {
|
|
30312
|
+
fs29.appendFileSync(eventsPath, `${JSON.stringify(rollbackEvent)}
|
|
30313
|
+
`);
|
|
30314
|
+
} catch (error2) {
|
|
30315
|
+
console.error("Failed to write rollback event:", error2 instanceof Error ? error2.message : String(error2));
|
|
30316
|
+
}
|
|
30317
|
+
return `Rolled back to checkpoint "${selected.label}" (${selected.sha.slice(0, 12)})`;
|
|
30318
|
+
}
|
|
30218
30319
|
async function handleRollbackCommand(directory, args) {
|
|
30219
30320
|
const phaseArg = args[0];
|
|
30220
30321
|
if (!phaseArg) {
|
|
30221
30322
|
const manifestPath2 = validateSwarmPath(directory, "checkpoints/manifest.json");
|
|
30222
|
-
if (!
|
|
30223
|
-
|
|
30323
|
+
if (!fs29.existsSync(manifestPath2)) {
|
|
30324
|
+
const gitCheckpoints = await listGitCheckpoints(directory);
|
|
30325
|
+
if (gitCheckpoints) {
|
|
30326
|
+
return formatGitCheckpointList(gitCheckpoints);
|
|
30327
|
+
}
|
|
30328
|
+
return "No checkpoints found. Use `/swarm checkpoint save <label>` to create checkpoints.";
|
|
30224
30329
|
}
|
|
30225
30330
|
let manifest2;
|
|
30226
30331
|
try {
|
|
30227
|
-
manifest2 = JSON.parse(
|
|
30332
|
+
manifest2 = JSON.parse(fs29.readFileSync(manifestPath2, "utf-8"));
|
|
30228
30333
|
} catch {
|
|
30229
30334
|
return "Error: Checkpoint manifest is corrupted. Delete .swarm/checkpoints/manifest.json and re-checkpoint.";
|
|
30230
30335
|
}
|
|
@@ -30243,15 +30348,31 @@ async function handleRollbackCommand(directory, args) {
|
|
|
30243
30348
|
}
|
|
30244
30349
|
const targetPhase = parseInt(phaseArg, 10);
|
|
30245
30350
|
if (Number.isNaN(targetPhase) || targetPhase < 1) {
|
|
30246
|
-
|
|
30351
|
+
const gitCheckpoints = await listGitCheckpoints(directory);
|
|
30352
|
+
if (!gitCheckpoints) {
|
|
30353
|
+
return "Error: Phase number must be a positive integer.";
|
|
30354
|
+
}
|
|
30355
|
+
const selected = resolveGitCheckpoint(gitCheckpoints, phaseArg);
|
|
30356
|
+
if (!selected) {
|
|
30357
|
+
return `Error: Checkpoint "${phaseArg}" not found. Available checkpoints: ${gitCheckpoints.map((c) => `"${c.label}"`).join(", ") || "none"}`;
|
|
30358
|
+
}
|
|
30359
|
+
return restoreGitCheckpoint(directory, selected);
|
|
30247
30360
|
}
|
|
30248
30361
|
const manifestPath = validateSwarmPath(directory, "checkpoints/manifest.json");
|
|
30249
|
-
if (!
|
|
30250
|
-
|
|
30362
|
+
if (!fs29.existsSync(manifestPath)) {
|
|
30363
|
+
const gitCheckpoints = await listGitCheckpoints(directory);
|
|
30364
|
+
if (!gitCheckpoints) {
|
|
30365
|
+
return `Error: No checkpoints found. Cannot rollback to phase ${targetPhase}.`;
|
|
30366
|
+
}
|
|
30367
|
+
const selected = resolveGitCheckpoint(gitCheckpoints, phaseArg);
|
|
30368
|
+
if (!selected) {
|
|
30369
|
+
return `Error: Checkpoint ${phaseArg} not found. Available checkpoints: ${gitCheckpoints.map((c, index) => `${index + 1}="${c.label}"`).join(", ") || "none"}`;
|
|
30370
|
+
}
|
|
30371
|
+
return restoreGitCheckpoint(directory, selected);
|
|
30251
30372
|
}
|
|
30252
30373
|
let manifest;
|
|
30253
30374
|
try {
|
|
30254
|
-
manifest = JSON.parse(
|
|
30375
|
+
manifest = JSON.parse(fs29.readFileSync(manifestPath, "utf-8"));
|
|
30255
30376
|
} catch {
|
|
30256
30377
|
return `Error: Checkpoint manifest is corrupted. Delete .swarm/checkpoints/manifest.json and re-checkpoint.`;
|
|
30257
30378
|
}
|
|
@@ -30261,10 +30382,10 @@ async function handleRollbackCommand(directory, args) {
|
|
|
30261
30382
|
return `Error: Checkpoint for phase ${targetPhase} not found. Available phases: ${available}`;
|
|
30262
30383
|
}
|
|
30263
30384
|
const checkpointDir = validateSwarmPath(directory, `checkpoints/phase-${targetPhase}`);
|
|
30264
|
-
if (!
|
|
30385
|
+
if (!fs29.existsSync(checkpointDir)) {
|
|
30265
30386
|
return `Error: Checkpoint directory for phase ${targetPhase} does not exist.`;
|
|
30266
30387
|
}
|
|
30267
|
-
const checkpointFiles =
|
|
30388
|
+
const checkpointFiles = fs29.readdirSync(checkpointDir);
|
|
30268
30389
|
if (checkpointFiles.length === 0) {
|
|
30269
30390
|
return `Error: Checkpoint for phase ${targetPhase} is empty. Cannot rollback.`;
|
|
30270
30391
|
}
|
|
@@ -30283,7 +30404,7 @@ async function handleRollbackCommand(directory, args) {
|
|
|
30283
30404
|
const src = path61.join(checkpointDir, file);
|
|
30284
30405
|
const dest = path61.join(swarmDir, file);
|
|
30285
30406
|
try {
|
|
30286
|
-
|
|
30407
|
+
fs29.cpSync(src, dest, { recursive: true, force: true });
|
|
30287
30408
|
successes.push(file);
|
|
30288
30409
|
} catch (error2) {
|
|
30289
30410
|
failures.push({ file, error: error2.message });
|
|
@@ -30302,9 +30423,9 @@ async function handleRollbackCommand(directory, args) {
|
|
|
30302
30423
|
}
|
|
30303
30424
|
const existingLedgerPath = path61.join(swarmDir, "plan-ledger.jsonl");
|
|
30304
30425
|
let ledgerDeletionFailed = false;
|
|
30305
|
-
if (
|
|
30426
|
+
if (fs29.existsSync(existingLedgerPath)) {
|
|
30306
30427
|
try {
|
|
30307
|
-
|
|
30428
|
+
fs29.unlinkSync(existingLedgerPath);
|
|
30308
30429
|
} catch (err) {
|
|
30309
30430
|
ledgerDeletionFailed = true;
|
|
30310
30431
|
const errMsg = err instanceof Error ? err.message : String(err);
|
|
@@ -30314,8 +30435,8 @@ async function handleRollbackCommand(directory, args) {
|
|
|
30314
30435
|
if (!ledgerDeletionFailed) {
|
|
30315
30436
|
try {
|
|
30316
30437
|
const planJsonPath = path61.join(swarmDir, "plan.json");
|
|
30317
|
-
if (
|
|
30318
|
-
const planRaw =
|
|
30438
|
+
if (fs29.existsSync(planJsonPath)) {
|
|
30439
|
+
const planRaw = fs29.readFileSync(planJsonPath, "utf-8");
|
|
30319
30440
|
const plan = PlanSchema.parse(JSON.parse(planRaw));
|
|
30320
30441
|
const planId = derivePlanId(plan);
|
|
30321
30442
|
const planHash = computePlanHash(plan);
|
|
@@ -30343,7 +30464,7 @@ async function handleRollbackCommand(directory, args) {
|
|
|
30343
30464
|
timestamp: new Date().toISOString()
|
|
30344
30465
|
};
|
|
30345
30466
|
try {
|
|
30346
|
-
|
|
30467
|
+
fs29.appendFileSync(eventsPath, `${JSON.stringify(rollbackEvent)}
|
|
30347
30468
|
`);
|
|
30348
30469
|
} catch (error2) {
|
|
30349
30470
|
console.error("Failed to write rollback event:", error2 instanceof Error ? error2.message : String(error2));
|
|
@@ -30360,7 +30481,7 @@ async function handleRollbackCommand(directory, args) {
|
|
|
30360
30481
|
}
|
|
30361
30482
|
|
|
30362
30483
|
// src/commands/sdd.ts
|
|
30363
|
-
import * as
|
|
30484
|
+
import * as fs30 from "fs";
|
|
30364
30485
|
import * as path62 from "path";
|
|
30365
30486
|
var SWARM_SPEC_REL = path62.join(".swarm", "spec.md");
|
|
30366
30487
|
var USAGE9 = `Usage:
|
|
@@ -30478,7 +30599,7 @@ ${USAGE9}`;
|
|
|
30478
30599
|
}
|
|
30479
30600
|
const speckitDetection = detectSpeckit(directory);
|
|
30480
30601
|
const speckitPresent = speckitDetection.features.length > 0;
|
|
30481
|
-
const nativeSpecExists =
|
|
30602
|
+
const nativeSpecExists = fs30.existsSync(path62.join(directory, SWARM_SPEC_REL));
|
|
30482
30603
|
if (speckitPresent && !parsed.source && !nativeSpecExists) {
|
|
30483
30604
|
const openspecProjection = buildOpenSpecProjectionSync(directory);
|
|
30484
30605
|
if (openspecProjection !== null) {
|
|
@@ -30548,7 +30669,7 @@ ${USAGE9}`;
|
|
|
30548
30669
|
${USAGE9}`;
|
|
30549
30670
|
}
|
|
30550
30671
|
let useSpeckit = false;
|
|
30551
|
-
const nativeSpecExists =
|
|
30672
|
+
const nativeSpecExists = fs30.existsSync(path62.join(directory, SWARM_SPEC_REL));
|
|
30552
30673
|
if (parsed.source === "speckit") {
|
|
30553
30674
|
useSpeckit = true;
|
|
30554
30675
|
} else if (!parsed.source && !nativeSpecExists) {
|
|
@@ -30859,13 +30980,13 @@ Ensure this is a git repository with commit history.`;
|
|
|
30859
30980
|
const report = reportLines.filter(Boolean).join(`
|
|
30860
30981
|
`);
|
|
30861
30982
|
try {
|
|
30862
|
-
const
|
|
30983
|
+
const fs31 = await import("fs/promises");
|
|
30863
30984
|
const path63 = await import("path");
|
|
30864
30985
|
const reportPath = path63.join(directory, ".swarm", "simulate-report.md");
|
|
30865
|
-
await
|
|
30986
|
+
await fs31.mkdir(path63.dirname(reportPath), { recursive: true });
|
|
30866
30987
|
const reportTempPath = path63.join(path63.dirname(reportPath), `${path63.basename(reportPath)}.tmp.${Date.now()}.${Math.floor(Math.random() * 1e9)}`);
|
|
30867
30988
|
try {
|
|
30868
|
-
await
|
|
30989
|
+
await fs31.writeFile(reportTempPath, report, "utf-8");
|
|
30869
30990
|
renameSync11(reportTempPath, reportPath);
|
|
30870
30991
|
} catch (err) {
|
|
30871
30992
|
try {
|
|
@@ -30891,7 +31012,7 @@ async function handleSpecifyCommand(_directory, args) {
|
|
|
30891
31012
|
|
|
30892
31013
|
// src/services/status-service.ts
|
|
30893
31014
|
import * as fsSync2 from "fs";
|
|
30894
|
-
import { readFile as
|
|
31015
|
+
import { readFile as readFile17 } from "fs/promises";
|
|
30895
31016
|
import * as path64 from "path";
|
|
30896
31017
|
|
|
30897
31018
|
// src/hooks/extractors.ts
|
|
@@ -30936,7 +31057,7 @@ function extractCurrentPhaseFromPlan2(plan) {
|
|
|
30936
31057
|
|
|
30937
31058
|
// src/turbo/lean/state.ts
|
|
30938
31059
|
init_logger();
|
|
30939
|
-
import * as
|
|
31060
|
+
import * as fs31 from "fs";
|
|
30940
31061
|
import * as path63 from "path";
|
|
30941
31062
|
var STATE_FILE3 = "turbo-state.json";
|
|
30942
31063
|
function nowISO3() {
|
|
@@ -30944,8 +31065,8 @@ function nowISO3() {
|
|
|
30944
31065
|
}
|
|
30945
31066
|
function ensureSwarmDir2(directory) {
|
|
30946
31067
|
const swarmDir = path63.resolve(directory, ".swarm");
|
|
30947
|
-
if (!
|
|
30948
|
-
|
|
31068
|
+
if (!fs31.existsSync(swarmDir)) {
|
|
31069
|
+
fs31.mkdirSync(swarmDir, { recursive: true });
|
|
30949
31070
|
}
|
|
30950
31071
|
return swarmDir;
|
|
30951
31072
|
}
|
|
@@ -30989,16 +31110,16 @@ function markStateUnreadable2(directory, reason) {
|
|
|
30989
31110
|
function readPersisted2(directory) {
|
|
30990
31111
|
try {
|
|
30991
31112
|
const filePath = path63.join(directory, ".swarm", STATE_FILE3);
|
|
30992
|
-
if (!
|
|
31113
|
+
if (!fs31.existsSync(filePath)) {
|
|
30993
31114
|
const seed = emptyPersisted2();
|
|
30994
31115
|
try {
|
|
30995
31116
|
ensureSwarmDir2(directory);
|
|
30996
|
-
|
|
31117
|
+
fs31.writeFileSync(filePath, `${JSON.stringify(seed, null, 2)}
|
|
30997
31118
|
`, "utf-8");
|
|
30998
31119
|
} catch {}
|
|
30999
31120
|
return seed;
|
|
31000
31121
|
}
|
|
31001
|
-
const raw =
|
|
31122
|
+
const raw = fs31.readFileSync(filePath, "utf-8");
|
|
31002
31123
|
const parsed = JSON.parse(raw);
|
|
31003
31124
|
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed) || parsed.version !== 1 || !parsed.sessions || typeof parsed.sessions !== "object" || Array.isArray(parsed.sessions)) {
|
|
31004
31125
|
markStateUnreadable2(directory, `malformed shape (version=${parsed?.version}, sessions type=${Array.isArray(parsed?.sessions) ? "array" : typeof parsed?.sessions})`);
|
|
@@ -31035,14 +31156,14 @@ function writePersisted2(directory, persisted) {
|
|
|
31035
31156
|
throw new Error(`Lean Turbo state persistence prepare failed: ${msg}`);
|
|
31036
31157
|
}
|
|
31037
31158
|
try {
|
|
31038
|
-
|
|
31039
|
-
|
|
31159
|
+
fs31.writeFileSync(tmpPath, payload, "utf-8");
|
|
31160
|
+
fs31.renameSync(tmpPath, filePath);
|
|
31040
31161
|
} catch (error2) {
|
|
31041
31162
|
const msg = error2 instanceof Error ? error2.message : String(error2);
|
|
31042
31163
|
error(`[turbo/lean/state] Failed to persist ${STATE_FILE3} atomically: ${msg}`);
|
|
31043
31164
|
try {
|
|
31044
|
-
if (
|
|
31045
|
-
|
|
31165
|
+
if (fs31.existsSync(tmpPath)) {
|
|
31166
|
+
fs31.unlinkSync(tmpPath);
|
|
31046
31167
|
}
|
|
31047
31168
|
} catch {}
|
|
31048
31169
|
throw new Error(`Lean Turbo state persistence failed: ${msg}`);
|
|
@@ -31395,7 +31516,7 @@ async function safeLineCount(filePath) {
|
|
|
31395
31516
|
try {
|
|
31396
31517
|
if (!fsSync2.existsSync(filePath))
|
|
31397
31518
|
return 0;
|
|
31398
|
-
const content = await
|
|
31519
|
+
const content = await readFile17(filePath, "utf-8");
|
|
31399
31520
|
let n = 0;
|
|
31400
31521
|
for (const line of content.split(`
|
|
31401
31522
|
`)) {
|
|
@@ -31876,7 +31997,7 @@ function buildDetailedHelp(commandName, entry) {
|
|
|
31876
31997
|
async function handleHelpCommand(ctx) {
|
|
31877
31998
|
const targetCommand = ctx.args.join(" ");
|
|
31878
31999
|
if (!targetCommand) {
|
|
31879
|
-
const { buildHelpText } = await import("./index-
|
|
32000
|
+
const { buildHelpText } = await import("./index-r87xhtmx.js");
|
|
31880
32001
|
return buildHelpText();
|
|
31881
32002
|
}
|
|
31882
32003
|
const tokens = targetCommand.split(/\s+/);
|
|
@@ -31885,7 +32006,7 @@ async function handleHelpCommand(ctx) {
|
|
|
31885
32006
|
return _internals49.buildDetailedHelp(resolved.key, resolved.entry);
|
|
31886
32007
|
}
|
|
31887
32008
|
const similar = _internals49.findSimilarCommands(targetCommand);
|
|
31888
|
-
const { buildHelpText: fullHelp } = await import("./index-
|
|
32009
|
+
const { buildHelpText: fullHelp } = await import("./index-r87xhtmx.js");
|
|
31889
32010
|
if (similar.length > 0) {
|
|
31890
32011
|
return `Command '/swarm ${targetCommand}' not found.
|
|
31891
32012
|
|
|
@@ -32018,7 +32139,7 @@ var COMMAND_REGISTRY = {
|
|
|
32018
32139
|
},
|
|
32019
32140
|
"guardrail explain": {
|
|
32020
32141
|
handler: async (ctx) => {
|
|
32021
|
-
const { handleGuardrailExplain } = await import("./guardrail-explain-
|
|
32142
|
+
const { handleGuardrailExplain } = await import("./guardrail-explain-zajegz3a.js");
|
|
32022
32143
|
return handleGuardrailExplain(ctx.directory, ctx.args);
|
|
32023
32144
|
},
|
|
32024
32145
|
description: "Dry-run: show what the guardrails would do to a command or write target (executes nothing)",
|
|
@@ -32540,9 +32661,9 @@ Subcommands:
|
|
|
32540
32661
|
},
|
|
32541
32662
|
rollback: {
|
|
32542
32663
|
handler: (ctx) => handleRollbackCommand(ctx.directory, ctx.args),
|
|
32543
|
-
description: "Restore swarm state to a checkpoint
|
|
32544
|
-
details: "Restores .swarm/
|
|
32545
|
-
args: "<phase-number>",
|
|
32664
|
+
description: "Restore swarm state or project files to a checkpoint",
|
|
32665
|
+
details: "Restores legacy .swarm/ phase checkpoints from checkpoints/phase-<N> when present. Otherwise restores named git checkpoints from .swarm/checkpoints.json by label or list number. Writes rollback event to events.jsonl. Without an argument, lists available checkpoints.",
|
|
32666
|
+
args: "<phase-number|label|list-number>",
|
|
32546
32667
|
category: "utility",
|
|
32547
32668
|
toolPolicy: "restricted"
|
|
32548
32669
|
},
|
|
@@ -32555,7 +32676,7 @@ Subcommands:
|
|
|
32555
32676
|
toolPolicy: "agent"
|
|
32556
32677
|
},
|
|
32557
32678
|
handoff: {
|
|
32558
|
-
handler: (ctx) => handleHandoffCommand(ctx.directory, ctx.args),
|
|
32679
|
+
handler: (ctx) => handleHandoffCommand(ctx.directory, ctx.args, ctx.sessionID),
|
|
32559
32680
|
description: "Prepare state for clean model switch (new session)",
|
|
32560
32681
|
args: "",
|
|
32561
32682
|
details: "Generates handoff.md with full session state snapshot, including plan progress, recent decisions, and agent delegation history. Prepended to the next session prompt for seamless model switches.",
|
|
@@ -32781,7 +32902,7 @@ Subcommands:
|
|
|
32781
32902
|
checkpoint: {
|
|
32782
32903
|
handler: (ctx) => handleCheckpointCommand(ctx.directory, ctx.args),
|
|
32783
32904
|
description: "Manage project checkpoints [save|restore|delete|list] <label>",
|
|
32784
|
-
details: "save: creates named
|
|
32905
|
+
details: "save: creates named git checkpoint. restore: hard-resets tracked files to the checkpoint. delete: removes named checkpoint metadata. list: shows all checkpoints with timestamps. All subcommands require a label except list.",
|
|
32785
32906
|
args: "<save|restore|delete|list> <label>",
|
|
32786
32907
|
category: "utility",
|
|
32787
32908
|
clashesWithNativeCcCommand: "/checkpoint",
|
|
@@ -34369,8 +34490,8 @@ function dcValidateTargets(targets, cwd) {
|
|
|
34369
34490
|
const lstatBlock = dcLstatAncestorWalk(t, cwd);
|
|
34370
34491
|
if (lstatBlock)
|
|
34371
34492
|
return lstatBlock;
|
|
34372
|
-
const
|
|
34373
|
-
if (t ===
|
|
34493
|
+
const basename12 = path66.basename(t);
|
|
34494
|
+
if (t === basename12 && DC_SAFE_TARGETS.has(t)) {
|
|
34374
34495
|
continue;
|
|
34375
34496
|
}
|
|
34376
34497
|
if (DC_FS_ROOTS.has(t) || DC_FS_ROOTS.has(t.replace(/\//g, "\\"))) {
|
|
@@ -36779,7 +36900,7 @@ function evidenceToWorkflowState(evidence) {
|
|
|
36779
36900
|
async function readPlanFromDisk(directory) {
|
|
36780
36901
|
try {
|
|
36781
36902
|
const planPath = path68.join(directory, ".swarm", "plan.json");
|
|
36782
|
-
const content = await
|
|
36903
|
+
const content = await fs32.readFile(planPath, "utf-8");
|
|
36783
36904
|
const parsed = JSON.parse(content);
|
|
36784
36905
|
return PlanSchema.parse(parsed);
|
|
36785
36906
|
} catch {
|
|
@@ -36790,7 +36911,7 @@ async function readGateEvidenceFromDisk(directory) {
|
|
|
36790
36911
|
const evidenceMap = new Map;
|
|
36791
36912
|
try {
|
|
36792
36913
|
const evidenceDir = path68.join(directory, ".swarm", "evidence");
|
|
36793
|
-
const entries = await
|
|
36914
|
+
const entries = await fs32.readdir(evidenceDir, { withFileTypes: true });
|
|
36794
36915
|
for (const entry of entries) {
|
|
36795
36916
|
if (!entry.isFile() || !entry.name.endsWith(".json")) {
|
|
36796
36917
|
continue;
|
|
@@ -36801,7 +36922,7 @@ async function readGateEvidenceFromDisk(directory) {
|
|
|
36801
36922
|
}
|
|
36802
36923
|
try {
|
|
36803
36924
|
const filePath = path68.join(evidenceDir, entry.name);
|
|
36804
|
-
const content = await
|
|
36925
|
+
const content = await fs32.readFile(filePath, "utf-8");
|
|
36805
36926
|
const parsed = JSON.parse(content);
|
|
36806
36927
|
if (parsed && typeof parsed.taskId === "string" && Array.isArray(parsed.required_gates)) {
|
|
36807
36928
|
evidenceMap.set(taskId, parsed);
|