opencode-swarm 7.107.2 → 7.107.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli/{curator-6zvpn7fs.js → curator-1nr4qszq.js} +6 -6
- package/dist/cli/{curator-drift-6ad8mxxb.js → curator-drift-ed7p5mfy.js} +2 -2
- package/dist/cli/{curator-llm-factory-r3m5e7n8.js → curator-llm-factory-x9tk7e6m.js} +6 -6
- package/dist/cli/{evidence-summary-service-7nwhd8s4.js → evidence-summary-service-9r28ds8t.js} +3 -3
- package/dist/cli/{guardrail-explain-zajegz3a.js → guardrail-explain-etdrhd4d.js} +7 -7
- package/dist/cli/{guardrail-log-fsc85hwa.js → guardrail-log-2rns4g6d.js} +2 -2
- package/dist/cli/{hive-promoter-nwcsha2j.js → hive-promoter-j4e6rfa6.js} +6 -6
- package/dist/cli/{index-r87xhtmx.js → index-502f6np6.js} +8 -8
- package/dist/cli/{index-mpe0yk9s.js → index-57ymmh7h.js} +5 -3
- package/dist/cli/{index-357p0baj.js → index-91j1sqzm.js} +14 -2
- package/dist/cli/{index-168p3bfr.js → index-cyzzdbvw.js} +573 -509
- package/dist/cli/{index-t4hbye3v.js → index-hkpw4wwa.js} +1 -1
- package/dist/cli/{index-f12bmedv.js → index-kzfkggjx.js} +88 -31
- package/dist/cli/{index-w8dzxnx4.js → index-m1xjr58n.js} +1 -1
- package/dist/cli/{index-fxtrk7y8.js → index-tgtmbf3r.js} +1 -1
- package/dist/cli/{index-jr54w7pb.js → index-w15984gg.js} +2 -2
- package/dist/cli/index.js +6 -6
- package/dist/cli/{pending-delegations-46xf2n2e.js → pending-delegations-ws51m1e1.js} +1 -1
- package/dist/cli/{pr-subscriptions-3c34rnm1.js → pr-subscriptions-0dpn4epk.js} +2 -2
- package/dist/hooks/guardrails/file-authority.d.ts +1 -1
- package/dist/hooks/knowledge-injector.d.ts +3 -0
- package/dist/hooks/knowledge-reader.d.ts +17 -0
- package/dist/hooks/semantic-diff-injection.d.ts +19 -0
- package/dist/index.js +236 -237
- package/dist/services/directive-predicate-runner.d.ts +1 -1
- package/dist/tools/knowledge-remove.d.ts +11 -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-kzfkggjx.js";
|
|
48
48
|
import {
|
|
49
49
|
_internals as _internals2,
|
|
50
50
|
_internals1 as _internals3,
|
|
@@ -136,7 +136,7 @@ import {
|
|
|
136
136
|
resolveSpeckitProjection,
|
|
137
137
|
validateSpeckit,
|
|
138
138
|
writeProjectedSpecSync
|
|
139
|
-
} from "./index-
|
|
139
|
+
} from "./index-91j1sqzm.js";
|
|
140
140
|
import {
|
|
141
141
|
SandboxCapabilityProbe,
|
|
142
142
|
_internals,
|
|
@@ -154,12 +154,12 @@ import {
|
|
|
154
154
|
listActive,
|
|
155
155
|
subscribe,
|
|
156
156
|
unsubscribe
|
|
157
|
-
} from "./index-
|
|
157
|
+
} from "./index-hkpw4wwa.js";
|
|
158
158
|
import {
|
|
159
159
|
readSwarmFileAsync,
|
|
160
160
|
safeHook,
|
|
161
161
|
validateSwarmPath
|
|
162
|
-
} from "./index-
|
|
162
|
+
} from "./index-57ymmh7h.js";
|
|
163
163
|
import {
|
|
164
164
|
deepMerge
|
|
165
165
|
} from "./index-p0arc26j.js";
|
|
@@ -329,7 +329,7 @@ var init_bubblewrap = __esm(() => {
|
|
|
329
329
|
import { spawnSync as spawnSync4 } from "child_process";
|
|
330
330
|
import { mkdtempSync as mkdtempSync2, writeFileSync as writeFileSync6 } from "fs";
|
|
331
331
|
import * as os8 from "os";
|
|
332
|
-
import * as
|
|
332
|
+
import * as path35 from "path";
|
|
333
333
|
function probeSandboxExec() {
|
|
334
334
|
try {
|
|
335
335
|
const result = spawnSync4("sandbox-exec", ["--version"], {
|
|
@@ -357,8 +357,8 @@ function probeSandboxExec() {
|
|
|
357
357
|
function shellEscape2(s) {
|
|
358
358
|
return s.replace(/'/g, "'\\''");
|
|
359
359
|
}
|
|
360
|
-
function sbplEscapePath(
|
|
361
|
-
const withoutControlChars =
|
|
360
|
+
function sbplEscapePath(path36) {
|
|
361
|
+
const withoutControlChars = path36.split("").filter((ch) => {
|
|
362
362
|
const cp = ch.codePointAt(0);
|
|
363
363
|
return cp >= 32 && cp !== 127;
|
|
364
364
|
}).join("");
|
|
@@ -434,8 +434,8 @@ class MacOSSandboxExecutor {
|
|
|
434
434
|
const profile = buildSandboxProfile(allScopes, temp);
|
|
435
435
|
let profilePath;
|
|
436
436
|
try {
|
|
437
|
-
const profileDir = mkdtempSync2(
|
|
438
|
-
profilePath =
|
|
437
|
+
const profileDir = mkdtempSync2(path35.join(os8.tmpdir(), "sandbox-"));
|
|
438
|
+
profilePath = path35.join(profileDir, `profile-${process.pid}-${Date.now()}.sb`);
|
|
439
439
|
writeFileSync6(profilePath, profile, { mode: 384 });
|
|
440
440
|
} catch (err) {
|
|
441
441
|
const message = err instanceof Error ? err.message : String(err);
|
|
@@ -542,7 +542,7 @@ var init_edge_cases = () => {};
|
|
|
542
542
|
// src/sandbox/win32/restricted-environment-executor.ts
|
|
543
543
|
import { spawnSync as spawnSync5 } from "child_process";
|
|
544
544
|
import * as os9 from "os";
|
|
545
|
-
import * as
|
|
545
|
+
import * as path36 from "path";
|
|
546
546
|
function probeWindowsSandbox() {
|
|
547
547
|
try {
|
|
548
548
|
const result = spawnSync5("cmd", ["/c", "echo", "ok"], {
|
|
@@ -589,7 +589,7 @@ function isPathInScopes(command, scopes) {
|
|
|
589
589
|
const paths = command.match(pathPattern) || [];
|
|
590
590
|
if (paths.length === 0)
|
|
591
591
|
return true;
|
|
592
|
-
const normalizedPaths = paths.map((p) =>
|
|
592
|
+
const normalizedPaths = paths.map((p) => path36.win32.resolve(p));
|
|
593
593
|
const normalizedScopes = scopes.map((s) => s.toLowerCase().replace(/\\+$/, ""));
|
|
594
594
|
return normalizedPaths.every((p) => {
|
|
595
595
|
const lower = p.toLowerCase();
|
|
@@ -726,7 +726,7 @@ var init_restricted_environment_executor = __esm(() => {
|
|
|
726
726
|
import * as crypto3 from "crypto";
|
|
727
727
|
import * as fs12 from "fs";
|
|
728
728
|
import * as os10 from "os";
|
|
729
|
-
import * as
|
|
729
|
+
import * as path37 from "path";
|
|
730
730
|
|
|
731
731
|
class NativeWindowsSandboxExecutor {
|
|
732
732
|
mechanism;
|
|
@@ -788,11 +788,11 @@ class NativeWindowsSandboxExecutor {
|
|
|
788
788
|
policy.workspace_roots = scopePaths.length > 0 ? scopePaths : [workspaceRoot];
|
|
789
789
|
policy.writable_roots = policy.workspace_roots;
|
|
790
790
|
const policyJson = JSON.stringify(policy);
|
|
791
|
-
const policyDir =
|
|
791
|
+
const policyDir = path37.join(os10.tmpdir(), "swarm-sandbox-policies");
|
|
792
792
|
try {
|
|
793
793
|
fs12.mkdirSync(policyDir, { recursive: true });
|
|
794
794
|
} catch {}
|
|
795
|
-
const policyFile =
|
|
795
|
+
const policyFile = path37.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;
|
|
@@ -925,7 +925,7 @@ var init_executor = __esm(() => {
|
|
|
925
925
|
|
|
926
926
|
// src/state.ts
|
|
927
927
|
import * as fs32 from "fs/promises";
|
|
928
|
-
import * as
|
|
928
|
+
import * as path69 from "path";
|
|
929
929
|
|
|
930
930
|
// src/db/qa-gate-profile.ts
|
|
931
931
|
import { createHash } from "crypto";
|
|
@@ -6940,7 +6940,9 @@ function handleRestore(label, directory) {
|
|
|
6940
6940
|
error: `checkpoint not found: "${label}"`
|
|
6941
6941
|
}, null, 2);
|
|
6942
6942
|
}
|
|
6943
|
+
const logBeforeReset = log2;
|
|
6943
6944
|
gitExec(["reset", "--hard", checkpoint.sha], directory);
|
|
6945
|
+
writeCheckpointLog(logBeforeReset, directory);
|
|
6944
6946
|
return JSON.stringify({
|
|
6945
6947
|
action: "restore",
|
|
6946
6948
|
success: true,
|
|
@@ -7199,7 +7201,7 @@ async function handleClarifyCommand(_directory, args) {
|
|
|
7199
7201
|
import { spawnSync as spawnSync2 } from "child_process";
|
|
7200
7202
|
import * as fsSync from "fs";
|
|
7201
7203
|
import { promises as fs10 } from "fs";
|
|
7202
|
-
import
|
|
7204
|
+
import path28 from "path";
|
|
7203
7205
|
|
|
7204
7206
|
// src/hooks/curator-postmortem.ts
|
|
7205
7207
|
import { existsSync as existsSync7, readdirSync, readFileSync as readFileSync4 } from "fs";
|
|
@@ -7918,11 +7920,11 @@ var _internals8 = {
|
|
|
7918
7920
|
return KnowledgeConfigSchema2.parse({});
|
|
7919
7921
|
},
|
|
7920
7922
|
applyCuratorKnowledgeUpdates: async (directory, recommendations, knowledgeConfig) => {
|
|
7921
|
-
const { applyCuratorKnowledgeUpdates } = await import("./curator-
|
|
7923
|
+
const { applyCuratorKnowledgeUpdates } = await import("./curator-1nr4qszq.js");
|
|
7922
7924
|
return applyCuratorKnowledgeUpdates(directory, recommendations, knowledgeConfig);
|
|
7923
7925
|
},
|
|
7924
7926
|
checkHivePromotions: async (entries, knowledgeConfig) => {
|
|
7925
|
-
const { checkHivePromotions } = await import("./hive-promoter-
|
|
7927
|
+
const { checkHivePromotions } = await import("./hive-promoter-j4e6rfa6.js");
|
|
7926
7928
|
return checkHivePromotions(entries, knowledgeConfig);
|
|
7927
7929
|
},
|
|
7928
7930
|
applyProposalTriage: async (directory, triage) => {
|
|
@@ -7972,7 +7974,7 @@ var _internals8 = {
|
|
|
7972
7974
|
return result;
|
|
7973
7975
|
},
|
|
7974
7976
|
readPriorDriftReports: async (directory) => {
|
|
7975
|
-
const { readPriorDriftReports } = await import("./curator-drift-
|
|
7977
|
+
const { readPriorDriftReports } = await import("./curator-drift-ed7p5mfy.js");
|
|
7976
7978
|
return readPriorDriftReports(directory);
|
|
7977
7979
|
},
|
|
7978
7980
|
readSwarmKnowledge: (directory) => readKnowledge(resolveSwarmKnowledgePath(directory))
|
|
@@ -9411,13 +9413,25 @@ async function autoRetireSkills(directory, _curatorKnowledgePath, excludeSlugs)
|
|
|
9411
9413
|
warn(`[curator] ${observations[observations.length - 1]}`);
|
|
9412
9414
|
continue;
|
|
9413
9415
|
}
|
|
9414
|
-
|
|
9415
|
-
if (
|
|
9416
|
-
|
|
9417
|
-
|
|
9418
|
-
|
|
9419
|
-
|
|
9420
|
-
|
|
9416
|
+
let archivedSourceMatched = false;
|
|
9417
|
+
if (allArchivedIds.size > 0) {
|
|
9418
|
+
try {
|
|
9419
|
+
const content = await _internals11.readFileAsync(active.path, "utf-8");
|
|
9420
|
+
const sourceIds = _internals11.parseDraftFrontmatter(content)?.sourceKnowledgeIds ?? [];
|
|
9421
|
+
archivedSourceMatched = sourceIds.some((id) => allArchivedIds.has(id));
|
|
9422
|
+
} catch {
|
|
9423
|
+
archivedSourceMatched = false;
|
|
9424
|
+
}
|
|
9425
|
+
}
|
|
9426
|
+
if (archivedSourceMatched) {
|
|
9427
|
+
const result = await _internals11.retireOrMarkStale(directory, path15.dirname(active.path), allArchivedIds);
|
|
9428
|
+
if (result.action === "retire") {
|
|
9429
|
+
observations.push(`Skill '${active.slug}' auto-retired: all source knowledge entries archived`);
|
|
9430
|
+
warn(`[curator] ${observations[observations.length - 1]}`);
|
|
9431
|
+
} else if (result.action === "stale") {
|
|
9432
|
+
observations.push(`Skill '${active.slug}' marked stale: some source knowledge entries archived`);
|
|
9433
|
+
warn(`[curator] ${observations[observations.length - 1]}`);
|
|
9434
|
+
}
|
|
9421
9435
|
}
|
|
9422
9436
|
}
|
|
9423
9437
|
} catch (autoRetireErr) {
|
|
@@ -9442,6 +9456,29 @@ function parseKnowledgeRecommendationsWithDiagnostics(llmOutput) {
|
|
|
9442
9456
|
continue;
|
|
9443
9457
|
const match = trimmed.match(/^-\s+entry\s+(\S+)\s+\(([^)]+)\):\s+(.+)$/i);
|
|
9444
9458
|
if (!match) {
|
|
9459
|
+
const newCandidate = trimmed.match(/^-\s+new candidate:\s+(.+)$/i);
|
|
9460
|
+
if (newCandidate) {
|
|
9461
|
+
const text2 = newCandidate[1].trim().replace(/\s+\([^)]+\)$/, "");
|
|
9462
|
+
recommendations.push({
|
|
9463
|
+
action: "promote",
|
|
9464
|
+
entry_id: undefined,
|
|
9465
|
+
lesson: text2,
|
|
9466
|
+
reason: text2
|
|
9467
|
+
});
|
|
9468
|
+
continue;
|
|
9469
|
+
}
|
|
9470
|
+
const staleEntry = trimmed.match(/^-\s+entry\s+(\S+)\s+appears stale:\s+(.+)$/i);
|
|
9471
|
+
if (staleEntry) {
|
|
9472
|
+
const uuid2 = staleEntry[1];
|
|
9473
|
+
const text2 = staleEntry[2].trim().replace(/\s+\([^)]+\)$/, "");
|
|
9474
|
+
recommendations.push({
|
|
9475
|
+
action: "archive",
|
|
9476
|
+
entry_id: UUID_V4.test(uuid2) ? uuid2 : undefined,
|
|
9477
|
+
lesson: text2,
|
|
9478
|
+
reason: text2
|
|
9479
|
+
});
|
|
9480
|
+
continue;
|
|
9481
|
+
}
|
|
9445
9482
|
diagnostics.push({
|
|
9446
9483
|
section: "OBSERVATIONS",
|
|
9447
9484
|
line: trimmed,
|
|
@@ -11015,6 +11052,9 @@ function normalizeTriggerList(values) {
|
|
|
11015
11052
|
}
|
|
11016
11053
|
return out;
|
|
11017
11054
|
}
|
|
11055
|
+
function finiteRankValue(value) {
|
|
11056
|
+
return Number.isFinite(value) ? value : 0;
|
|
11057
|
+
}
|
|
11018
11058
|
function parseInlineStringList(rawValue) {
|
|
11019
11059
|
const trimmed = rawValue.trim();
|
|
11020
11060
|
if (!trimmed)
|
|
@@ -11233,15 +11273,19 @@ function rankSkillsForContext(skills, taskContext, directory) {
|
|
|
11233
11273
|
const complianceRate = entriesWithVerdict.length > 0 ? compliantCount / entriesWithVerdict.length : 0;
|
|
11234
11274
|
results.push({
|
|
11235
11275
|
skillPath,
|
|
11236
|
-
score,
|
|
11276
|
+
score: finiteRankValue(score),
|
|
11237
11277
|
usageCount: skillEntries.length,
|
|
11238
11278
|
complianceRate
|
|
11239
11279
|
});
|
|
11240
11280
|
}
|
|
11241
11281
|
results.sort((a, b) => {
|
|
11242
|
-
|
|
11243
|
-
|
|
11244
|
-
|
|
11282
|
+
const scoreDelta = finiteRankValue(b.score) - finiteRankValue(a.score);
|
|
11283
|
+
if (scoreDelta !== 0)
|
|
11284
|
+
return scoreDelta;
|
|
11285
|
+
const usageDelta = b.usageCount - a.usageCount;
|
|
11286
|
+
if (usageDelta !== 0)
|
|
11287
|
+
return usageDelta;
|
|
11288
|
+
return a.skillPath.localeCompare(b.skillPath);
|
|
11245
11289
|
});
|
|
11246
11290
|
return results;
|
|
11247
11291
|
}
|
|
@@ -14286,6 +14330,8 @@ function readEarliestSessionStart(directory) {
|
|
|
14286
14330
|
}
|
|
14287
14331
|
|
|
14288
14332
|
// src/tools/write-retro.ts
|
|
14333
|
+
import { existsSync as existsSync17 } from "fs";
|
|
14334
|
+
import path27 from "path";
|
|
14289
14335
|
async function executeWriteRetro(args, directory) {
|
|
14290
14336
|
if (/^(CON|PRN|AUX|NUL|COM[0-9]|LPT[0-9])(:|$)/i.test(directory)) {
|
|
14291
14337
|
return JSON.stringify({
|
|
@@ -14293,6 +14339,12 @@ async function executeWriteRetro(args, directory) {
|
|
|
14293
14339
|
message: "Invalid directory: reserved device name"
|
|
14294
14340
|
}, null, 2);
|
|
14295
14341
|
}
|
|
14342
|
+
if (!existsSync17(path27.join(directory, ".swarm"))) {
|
|
14343
|
+
return JSON.stringify({
|
|
14344
|
+
success: false,
|
|
14345
|
+
message: `Cannot write evidence in "${directory}" \u2014 no .swarm/ folder was found. Run write_retro from an initialized project root.`
|
|
14346
|
+
}, null, 2);
|
|
14347
|
+
}
|
|
14296
14348
|
const phase = args.phase;
|
|
14297
14349
|
if (!Number.isInteger(phase) || phase < 1) {
|
|
14298
14350
|
return JSON.stringify({
|
|
@@ -14703,8 +14755,8 @@ async function copyDirRecursiveWithFailures(src, dest) {
|
|
|
14703
14755
|
const entries = await fs10.readdir(src);
|
|
14704
14756
|
await fs10.mkdir(dest, { recursive: true });
|
|
14705
14757
|
for (const entry of entries) {
|
|
14706
|
-
const srcEntry =
|
|
14707
|
-
const destEntry =
|
|
14758
|
+
const srcEntry = path28.join(src, entry);
|
|
14759
|
+
const destEntry = path28.join(dest, entry);
|
|
14708
14760
|
try {
|
|
14709
14761
|
const stat4 = await fs10.stat(srcEntry);
|
|
14710
14762
|
if (stat4.isDirectory()) {
|
|
@@ -14889,18 +14941,18 @@ async function runFinalizeStage(ctx) {
|
|
|
14889
14941
|
ctx.warnings.push(`Session retrospective write threw: ${retroError instanceof Error ? retroError.message : String(retroError)}`);
|
|
14890
14942
|
}
|
|
14891
14943
|
}
|
|
14892
|
-
const lessonsFilePath =
|
|
14944
|
+
const lessonsFilePath = path28.join(ctx.swarmDir, "close-lessons.md");
|
|
14893
14945
|
try {
|
|
14894
14946
|
const lessonsText = await fs10.readFile(lessonsFilePath, "utf-8");
|
|
14895
14947
|
ctx.explicitLessons = lessonsText.split(`
|
|
14896
14948
|
`).map((line) => line.trim()).filter((line) => line.length > 0 && !line.startsWith("#"));
|
|
14897
14949
|
} catch {}
|
|
14898
14950
|
try {
|
|
14899
|
-
const evidenceDir =
|
|
14951
|
+
const evidenceDir = path28.join(ctx.swarmDir, "evidence");
|
|
14900
14952
|
const evidenceEntries = await fs10.readdir(evidenceDir);
|
|
14901
14953
|
const retroDirs = evidenceEntries.filter((e) => e.startsWith("retro-")).sort((a, b) => a.localeCompare(b, undefined, { numeric: true }));
|
|
14902
14954
|
for (const retroDir of retroDirs) {
|
|
14903
|
-
const evidencePath =
|
|
14955
|
+
const evidencePath = path28.join(evidenceDir, retroDir, "evidence.json");
|
|
14904
14956
|
try {
|
|
14905
14957
|
const content = await fs10.readFile(evidencePath, "utf-8");
|
|
14906
14958
|
const parsed = JSON.parse(content);
|
|
@@ -15084,7 +15136,7 @@ async function copySqliteSafe(srcPath, destPath) {
|
|
|
15084
15136
|
let checkpointVerified = false;
|
|
15085
15137
|
try {
|
|
15086
15138
|
const result = spawnSync2("sqlite3", [srcPath, "PRAGMA wal_checkpoint(TRUNCATE);"], {
|
|
15087
|
-
cwd:
|
|
15139
|
+
cwd: path28.dirname(srcPath),
|
|
15088
15140
|
encoding: "utf-8",
|
|
15089
15141
|
stdio: ["ignore", "pipe", "pipe"],
|
|
15090
15142
|
timeout: 1e4,
|
|
@@ -15152,7 +15204,7 @@ async function copySqliteSafe(srcPath, destPath) {
|
|
|
15152
15204
|
async function runArchiveStage(ctx) {
|
|
15153
15205
|
ctx.timestamp = new Date().toISOString().replace(/[:.]/g, "-");
|
|
15154
15206
|
ctx.archiveSuffix = Math.random().toString(36).slice(2, 8);
|
|
15155
|
-
ctx.archiveDir =
|
|
15207
|
+
ctx.archiveDir = path28.join(ctx.swarmDir, "archive", `swarm-${ctx.timestamp}-${ctx.archiveSuffix}`);
|
|
15156
15208
|
try {
|
|
15157
15209
|
await fs10.mkdir(ctx.archiveDir, { recursive: true });
|
|
15158
15210
|
const WAL_SIDECAR_FILES = new Set(["swarm.db-shm", "swarm.db-wal"]);
|
|
@@ -15167,8 +15219,8 @@ async function runArchiveStage(ctx) {
|
|
|
15167
15219
|
if (linkedKnowledgeShared && KNOWLEDGE_FAMILY_ARTIFACTS.has(artifact)) {
|
|
15168
15220
|
continue;
|
|
15169
15221
|
}
|
|
15170
|
-
const srcPath =
|
|
15171
|
-
const destPath =
|
|
15222
|
+
const srcPath = path28.join(ctx.swarmDir, artifact);
|
|
15223
|
+
const destPath = path28.join(ctx.archiveDir, artifact);
|
|
15172
15224
|
if (artifact === "swarm.db") {
|
|
15173
15225
|
const result = await copySqliteSafe(srcPath, destPath);
|
|
15174
15226
|
if (result.skipped) {} else if (result.success) {
|
|
@@ -15201,8 +15253,8 @@ async function runArchiveStage(ctx) {
|
|
|
15201
15253
|
}
|
|
15202
15254
|
const dynamicArchiveArtifacts = (await fs10.readdir(ctx.swarmDir).catch(() => [])).filter((name) => /^post-mortem-[^/\\]+\.md$/.test(name) || /^drift-report-phase-\d+\.json$/.test(name));
|
|
15203
15255
|
for (const artifact of dynamicArchiveArtifacts) {
|
|
15204
|
-
const srcPath =
|
|
15205
|
-
const destPath =
|
|
15256
|
+
const srcPath = path28.join(ctx.swarmDir, artifact);
|
|
15257
|
+
const destPath = path28.join(ctx.archiveDir, artifact);
|
|
15206
15258
|
try {
|
|
15207
15259
|
await fs10.copyFile(srcPath, destPath);
|
|
15208
15260
|
ctx.archivedFileCount++;
|
|
@@ -15217,8 +15269,8 @@ async function runArchiveStage(ctx) {
|
|
|
15217
15269
|
}
|
|
15218
15270
|
}
|
|
15219
15271
|
for (const dirName of ACTIVE_STATE_DIRS_TO_CLEAN) {
|
|
15220
|
-
const srcDir =
|
|
15221
|
-
const destDir =
|
|
15272
|
+
const srcDir = path28.join(ctx.swarmDir, dirName);
|
|
15273
|
+
const destDir = path28.join(ctx.archiveDir, dirName);
|
|
15222
15274
|
try {
|
|
15223
15275
|
const result = await copyDirRecursiveWithFailures(srcDir, destDir);
|
|
15224
15276
|
ctx.archivedFileCount += result.copied;
|
|
@@ -15295,7 +15347,7 @@ async function runCleanStage(ctx) {
|
|
|
15295
15347
|
ctx.warnings.push(reason ? `Preserved ${artifact} because it was not successfully archived: ${reason}.` : `Preserved ${artifact} because it was not successfully archived.`);
|
|
15296
15348
|
continue;
|
|
15297
15349
|
}
|
|
15298
|
-
const filePath =
|
|
15350
|
+
const filePath = path28.join(ctx.swarmDir, artifact);
|
|
15299
15351
|
try {
|
|
15300
15352
|
await fs10.unlink(filePath);
|
|
15301
15353
|
cleanedFiles.push(artifact);
|
|
@@ -15315,7 +15367,7 @@ async function runCleanStage(ctx) {
|
|
|
15315
15367
|
continue;
|
|
15316
15368
|
}
|
|
15317
15369
|
try {
|
|
15318
|
-
await fs10.unlink(
|
|
15370
|
+
await fs10.unlink(path28.join(ctx.swarmDir, artifact));
|
|
15319
15371
|
cleanedFiles.push(artifact);
|
|
15320
15372
|
} catch (err) {
|
|
15321
15373
|
const errno = err?.code;
|
|
@@ -15329,7 +15381,7 @@ async function runCleanStage(ctx) {
|
|
|
15329
15381
|
if (!ctx.archivedActiveStateDirs.has(dirName)) {
|
|
15330
15382
|
continue;
|
|
15331
15383
|
}
|
|
15332
|
-
const dirPath =
|
|
15384
|
+
const dirPath = path28.join(ctx.swarmDir, dirName);
|
|
15333
15385
|
try {
|
|
15334
15386
|
await fs10.rm(dirPath, { recursive: true, force: true });
|
|
15335
15387
|
cleanedFiles.push(`${dirName}/`);
|
|
@@ -15340,7 +15392,7 @@ async function runCleanStage(ctx) {
|
|
|
15340
15392
|
const configBackups = swarmFiles.filter((f) => f.startsWith("config-backup-") && f.endsWith(".json"));
|
|
15341
15393
|
for (const backup of configBackups) {
|
|
15342
15394
|
try {
|
|
15343
|
-
await fs10.unlink(
|
|
15395
|
+
await fs10.unlink(path28.join(ctx.swarmDir, backup));
|
|
15344
15396
|
configBackupsRemoved++;
|
|
15345
15397
|
} catch (err) {
|
|
15346
15398
|
const errno = err?.code;
|
|
@@ -15353,7 +15405,7 @@ async function runCleanStage(ctx) {
|
|
|
15353
15405
|
const ledgerSiblings = swarmFiles.filter((f) => (f.startsWith("plan-ledger.archived-") || f.startsWith("plan-ledger.backup-")) && f.endsWith(".jsonl"));
|
|
15354
15406
|
for (const sibling of ledgerSiblings) {
|
|
15355
15407
|
try {
|
|
15356
|
-
await fs10.unlink(
|
|
15408
|
+
await fs10.unlink(path28.join(ctx.swarmDir, sibling));
|
|
15357
15409
|
} catch (err) {
|
|
15358
15410
|
const errno = err?.code;
|
|
15359
15411
|
if (errno === "ENOENT") {} else {
|
|
@@ -15371,12 +15423,12 @@ async function runCleanStage(ctx) {
|
|
|
15371
15423
|
}
|
|
15372
15424
|
let swarmPlanFilesRemoved = 0;
|
|
15373
15425
|
const candidates = [
|
|
15374
|
-
|
|
15375
|
-
|
|
15376
|
-
|
|
15377
|
-
|
|
15378
|
-
|
|
15379
|
-
|
|
15426
|
+
path28.join(ctx.directory, ".swarm", "plan-export", "SWARM_PLAN.json"),
|
|
15427
|
+
path28.join(ctx.directory, ".swarm", "plan-export", "SWARM_PLAN.md"),
|
|
15428
|
+
path28.join(ctx.directory, ".swarm", "SWARM_PLAN.json"),
|
|
15429
|
+
path28.join(ctx.directory, ".swarm", "SWARM_PLAN.md"),
|
|
15430
|
+
path28.join(ctx.directory, "SWARM_PLAN.json"),
|
|
15431
|
+
path28.join(ctx.directory, "SWARM_PLAN.md")
|
|
15380
15432
|
];
|
|
15381
15433
|
for (const candidate of candidates) {
|
|
15382
15434
|
try {
|
|
@@ -15394,7 +15446,7 @@ async function runCleanStage(ctx) {
|
|
|
15394
15446
|
const tmpFiles = swarmFiles.filter((f) => f.startsWith(".tmp."));
|
|
15395
15447
|
for (const tmp of tmpFiles) {
|
|
15396
15448
|
try {
|
|
15397
|
-
await fs10.unlink(
|
|
15449
|
+
await fs10.unlink(path28.join(ctx.swarmDir, tmp));
|
|
15398
15450
|
tmpFilesRemoved++;
|
|
15399
15451
|
} catch (err) {
|
|
15400
15452
|
const errno = err?.code;
|
|
@@ -15416,7 +15468,7 @@ async function runCleanStage(ctx) {
|
|
|
15416
15468
|
}
|
|
15417
15469
|
for (const terminalFile of TERMINAL_STATE_FILES) {
|
|
15418
15470
|
try {
|
|
15419
|
-
await fs10.unlink(
|
|
15471
|
+
await fs10.unlink(path28.join(ctx.swarmDir, terminalFile));
|
|
15420
15472
|
if (!cleanedFiles.includes(terminalFile)) {
|
|
15421
15473
|
cleanedFiles.push(terminalFile);
|
|
15422
15474
|
}
|
|
@@ -15429,7 +15481,7 @@ async function runCleanStage(ctx) {
|
|
|
15429
15481
|
}
|
|
15430
15482
|
}
|
|
15431
15483
|
clearAllScopes(ctx.directory);
|
|
15432
|
-
const contextPath =
|
|
15484
|
+
const contextPath = path28.join(ctx.swarmDir, "context.md");
|
|
15433
15485
|
const contextContent = [
|
|
15434
15486
|
"# Context",
|
|
15435
15487
|
"",
|
|
@@ -15441,7 +15493,7 @@ async function runCleanStage(ctx) {
|
|
|
15441
15493
|
""
|
|
15442
15494
|
].join(`
|
|
15443
15495
|
`);
|
|
15444
|
-
const contextTempPath =
|
|
15496
|
+
const contextTempPath = path28.join(path28.dirname(contextPath), `${path28.basename(contextPath)}.tmp.${Date.now()}.${Math.floor(Math.random() * 1e9)}`);
|
|
15445
15497
|
try {
|
|
15446
15498
|
await fs10.writeFile(contextTempPath, contextContent, "utf-8");
|
|
15447
15499
|
fsSync.renameSync(contextTempPath, contextPath);
|
|
@@ -15505,7 +15557,7 @@ async function runAlignStage(ctx) {
|
|
|
15505
15557
|
return { gitAlignResult, prunedBranches };
|
|
15506
15558
|
}
|
|
15507
15559
|
async function handleCloseCommand(directory, args, options = {}) {
|
|
15508
|
-
const swarmDir =
|
|
15560
|
+
const swarmDir = path28.join(directory, ".swarm");
|
|
15509
15561
|
try {
|
|
15510
15562
|
const stat4 = fsSync.lstatSync(swarmDir);
|
|
15511
15563
|
if (stat4.isSymbolicLink()) {
|
|
@@ -15519,7 +15571,7 @@ async function handleCloseCommand(directory, args, options = {}) {
|
|
|
15519
15571
|
const planPath = validateSwarmPath(directory, "plan.json");
|
|
15520
15572
|
let planExists = false;
|
|
15521
15573
|
let planData = {
|
|
15522
|
-
title:
|
|
15574
|
+
title: path28.basename(directory) || "Ad-hoc session",
|
|
15523
15575
|
phases: []
|
|
15524
15576
|
};
|
|
15525
15577
|
try {
|
|
@@ -15544,7 +15596,7 @@ async function handleCloseCommand(directory, args, options = {}) {
|
|
|
15544
15596
|
}
|
|
15545
15597
|
try {
|
|
15546
15598
|
if (!planExists) {
|
|
15547
|
-
const archiveDir =
|
|
15599
|
+
const archiveDir = path28.join(swarmDir, "archive");
|
|
15548
15600
|
try {
|
|
15549
15601
|
const archiveEntries = await fs10.readdir(archiveDir);
|
|
15550
15602
|
const hasArchiveBundle = archiveEntries.some((entry) => entry.startsWith("swarm-"));
|
|
@@ -15552,7 +15604,7 @@ async function handleCloseCommand(directory, args, options = {}) {
|
|
|
15552
15604
|
const hasActiveState = [
|
|
15553
15605
|
...ACTIVE_STATE_TO_CLEAN,
|
|
15554
15606
|
...ACTIVE_STATE_DIRS_TO_CLEAN
|
|
15555
|
-
].some((entry) => fsSync.existsSync(
|
|
15607
|
+
].some((entry) => fsSync.existsSync(path28.join(swarmDir, entry)));
|
|
15556
15608
|
if (!hasActiveState) {
|
|
15557
15609
|
return `\u2705 Already finalized \u2014 nothing to do.
|
|
15558
15610
|
|
|
@@ -15680,7 +15732,7 @@ This project was already finalized in a previous /swarm close run. The plan has
|
|
|
15680
15732
|
...ctx.warnings.length > 0 ? ["## Warnings", ...ctx.warnings.map((w) => `- ${w}`), ""] : []
|
|
15681
15733
|
].join(`
|
|
15682
15734
|
`);
|
|
15683
|
-
const closeSummaryTempPath =
|
|
15735
|
+
const closeSummaryTempPath = path28.join(path28.dirname(closeSummaryPath), `${path28.basename(closeSummaryPath)}.tmp.${Date.now()}.${Math.floor(Math.random() * 1e9)}`);
|
|
15684
15736
|
try {
|
|
15685
15737
|
await fs10.writeFile(closeSummaryTempPath, summaryContent, "utf-8");
|
|
15686
15738
|
fsSync.renameSync(closeSummaryTempPath, closeSummaryPath);
|
|
@@ -16024,14 +16076,14 @@ function buildStatusMessage(session, plan) {
|
|
|
16024
16076
|
|
|
16025
16077
|
// src/commands/config.ts
|
|
16026
16078
|
import * as os6 from "os";
|
|
16027
|
-
import * as
|
|
16079
|
+
import * as path29 from "path";
|
|
16028
16080
|
function getUserConfigDir2() {
|
|
16029
|
-
return process.env.XDG_CONFIG_HOME ||
|
|
16081
|
+
return process.env.XDG_CONFIG_HOME || path29.join(os6.homedir(), ".config");
|
|
16030
16082
|
}
|
|
16031
16083
|
async function handleConfigCommand(directory, _args) {
|
|
16032
16084
|
const config = loadPluginConfig(directory);
|
|
16033
|
-
const userConfigPath =
|
|
16034
|
-
const projectConfigPath =
|
|
16085
|
+
const userConfigPath = path29.join(getUserConfigDir2(), "opencode", "opencode-swarm.json");
|
|
16086
|
+
const projectConfigPath = path29.join(directory, ".opencode", "opencode-swarm.json");
|
|
16035
16087
|
const lines = [
|
|
16036
16088
|
"## Swarm Configuration",
|
|
16037
16089
|
"",
|
|
@@ -16049,9 +16101,9 @@ async function handleConfigCommand(directory, _args) {
|
|
|
16049
16101
|
}
|
|
16050
16102
|
|
|
16051
16103
|
// src/services/skill-consolidation.ts
|
|
16052
|
-
import { existsSync as
|
|
16104
|
+
import { existsSync as existsSync19 } from "fs";
|
|
16053
16105
|
import { mkdir as mkdir9, readFile as readFile10, rename as rename7, writeFile as writeFile11 } from "fs/promises";
|
|
16054
|
-
import * as
|
|
16106
|
+
import * as path30 from "path";
|
|
16055
16107
|
|
|
16056
16108
|
// src/utils/timeout.ts
|
|
16057
16109
|
async function withTimeout(promise, ms, timeoutError) {
|
|
@@ -16076,11 +16128,11 @@ var DEFAULT_CONSOLIDATION_MAX_CALLS_PER_RUN = 1;
|
|
|
16076
16128
|
var CONSOLIDATION_RUN_TIMEOUT_MS = 5 * 60 * 1000;
|
|
16077
16129
|
var runningByDirectory = new Map;
|
|
16078
16130
|
function consolidationStatePath(directory) {
|
|
16079
|
-
return
|
|
16131
|
+
return path30.join(directory, ".swarm", "skill-improver", "consolidation-state.json");
|
|
16080
16132
|
}
|
|
16081
16133
|
async function readState2(directory) {
|
|
16082
16134
|
const filePath = consolidationStatePath(directory);
|
|
16083
|
-
if (!
|
|
16135
|
+
if (!existsSync19(filePath))
|
|
16084
16136
|
return {};
|
|
16085
16137
|
try {
|
|
16086
16138
|
const parsed = JSON.parse(await readFile10(filePath, "utf-8"));
|
|
@@ -16092,7 +16144,7 @@ async function readState2(directory) {
|
|
|
16092
16144
|
}
|
|
16093
16145
|
}
|
|
16094
16146
|
async function atomicWrite2(filePath, content) {
|
|
16095
|
-
await mkdir9(
|
|
16147
|
+
await mkdir9(path30.dirname(filePath), { recursive: true });
|
|
16096
16148
|
const tmp = `${filePath}.tmp-${process.pid}-${Date.now()}`;
|
|
16097
16149
|
await writeFile11(tmp, content, "utf-8");
|
|
16098
16150
|
await rename7(tmp, filePath);
|
|
@@ -16172,7 +16224,7 @@ async function runSkillConsolidationInner(req) {
|
|
|
16172
16224
|
};
|
|
16173
16225
|
}
|
|
16174
16226
|
async function runSkillConsolidation(req) {
|
|
16175
|
-
const key =
|
|
16227
|
+
const key = path30.resolve(req.directory);
|
|
16176
16228
|
const existing = runningByDirectory.get(key);
|
|
16177
16229
|
if (existing) {
|
|
16178
16230
|
return {
|
|
@@ -16374,7 +16426,7 @@ async function handleCouncilCommand(_directory, args) {
|
|
|
16374
16426
|
// src/commands/coupling.ts
|
|
16375
16427
|
import { randomBytes } from "crypto";
|
|
16376
16428
|
import * as fs11 from "fs";
|
|
16377
|
-
import * as
|
|
16429
|
+
import * as path32 from "path";
|
|
16378
16430
|
|
|
16379
16431
|
// src/turbo/epic/cochange-source.ts
|
|
16380
16432
|
import * as child_process3 from "child_process";
|
|
@@ -16384,7 +16436,7 @@ import { promisify as promisify2 } from "util";
|
|
|
16384
16436
|
import * as child_process2 from "child_process";
|
|
16385
16437
|
import { randomUUID as randomUUID6 } from "crypto";
|
|
16386
16438
|
import { readdir as readdir2, readFile as readFile11, stat as stat4 } from "fs/promises";
|
|
16387
|
-
import * as
|
|
16439
|
+
import * as path31 from "path";
|
|
16388
16440
|
import { promisify } from "util";
|
|
16389
16441
|
function getExecFileAsync() {
|
|
16390
16442
|
return promisify(child_process2.execFile);
|
|
@@ -16488,7 +16540,7 @@ async function scanSourceFiles(dir) {
|
|
|
16488
16540
|
try {
|
|
16489
16541
|
const entries = await readdir2(dir, { withFileTypes: true });
|
|
16490
16542
|
for (const entry of entries) {
|
|
16491
|
-
const fullPath =
|
|
16543
|
+
const fullPath = path31.join(dir, entry.name);
|
|
16492
16544
|
if (entry.isDirectory()) {
|
|
16493
16545
|
if (skipDirs.has(entry.name)) {
|
|
16494
16546
|
continue;
|
|
@@ -16496,7 +16548,7 @@ async function scanSourceFiles(dir) {
|
|
|
16496
16548
|
const subFiles = await scanSourceFiles(fullPath);
|
|
16497
16549
|
results.push(...subFiles);
|
|
16498
16550
|
} else if (entry.isFile()) {
|
|
16499
|
-
const ext =
|
|
16551
|
+
const ext = path31.extname(entry.name);
|
|
16500
16552
|
if ([".ts", ".tsx", ".js", ".jsx", ".mjs"].includes(ext)) {
|
|
16501
16553
|
results.push(fullPath);
|
|
16502
16554
|
}
|
|
@@ -16518,8 +16570,8 @@ async function getStaticEdges(directory) {
|
|
|
16518
16570
|
continue;
|
|
16519
16571
|
}
|
|
16520
16572
|
try {
|
|
16521
|
-
const sourceDir =
|
|
16522
|
-
const resolvedPath =
|
|
16573
|
+
const sourceDir = path31.dirname(sourceFile);
|
|
16574
|
+
const resolvedPath = path31.resolve(sourceDir, importPath);
|
|
16523
16575
|
const extensions = [
|
|
16524
16576
|
"",
|
|
16525
16577
|
".ts",
|
|
@@ -16544,8 +16596,8 @@ async function getStaticEdges(directory) {
|
|
|
16544
16596
|
if (!targetFile) {
|
|
16545
16597
|
continue;
|
|
16546
16598
|
}
|
|
16547
|
-
const relSource =
|
|
16548
|
-
const relTarget =
|
|
16599
|
+
const relSource = path31.relative(directory, sourceFile).replace(/\\/g, "/");
|
|
16600
|
+
const relTarget = path31.relative(directory, targetFile).replace(/\\/g, "/");
|
|
16549
16601
|
const [key] = relSource < relTarget ? [`${relSource}::${relTarget}`, relSource, relTarget] : [`${relTarget}::${relSource}`, relTarget, relSource];
|
|
16550
16602
|
edges.add(key);
|
|
16551
16603
|
} catch {}
|
|
@@ -16557,7 +16609,7 @@ async function getStaticEdges(directory) {
|
|
|
16557
16609
|
function isTestImplementationPair(fileA, fileB) {
|
|
16558
16610
|
const testPatterns = [".test.ts", ".test.js", ".spec.ts", ".spec.js"];
|
|
16559
16611
|
const getBaseName = (filePath) => {
|
|
16560
|
-
const base =
|
|
16612
|
+
const base = path31.basename(filePath);
|
|
16561
16613
|
for (const pattern of testPatterns) {
|
|
16562
16614
|
if (base.endsWith(pattern)) {
|
|
16563
16615
|
return base.slice(0, -pattern.length);
|
|
@@ -16567,16 +16619,16 @@ function isTestImplementationPair(fileA, fileB) {
|
|
|
16567
16619
|
};
|
|
16568
16620
|
const baseA = getBaseName(fileA);
|
|
16569
16621
|
const baseB = getBaseName(fileB);
|
|
16570
|
-
return baseA === baseB && baseA !==
|
|
16622
|
+
return baseA === baseB && baseA !== path31.basename(fileA) && baseA !== path31.basename(fileB);
|
|
16571
16623
|
}
|
|
16572
16624
|
function hasSharedPrefix(fileA, fileB) {
|
|
16573
|
-
const dirA =
|
|
16574
|
-
const dirB =
|
|
16625
|
+
const dirA = path31.dirname(fileA);
|
|
16626
|
+
const dirB = path31.dirname(fileB);
|
|
16575
16627
|
if (dirA !== dirB) {
|
|
16576
16628
|
return false;
|
|
16577
16629
|
}
|
|
16578
|
-
const baseA =
|
|
16579
|
-
const baseB =
|
|
16630
|
+
const baseA = path31.basename(fileA).replace(/\.(ts|js|tsx|jsx|mjs)$/, "");
|
|
16631
|
+
const baseB = path31.basename(fileB).replace(/\.(ts|js|tsx|jsx|mjs)$/, "");
|
|
16580
16632
|
if (baseA.startsWith(baseB) || baseB.startsWith(baseA)) {
|
|
16581
16633
|
return true;
|
|
16582
16634
|
}
|
|
@@ -16631,8 +16683,8 @@ function darkMatterToKnowledgeEntries(pairs, projectName) {
|
|
|
16631
16683
|
const entries = [];
|
|
16632
16684
|
const now = new Date().toISOString();
|
|
16633
16685
|
for (const pair of pairs.slice(0, 10)) {
|
|
16634
|
-
const baseA =
|
|
16635
|
-
const baseB =
|
|
16686
|
+
const baseA = path31.basename(pair.fileA);
|
|
16687
|
+
const baseB = path31.basename(pair.fileB);
|
|
16636
16688
|
let lesson = `Files ${pair.fileA} and ${pair.fileB} co-change with NPMI=${pair.npmi.toFixed(3)} but have no import relationship. This hidden coupling suggests a shared architectural concern \u2014 changes to one likely require changes to the other.`;
|
|
16637
16689
|
if (lesson.length > 280) {
|
|
16638
16690
|
lesson = `Files ${baseA} and ${baseB} co-change with NPMI=${pair.npmi.toFixed(3)} but have no import relationship. This hidden coupling suggests a shared architectural concern \u2014 changes to one likely require changes to the other.`;
|
|
@@ -17058,9 +17110,9 @@ function parseArgs3(args) {
|
|
|
17058
17110
|
return parsed;
|
|
17059
17111
|
}
|
|
17060
17112
|
function persistReportJson(directory, report) {
|
|
17061
|
-
const epicDir =
|
|
17113
|
+
const epicDir = path32.join(directory, ".swarm", "epic");
|
|
17062
17114
|
fs11.mkdirSync(epicDir, { recursive: true });
|
|
17063
|
-
const filePath =
|
|
17115
|
+
const filePath = path32.join(epicDir, "coupling-report.json");
|
|
17064
17116
|
const tmpPath = `${filePath}.tmp.${randomBytes(8).toString("hex")}`;
|
|
17065
17117
|
fs11.writeFileSync(tmpPath, `${JSON.stringify(report, null, 2)}
|
|
17066
17118
|
`, "utf-8");
|
|
@@ -17119,7 +17171,7 @@ Usage: /swarm coupling [--phase <n>] [--threshold <-1..1>] [--min-co-changes <n>
|
|
|
17119
17171
|
persistStatus = {
|
|
17120
17172
|
requested: true,
|
|
17121
17173
|
written: true,
|
|
17122
|
-
path:
|
|
17174
|
+
path: path32.relative(directory, writtenAt).replace(/\\/g, "/")
|
|
17123
17175
|
};
|
|
17124
17176
|
} catch (err) {
|
|
17125
17177
|
persistStatus = {
|
|
@@ -17158,8 +17210,8 @@ var _internals22 = {
|
|
|
17158
17210
|
loadCuratorDeps: async () => {
|
|
17159
17211
|
const [{ CuratorConfigSchema }, curator, { createCuratorLLMDelegate: createCuratorLLMDelegate2 }] = await Promise.all([
|
|
17160
17212
|
import("./schema-vw2ffhe9.js"),
|
|
17161
|
-
import("./curator-
|
|
17162
|
-
import("./curator-llm-factory-
|
|
17213
|
+
import("./curator-1nr4qszq.js"),
|
|
17214
|
+
import("./curator-llm-factory-x9tk7e6m.js")
|
|
17163
17215
|
]);
|
|
17164
17216
|
return { CuratorConfigSchema, curator, createCuratorLLMDelegate: createCuratorLLMDelegate2 };
|
|
17165
17217
|
}
|
|
@@ -17251,7 +17303,7 @@ function formatCurationSummary(summary) {
|
|
|
17251
17303
|
}
|
|
17252
17304
|
|
|
17253
17305
|
// src/commands/dark-matter.ts
|
|
17254
|
-
import
|
|
17306
|
+
import path33 from "path";
|
|
17255
17307
|
async function handleDarkMatterCommand(directory, args) {
|
|
17256
17308
|
const options = {};
|
|
17257
17309
|
for (let i = 0;i < args.length; i++) {
|
|
@@ -17283,7 +17335,7 @@ Ensure this is a git repository with commit history.`;
|
|
|
17283
17335
|
const output = formatDarkMatterOutput(pairs);
|
|
17284
17336
|
if (pairs.length > 0) {
|
|
17285
17337
|
try {
|
|
17286
|
-
const projectName =
|
|
17338
|
+
const projectName = path33.basename(path33.resolve(directory));
|
|
17287
17339
|
const entries = darkMatterToKnowledgeEntries(pairs, projectName);
|
|
17288
17340
|
if (entries.length > 0) {
|
|
17289
17341
|
const knowledgePath = resolveSwarmKnowledgePath(directory);
|
|
@@ -17649,13 +17701,13 @@ ${USAGE5}`;
|
|
|
17649
17701
|
|
|
17650
17702
|
// src/services/diagnose-service.ts
|
|
17651
17703
|
import * as child_process4 from "child_process";
|
|
17652
|
-
import { existsSync as
|
|
17653
|
-
import
|
|
17704
|
+
import { existsSync as existsSync22, readdirSync as readdirSync4, readFileSync as readFileSync11, statSync as statSync7 } from "fs";
|
|
17705
|
+
import * as path38 from "path";
|
|
17654
17706
|
import { fileURLToPath } from "url";
|
|
17655
17707
|
// package.json
|
|
17656
17708
|
var package_default = {
|
|
17657
17709
|
name: "opencode-swarm",
|
|
17658
|
-
version: "7.107.
|
|
17710
|
+
version: "7.107.3",
|
|
17659
17711
|
description: "Architect-centric agentic swarm plugin for OpenCode - hub-and-spoke orchestration with SME consultation, code generation, and QA review",
|
|
17660
17712
|
main: "dist/index.js",
|
|
17661
17713
|
types: "dist/index.d.ts",
|
|
@@ -17763,44 +17815,44 @@ var package_default = {
|
|
|
17763
17815
|
|
|
17764
17816
|
// src/config/cache-paths.ts
|
|
17765
17817
|
import * as os7 from "os";
|
|
17766
|
-
import * as
|
|
17818
|
+
import * as path34 from "path";
|
|
17767
17819
|
function getPluginConfigDir() {
|
|
17768
|
-
return
|
|
17820
|
+
return path34.join(process.env.XDG_CONFIG_HOME || path34.join(os7.homedir(), ".config"), "opencode");
|
|
17769
17821
|
}
|
|
17770
17822
|
function getPluginCachePaths() {
|
|
17771
|
-
const cacheBase = process.env.XDG_CACHE_HOME ||
|
|
17823
|
+
const cacheBase = process.env.XDG_CACHE_HOME || path34.join(os7.homedir(), ".cache");
|
|
17772
17824
|
const configDir = getPluginConfigDir();
|
|
17773
17825
|
const paths = [
|
|
17774
|
-
|
|
17775
|
-
|
|
17776
|
-
|
|
17826
|
+
path34.join(cacheBase, "opencode", "node_modules", "opencode-swarm"),
|
|
17827
|
+
path34.join(cacheBase, "opencode", "packages", "opencode-swarm@latest"),
|
|
17828
|
+
path34.join(configDir, "node_modules", "opencode-swarm")
|
|
17777
17829
|
];
|
|
17778
17830
|
if (process.platform === "darwin") {
|
|
17779
|
-
const libCaches =
|
|
17780
|
-
paths.push(
|
|
17831
|
+
const libCaches = path34.join(os7.homedir(), "Library", "Caches");
|
|
17832
|
+
paths.push(path34.join(libCaches, "opencode", "node_modules", "opencode-swarm"), path34.join(libCaches, "opencode", "packages", "opencode-swarm@latest"));
|
|
17781
17833
|
}
|
|
17782
17834
|
if (process.platform === "win32") {
|
|
17783
|
-
const localAppData = process.env.LOCALAPPDATA ||
|
|
17784
|
-
const appData = process.env.APPDATA ||
|
|
17785
|
-
paths.push(
|
|
17835
|
+
const localAppData = process.env.LOCALAPPDATA || path34.join(os7.homedir(), "AppData", "Local");
|
|
17836
|
+
const appData = process.env.APPDATA || path34.join(os7.homedir(), "AppData", "Roaming");
|
|
17837
|
+
paths.push(path34.join(localAppData, "opencode", "node_modules", "opencode-swarm"), path34.join(localAppData, "opencode", "packages", "opencode-swarm@latest"), path34.join(appData, "opencode", "node_modules", "opencode-swarm"));
|
|
17786
17838
|
}
|
|
17787
17839
|
return paths;
|
|
17788
17840
|
}
|
|
17789
17841
|
function getPluginLockFilePaths() {
|
|
17790
|
-
const cacheBase = process.env.XDG_CACHE_HOME ||
|
|
17842
|
+
const cacheBase = process.env.XDG_CACHE_HOME || path34.join(os7.homedir(), ".cache");
|
|
17791
17843
|
const configDir = getPluginConfigDir();
|
|
17792
17844
|
const paths = [
|
|
17793
|
-
|
|
17794
|
-
|
|
17795
|
-
|
|
17845
|
+
path34.join(cacheBase, "opencode", "bun.lock"),
|
|
17846
|
+
path34.join(cacheBase, "opencode", "bun.lockb"),
|
|
17847
|
+
path34.join(configDir, "package-lock.json")
|
|
17796
17848
|
];
|
|
17797
17849
|
if (process.platform === "darwin") {
|
|
17798
|
-
const libCaches =
|
|
17799
|
-
paths.push(
|
|
17850
|
+
const libCaches = path34.join(os7.homedir(), "Library", "Caches");
|
|
17851
|
+
paths.push(path34.join(libCaches, "opencode", "bun.lock"), path34.join(libCaches, "opencode", "bun.lockb"));
|
|
17800
17852
|
}
|
|
17801
17853
|
if (process.platform === "win32") {
|
|
17802
|
-
const localAppData = process.env.LOCALAPPDATA ||
|
|
17803
|
-
paths.push(
|
|
17854
|
+
const localAppData = process.env.LOCALAPPDATA || path34.join(os7.homedir(), "AppData", "Local");
|
|
17855
|
+
paths.push(path34.join(localAppData, "opencode", "bun.lock"), path34.join(localAppData, "opencode", "bun.lockb"));
|
|
17804
17856
|
}
|
|
17805
17857
|
return paths;
|
|
17806
17858
|
}
|
|
@@ -17810,11 +17862,11 @@ init_capability_probe();
|
|
|
17810
17862
|
init_executor();
|
|
17811
17863
|
|
|
17812
17864
|
// src/services/knowledge-diagnostics.ts
|
|
17813
|
-
import { existsSync as
|
|
17865
|
+
import { existsSync as existsSync21 } from "fs";
|
|
17814
17866
|
import { readFile as readFile12 } from "fs/promises";
|
|
17815
17867
|
|
|
17816
17868
|
// src/services/version-check.ts
|
|
17817
|
-
import { existsSync as
|
|
17869
|
+
import { existsSync as existsSync20, mkdirSync as mkdirSync13, readFileSync as readFileSync10, writeFileSync as writeFileSync8 } from "fs";
|
|
17818
17870
|
import { homedir as homedir6 } from "os";
|
|
17819
17871
|
import { join as join32 } from "path";
|
|
17820
17872
|
var CHECK_INTERVAL_MS = 24 * 60 * 60 * 1000;
|
|
@@ -17830,10 +17882,10 @@ function cacheFile() {
|
|
|
17830
17882
|
}
|
|
17831
17883
|
function readVersionCache() {
|
|
17832
17884
|
try {
|
|
17833
|
-
const
|
|
17834
|
-
if (!
|
|
17885
|
+
const path38 = cacheFile();
|
|
17886
|
+
if (!existsSync20(path38))
|
|
17835
17887
|
return null;
|
|
17836
|
-
const raw = readFileSync10(
|
|
17888
|
+
const raw = readFileSync10(path38, "utf-8");
|
|
17837
17889
|
const parsed = JSON.parse(raw);
|
|
17838
17890
|
if (typeof parsed?.checkedAt !== "number")
|
|
17839
17891
|
return null;
|
|
@@ -17885,7 +17937,7 @@ var SEVEN_DAYS_MS2 = 7 * 24 * 60 * 60 * 1000;
|
|
|
17885
17937
|
var UNACTIONABLE_BACKLOG_WARN = 100;
|
|
17886
17938
|
var INSIGHT_BACKLOG_WARN = 50;
|
|
17887
17939
|
async function readRawLines(filePath) {
|
|
17888
|
-
if (!
|
|
17940
|
+
if (!existsSync21(filePath))
|
|
17889
17941
|
return { entries: [], corrupt: 0 };
|
|
17890
17942
|
const content = await readFile12(filePath, "utf-8");
|
|
17891
17943
|
const entries = [];
|
|
@@ -18010,7 +18062,7 @@ async function computeKnowledgeDebug(directory) {
|
|
|
18010
18062
|
};
|
|
18011
18063
|
}
|
|
18012
18064
|
async function safeJsonlCount(filePath) {
|
|
18013
|
-
if (!filePath || !
|
|
18065
|
+
if (!filePath || !existsSync21(filePath))
|
|
18014
18066
|
return 0;
|
|
18015
18067
|
try {
|
|
18016
18068
|
const content = await readFile12(filePath, "utf-8");
|
|
@@ -18088,8 +18140,8 @@ var REQUIRED_CACHE_GRAMMAR_ASSETS = [
|
|
|
18088
18140
|
"tree-sitter-typescript.wasm"
|
|
18089
18141
|
];
|
|
18090
18142
|
function resolveCachePackageRoot(cachePath) {
|
|
18091
|
-
const nestedPackageRoot =
|
|
18092
|
-
return
|
|
18143
|
+
const nestedPackageRoot = path38.join(cachePath, "node_modules", "opencode-swarm");
|
|
18144
|
+
return existsSync22(nestedPackageRoot) ? nestedPackageRoot : cachePath;
|
|
18093
18145
|
}
|
|
18094
18146
|
var _internals26 = {
|
|
18095
18147
|
detectSandboxCapability: () => sandboxCapabilityProbe.detect(),
|
|
@@ -18340,7 +18392,7 @@ async function checkConfigBackups(directory) {
|
|
|
18340
18392
|
}
|
|
18341
18393
|
async function checkGitRepository(directory) {
|
|
18342
18394
|
try {
|
|
18343
|
-
if (!
|
|
18395
|
+
if (!existsSync22(directory) || !statSync7(directory).isDirectory()) {
|
|
18344
18396
|
return {
|
|
18345
18397
|
name: "Git Repository",
|
|
18346
18398
|
status: "\u274C",
|
|
@@ -18404,8 +18456,8 @@ async function checkSpecStaleness(directory, plan) {
|
|
|
18404
18456
|
};
|
|
18405
18457
|
}
|
|
18406
18458
|
async function checkConfigParseability(directory) {
|
|
18407
|
-
const configPath =
|
|
18408
|
-
if (!
|
|
18459
|
+
const configPath = path38.join(directory, ".opencode/opencode-swarm.json");
|
|
18460
|
+
if (!existsSync22(configPath)) {
|
|
18409
18461
|
return {
|
|
18410
18462
|
name: "Config Parseability",
|
|
18411
18463
|
status: "\u2705",
|
|
@@ -18433,7 +18485,7 @@ function resolveGrammarDir(thisDir) {
|
|
|
18433
18485
|
const normalized = thisDir.replace(/\\/g, "/");
|
|
18434
18486
|
const isSource = normalized.endsWith("/src/services");
|
|
18435
18487
|
const isCliBundle = normalized.endsWith("/cli");
|
|
18436
|
-
return isSource || isCliBundle ?
|
|
18488
|
+
return isSource || isCliBundle ? path38.join(thisDir, "..", "lang", "grammars") : path38.join(thisDir, "lang", "grammars");
|
|
18437
18489
|
}
|
|
18438
18490
|
async function checkGrammarWasmFiles() {
|
|
18439
18491
|
const grammarFiles = [
|
|
@@ -18457,14 +18509,14 @@ async function checkGrammarWasmFiles() {
|
|
|
18457
18509
|
"tree-sitter-ini.wasm",
|
|
18458
18510
|
"tree-sitter-regex.wasm"
|
|
18459
18511
|
];
|
|
18460
|
-
const thisDir =
|
|
18512
|
+
const thisDir = path38.dirname(fileURLToPath(import.meta.url));
|
|
18461
18513
|
const grammarDir = resolveGrammarDir(thisDir);
|
|
18462
18514
|
const missing = [];
|
|
18463
|
-
if (!
|
|
18515
|
+
if (!existsSync22(path38.join(grammarDir, "tree-sitter.wasm"))) {
|
|
18464
18516
|
missing.push("tree-sitter.wasm (core runtime)");
|
|
18465
18517
|
}
|
|
18466
18518
|
for (const file of grammarFiles) {
|
|
18467
|
-
if (!
|
|
18519
|
+
if (!existsSync22(path38.join(grammarDir, file))) {
|
|
18468
18520
|
missing.push(file);
|
|
18469
18521
|
}
|
|
18470
18522
|
}
|
|
@@ -18482,8 +18534,8 @@ async function checkGrammarWasmFiles() {
|
|
|
18482
18534
|
};
|
|
18483
18535
|
}
|
|
18484
18536
|
async function checkCheckpointManifest(directory) {
|
|
18485
|
-
const manifestPath =
|
|
18486
|
-
if (!
|
|
18537
|
+
const manifestPath = path38.join(directory, ".swarm/checkpoints.json");
|
|
18538
|
+
if (!existsSync22(manifestPath)) {
|
|
18487
18539
|
return {
|
|
18488
18540
|
name: "Checkpoint Manifest",
|
|
18489
18541
|
status: "\u2705",
|
|
@@ -18534,8 +18586,8 @@ async function checkCheckpointManifest(directory) {
|
|
|
18534
18586
|
}
|
|
18535
18587
|
}
|
|
18536
18588
|
async function checkEventStreamIntegrity(directory) {
|
|
18537
|
-
const eventsPath =
|
|
18538
|
-
if (!
|
|
18589
|
+
const eventsPath = path38.join(directory, ".swarm/events.jsonl");
|
|
18590
|
+
if (!existsSync22(eventsPath)) {
|
|
18539
18591
|
return {
|
|
18540
18592
|
name: "Event Stream",
|
|
18541
18593
|
status: "\u2705",
|
|
@@ -18575,8 +18627,8 @@ async function checkEventStreamIntegrity(directory) {
|
|
|
18575
18627
|
}
|
|
18576
18628
|
}
|
|
18577
18629
|
async function checkSteeringDirectives(directory) {
|
|
18578
|
-
const eventsPath =
|
|
18579
|
-
if (!
|
|
18630
|
+
const eventsPath = path38.join(directory, ".swarm/events.jsonl");
|
|
18631
|
+
if (!existsSync22(eventsPath)) {
|
|
18580
18632
|
return {
|
|
18581
18633
|
name: "Steering Directives",
|
|
18582
18634
|
status: "\u2705",
|
|
@@ -18631,8 +18683,8 @@ async function checkCurator(directory) {
|
|
|
18631
18683
|
detail: "Disabled (enable via curator.enabled)"
|
|
18632
18684
|
};
|
|
18633
18685
|
}
|
|
18634
|
-
const summaryPath =
|
|
18635
|
-
if (!
|
|
18686
|
+
const summaryPath = path38.join(directory, ".swarm/curator-summary.json");
|
|
18687
|
+
if (!existsSync22(summaryPath)) {
|
|
18636
18688
|
return {
|
|
18637
18689
|
name: "Curator",
|
|
18638
18690
|
status: "\u2705",
|
|
@@ -18833,8 +18885,8 @@ async function getDiagnoseData(directory) {
|
|
|
18833
18885
|
checks.push(await checkCurator(directory));
|
|
18834
18886
|
checks.push(await checkKnowledgeHealth(directory));
|
|
18835
18887
|
try {
|
|
18836
|
-
const evidenceDir =
|
|
18837
|
-
const snapshotFiles =
|
|
18888
|
+
const evidenceDir = path38.join(directory, ".swarm", "evidence");
|
|
18889
|
+
const snapshotFiles = existsSync22(evidenceDir) ? readdirSync4(evidenceDir).filter((f) => f.startsWith("agent-tools-") && f.endsWith(".json")) : [];
|
|
18838
18890
|
if (snapshotFiles.length > 0) {
|
|
18839
18891
|
const latest = snapshotFiles.sort().pop();
|
|
18840
18892
|
checks.push({
|
|
@@ -18867,14 +18919,14 @@ async function getDiagnoseData(directory) {
|
|
|
18867
18919
|
const cacheRows = [];
|
|
18868
18920
|
for (const cachePath of cachePaths) {
|
|
18869
18921
|
try {
|
|
18870
|
-
if (!
|
|
18922
|
+
if (!existsSync22(cachePath)) {
|
|
18871
18923
|
cacheRows.push(`\u2B1C ${cachePath} \u2014 absent`);
|
|
18872
18924
|
continue;
|
|
18873
18925
|
}
|
|
18874
18926
|
const packageRoot = resolveCachePackageRoot(cachePath);
|
|
18875
18927
|
const cacheLabel = packageRoot === cachePath ? cachePath : `${cachePath} -> ${packageRoot}`;
|
|
18876
|
-
const missingGrammarAssets = REQUIRED_CACHE_GRAMMAR_ASSETS.filter((file) => !
|
|
18877
|
-
const pkgJsonPath =
|
|
18928
|
+
const missingGrammarAssets = REQUIRED_CACHE_GRAMMAR_ASSETS.filter((file) => !existsSync22(path38.join(packageRoot, "dist", "lang", "grammars", file)));
|
|
18929
|
+
const pkgJsonPath = path38.join(packageRoot, "package.json");
|
|
18878
18930
|
try {
|
|
18879
18931
|
const raw = readFileSync11(pkgJsonPath, "utf-8");
|
|
18880
18932
|
const parsed = JSON.parse(raw);
|
|
@@ -19250,9 +19302,9 @@ function decideEpicActivation(tasks, cochangePairs, commitsObserved, options) {
|
|
|
19250
19302
|
// src/turbo/epic/calibration.ts
|
|
19251
19303
|
init_logger();
|
|
19252
19304
|
import * as fs13 from "fs";
|
|
19253
|
-
import * as
|
|
19305
|
+
import * as path39 from "path";
|
|
19254
19306
|
var STATE_FILE = "calibration.json";
|
|
19255
|
-
var STATE_REL_DIR =
|
|
19307
|
+
var STATE_REL_DIR = path39.join(".swarm", "epic");
|
|
19256
19308
|
function nowISO() {
|
|
19257
19309
|
return new Date().toISOString();
|
|
19258
19310
|
}
|
|
@@ -19274,7 +19326,7 @@ function markUnreadable(directory, reason) {
|
|
|
19274
19326
|
error(`[epic/calibration] state file unreadable for ${directory}: ${reason} \u2014 failing closed`);
|
|
19275
19327
|
}
|
|
19276
19328
|
function repairCalibrationUnreadable(directory) {
|
|
19277
|
-
const filePath =
|
|
19329
|
+
const filePath = path39.join(directory, STATE_REL_DIR, STATE_FILE);
|
|
19278
19330
|
if (!fs13.existsSync(filePath)) {
|
|
19279
19331
|
stateUnreadableMap.delete(directory);
|
|
19280
19332
|
return;
|
|
@@ -19306,7 +19358,7 @@ function isValidCalibrationShape(candidate) {
|
|
|
19306
19358
|
return true;
|
|
19307
19359
|
}
|
|
19308
19360
|
function ensureSwarmEpicDir(directory) {
|
|
19309
|
-
const dir =
|
|
19361
|
+
const dir = path39.resolve(directory, STATE_REL_DIR);
|
|
19310
19362
|
if (!fs13.existsSync(dir)) {
|
|
19311
19363
|
fs13.mkdirSync(dir, { recursive: true });
|
|
19312
19364
|
}
|
|
@@ -19318,7 +19370,7 @@ function loadCalibrationState(directory) {
|
|
|
19318
19370
|
if (stateUnreadableMap.get(directory))
|
|
19319
19371
|
return null;
|
|
19320
19372
|
}
|
|
19321
|
-
const filePath =
|
|
19373
|
+
const filePath = path39.join(directory, STATE_REL_DIR, STATE_FILE);
|
|
19322
19374
|
try {
|
|
19323
19375
|
if (!fs13.existsSync(filePath)) {
|
|
19324
19376
|
const seed = emptyCalibrationState();
|
|
@@ -19345,12 +19397,12 @@ function loadCalibrationState(directory) {
|
|
|
19345
19397
|
// src/turbo/epic/divergence-recorder.ts
|
|
19346
19398
|
init_logger();
|
|
19347
19399
|
import * as fs14 from "fs";
|
|
19348
|
-
import * as
|
|
19349
|
-
var EVIDENCE_REL_DIR =
|
|
19400
|
+
import * as path40 from "path";
|
|
19401
|
+
var EVIDENCE_REL_DIR = path40.join(".swarm", "epic");
|
|
19350
19402
|
var EVIDENCE_FILE = "divergence.jsonl";
|
|
19351
19403
|
var MAX_TAIL_BYTES2 = 16 * 1024 * 1024;
|
|
19352
19404
|
function readDivergenceHistory(directory, options) {
|
|
19353
|
-
const filePath =
|
|
19405
|
+
const filePath = path40.join(directory, EVIDENCE_REL_DIR, EVIDENCE_FILE);
|
|
19354
19406
|
if (!fs14.existsSync(filePath)) {
|
|
19355
19407
|
return [];
|
|
19356
19408
|
}
|
|
@@ -19399,11 +19451,11 @@ function readDivergenceHistory(directory, options) {
|
|
|
19399
19451
|
|
|
19400
19452
|
// src/turbo/epic/promotion-evidence.ts
|
|
19401
19453
|
import * as fs15 from "fs";
|
|
19402
|
-
import * as
|
|
19403
|
-
var EVIDENCE_REL_DIR2 =
|
|
19454
|
+
import * as path41 from "path";
|
|
19455
|
+
var EVIDENCE_REL_DIR2 = path41.join(".swarm", "evidence");
|
|
19404
19456
|
var EVIDENCE_FILE2 = "epic-promotions.jsonl";
|
|
19405
19457
|
function readPromotionEvidence(directory) {
|
|
19406
|
-
const filePath =
|
|
19458
|
+
const filePath = path41.join(directory, EVIDENCE_REL_DIR2, EVIDENCE_FILE2);
|
|
19407
19459
|
if (!fs15.existsSync(filePath)) {
|
|
19408
19460
|
return [];
|
|
19409
19461
|
}
|
|
@@ -19912,7 +19964,7 @@ async function handleEvidenceCommand(directory, args) {
|
|
|
19912
19964
|
return formatTaskEvidenceMarkdown(evidenceData);
|
|
19913
19965
|
}
|
|
19914
19966
|
async function handleEvidenceSummaryCommand(directory) {
|
|
19915
|
-
const { buildEvidenceSummary } = await import("./evidence-summary-service-
|
|
19967
|
+
const { buildEvidenceSummary } = await import("./evidence-summary-service-9r28ds8t.js");
|
|
19916
19968
|
const artifact = await buildEvidenceSummary(directory);
|
|
19917
19969
|
if (!artifact) {
|
|
19918
19970
|
return "No plan found. Run `/swarm plan` to check plan status.";
|
|
@@ -19977,7 +20029,7 @@ async function handleExportCommand(directory, _args) {
|
|
|
19977
20029
|
// src/full-auto/state.ts
|
|
19978
20030
|
var import_proper_lockfile4 = __toESM(require_proper_lockfile(), 1);
|
|
19979
20031
|
import * as fs16 from "fs";
|
|
19980
|
-
import * as
|
|
20032
|
+
import * as path42 from "path";
|
|
19981
20033
|
init_logger();
|
|
19982
20034
|
var lockfile4 = import_proper_lockfile4.default;
|
|
19983
20035
|
var STATE_FILE2 = "full-auto-state.json";
|
|
@@ -19985,7 +20037,7 @@ function nowISO2() {
|
|
|
19985
20037
|
return new Date().toISOString();
|
|
19986
20038
|
}
|
|
19987
20039
|
function ensureSwarmDir(directory) {
|
|
19988
|
-
const swarmDir =
|
|
20040
|
+
const swarmDir = path42.resolve(directory, ".swarm");
|
|
19989
20041
|
if (!fs16.existsSync(swarmDir)) {
|
|
19990
20042
|
fs16.mkdirSync(swarmDir, { recursive: true });
|
|
19991
20043
|
}
|
|
@@ -20797,7 +20849,7 @@ var _internals29 = {
|
|
|
20797
20849
|
|
|
20798
20850
|
// src/session/snapshot-writer.ts
|
|
20799
20851
|
import { closeSync as closeSync6, fsyncSync as fsyncSync2, mkdirSync as mkdirSync18, openSync as openSync6, renameSync as renameSync9 } from "fs";
|
|
20800
|
-
import * as
|
|
20852
|
+
import * as path43 from "path";
|
|
20801
20853
|
var _writeInFlight = Promise.resolve();
|
|
20802
20854
|
function serializeAgentSession(s) {
|
|
20803
20855
|
const gateLog = {};
|
|
@@ -20910,7 +20962,7 @@ async function writeSnapshot(directory, state) {
|
|
|
20910
20962
|
}
|
|
20911
20963
|
const content = JSON.stringify(snapshot, null, 2);
|
|
20912
20964
|
const resolvedPath = validateSwarmPath(directory, "session/state.json");
|
|
20913
|
-
const dir =
|
|
20965
|
+
const dir = path43.dirname(resolvedPath);
|
|
20914
20966
|
mkdirSync18(dir, { recursive: true });
|
|
20915
20967
|
const tempPath = `${resolvedPath}.tmp.${Date.now()}.${Math.random().toString(36).slice(2)}`;
|
|
20916
20968
|
await bunWrite(tempPath, content);
|
|
@@ -21421,23 +21473,23 @@ ${USAGE6}`;
|
|
|
21421
21473
|
}
|
|
21422
21474
|
|
|
21423
21475
|
// src/commands/knowledge.ts
|
|
21424
|
-
import { join as
|
|
21476
|
+
import { join as join38 } from "path";
|
|
21425
21477
|
|
|
21426
21478
|
// src/hooks/knowledge-migrator.ts
|
|
21427
21479
|
init_logger();
|
|
21428
21480
|
import { randomUUID as randomUUID8 } from "crypto";
|
|
21429
|
-
import { existsSync as
|
|
21481
|
+
import { existsSync as existsSync27, readFileSync as readFileSync16 } from "fs";
|
|
21430
21482
|
import { mkdir as mkdir10, readFile as readFile13, writeFile as writeFile12 } from "fs/promises";
|
|
21431
21483
|
import * as os11 from "os";
|
|
21432
|
-
import * as
|
|
21484
|
+
import * as path44 from "path";
|
|
21433
21485
|
|
|
21434
21486
|
// src/hooks/knowledge-types.ts
|
|
21435
21487
|
var KNOWLEDGE_SCHEMA_VERSION = 2;
|
|
21436
21488
|
|
|
21437
21489
|
// src/hooks/knowledge-migrator.ts
|
|
21438
21490
|
async function migrateKnowledgeToExternal(_directory, _config) {
|
|
21439
|
-
const externalSentinelPath =
|
|
21440
|
-
const contextPath =
|
|
21491
|
+
const externalSentinelPath = path44.join(_directory, ".swarm", ".knowledge-external-migrated");
|
|
21492
|
+
const contextPath = path44.join(_directory, ".swarm", "context.md");
|
|
21441
21493
|
if (_internals32.existsSync(externalSentinelPath)) {
|
|
21442
21494
|
return {
|
|
21443
21495
|
migrated: false,
|
|
@@ -21495,17 +21547,17 @@ var _internals32 = {
|
|
|
21495
21547
|
inferProjectName,
|
|
21496
21548
|
writeSentinel,
|
|
21497
21549
|
resolveLegacyHiveKnowledgePath,
|
|
21498
|
-
existsSync:
|
|
21550
|
+
existsSync: existsSync27,
|
|
21499
21551
|
readFileSync: readFileSync16,
|
|
21500
21552
|
readFile: readFile13,
|
|
21501
21553
|
mkdir: mkdir10,
|
|
21502
21554
|
writeFile: writeFile12
|
|
21503
21555
|
};
|
|
21504
21556
|
async function migrateContextToKnowledge(directory, config) {
|
|
21505
|
-
const sentinelPath =
|
|
21506
|
-
const contextPath =
|
|
21557
|
+
const sentinelPath = path44.join(directory, ".swarm", ".knowledge-migrated");
|
|
21558
|
+
const contextPath = path44.join(directory, ".swarm", "context.md");
|
|
21507
21559
|
const knowledgePath = resolveSwarmKnowledgePath(directory);
|
|
21508
|
-
if (
|
|
21560
|
+
if (existsSync27(sentinelPath)) {
|
|
21509
21561
|
return {
|
|
21510
21562
|
migrated: false,
|
|
21511
21563
|
entriesMigrated: 0,
|
|
@@ -21514,7 +21566,7 @@ async function migrateContextToKnowledge(directory, config) {
|
|
|
21514
21566
|
skippedReason: "sentinel-exists"
|
|
21515
21567
|
};
|
|
21516
21568
|
}
|
|
21517
|
-
if (!
|
|
21569
|
+
if (!existsSync27(contextPath)) {
|
|
21518
21570
|
return {
|
|
21519
21571
|
migrated: false,
|
|
21520
21572
|
entriesMigrated: 0,
|
|
@@ -21605,8 +21657,8 @@ async function migrateContextToKnowledge(directory, config) {
|
|
|
21605
21657
|
async function migrateHiveKnowledgeLegacy(config) {
|
|
21606
21658
|
const legacyHivePath = _internals32.resolveLegacyHiveKnowledgePath();
|
|
21607
21659
|
const canonicalHivePath = resolveHiveKnowledgePath();
|
|
21608
|
-
const sentinelPath =
|
|
21609
|
-
if (
|
|
21660
|
+
const sentinelPath = path44.join(path44.dirname(canonicalHivePath), ".hive-knowledge-migrated");
|
|
21661
|
+
if (existsSync27(sentinelPath)) {
|
|
21610
21662
|
return {
|
|
21611
21663
|
migrated: false,
|
|
21612
21664
|
entriesMigrated: 0,
|
|
@@ -21615,7 +21667,7 @@ async function migrateHiveKnowledgeLegacy(config) {
|
|
|
21615
21667
|
skippedReason: "sentinel-exists"
|
|
21616
21668
|
};
|
|
21617
21669
|
}
|
|
21618
|
-
if (!
|
|
21670
|
+
if (!existsSync27(legacyHivePath)) {
|
|
21619
21671
|
return {
|
|
21620
21672
|
migrated: false,
|
|
21621
21673
|
entriesMigrated: 0,
|
|
@@ -21816,8 +21868,8 @@ function truncateLesson2(text) {
|
|
|
21816
21868
|
return `${text.slice(0, 277)}...`;
|
|
21817
21869
|
}
|
|
21818
21870
|
function inferProjectName(directory) {
|
|
21819
|
-
const packageJsonPath =
|
|
21820
|
-
if (
|
|
21871
|
+
const packageJsonPath = path44.join(directory, "package.json");
|
|
21872
|
+
if (existsSync27(packageJsonPath)) {
|
|
21821
21873
|
try {
|
|
21822
21874
|
const pkg = JSON.parse(readFileSync16(packageJsonPath, "utf-8"));
|
|
21823
21875
|
if (pkg.name && typeof pkg.name === "string") {
|
|
@@ -21825,7 +21877,7 @@ function inferProjectName(directory) {
|
|
|
21825
21877
|
}
|
|
21826
21878
|
} catch {}
|
|
21827
21879
|
}
|
|
21828
|
-
return
|
|
21880
|
+
return path44.basename(directory);
|
|
21829
21881
|
}
|
|
21830
21882
|
async function writeSentinel(sentinelPath, migrated, dropped) {
|
|
21831
21883
|
const sentinel = {
|
|
@@ -21837,7 +21889,7 @@ async function writeSentinel(sentinelPath, migrated, dropped) {
|
|
|
21837
21889
|
schema_version: 1,
|
|
21838
21890
|
migration_tool: "knowledge-migrator.ts"
|
|
21839
21891
|
};
|
|
21840
|
-
await _internals32.mkdir(
|
|
21892
|
+
await _internals32.mkdir(path44.dirname(sentinelPath), { recursive: true });
|
|
21841
21893
|
await _internals32.writeFile(sentinelPath, JSON.stringify(sentinel, null, 2), "utf-8");
|
|
21842
21894
|
}
|
|
21843
21895
|
function resolveLegacyHiveKnowledgePath() {
|
|
@@ -21845,13 +21897,13 @@ function resolveLegacyHiveKnowledgePath() {
|
|
|
21845
21897
|
const home = process.env.HOME || os11.homedir();
|
|
21846
21898
|
let dataDir;
|
|
21847
21899
|
if (platform === "win32") {
|
|
21848
|
-
dataDir =
|
|
21900
|
+
dataDir = path44.join(process.env.LOCALAPPDATA || path44.join(home, "AppData", "Local"), "opencode-swarm", "Data");
|
|
21849
21901
|
} else if (platform === "darwin") {
|
|
21850
|
-
dataDir =
|
|
21902
|
+
dataDir = path44.join(home, "Library", "Application Support", "opencode-swarm");
|
|
21851
21903
|
} else {
|
|
21852
|
-
dataDir =
|
|
21904
|
+
dataDir = path44.join(process.env.XDG_DATA_HOME || path44.join(home, ".local", "share"), "opencode-swarm");
|
|
21853
21905
|
}
|
|
21854
|
-
return
|
|
21906
|
+
return path44.join(dataDir, "hive-knowledge.jsonl");
|
|
21855
21907
|
}
|
|
21856
21908
|
|
|
21857
21909
|
// src/commands/knowledge.ts
|
|
@@ -21905,7 +21957,7 @@ async function handleKnowledgeRestoreCommand(directory, args) {
|
|
|
21905
21957
|
return "Invalid entry ID. IDs must be 1-64 characters: letters, digits, hyphens, underscores only.";
|
|
21906
21958
|
}
|
|
21907
21959
|
try {
|
|
21908
|
-
const quarantinePath =
|
|
21960
|
+
const quarantinePath = join38(resolveKnowledgeStoreDir(directory), "knowledge-quarantined.jsonl");
|
|
21909
21961
|
const entries = await readKnowledge(quarantinePath);
|
|
21910
21962
|
const resolved = resolveEntryByPrefix(entries, inputId);
|
|
21911
21963
|
if ("error" in resolved) {
|
|
@@ -22156,15 +22208,15 @@ var _internals33 = {
|
|
|
22156
22208
|
};
|
|
22157
22209
|
|
|
22158
22210
|
// src/commands/link.ts
|
|
22159
|
-
import { existsSync as
|
|
22160
|
-
import * as
|
|
22211
|
+
import { existsSync as existsSync28 } from "fs";
|
|
22212
|
+
import * as path46 from "path";
|
|
22161
22213
|
|
|
22162
22214
|
// src/knowledge/identity.ts
|
|
22163
22215
|
import * as child_process5 from "child_process";
|
|
22164
22216
|
import { createHash as createHash5 } from "crypto";
|
|
22165
|
-
import * as
|
|
22217
|
+
import * as path45 from "path";
|
|
22166
22218
|
function deriveProjectHash(directory) {
|
|
22167
|
-
const absolutePath =
|
|
22219
|
+
const absolutePath = path45.resolve(directory);
|
|
22168
22220
|
let hashInput;
|
|
22169
22221
|
try {
|
|
22170
22222
|
const remoteUrl = child_process5.execSync("git remote get-url origin", {
|
|
@@ -22184,9 +22236,9 @@ function deriveProjectHash(directory) {
|
|
|
22184
22236
|
// src/commands/link.ts
|
|
22185
22237
|
var DEDUP_THRESHOLD = 0.6;
|
|
22186
22238
|
async function mergeLocalKnowledgeIntoLink(localSwarmDir, linkDir) {
|
|
22187
|
-
const localPath =
|
|
22188
|
-
const sharedPath =
|
|
22189
|
-
if (!
|
|
22239
|
+
const localPath = path46.join(localSwarmDir, "knowledge.jsonl");
|
|
22240
|
+
const sharedPath = path46.join(linkDir, "knowledge.jsonl");
|
|
22241
|
+
if (!existsSync28(localPath))
|
|
22190
22242
|
return { merged: 0, skipped: 0 };
|
|
22191
22243
|
let merged = 0;
|
|
22192
22244
|
let skipped = 0;
|
|
@@ -22283,7 +22335,7 @@ ${formatStatus(directory)}`;
|
|
|
22283
22335
|
const linkDir = resolveLinkDir(linkId);
|
|
22284
22336
|
let merge;
|
|
22285
22337
|
try {
|
|
22286
|
-
merge = await mergeLocalKnowledgeIntoLink(
|
|
22338
|
+
merge = await mergeLocalKnowledgeIntoLink(path46.join(directory, ".swarm"), linkDir);
|
|
22287
22339
|
} catch (error2) {
|
|
22288
22340
|
return `\u274C Failed to merge local knowledge into the link store: ${error2 instanceof Error ? error2.message : String(error2)}`;
|
|
22289
22341
|
}
|
|
@@ -22479,13 +22531,13 @@ ${USAGE7}`;
|
|
|
22479
22531
|
}
|
|
22480
22532
|
|
|
22481
22533
|
// src/commands/memory.ts
|
|
22482
|
-
import { existsSync as
|
|
22483
|
-
import * as
|
|
22534
|
+
import { existsSync as existsSync29 } from "fs";
|
|
22535
|
+
import * as path49 from "path";
|
|
22484
22536
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
22485
22537
|
// src/memory/evaluation.ts
|
|
22486
22538
|
import * as fs17 from "fs/promises";
|
|
22487
22539
|
import * as os12 from "os";
|
|
22488
|
-
import * as
|
|
22540
|
+
import * as path47 from "path";
|
|
22489
22541
|
var DEFAULT_PROVIDERS = [
|
|
22490
22542
|
"local-jsonl",
|
|
22491
22543
|
"sqlite"
|
|
@@ -22497,7 +22549,7 @@ var DEFAULT_MODES = [
|
|
|
22497
22549
|
];
|
|
22498
22550
|
var DEFAULT_TIMESTAMP = "2026-05-26T12:00:00.000Z";
|
|
22499
22551
|
async function evaluateMemoryRecallFixtures(options) {
|
|
22500
|
-
const fixtureDirectory =
|
|
22552
|
+
const fixtureDirectory = path47.resolve(options.fixtureDirectory);
|
|
22501
22553
|
const providers = options.providers ?? DEFAULT_PROVIDERS;
|
|
22502
22554
|
const modes = options.modes ?? DEFAULT_MODES;
|
|
22503
22555
|
const generatedAt = new Date().toISOString();
|
|
@@ -22506,7 +22558,7 @@ async function evaluateMemoryRecallFixtures(options) {
|
|
|
22506
22558
|
for (const fixture of fixtures) {
|
|
22507
22559
|
const materialized = materializeFixture(fixture);
|
|
22508
22560
|
for (const providerName of providers) {
|
|
22509
|
-
const tempRoot = await fs17.realpath(await fs17.mkdtemp(
|
|
22561
|
+
const tempRoot = await fs17.realpath(await fs17.mkdtemp(path47.join(os12.tmpdir(), "swarm-memory-eval-")));
|
|
22510
22562
|
const provider = createEvaluationProvider(providerName, tempRoot);
|
|
22511
22563
|
try {
|
|
22512
22564
|
await provider.initialize?.();
|
|
@@ -22563,7 +22615,7 @@ async function loadRecallEvaluationFixtures(fixtureDirectory) {
|
|
|
22563
22615
|
const files = entries.filter((entry) => entry.isFile() && entry.name.endsWith(".json")).map((entry) => entry.name).sort((a, b) => a.localeCompare(b));
|
|
22564
22616
|
const fixtures = [];
|
|
22565
22617
|
for (const file of files) {
|
|
22566
|
-
const raw = await fs17.readFile(
|
|
22618
|
+
const raw = await fs17.readFile(path47.join(fixtureDirectory, file), "utf-8");
|
|
22567
22619
|
fixtures.push(validateFixture(JSON.parse(raw), file));
|
|
22568
22620
|
}
|
|
22569
22621
|
return fixtures;
|
|
@@ -22840,8 +22892,8 @@ var CuratorOutputMemoryDecisionSchema = exports_external.object({
|
|
|
22840
22892
|
}).passthrough();
|
|
22841
22893
|
// src/memory/consolidation-log.ts
|
|
22842
22894
|
import { appendFile as appendFile3, mkdir as mkdir11, readFile as readFile15 } from "fs/promises";
|
|
22843
|
-
import * as
|
|
22844
|
-
var LOG_RELATIVE_PATH =
|
|
22895
|
+
import * as path48 from "path";
|
|
22896
|
+
var LOG_RELATIVE_PATH = path48.join("memory", "consolidation-log.jsonl");
|
|
22845
22897
|
async function readConsolidationLog(directory) {
|
|
22846
22898
|
const filePath = validateSwarmPath(directory, LOG_RELATIVE_PATH);
|
|
22847
22899
|
let raw;
|
|
@@ -22864,7 +22916,7 @@ async function readConsolidationLog(directory) {
|
|
|
22864
22916
|
}
|
|
22865
22917
|
|
|
22866
22918
|
// src/commands/memory.ts
|
|
22867
|
-
var PACKAGE_ROOT =
|
|
22919
|
+
var PACKAGE_ROOT = path49.resolve(resolvePackageRootFromModule(fileURLToPath2(import.meta.url)));
|
|
22868
22920
|
async function handleMemoryCommand(_directory, _args) {
|
|
22869
22921
|
return [
|
|
22870
22922
|
"## Swarm Memory",
|
|
@@ -22923,7 +22975,7 @@ async function handleMemoryStatusCommand(directory, _args) {
|
|
|
22923
22975
|
`- Provider: \`${config.provider}\``,
|
|
22924
22976
|
`- Storage: \`${storageDir}\``,
|
|
22925
22977
|
`- SQLite path: \`${sqlitePath}\``,
|
|
22926
|
-
`- SQLite database exists: \`${
|
|
22978
|
+
`- SQLite database exists: \`${existsSync29(sqlitePath)}\``,
|
|
22927
22979
|
`- Automatic destructive cleanup: \`disabled\``,
|
|
22928
22980
|
"",
|
|
22929
22981
|
"### Legacy JSONL"
|
|
@@ -23221,7 +23273,7 @@ function resolveCommandMemoryConfig(directory) {
|
|
|
23221
23273
|
}
|
|
23222
23274
|
function parseEvaluateArgs(directory, args) {
|
|
23223
23275
|
let json = false;
|
|
23224
|
-
let fixtureDirectory =
|
|
23276
|
+
let fixtureDirectory = path49.join(PACKAGE_ROOT, "tests", "fixtures", "memory-recall");
|
|
23225
23277
|
for (let i = 0;i < args.length; i++) {
|
|
23226
23278
|
const arg = args[i];
|
|
23227
23279
|
if (arg === "--json") {
|
|
@@ -23235,10 +23287,10 @@ function parseEvaluateArgs(directory, args) {
|
|
|
23235
23287
|
error: "Usage: /swarm memory evaluate [--json] [--fixtures <directory>]"
|
|
23236
23288
|
};
|
|
23237
23289
|
}
|
|
23238
|
-
const resolvedFixtures =
|
|
23239
|
-
const canonical =
|
|
23240
|
-
const allowedRootA =
|
|
23241
|
-
const allowedRootB =
|
|
23290
|
+
const resolvedFixtures = path49.resolve(directory, next);
|
|
23291
|
+
const canonical = path49.normalize(resolvedFixtures) + path49.sep;
|
|
23292
|
+
const allowedRootA = path49.normalize(directory) + path49.sep;
|
|
23293
|
+
const allowedRootB = path49.normalize(path49.join(PACKAGE_ROOT, "tests", "fixtures", "memory-recall")) + path49.sep;
|
|
23242
23294
|
if (!canonical.startsWith(allowedRootA) && !canonical.startsWith(allowedRootB)) {
|
|
23243
23295
|
return {
|
|
23244
23296
|
error: "--fixtures <directory> must resolve under the project directory or the bundled tests/fixtures/memory-recall directory"
|
|
@@ -23277,15 +23329,15 @@ function parseMaintenanceArgs(args, options) {
|
|
|
23277
23329
|
return { limit, confirm };
|
|
23278
23330
|
}
|
|
23279
23331
|
function resolvePackageRootFromModule(modulePath) {
|
|
23280
|
-
const moduleDir =
|
|
23281
|
-
const leaf =
|
|
23332
|
+
const moduleDir = path49.dirname(modulePath);
|
|
23333
|
+
const leaf = path49.basename(moduleDir);
|
|
23282
23334
|
if (leaf === "commands" || leaf === "cli") {
|
|
23283
|
-
return
|
|
23335
|
+
return path49.resolve(moduleDir, "..", "..");
|
|
23284
23336
|
}
|
|
23285
23337
|
if (leaf === "dist") {
|
|
23286
|
-
return
|
|
23338
|
+
return path49.resolve(moduleDir, "..");
|
|
23287
23339
|
}
|
|
23288
|
-
return
|
|
23340
|
+
return path49.resolve(moduleDir, "..");
|
|
23289
23341
|
}
|
|
23290
23342
|
function formatMigrationResult(label, report) {
|
|
23291
23343
|
if (!report) {
|
|
@@ -24020,11 +24072,11 @@ var _internals39 = {
|
|
|
24020
24072
|
|
|
24021
24073
|
// src/services/preflight-service.ts
|
|
24022
24074
|
import * as fs24 from "fs";
|
|
24023
|
-
import * as
|
|
24075
|
+
import * as path56 from "path";
|
|
24024
24076
|
|
|
24025
24077
|
// src/tools/lint.ts
|
|
24026
24078
|
import * as fs18 from "fs";
|
|
24027
|
-
import * as
|
|
24079
|
+
import * as path50 from "path";
|
|
24028
24080
|
|
|
24029
24081
|
// src/utils/path-security.ts
|
|
24030
24082
|
function containsPathTraversal(str) {
|
|
@@ -24080,9 +24132,9 @@ function validateArgs(args) {
|
|
|
24080
24132
|
}
|
|
24081
24133
|
function getLinterCommand(linter, mode, projectDir) {
|
|
24082
24134
|
const isWindows = process.platform === "win32";
|
|
24083
|
-
const binDir =
|
|
24084
|
-
const biomeBin = isWindows ?
|
|
24085
|
-
const eslintBin = isWindows ?
|
|
24135
|
+
const binDir = path50.join(projectDir, "node_modules", ".bin");
|
|
24136
|
+
const biomeBin = isWindows ? path50.join(binDir, "biome.EXE") : path50.join(binDir, "biome");
|
|
24137
|
+
const eslintBin = isWindows ? path50.join(binDir, "eslint.cmd") : path50.join(binDir, "eslint");
|
|
24086
24138
|
switch (linter) {
|
|
24087
24139
|
case "biome":
|
|
24088
24140
|
if (mode === "fix") {
|
|
@@ -24098,7 +24150,7 @@ function getLinterCommand(linter, mode, projectDir) {
|
|
|
24098
24150
|
}
|
|
24099
24151
|
function getAdditionalLinterCommand(linter, mode, cwd) {
|
|
24100
24152
|
const gradlewName = process.platform === "win32" ? "gradlew.bat" : "gradlew";
|
|
24101
|
-
const gradlew = fs18.existsSync(
|
|
24153
|
+
const gradlew = fs18.existsSync(path50.join(cwd, gradlewName)) ? path50.join(cwd, gradlewName) : null;
|
|
24102
24154
|
switch (linter) {
|
|
24103
24155
|
case "ruff":
|
|
24104
24156
|
return mode === "fix" ? ["ruff", "check", "--fix", "."] : ["ruff", "check", "."];
|
|
@@ -24132,10 +24184,10 @@ function getAdditionalLinterCommand(linter, mode, cwd) {
|
|
|
24132
24184
|
}
|
|
24133
24185
|
}
|
|
24134
24186
|
function detectRuff(cwd) {
|
|
24135
|
-
if (fs18.existsSync(
|
|
24187
|
+
if (fs18.existsSync(path50.join(cwd, "ruff.toml")))
|
|
24136
24188
|
return isCommandAvailable("ruff");
|
|
24137
24189
|
try {
|
|
24138
|
-
const pyproject =
|
|
24190
|
+
const pyproject = path50.join(cwd, "pyproject.toml");
|
|
24139
24191
|
if (fs18.existsSync(pyproject)) {
|
|
24140
24192
|
const content = fs18.readFileSync(pyproject, "utf-8");
|
|
24141
24193
|
if (content.includes("[tool.ruff]"))
|
|
@@ -24145,19 +24197,19 @@ function detectRuff(cwd) {
|
|
|
24145
24197
|
return false;
|
|
24146
24198
|
}
|
|
24147
24199
|
function detectClippy(cwd) {
|
|
24148
|
-
return fs18.existsSync(
|
|
24200
|
+
return fs18.existsSync(path50.join(cwd, "Cargo.toml")) && isCommandAvailable("cargo");
|
|
24149
24201
|
}
|
|
24150
24202
|
function detectGolangciLint(cwd) {
|
|
24151
|
-
return fs18.existsSync(
|
|
24203
|
+
return fs18.existsSync(path50.join(cwd, "go.mod")) && isCommandAvailable("golangci-lint");
|
|
24152
24204
|
}
|
|
24153
24205
|
function detectCheckstyle(cwd) {
|
|
24154
|
-
const hasMaven = fs18.existsSync(
|
|
24155
|
-
const hasGradle = fs18.existsSync(
|
|
24156
|
-
const hasBinary = hasMaven && isCommandAvailable("mvn") || hasGradle && (fs18.existsSync(
|
|
24206
|
+
const hasMaven = fs18.existsSync(path50.join(cwd, "pom.xml"));
|
|
24207
|
+
const hasGradle = fs18.existsSync(path50.join(cwd, "build.gradle")) || fs18.existsSync(path50.join(cwd, "build.gradle.kts"));
|
|
24208
|
+
const hasBinary = hasMaven && isCommandAvailable("mvn") || hasGradle && (fs18.existsSync(path50.join(cwd, "gradlew")) || isCommandAvailable("gradle"));
|
|
24157
24209
|
return (hasMaven || hasGradle) && hasBinary;
|
|
24158
24210
|
}
|
|
24159
24211
|
function detectKtlint(cwd) {
|
|
24160
|
-
const hasKotlin = fs18.existsSync(
|
|
24212
|
+
const hasKotlin = fs18.existsSync(path50.join(cwd, "build.gradle.kts")) || fs18.existsSync(path50.join(cwd, "build.gradle")) || (() => {
|
|
24161
24213
|
try {
|
|
24162
24214
|
return fs18.readdirSync(cwd).some((f) => f.endsWith(".kt") || f.endsWith(".kts"));
|
|
24163
24215
|
} catch {
|
|
@@ -24176,11 +24228,11 @@ function detectDotnetFormat(cwd) {
|
|
|
24176
24228
|
}
|
|
24177
24229
|
}
|
|
24178
24230
|
function detectCppcheck(cwd) {
|
|
24179
|
-
if (fs18.existsSync(
|
|
24231
|
+
if (fs18.existsSync(path50.join(cwd, "CMakeLists.txt"))) {
|
|
24180
24232
|
return isCommandAvailable("cppcheck");
|
|
24181
24233
|
}
|
|
24182
24234
|
try {
|
|
24183
|
-
const dirsToCheck = [cwd,
|
|
24235
|
+
const dirsToCheck = [cwd, path50.join(cwd, "src")];
|
|
24184
24236
|
const hasCpp = dirsToCheck.some((dir) => {
|
|
24185
24237
|
try {
|
|
24186
24238
|
return fs18.readdirSync(dir).some((f) => /\.(c|cpp|cc|cxx|h|hpp)$/.test(f));
|
|
@@ -24194,13 +24246,13 @@ function detectCppcheck(cwd) {
|
|
|
24194
24246
|
}
|
|
24195
24247
|
}
|
|
24196
24248
|
function detectSwiftlint(cwd) {
|
|
24197
|
-
return fs18.existsSync(
|
|
24249
|
+
return fs18.existsSync(path50.join(cwd, "Package.swift")) && isCommandAvailable("swiftlint");
|
|
24198
24250
|
}
|
|
24199
24251
|
function detectDartAnalyze(cwd) {
|
|
24200
|
-
return fs18.existsSync(
|
|
24252
|
+
return fs18.existsSync(path50.join(cwd, "pubspec.yaml")) && (isCommandAvailable("dart") || isCommandAvailable("flutter"));
|
|
24201
24253
|
}
|
|
24202
24254
|
function detectRubocop(cwd) {
|
|
24203
|
-
return (fs18.existsSync(
|
|
24255
|
+
return (fs18.existsSync(path50.join(cwd, "Gemfile")) || fs18.existsSync(path50.join(cwd, "gems.rb")) || fs18.existsSync(path50.join(cwd, ".rubocop.yml"))) && (isCommandAvailable("rubocop") || isCommandAvailable("bundle"));
|
|
24204
24256
|
}
|
|
24205
24257
|
function detectAdditionalLinter(cwd) {
|
|
24206
24258
|
if (detectRuff(cwd))
|
|
@@ -24228,10 +24280,10 @@ function detectAdditionalLinter(cwd) {
|
|
|
24228
24280
|
function findBinInAncestors(startDir, binName) {
|
|
24229
24281
|
let dir = startDir;
|
|
24230
24282
|
while (true) {
|
|
24231
|
-
const candidate =
|
|
24283
|
+
const candidate = path50.join(dir, "node_modules", ".bin", binName);
|
|
24232
24284
|
if (fs18.existsSync(candidate))
|
|
24233
24285
|
return candidate;
|
|
24234
|
-
const parent =
|
|
24286
|
+
const parent = path50.dirname(dir);
|
|
24235
24287
|
if (parent === dir)
|
|
24236
24288
|
break;
|
|
24237
24289
|
dir = parent;
|
|
@@ -24240,10 +24292,10 @@ function findBinInAncestors(startDir, binName) {
|
|
|
24240
24292
|
}
|
|
24241
24293
|
function findBinInEnvPath(binName) {
|
|
24242
24294
|
const searchPath = process.env.PATH ?? "";
|
|
24243
|
-
for (const dir of searchPath.split(
|
|
24295
|
+
for (const dir of searchPath.split(path50.delimiter)) {
|
|
24244
24296
|
if (!dir)
|
|
24245
24297
|
continue;
|
|
24246
|
-
const candidate =
|
|
24298
|
+
const candidate = path50.join(dir, binName);
|
|
24247
24299
|
if (fs18.existsSync(candidate))
|
|
24248
24300
|
return candidate;
|
|
24249
24301
|
}
|
|
@@ -24256,13 +24308,13 @@ async function detectAvailableLinter(directory) {
|
|
|
24256
24308
|
return null;
|
|
24257
24309
|
const projectDir = directory;
|
|
24258
24310
|
const isWindows = process.platform === "win32";
|
|
24259
|
-
const biomeBin = isWindows ?
|
|
24260
|
-
const eslintBin = isWindows ?
|
|
24311
|
+
const biomeBin = isWindows ? path50.join(projectDir, "node_modules", ".bin", "biome.EXE") : path50.join(projectDir, "node_modules", ".bin", "biome");
|
|
24312
|
+
const eslintBin = isWindows ? path50.join(projectDir, "node_modules", ".bin", "eslint.cmd") : path50.join(projectDir, "node_modules", ".bin", "eslint");
|
|
24261
24313
|
const localResult = await _detectAvailableLinter(projectDir, biomeBin, eslintBin);
|
|
24262
24314
|
if (localResult)
|
|
24263
24315
|
return localResult;
|
|
24264
|
-
const biomeAncestor = findBinInAncestors(
|
|
24265
|
-
const eslintAncestor = findBinInAncestors(
|
|
24316
|
+
const biomeAncestor = findBinInAncestors(path50.dirname(projectDir), isWindows ? "biome.EXE" : "biome");
|
|
24317
|
+
const eslintAncestor = findBinInAncestors(path50.dirname(projectDir), isWindows ? "eslint.cmd" : "eslint");
|
|
24266
24318
|
if (biomeAncestor || eslintAncestor) {
|
|
24267
24319
|
return _detectAvailableLinter(projectDir, biomeAncestor ?? biomeBin, eslintAncestor ?? eslintBin);
|
|
24268
24320
|
}
|
|
@@ -24476,7 +24528,7 @@ var _internals40 = {
|
|
|
24476
24528
|
|
|
24477
24529
|
// src/tools/secretscan.ts
|
|
24478
24530
|
import * as fs19 from "fs";
|
|
24479
|
-
import * as
|
|
24531
|
+
import * as path51 from "path";
|
|
24480
24532
|
var MAX_FILE_PATH_LENGTH = 500;
|
|
24481
24533
|
var MAX_FILE_SIZE_BYTES = 512 * 1024;
|
|
24482
24534
|
var MAX_FILES_SCANNED = 1000;
|
|
@@ -24703,7 +24755,7 @@ function isGlobOrPathPattern(pattern) {
|
|
|
24703
24755
|
return pattern.includes("/") || pattern.includes("\\") || /[*?[\]{}]/.test(pattern);
|
|
24704
24756
|
}
|
|
24705
24757
|
function loadSecretScanIgnore(scanDir) {
|
|
24706
|
-
const ignorePath =
|
|
24758
|
+
const ignorePath = path51.join(scanDir, ".secretscanignore");
|
|
24707
24759
|
try {
|
|
24708
24760
|
if (!fs19.existsSync(ignorePath))
|
|
24709
24761
|
return [];
|
|
@@ -24726,7 +24778,7 @@ function isExcluded(entry, relPath, exactNames, globPatterns) {
|
|
|
24726
24778
|
if (exactNames.has(entry))
|
|
24727
24779
|
return true;
|
|
24728
24780
|
for (const pattern of globPatterns) {
|
|
24729
|
-
if (
|
|
24781
|
+
if (path51.matchesGlob(relPath, pattern))
|
|
24730
24782
|
return true;
|
|
24731
24783
|
}
|
|
24732
24784
|
return false;
|
|
@@ -24747,7 +24799,7 @@ function validateDirectoryInput(dir) {
|
|
|
24747
24799
|
return null;
|
|
24748
24800
|
}
|
|
24749
24801
|
function isBinaryFile(filePath, buffer) {
|
|
24750
|
-
const ext =
|
|
24802
|
+
const ext = path51.extname(filePath).toLowerCase();
|
|
24751
24803
|
if (DEFAULT_EXCLUDE_EXTENSIONS.has(ext)) {
|
|
24752
24804
|
return true;
|
|
24753
24805
|
}
|
|
@@ -24884,9 +24936,9 @@ function isSymlinkLoop(realPath, visited) {
|
|
|
24884
24936
|
return false;
|
|
24885
24937
|
}
|
|
24886
24938
|
function isPathWithinScope(realPath, scanDir) {
|
|
24887
|
-
const resolvedScanDir =
|
|
24888
|
-
const resolvedRealPath =
|
|
24889
|
-
return resolvedRealPath === resolvedScanDir || resolvedRealPath.startsWith(resolvedScanDir +
|
|
24939
|
+
const resolvedScanDir = path51.resolve(scanDir);
|
|
24940
|
+
const resolvedRealPath = path51.resolve(realPath);
|
|
24941
|
+
return resolvedRealPath === resolvedScanDir || resolvedRealPath.startsWith(resolvedScanDir + path51.sep) || resolvedRealPath.startsWith(`${resolvedScanDir}/`) || resolvedRealPath.startsWith(`${resolvedScanDir}\\`);
|
|
24890
24942
|
}
|
|
24891
24943
|
function findScannableFiles(dir, excludeExact, excludeGlobs, scanDir, visited, stats = {
|
|
24892
24944
|
skippedDirs: 0,
|
|
@@ -24912,8 +24964,8 @@ function findScannableFiles(dir, excludeExact, excludeGlobs, scanDir, visited, s
|
|
|
24912
24964
|
return a.localeCompare(b);
|
|
24913
24965
|
});
|
|
24914
24966
|
for (const entry of entries) {
|
|
24915
|
-
const fullPath =
|
|
24916
|
-
const relPath =
|
|
24967
|
+
const fullPath = path51.join(dir, entry);
|
|
24968
|
+
const relPath = path51.relative(scanDir, fullPath).replace(/\\/g, "/");
|
|
24917
24969
|
if (isExcluded(entry, relPath, excludeExact, excludeGlobs)) {
|
|
24918
24970
|
stats.skippedDirs++;
|
|
24919
24971
|
continue;
|
|
@@ -24948,7 +25000,7 @@ function findScannableFiles(dir, excludeExact, excludeGlobs, scanDir, visited, s
|
|
|
24948
25000
|
const subFiles = findScannableFiles(fullPath, excludeExact, excludeGlobs, scanDir, visited, stats);
|
|
24949
25001
|
files.push(...subFiles);
|
|
24950
25002
|
} else if (lstat2.isFile()) {
|
|
24951
|
-
const ext =
|
|
25003
|
+
const ext = path51.extname(fullPath).toLowerCase();
|
|
24952
25004
|
if (!DEFAULT_EXCLUDE_EXTENSIONS.has(ext)) {
|
|
24953
25005
|
files.push(fullPath);
|
|
24954
25006
|
} else {
|
|
@@ -25014,7 +25066,7 @@ var secretscan = createSwarmTool({
|
|
|
25014
25066
|
}
|
|
25015
25067
|
}
|
|
25016
25068
|
try {
|
|
25017
|
-
const _scanDirRaw =
|
|
25069
|
+
const _scanDirRaw = path51.resolve(directory);
|
|
25018
25070
|
const scanDir = (() => {
|
|
25019
25071
|
try {
|
|
25020
25072
|
return fs19.realpathSync(_scanDirRaw);
|
|
@@ -25177,11 +25229,11 @@ var _internals41 = {
|
|
|
25177
25229
|
|
|
25178
25230
|
// src/tools/test-runner.ts
|
|
25179
25231
|
import * as fs23 from "fs";
|
|
25180
|
-
import * as
|
|
25232
|
+
import * as path55 from "path";
|
|
25181
25233
|
|
|
25182
25234
|
// src/test-impact/analyzer.ts
|
|
25183
25235
|
import fs20 from "fs";
|
|
25184
|
-
import
|
|
25236
|
+
import path52 from "path";
|
|
25185
25237
|
var IMPORT_REGEX_ES = /import\s+[\s\S]*?\s+from\s+['"]([^'"]+)['"]/g;
|
|
25186
25238
|
var IMPORT_REGEX_REQUIRE = /require\s*\(\s*['"]([^'"]+)['"]\s*\)/g;
|
|
25187
25239
|
var IMPORT_REGEX_REEXPORT = /export\s+(?:\{[^}]*\}|\*)\s+from\s+['"]([^'"]+)['"]/g;
|
|
@@ -25222,8 +25274,8 @@ function resolveRelativeImport(fromDir, importPath) {
|
|
|
25222
25274
|
if (!importPath.startsWith(".")) {
|
|
25223
25275
|
return null;
|
|
25224
25276
|
}
|
|
25225
|
-
const resolved =
|
|
25226
|
-
if (
|
|
25277
|
+
const resolved = path52.resolve(fromDir, importPath);
|
|
25278
|
+
if (path52.extname(resolved)) {
|
|
25227
25279
|
if (fs20.existsSync(resolved) && fs20.statSync(resolved).isFile()) {
|
|
25228
25280
|
return normalizePath2(resolved);
|
|
25229
25281
|
}
|
|
@@ -25243,20 +25295,20 @@ function resolvePythonImport(fromDir, module) {
|
|
|
25243
25295
|
const leadingDots = module.match(/^\.+/)?.[0].length ?? 0;
|
|
25244
25296
|
let baseDir = fromDir;
|
|
25245
25297
|
for (let i = 1;i < leadingDots; i++) {
|
|
25246
|
-
baseDir =
|
|
25298
|
+
baseDir = path52.dirname(baseDir);
|
|
25247
25299
|
}
|
|
25248
25300
|
const rest = module.slice(leadingDots);
|
|
25249
25301
|
if (rest.length === 0) {
|
|
25250
|
-
const initPath =
|
|
25302
|
+
const initPath = path52.join(baseDir, "__init__.py");
|
|
25251
25303
|
if (fs20.existsSync(initPath) && fs20.statSync(initPath).isFile()) {
|
|
25252
25304
|
return normalizePath2(initPath);
|
|
25253
25305
|
}
|
|
25254
25306
|
return null;
|
|
25255
25307
|
}
|
|
25256
|
-
const subpath = rest.replace(/\./g,
|
|
25308
|
+
const subpath = rest.replace(/\./g, path52.sep);
|
|
25257
25309
|
const candidates = [
|
|
25258
|
-
`${
|
|
25259
|
-
|
|
25310
|
+
`${path52.join(baseDir, subpath)}.py`,
|
|
25311
|
+
path52.join(baseDir, subpath, "__init__.py")
|
|
25260
25312
|
];
|
|
25261
25313
|
for (const c of candidates) {
|
|
25262
25314
|
if (fs20.existsSync(c) && fs20.statSync(c).isFile())
|
|
@@ -25266,7 +25318,7 @@ function resolvePythonImport(fromDir, module) {
|
|
|
25266
25318
|
}
|
|
25267
25319
|
var goModuleCache = new Map;
|
|
25268
25320
|
function findGoModule(fromDir) {
|
|
25269
|
-
const resolved =
|
|
25321
|
+
const resolved = path52.resolve(fromDir);
|
|
25270
25322
|
let cur = resolved;
|
|
25271
25323
|
const walked = [];
|
|
25272
25324
|
for (let i = 0;i < 16; i++) {
|
|
@@ -25278,7 +25330,7 @@ function findGoModule(fromDir) {
|
|
|
25278
25330
|
}
|
|
25279
25331
|
walked.push(cur);
|
|
25280
25332
|
try {
|
|
25281
|
-
const goMod =
|
|
25333
|
+
const goMod = path52.join(cur, "go.mod");
|
|
25282
25334
|
const content = fs20.readFileSync(goMod, "utf-8");
|
|
25283
25335
|
const moduleMatch = content.match(/^\s*module\s+"?([^"\s/]+(?:\/[^"\s]+)*)"?/m);
|
|
25284
25336
|
if (moduleMatch) {
|
|
@@ -25289,10 +25341,10 @@ function findGoModule(fromDir) {
|
|
|
25289
25341
|
}
|
|
25290
25342
|
} catch {}
|
|
25291
25343
|
try {
|
|
25292
|
-
fs20.accessSync(
|
|
25344
|
+
fs20.accessSync(path52.join(cur, ".git"));
|
|
25293
25345
|
break;
|
|
25294
25346
|
} catch {}
|
|
25295
|
-
const parent =
|
|
25347
|
+
const parent = path52.dirname(cur);
|
|
25296
25348
|
if (parent === cur)
|
|
25297
25349
|
break;
|
|
25298
25350
|
cur = parent;
|
|
@@ -25304,12 +25356,12 @@ function findGoModule(fromDir) {
|
|
|
25304
25356
|
function resolveGoImport(fromDir, importPath) {
|
|
25305
25357
|
let dir = null;
|
|
25306
25358
|
if (importPath.startsWith(".")) {
|
|
25307
|
-
dir =
|
|
25359
|
+
dir = path52.resolve(fromDir, importPath);
|
|
25308
25360
|
} else {
|
|
25309
25361
|
const mod = findGoModule(fromDir);
|
|
25310
25362
|
if (mod && (importPath === mod.modulePath || importPath.startsWith(`${mod.modulePath}/`))) {
|
|
25311
25363
|
const subpath = importPath.slice(mod.modulePath.length);
|
|
25312
|
-
dir =
|
|
25364
|
+
dir = path52.join(mod.moduleRoot, subpath);
|
|
25313
25365
|
}
|
|
25314
25366
|
}
|
|
25315
25367
|
if (dir === null)
|
|
@@ -25317,7 +25369,7 @@ function resolveGoImport(fromDir, importPath) {
|
|
|
25317
25369
|
if (!fs20.existsSync(dir) || !fs20.statSync(dir).isDirectory())
|
|
25318
25370
|
return [];
|
|
25319
25371
|
try {
|
|
25320
|
-
return fs20.readdirSync(dir).filter((f) => f.endsWith(".go") && !f.endsWith("_test.go")).map((f) => normalizePath2(
|
|
25372
|
+
return fs20.readdirSync(dir).filter((f) => f.endsWith(".go") && !f.endsWith("_test.go")).map((f) => normalizePath2(path52.join(dir, f)));
|
|
25321
25373
|
} catch {
|
|
25322
25374
|
return [];
|
|
25323
25375
|
}
|
|
@@ -25356,15 +25408,15 @@ function findTestFilesSync(cwd) {
|
|
|
25356
25408
|
for (const entry of entries) {
|
|
25357
25409
|
if (entry.isDirectory()) {
|
|
25358
25410
|
if (!skipDirs.has(entry.name)) {
|
|
25359
|
-
walk(
|
|
25411
|
+
walk(path52.join(dir, entry.name), visitedInodes);
|
|
25360
25412
|
}
|
|
25361
25413
|
} else if (entry.isFile()) {
|
|
25362
25414
|
const name = entry.name;
|
|
25363
25415
|
const isTsTest = /\.(test|spec)\.(ts|tsx|js|jsx)$/.test(name) || dir.includes("__tests__") && /\.(ts|tsx|js|jsx)$/.test(name);
|
|
25364
|
-
const isPyTest = /^test_.+\.py$/.test(name) || /.+_test\.py$/.test(name) || dir.includes(`${
|
|
25416
|
+
const isPyTest = /^test_.+\.py$/.test(name) || /.+_test\.py$/.test(name) || dir.includes(`${path52.sep}tests${path52.sep}`) && name.endsWith(".py");
|
|
25365
25417
|
const isGoTest = /.+_test\.go$/.test(name);
|
|
25366
25418
|
if (isTsTest || isPyTest || isGoTest) {
|
|
25367
|
-
testFiles.push(normalizePath2(
|
|
25419
|
+
testFiles.push(normalizePath2(path52.join(dir, entry.name)));
|
|
25368
25420
|
}
|
|
25369
25421
|
}
|
|
25370
25422
|
}
|
|
@@ -25389,8 +25441,8 @@ function extractImports(content) {
|
|
|
25389
25441
|
];
|
|
25390
25442
|
}
|
|
25391
25443
|
function addImpactEdgesForTestFile(testFile, content, impactMap) {
|
|
25392
|
-
const ext =
|
|
25393
|
-
const testDir =
|
|
25444
|
+
const ext = path52.extname(testFile).toLowerCase();
|
|
25445
|
+
const testDir = path52.dirname(testFile);
|
|
25394
25446
|
function addEdge(source) {
|
|
25395
25447
|
if (!impactMap[source])
|
|
25396
25448
|
impactMap[source] = [];
|
|
@@ -25427,6 +25479,7 @@ function addImpactEdgesForTestFile(testFile, content, impactMap) {
|
|
|
25427
25479
|
}
|
|
25428
25480
|
}
|
|
25429
25481
|
async function buildImpactMapInternal(cwd) {
|
|
25482
|
+
_clearGoModuleCache();
|
|
25430
25483
|
const testFiles = findTestFilesSync(cwd);
|
|
25431
25484
|
const impactMap = {};
|
|
25432
25485
|
for (const testFile of testFiles) {
|
|
@@ -25463,7 +25516,7 @@ async function buildImpactMap(cwd) {
|
|
|
25463
25516
|
return impactMap;
|
|
25464
25517
|
}
|
|
25465
25518
|
async function loadImpactMap(cwd, options) {
|
|
25466
|
-
const cachePath =
|
|
25519
|
+
const cachePath = path52.join(cwd, ".swarm", "cache", "impact-map.json");
|
|
25467
25520
|
if (fs20.existsSync(cachePath)) {
|
|
25468
25521
|
try {
|
|
25469
25522
|
const content = fs20.readFileSync(cachePath, "utf-8");
|
|
@@ -25496,12 +25549,12 @@ async function loadImpactMap(cwd, options) {
|
|
|
25496
25549
|
return _internals42.buildImpactMap(cwd);
|
|
25497
25550
|
}
|
|
25498
25551
|
async function saveImpactMap(cwd, impactMap) {
|
|
25499
|
-
if (!
|
|
25552
|
+
if (!path52.isAbsolute(cwd)) {
|
|
25500
25553
|
throw new Error(`saveImpactMap requires an absolute project root path, got: "${cwd}"`);
|
|
25501
25554
|
}
|
|
25502
25555
|
_internals42.validateProjectRoot(cwd);
|
|
25503
|
-
const cacheDir2 =
|
|
25504
|
-
const cachePath =
|
|
25556
|
+
const cacheDir2 = path52.join(cwd, ".swarm", "cache");
|
|
25557
|
+
const cachePath = path52.join(cacheDir2, "impact-map.json");
|
|
25505
25558
|
if (!fs20.existsSync(cacheDir2)) {
|
|
25506
25559
|
fs20.mkdirSync(cacheDir2, { recursive: true });
|
|
25507
25560
|
}
|
|
@@ -25533,7 +25586,7 @@ async function analyzeImpact(changedFiles, cwd, budget) {
|
|
|
25533
25586
|
budgetExceeded = true;
|
|
25534
25587
|
break;
|
|
25535
25588
|
}
|
|
25536
|
-
const normalizedChanged = normalizePath2(
|
|
25589
|
+
const normalizedChanged = normalizePath2(path52.resolve(changedFile));
|
|
25537
25590
|
const tests = impactMap[normalizedChanged];
|
|
25538
25591
|
if (tests && tests.length > 0) {
|
|
25539
25592
|
for (const test of tests) {
|
|
@@ -25547,13 +25600,13 @@ async function analyzeImpact(changedFiles, cwd, budget) {
|
|
|
25547
25600
|
if (budgetExceeded)
|
|
25548
25601
|
break;
|
|
25549
25602
|
} else {
|
|
25550
|
-
const changedDir = normalizePath2(
|
|
25551
|
-
const changedInputDir = normalizePath2(
|
|
25603
|
+
const changedDir = normalizePath2(path52.dirname(normalizedChanged));
|
|
25604
|
+
const changedInputDir = normalizePath2(path52.dirname(changedFile));
|
|
25552
25605
|
const suffixMatches = Object.entries(impactMap).filter(([sourcePath]) => {
|
|
25553
25606
|
return sourcePath.endsWith(changedFile) || changedFile.endsWith(sourcePath) || sourcePath.endsWith(normalizedChanged) || normalizedChanged.endsWith(sourcePath);
|
|
25554
25607
|
}).sort(([sourceA], [sourceB]) => {
|
|
25555
|
-
const sourceDirA = normalizePath2(
|
|
25556
|
-
const sourceDirB = normalizePath2(
|
|
25608
|
+
const sourceDirA = normalizePath2(path52.dirname(sourceA));
|
|
25609
|
+
const sourceDirB = normalizePath2(path52.dirname(sourceB));
|
|
25557
25610
|
const exactA = sourceDirA === changedDir || changedInputDir !== "." && (sourceDirA === changedInputDir || sourceDirA.endsWith(`/${changedInputDir}`));
|
|
25558
25611
|
const exactB = sourceDirB === changedDir || changedInputDir !== "." && (sourceDirB === changedInputDir || sourceDirB.endsWith(`/${changedInputDir}`));
|
|
25559
25612
|
if (exactA !== exactB)
|
|
@@ -25880,7 +25933,7 @@ function detectFlakyTests(allHistory) {
|
|
|
25880
25933
|
|
|
25881
25934
|
// src/test-impact/history-store.ts
|
|
25882
25935
|
import fs21 from "fs";
|
|
25883
|
-
import
|
|
25936
|
+
import path53 from "path";
|
|
25884
25937
|
var MAX_HISTORY_PER_TEST = 20;
|
|
25885
25938
|
var MAX_ERROR_LENGTH = 500;
|
|
25886
25939
|
var MAX_STACK_LENGTH = 200;
|
|
@@ -25892,10 +25945,10 @@ function getHistoryPath(workingDir) {
|
|
|
25892
25945
|
if (!workingDir) {
|
|
25893
25946
|
throw new Error("getHistoryPath requires a working directory \u2014 project root must be provided by the caller");
|
|
25894
25947
|
}
|
|
25895
|
-
if (!
|
|
25948
|
+
if (!path53.isAbsolute(workingDir)) {
|
|
25896
25949
|
throw new Error(`getHistoryPath requires an absolute project root path, got: "${workingDir}"`);
|
|
25897
25950
|
}
|
|
25898
|
-
return
|
|
25951
|
+
return path53.join(workingDir, ".swarm", "cache", "test-history.jsonl");
|
|
25899
25952
|
}
|
|
25900
25953
|
function sanitizeErrorMessage(errorMessage) {
|
|
25901
25954
|
if (errorMessage === undefined) {
|
|
@@ -25987,7 +26040,7 @@ function batchAppendTestRuns(records, workingDir) {
|
|
|
25987
26040
|
}
|
|
25988
26041
|
}
|
|
25989
26042
|
const historyPath = getHistoryPath(workingDir);
|
|
25990
|
-
const historyDir =
|
|
26043
|
+
const historyDir = path53.dirname(historyPath);
|
|
25991
26044
|
_internals43.validateProjectRoot(workingDir);
|
|
25992
26045
|
if (!fs21.existsSync(historyDir)) {
|
|
25993
26046
|
fs21.mkdirSync(historyDir, { recursive: true });
|
|
@@ -26117,7 +26170,7 @@ var _internals43 = {
|
|
|
26117
26170
|
|
|
26118
26171
|
// src/tools/resolve-working-directory.ts
|
|
26119
26172
|
import * as fs22 from "fs";
|
|
26120
|
-
import * as
|
|
26173
|
+
import * as path54 from "path";
|
|
26121
26174
|
function resolveWorkingDirectory(workingDirectory, fallbackDirectory) {
|
|
26122
26175
|
if (workingDirectory == null || workingDirectory === "") {
|
|
26123
26176
|
if (typeof fallbackDirectory !== "string" || fallbackDirectory === "") {
|
|
@@ -26140,14 +26193,12 @@ function resolveWorkingDirectory(workingDirectory, fallbackDirectory) {
|
|
|
26140
26193
|
message: "Invalid working_directory: null bytes are not allowed"
|
|
26141
26194
|
};
|
|
26142
26195
|
}
|
|
26143
|
-
|
|
26144
|
-
|
|
26145
|
-
|
|
26146
|
-
|
|
26147
|
-
|
|
26148
|
-
|
|
26149
|
-
};
|
|
26150
|
-
}
|
|
26196
|
+
const reservedDevicePattern = /^(NUL|CON|AUX|COM[1-9]|LPT[1-9])(\..*)?$/i;
|
|
26197
|
+
if (workingDirectory.startsWith("\\\\") || process.platform === "win32" && reservedDevicePattern.test(workingDirectory)) {
|
|
26198
|
+
return {
|
|
26199
|
+
success: false,
|
|
26200
|
+
message: "Invalid working_directory: Windows device paths are not allowed"
|
|
26201
|
+
};
|
|
26151
26202
|
}
|
|
26152
26203
|
const rawPathParts = workingDirectory.split(/[\\/]/);
|
|
26153
26204
|
if (rawPathParts.includes("..")) {
|
|
@@ -26156,8 +26207,8 @@ function resolveWorkingDirectory(workingDirectory, fallbackDirectory) {
|
|
|
26156
26207
|
message: "Invalid working_directory: path traversal sequences (..) are not allowed"
|
|
26157
26208
|
};
|
|
26158
26209
|
}
|
|
26159
|
-
const normalizedDir =
|
|
26160
|
-
const resolvedDir =
|
|
26210
|
+
const normalizedDir = path54.normalize(workingDirectory);
|
|
26211
|
+
const resolvedDir = path54.resolve(normalizedDir);
|
|
26161
26212
|
let statResult;
|
|
26162
26213
|
try {
|
|
26163
26214
|
statResult = fs22.statSync(resolvedDir);
|
|
@@ -26176,7 +26227,7 @@ function resolveWorkingDirectory(workingDirectory, fallbackDirectory) {
|
|
|
26176
26227
|
if (typeof fallbackDirectory !== "string" || fallbackDirectory === "") {
|
|
26177
26228
|
return { success: true, directory: resolvedDir };
|
|
26178
26229
|
}
|
|
26179
|
-
const resolvedFallback =
|
|
26230
|
+
const resolvedFallback = path54.resolve(fallbackDirectory);
|
|
26180
26231
|
let fallbackExists = false;
|
|
26181
26232
|
try {
|
|
26182
26233
|
fs22.statSync(resolvedFallback);
|
|
@@ -26185,7 +26236,7 @@ function resolveWorkingDirectory(workingDirectory, fallbackDirectory) {
|
|
|
26185
26236
|
fallbackExists = false;
|
|
26186
26237
|
}
|
|
26187
26238
|
if (fallbackExists) {
|
|
26188
|
-
const isSubdirectory = resolvedDir.startsWith(resolvedFallback +
|
|
26239
|
+
const isSubdirectory = resolvedDir.startsWith(resolvedFallback + path54.sep);
|
|
26189
26240
|
if (isSubdirectory) {
|
|
26190
26241
|
return {
|
|
26191
26242
|
success: false,
|
|
@@ -26208,7 +26259,7 @@ async function estimateFanOut(sourceFiles, cwd) {
|
|
|
26208
26259
|
const impactMap = await loadImpactMap(cwd, { skipRebuild: true });
|
|
26209
26260
|
const uniqueTestFiles = new Set;
|
|
26210
26261
|
for (const sourceFile of sourceFiles) {
|
|
26211
|
-
const resolvedPath =
|
|
26262
|
+
const resolvedPath = path55.resolve(cwd, sourceFile);
|
|
26212
26263
|
const normalizedPath = resolvedPath.replace(/\\/g, "/");
|
|
26213
26264
|
const testFiles = impactMap[normalizedPath];
|
|
26214
26265
|
if (testFiles) {
|
|
@@ -26293,14 +26344,14 @@ function hasDevDependency(devDeps, ...patterns) {
|
|
|
26293
26344
|
return hasPackageJsonDependency(devDeps, ...patterns);
|
|
26294
26345
|
}
|
|
26295
26346
|
function detectGoTest(cwd) {
|
|
26296
|
-
return fs23.existsSync(
|
|
26347
|
+
return fs23.existsSync(path55.join(cwd, "go.mod")) && isCommandAvailable("go");
|
|
26297
26348
|
}
|
|
26298
26349
|
function detectJavaMaven(cwd) {
|
|
26299
|
-
return fs23.existsSync(
|
|
26350
|
+
return fs23.existsSync(path55.join(cwd, "pom.xml")) && isCommandAvailable("mvn");
|
|
26300
26351
|
}
|
|
26301
26352
|
function detectGradle(cwd) {
|
|
26302
|
-
const hasBuildFile = fs23.existsSync(
|
|
26303
|
-
const hasGradlew = fs23.existsSync(
|
|
26353
|
+
const hasBuildFile = fs23.existsSync(path55.join(cwd, "build.gradle")) || fs23.existsSync(path55.join(cwd, "build.gradle.kts"));
|
|
26354
|
+
const hasGradlew = fs23.existsSync(path55.join(cwd, "gradlew")) || fs23.existsSync(path55.join(cwd, "gradlew.bat"));
|
|
26304
26355
|
return hasBuildFile && (hasGradlew || isCommandAvailable("gradle"));
|
|
26305
26356
|
}
|
|
26306
26357
|
function detectDotnetTest(cwd) {
|
|
@@ -26313,25 +26364,25 @@ function detectDotnetTest(cwd) {
|
|
|
26313
26364
|
}
|
|
26314
26365
|
}
|
|
26315
26366
|
function detectCTest(cwd) {
|
|
26316
|
-
const hasSource = fs23.existsSync(
|
|
26317
|
-
const hasBuildCache = fs23.existsSync(
|
|
26367
|
+
const hasSource = fs23.existsSync(path55.join(cwd, "CMakeLists.txt"));
|
|
26368
|
+
const hasBuildCache = fs23.existsSync(path55.join(cwd, "CMakeCache.txt")) || fs23.existsSync(path55.join(cwd, "build", "CMakeCache.txt"));
|
|
26318
26369
|
return (hasSource || hasBuildCache) && isCommandAvailable("ctest");
|
|
26319
26370
|
}
|
|
26320
26371
|
function detectSwiftTest(cwd) {
|
|
26321
|
-
return fs23.existsSync(
|
|
26372
|
+
return fs23.existsSync(path55.join(cwd, "Package.swift")) && isCommandAvailable("swift");
|
|
26322
26373
|
}
|
|
26323
26374
|
function detectDartTest(cwd) {
|
|
26324
|
-
return fs23.existsSync(
|
|
26375
|
+
return fs23.existsSync(path55.join(cwd, "pubspec.yaml")) && (isCommandAvailable("dart") || isCommandAvailable("flutter"));
|
|
26325
26376
|
}
|
|
26326
26377
|
function detectRSpec(cwd) {
|
|
26327
|
-
const hasRSpecFile = fs23.existsSync(
|
|
26328
|
-
const hasGemfile = fs23.existsSync(
|
|
26329
|
-
const hasSpecDir = fs23.existsSync(
|
|
26378
|
+
const hasRSpecFile = fs23.existsSync(path55.join(cwd, ".rspec"));
|
|
26379
|
+
const hasGemfile = fs23.existsSync(path55.join(cwd, "Gemfile"));
|
|
26380
|
+
const hasSpecDir = fs23.existsSync(path55.join(cwd, "spec"));
|
|
26330
26381
|
const hasRSpec = hasRSpecFile || hasGemfile && hasSpecDir;
|
|
26331
26382
|
return hasRSpec && (isCommandAvailable("bundle") || isCommandAvailable("rspec"));
|
|
26332
26383
|
}
|
|
26333
26384
|
function detectMinitest(cwd) {
|
|
26334
|
-
return fs23.existsSync(
|
|
26385
|
+
return fs23.existsSync(path55.join(cwd, "test")) && (fs23.existsSync(path55.join(cwd, "Gemfile")) || fs23.existsSync(path55.join(cwd, "Rakefile"))) && isCommandAvailable("ruby");
|
|
26335
26386
|
}
|
|
26336
26387
|
var DISPATCH_FRAMEWORK_MAP = {
|
|
26337
26388
|
bun: "bun",
|
|
@@ -26416,7 +26467,7 @@ async function parseTestOutputViaDispatch(framework, output, baseDir) {
|
|
|
26416
26467
|
async function detectTestFramework(cwd) {
|
|
26417
26468
|
const baseDir = cwd;
|
|
26418
26469
|
try {
|
|
26419
|
-
const packageJsonPath =
|
|
26470
|
+
const packageJsonPath = path55.join(baseDir, "package.json");
|
|
26420
26471
|
if (fs23.existsSync(packageJsonPath)) {
|
|
26421
26472
|
const content = fs23.readFileSync(packageJsonPath, "utf-8");
|
|
26422
26473
|
const pkg = JSON.parse(content);
|
|
@@ -26437,16 +26488,16 @@ async function detectTestFramework(cwd) {
|
|
|
26437
26488
|
return "jest";
|
|
26438
26489
|
if (hasDevDependency(devDeps, "mocha", "@types/mocha"))
|
|
26439
26490
|
return "mocha";
|
|
26440
|
-
if (fs23.existsSync(
|
|
26491
|
+
if (fs23.existsSync(path55.join(baseDir, "bun.lockb")) || fs23.existsSync(path55.join(baseDir, "bun.lock"))) {
|
|
26441
26492
|
if (scripts.test?.includes("bun"))
|
|
26442
26493
|
return "bun";
|
|
26443
26494
|
}
|
|
26444
26495
|
}
|
|
26445
26496
|
} catch {}
|
|
26446
26497
|
try {
|
|
26447
|
-
const pyprojectTomlPath =
|
|
26448
|
-
const setupCfgPath =
|
|
26449
|
-
const requirementsTxtPath =
|
|
26498
|
+
const pyprojectTomlPath = path55.join(baseDir, "pyproject.toml");
|
|
26499
|
+
const setupCfgPath = path55.join(baseDir, "setup.cfg");
|
|
26500
|
+
const requirementsTxtPath = path55.join(baseDir, "requirements.txt");
|
|
26450
26501
|
if (fs23.existsSync(pyprojectTomlPath)) {
|
|
26451
26502
|
const content = fs23.readFileSync(pyprojectTomlPath, "utf-8");
|
|
26452
26503
|
if (content.includes("[tool.pytest"))
|
|
@@ -26466,7 +26517,7 @@ async function detectTestFramework(cwd) {
|
|
|
26466
26517
|
}
|
|
26467
26518
|
} catch {}
|
|
26468
26519
|
try {
|
|
26469
|
-
const cargoTomlPath =
|
|
26520
|
+
const cargoTomlPath = path55.join(baseDir, "Cargo.toml");
|
|
26470
26521
|
if (fs23.existsSync(cargoTomlPath)) {
|
|
26471
26522
|
const content = fs23.readFileSync(cargoTomlPath, "utf-8");
|
|
26472
26523
|
if (content.includes("[dev-dependencies]")) {
|
|
@@ -26477,9 +26528,9 @@ async function detectTestFramework(cwd) {
|
|
|
26477
26528
|
}
|
|
26478
26529
|
} catch {}
|
|
26479
26530
|
try {
|
|
26480
|
-
const pesterConfigPath =
|
|
26481
|
-
const pesterConfigJsonPath =
|
|
26482
|
-
const pesterPs1Path =
|
|
26531
|
+
const pesterConfigPath = path55.join(baseDir, "pester.config.ps1");
|
|
26532
|
+
const pesterConfigJsonPath = path55.join(baseDir, "pester.config.ps1.json");
|
|
26533
|
+
const pesterPs1Path = path55.join(baseDir, "tests.ps1");
|
|
26483
26534
|
if (fs23.existsSync(pesterConfigPath) || fs23.existsSync(pesterConfigJsonPath) || fs23.existsSync(pesterPs1Path)) {
|
|
26484
26535
|
return "pester";
|
|
26485
26536
|
}
|
|
@@ -26522,12 +26573,12 @@ function isTestDirectoryPath(normalizedPath) {
|
|
|
26522
26573
|
return normalizedPath.split("/").some((segment) => TEST_DIRECTORY_NAMES.includes(segment));
|
|
26523
26574
|
}
|
|
26524
26575
|
function resolveWorkspacePath(file, workingDir) {
|
|
26525
|
-
return
|
|
26576
|
+
return path55.isAbsolute(file) ? path55.resolve(file) : path55.resolve(workingDir, file);
|
|
26526
26577
|
}
|
|
26527
26578
|
function toWorkspaceOutputPath(absolutePath, workingDir, preferRelative) {
|
|
26528
26579
|
if (!preferRelative)
|
|
26529
26580
|
return absolutePath;
|
|
26530
|
-
return
|
|
26581
|
+
return path55.relative(workingDir, absolutePath);
|
|
26531
26582
|
}
|
|
26532
26583
|
function dedupePush(target, value) {
|
|
26533
26584
|
if (!target.includes(value)) {
|
|
@@ -26564,18 +26615,18 @@ function buildLanguageSpecificTestNames(nameWithoutExt, ext) {
|
|
|
26564
26615
|
}
|
|
26565
26616
|
}
|
|
26566
26617
|
function getRepoLevelCandidateDirectories(workingDir, relativePath, ext) {
|
|
26567
|
-
const relativeDir =
|
|
26618
|
+
const relativeDir = path55.dirname(relativePath);
|
|
26568
26619
|
const nestedRelativeDir = relativeDir === "." ? "" : relativeDir;
|
|
26569
26620
|
const directories = TEST_DIRECTORY_NAMES.flatMap((dirName) => {
|
|
26570
|
-
const rootDir =
|
|
26571
|
-
return nestedRelativeDir ? [rootDir,
|
|
26621
|
+
const rootDir = path55.join(workingDir, dirName);
|
|
26622
|
+
return nestedRelativeDir ? [rootDir, path55.join(rootDir, nestedRelativeDir)] : [rootDir];
|
|
26572
26623
|
});
|
|
26573
26624
|
const normalizedRelativePath = relativePath.replace(/\\/g, "/");
|
|
26574
26625
|
if (ext === ".java" && normalizedRelativePath.startsWith("src/main/java/")) {
|
|
26575
|
-
directories.push(
|
|
26626
|
+
directories.push(path55.join(workingDir, "src/test/java", path55.dirname(normalizedRelativePath.slice("src/main/java/".length))));
|
|
26576
26627
|
}
|
|
26577
26628
|
if ((ext === ".kt" || ext === ".java") && normalizedRelativePath.startsWith("src/main/kotlin/")) {
|
|
26578
|
-
directories.push(
|
|
26629
|
+
directories.push(path55.join(workingDir, "src/test/kotlin", path55.dirname(normalizedRelativePath.slice("src/main/kotlin/".length))));
|
|
26579
26630
|
}
|
|
26580
26631
|
return [...new Set(directories)];
|
|
26581
26632
|
}
|
|
@@ -26603,23 +26654,23 @@ function isLanguageSpecificTestFile(basename11) {
|
|
|
26603
26654
|
}
|
|
26604
26655
|
function isConventionTestFilePath(filePath) {
|
|
26605
26656
|
const normalizedPath = filePath.replace(/\\/g, "/");
|
|
26606
|
-
const basename11 =
|
|
26657
|
+
const basename11 = path55.basename(filePath);
|
|
26607
26658
|
return hasCompoundTestExtension(basename11) || basename11.includes(".spec.") || basename11.includes(".test.") || isLanguageSpecificTestFile(basename11) || isTestDirectoryPath(normalizedPath);
|
|
26608
26659
|
}
|
|
26609
26660
|
function getTestFilesFromConvention(sourceFiles, workingDir = process.cwd()) {
|
|
26610
26661
|
const testFiles = [];
|
|
26611
26662
|
for (const file of sourceFiles) {
|
|
26612
26663
|
const absoluteFile = resolveWorkspacePath(file, workingDir);
|
|
26613
|
-
const relativeFile =
|
|
26614
|
-
const basename11 =
|
|
26615
|
-
const
|
|
26616
|
-
const preferRelativeOutput = !
|
|
26664
|
+
const relativeFile = path55.relative(workingDir, absoluteFile);
|
|
26665
|
+
const basename11 = path55.basename(absoluteFile);
|
|
26666
|
+
const dirname25 = path55.dirname(absoluteFile);
|
|
26667
|
+
const preferRelativeOutput = !path55.isAbsolute(file);
|
|
26617
26668
|
if (isConventionTestFilePath(relativeFile) || isConventionTestFilePath(file)) {
|
|
26618
26669
|
dedupePush(testFiles, toWorkspaceOutputPath(absoluteFile, workingDir, preferRelativeOutput));
|
|
26619
26670
|
continue;
|
|
26620
26671
|
}
|
|
26621
26672
|
const nameWithoutExt = basename11.replace(/\.[^.]+$/, "");
|
|
26622
|
-
const ext =
|
|
26673
|
+
const ext = path55.extname(basename11);
|
|
26623
26674
|
const genericTestNames = [
|
|
26624
26675
|
`${nameWithoutExt}.spec${ext}`,
|
|
26625
26676
|
`${nameWithoutExt}.test${ext}`
|
|
@@ -26628,7 +26679,7 @@ function getTestFilesFromConvention(sourceFiles, workingDir = process.cwd()) {
|
|
|
26628
26679
|
const colocatedCandidates = [
|
|
26629
26680
|
...genericTestNames,
|
|
26630
26681
|
...languageSpecificTestNames
|
|
26631
|
-
].map((candidateName) =>
|
|
26682
|
+
].map((candidateName) => path55.join(dirname25, candidateName));
|
|
26632
26683
|
const testDirectoryNames = [
|
|
26633
26684
|
basename11,
|
|
26634
26685
|
...genericTestNames,
|
|
@@ -26637,8 +26688,8 @@ function getTestFilesFromConvention(sourceFiles, workingDir = process.cwd()) {
|
|
|
26637
26688
|
const repoLevelDirectories = getRepoLevelCandidateDirectories(workingDir, relativeFile, ext);
|
|
26638
26689
|
const possibleTestFiles = [
|
|
26639
26690
|
...colocatedCandidates,
|
|
26640
|
-
...TEST_DIRECTORY_NAMES.flatMap((dirName) => testDirectoryNames.map((candidateName) =>
|
|
26641
|
-
...repoLevelDirectories.flatMap((candidateDir) => testDirectoryNames.map((candidateName) =>
|
|
26691
|
+
...TEST_DIRECTORY_NAMES.flatMap((dirName) => testDirectoryNames.map((candidateName) => path55.join(dirname25, dirName, candidateName))),
|
|
26692
|
+
...repoLevelDirectories.flatMap((candidateDir) => testDirectoryNames.map((candidateName) => path55.join(candidateDir, candidateName)))
|
|
26642
26693
|
];
|
|
26643
26694
|
for (const testFile of possibleTestFiles) {
|
|
26644
26695
|
if (fs23.existsSync(testFile)) {
|
|
@@ -26659,7 +26710,7 @@ async function getTestFilesFromGraph(sourceFiles, workingDir) {
|
|
|
26659
26710
|
try {
|
|
26660
26711
|
const absoluteTestFile = resolveWorkspacePath(testFile, workingDir);
|
|
26661
26712
|
const content = fs23.readFileSync(absoluteTestFile, "utf-8");
|
|
26662
|
-
const testDir =
|
|
26713
|
+
const testDir = path55.dirname(absoluteTestFile);
|
|
26663
26714
|
const importRegex = /import\s+.*?\s+from\s+['"]([^'"]+)['"]/g;
|
|
26664
26715
|
let match;
|
|
26665
26716
|
match = importRegex.exec(content);
|
|
@@ -26667,8 +26718,8 @@ async function getTestFilesFromGraph(sourceFiles, workingDir) {
|
|
|
26667
26718
|
const importPath = match[1];
|
|
26668
26719
|
let resolvedImport;
|
|
26669
26720
|
if (importPath.startsWith(".")) {
|
|
26670
|
-
resolvedImport =
|
|
26671
|
-
const existingExt =
|
|
26721
|
+
resolvedImport = path55.resolve(testDir, importPath);
|
|
26722
|
+
const existingExt = path55.extname(resolvedImport);
|
|
26672
26723
|
if (!existingExt) {
|
|
26673
26724
|
for (const extToTry of [
|
|
26674
26725
|
".ts",
|
|
@@ -26688,12 +26739,12 @@ async function getTestFilesFromGraph(sourceFiles, workingDir) {
|
|
|
26688
26739
|
} else {
|
|
26689
26740
|
continue;
|
|
26690
26741
|
}
|
|
26691
|
-
const importBasename =
|
|
26692
|
-
const importDir =
|
|
26742
|
+
const importBasename = path55.basename(resolvedImport, path55.extname(resolvedImport));
|
|
26743
|
+
const importDir = path55.dirname(resolvedImport);
|
|
26693
26744
|
for (const sourceFile of absoluteSourceFiles) {
|
|
26694
|
-
const sourceDir =
|
|
26695
|
-
const sourceBasename =
|
|
26696
|
-
const isRelatedDir = importDir === sourceDir || importDir ===
|
|
26745
|
+
const sourceDir = path55.dirname(sourceFile);
|
|
26746
|
+
const sourceBasename = path55.basename(sourceFile, path55.extname(sourceFile));
|
|
26747
|
+
const isRelatedDir = importDir === sourceDir || importDir === path55.join(sourceDir, "__tests__") || importDir === path55.join(sourceDir, "tests") || importDir === path55.join(sourceDir, "test") || importDir === path55.join(sourceDir, "spec");
|
|
26697
26748
|
if (resolvedImport === sourceFile || importBasename === sourceBasename && isRelatedDir) {
|
|
26698
26749
|
dedupePush(testFiles, testFile);
|
|
26699
26750
|
break;
|
|
@@ -26706,8 +26757,8 @@ async function getTestFilesFromGraph(sourceFiles, workingDir) {
|
|
|
26706
26757
|
while (match !== null) {
|
|
26707
26758
|
const importPath = match[1];
|
|
26708
26759
|
if (importPath.startsWith(".")) {
|
|
26709
|
-
let resolvedImport =
|
|
26710
|
-
const existingExt =
|
|
26760
|
+
let resolvedImport = path55.resolve(testDir, importPath);
|
|
26761
|
+
const existingExt = path55.extname(resolvedImport);
|
|
26711
26762
|
if (!existingExt) {
|
|
26712
26763
|
for (const extToTry of [
|
|
26713
26764
|
".ts",
|
|
@@ -26724,12 +26775,12 @@ async function getTestFilesFromGraph(sourceFiles, workingDir) {
|
|
|
26724
26775
|
}
|
|
26725
26776
|
}
|
|
26726
26777
|
}
|
|
26727
|
-
const importDir =
|
|
26728
|
-
const importBasename =
|
|
26778
|
+
const importDir = path55.dirname(resolvedImport);
|
|
26779
|
+
const importBasename = path55.basename(resolvedImport, path55.extname(resolvedImport));
|
|
26729
26780
|
for (const sourceFile of absoluteSourceFiles) {
|
|
26730
|
-
const sourceDir =
|
|
26731
|
-
const sourceBasename =
|
|
26732
|
-
const isRelatedDir = importDir === sourceDir || importDir ===
|
|
26781
|
+
const sourceDir = path55.dirname(sourceFile);
|
|
26782
|
+
const sourceBasename = path55.basename(sourceFile, path55.extname(sourceFile));
|
|
26783
|
+
const isRelatedDir = importDir === sourceDir || importDir === path55.join(sourceDir, "__tests__") || importDir === path55.join(sourceDir, "tests") || importDir === path55.join(sourceDir, "test") || importDir === path55.join(sourceDir, "spec");
|
|
26733
26784
|
if (resolvedImport === sourceFile || importBasename === sourceBasename && isRelatedDir) {
|
|
26734
26785
|
dedupePush(testFiles, testFile);
|
|
26735
26786
|
break;
|
|
@@ -26849,8 +26900,8 @@ function buildTestCommand(framework, scope, files, coverage, baseDir, bail) {
|
|
|
26849
26900
|
return ["mvn", "test"];
|
|
26850
26901
|
case "gradle": {
|
|
26851
26902
|
const isWindows = process.platform === "win32";
|
|
26852
|
-
const hasGradlewBat = fs23.existsSync(
|
|
26853
|
-
const hasGradlew = fs23.existsSync(
|
|
26903
|
+
const hasGradlewBat = fs23.existsSync(path55.join(baseDir, "gradlew.bat"));
|
|
26904
|
+
const hasGradlew = fs23.existsSync(path55.join(baseDir, "gradlew"));
|
|
26854
26905
|
if (hasGradlewBat && isWindows)
|
|
26855
26906
|
return ["gradlew.bat", "test"];
|
|
26856
26907
|
if (hasGradlew)
|
|
@@ -26867,7 +26918,7 @@ function buildTestCommand(framework, scope, files, coverage, baseDir, bail) {
|
|
|
26867
26918
|
"cmake-build-release",
|
|
26868
26919
|
"out"
|
|
26869
26920
|
];
|
|
26870
|
-
const actualBuildDir = buildDirCandidates.find((d) => fs23.existsSync(
|
|
26921
|
+
const actualBuildDir = buildDirCandidates.find((d) => fs23.existsSync(path55.join(baseDir, d, "CMakeCache.txt"))) ?? "build";
|
|
26871
26922
|
return ["ctest", "--test-dir", actualBuildDir];
|
|
26872
26923
|
}
|
|
26873
26924
|
case "swift-test":
|
|
@@ -27301,11 +27352,11 @@ async function runTests(framework, scope, files, coverage, timeout_ms, cwd, bail
|
|
|
27301
27352
|
};
|
|
27302
27353
|
}
|
|
27303
27354
|
const startTime = Date.now();
|
|
27304
|
-
const vitestJsonOutputPath = framework === "vitest" ?
|
|
27355
|
+
const vitestJsonOutputPath = framework === "vitest" ? path55.join(cwd, ".swarm", "cache", "test-runner-vitest.json") : undefined;
|
|
27305
27356
|
try {
|
|
27306
27357
|
if (vitestJsonOutputPath) {
|
|
27307
27358
|
try {
|
|
27308
|
-
fs23.mkdirSync(
|
|
27359
|
+
fs23.mkdirSync(path55.dirname(vitestJsonOutputPath), { recursive: true });
|
|
27309
27360
|
if (fs23.existsSync(vitestJsonOutputPath)) {
|
|
27310
27361
|
fs23.unlinkSync(vitestJsonOutputPath);
|
|
27311
27362
|
}
|
|
@@ -27473,10 +27524,10 @@ var SKIP_DIRECTORIES = new Set([
|
|
|
27473
27524
|
]);
|
|
27474
27525
|
function normalizeHistoryTestFile(testFile, workingDir) {
|
|
27475
27526
|
const normalized = testFile.replace(/\\/g, "/");
|
|
27476
|
-
if (!
|
|
27527
|
+
if (!path55.isAbsolute(testFile))
|
|
27477
27528
|
return normalized;
|
|
27478
|
-
const relative7 =
|
|
27479
|
-
if (relative7.startsWith("..") ||
|
|
27529
|
+
const relative7 = path55.relative(workingDir, testFile);
|
|
27530
|
+
if (relative7.startsWith("..") || path55.isAbsolute(relative7)) {
|
|
27480
27531
|
return normalized;
|
|
27481
27532
|
}
|
|
27482
27533
|
return relative7.replace(/\\/g, "/");
|
|
@@ -27715,7 +27766,7 @@ var test_runner = createSwarmTool({
|
|
|
27715
27766
|
const sourceFiles = args.files.filter((file) => {
|
|
27716
27767
|
if (directTestFiles.includes(file))
|
|
27717
27768
|
return false;
|
|
27718
|
-
const ext =
|
|
27769
|
+
const ext = path55.extname(file).toLowerCase();
|
|
27719
27770
|
return SOURCE_EXTENSIONS.has(ext);
|
|
27720
27771
|
});
|
|
27721
27772
|
const invalidFiles = args.files.filter((file) => !directTestFiles.includes(file) && !sourceFiles.includes(file));
|
|
@@ -27761,7 +27812,7 @@ var test_runner = createSwarmTool({
|
|
|
27761
27812
|
if (isConventionTestFilePath(f)) {
|
|
27762
27813
|
return false;
|
|
27763
27814
|
}
|
|
27764
|
-
const ext =
|
|
27815
|
+
const ext = path55.extname(f).toLowerCase();
|
|
27765
27816
|
return SOURCE_EXTENSIONS.has(ext);
|
|
27766
27817
|
});
|
|
27767
27818
|
if (sourceFiles.length === 0) {
|
|
@@ -27811,7 +27862,7 @@ var test_runner = createSwarmTool({
|
|
|
27811
27862
|
if (isConventionTestFilePath(f)) {
|
|
27812
27863
|
return false;
|
|
27813
27864
|
}
|
|
27814
|
-
const ext =
|
|
27865
|
+
const ext = path55.extname(f).toLowerCase();
|
|
27815
27866
|
return SOURCE_EXTENSIONS.has(ext);
|
|
27816
27867
|
});
|
|
27817
27868
|
if (sourceFiles.length === 0) {
|
|
@@ -27863,8 +27914,8 @@ var test_runner = createSwarmTool({
|
|
|
27863
27914
|
}
|
|
27864
27915
|
if (impactResult.impactedTests.length > 0) {
|
|
27865
27916
|
testFiles = impactResult.impactedTests.map((absPath) => {
|
|
27866
|
-
const relativePath =
|
|
27867
|
-
return
|
|
27917
|
+
const relativePath = path55.relative(workingDir, absPath);
|
|
27918
|
+
return path55.isAbsolute(relativePath) ? absPath : relativePath;
|
|
27868
27919
|
});
|
|
27869
27920
|
} else {
|
|
27870
27921
|
graphFallbackReason = "no impacted tests found via impact analysis, falling back to graph";
|
|
@@ -27959,8 +28010,8 @@ function validateDirectoryPath(dir) {
|
|
|
27959
28010
|
if (dir.includes("..")) {
|
|
27960
28011
|
throw new Error("Directory path must not contain path traversal sequences");
|
|
27961
28012
|
}
|
|
27962
|
-
const normalized =
|
|
27963
|
-
const absolutePath =
|
|
28013
|
+
const normalized = path56.normalize(dir);
|
|
28014
|
+
const absolutePath = path56.isAbsolute(normalized) ? normalized : path56.resolve(normalized);
|
|
27964
28015
|
return absolutePath;
|
|
27965
28016
|
}
|
|
27966
28017
|
function validateTimeout(timeoutMs, defaultValue) {
|
|
@@ -27983,7 +28034,7 @@ function validateTimeout(timeoutMs, defaultValue) {
|
|
|
27983
28034
|
}
|
|
27984
28035
|
function getPackageVersion(dir) {
|
|
27985
28036
|
try {
|
|
27986
|
-
const packagePath =
|
|
28037
|
+
const packagePath = path56.join(dir, "package.json");
|
|
27987
28038
|
if (fs24.existsSync(packagePath)) {
|
|
27988
28039
|
const content = fs24.readFileSync(packagePath, "utf-8");
|
|
27989
28040
|
const pkg = JSON.parse(content);
|
|
@@ -27994,7 +28045,7 @@ function getPackageVersion(dir) {
|
|
|
27994
28045
|
}
|
|
27995
28046
|
function getChangelogVersion(dir) {
|
|
27996
28047
|
try {
|
|
27997
|
-
const changelogPath =
|
|
28048
|
+
const changelogPath = path56.join(dir, "CHANGELOG.md");
|
|
27998
28049
|
if (fs24.existsSync(changelogPath)) {
|
|
27999
28050
|
const content = fs24.readFileSync(changelogPath, "utf-8");
|
|
28000
28051
|
const match = content.match(/^##\s*\[?(\d+\.\d+\.\d+)\]?/m);
|
|
@@ -28008,7 +28059,7 @@ function getChangelogVersion(dir) {
|
|
|
28008
28059
|
function getVersionFileVersion(dir) {
|
|
28009
28060
|
const possibleFiles = ["VERSION.txt", "version.txt", "VERSION", "version"];
|
|
28010
28061
|
for (const file of possibleFiles) {
|
|
28011
|
-
const filePath =
|
|
28062
|
+
const filePath = path56.join(dir, file);
|
|
28012
28063
|
if (fs24.existsSync(filePath)) {
|
|
28013
28064
|
try {
|
|
28014
28065
|
const content = fs24.readFileSync(filePath, "utf-8").trim();
|
|
@@ -28746,7 +28797,7 @@ async function handleQaGatesCommand(directory, args, sessionID) {
|
|
|
28746
28797
|
|
|
28747
28798
|
// src/commands/reset.ts
|
|
28748
28799
|
import * as fs25 from "fs";
|
|
28749
|
-
import * as
|
|
28800
|
+
import * as path57 from "path";
|
|
28750
28801
|
|
|
28751
28802
|
// src/background/circuit-breaker.ts
|
|
28752
28803
|
class CircuitBreaker {
|
|
@@ -29465,7 +29516,7 @@ async function handleResetCommand(directory, args) {
|
|
|
29465
29516
|
}
|
|
29466
29517
|
for (const filename of ["SWARM_PLAN.md", "SWARM_PLAN.json"]) {
|
|
29467
29518
|
try {
|
|
29468
|
-
const rootPath =
|
|
29519
|
+
const rootPath = path57.join(directory, filename);
|
|
29469
29520
|
if (fs25.existsSync(rootPath)) {
|
|
29470
29521
|
fs25.unlinkSync(rootPath);
|
|
29471
29522
|
results.push(`- \u2705 Deleted ${filename} (root)`);
|
|
@@ -29503,14 +29554,14 @@ async function handleResetCommand(directory, args) {
|
|
|
29503
29554
|
|
|
29504
29555
|
// src/commands/reset-session.ts
|
|
29505
29556
|
import * as fs28 from "fs";
|
|
29506
|
-
import * as
|
|
29557
|
+
import * as path60 from "path";
|
|
29507
29558
|
|
|
29508
29559
|
// src/prm/trajectory-store.ts
|
|
29509
29560
|
import * as fs26 from "fs/promises";
|
|
29510
|
-
import * as
|
|
29561
|
+
import * as path58 from "path";
|
|
29511
29562
|
var MAX_TRACKED_TRAJECTORY_SESSIONS = 500;
|
|
29512
29563
|
function getTrajectoryPath(sessionId, directory) {
|
|
29513
|
-
const relativePath =
|
|
29564
|
+
const relativePath = path58.join("trajectories", `${sessionId}.jsonl`);
|
|
29514
29565
|
return validateSwarmPath(directory, relativePath);
|
|
29515
29566
|
}
|
|
29516
29567
|
var _inMemoryTrajectoryCache = new Map;
|
|
@@ -29569,7 +29620,7 @@ async function cleanupOldTrajectoryFiles(directory, maxAgeDays = 7) {
|
|
|
29569
29620
|
for (const entry of entries) {
|
|
29570
29621
|
if (!entry.isFile())
|
|
29571
29622
|
continue;
|
|
29572
|
-
const filePath =
|
|
29623
|
+
const filePath = path58.join(dirPath, entry.name);
|
|
29573
29624
|
try {
|
|
29574
29625
|
const stat6 = await fs26.stat(filePath);
|
|
29575
29626
|
if (now - stat6.mtimeMs > cutoffMs) {
|
|
@@ -29996,16 +30047,16 @@ function detectPatterns(trajectory, config, lastProcessedStep = 0) {
|
|
|
29996
30047
|
}
|
|
29997
30048
|
// src/prm/replay.ts
|
|
29998
30049
|
import { promises as fs27 } from "fs";
|
|
29999
|
-
import
|
|
30050
|
+
import path59 from "path";
|
|
30000
30051
|
function isPathSafe(targetPath, basePath) {
|
|
30001
|
-
const resolvedTarget =
|
|
30002
|
-
const resolvedBase =
|
|
30003
|
-
const rel =
|
|
30004
|
-
return !rel.startsWith("..") && !
|
|
30052
|
+
const resolvedTarget = path59.resolve(targetPath);
|
|
30053
|
+
const resolvedBase = path59.resolve(basePath);
|
|
30054
|
+
const rel = path59.relative(resolvedBase, resolvedTarget);
|
|
30055
|
+
return !rel.startsWith("..") && !path59.isAbsolute(rel);
|
|
30005
30056
|
}
|
|
30006
30057
|
function isWithinReplaysDir(targetPath) {
|
|
30007
|
-
const resolved =
|
|
30008
|
-
const parts = resolved.split(
|
|
30058
|
+
const resolved = path59.resolve(targetPath);
|
|
30059
|
+
const parts = resolved.split(path59.sep);
|
|
30009
30060
|
for (let i = 0;i < parts.length - 1; i++) {
|
|
30010
30061
|
if (parts[i] === ".swarm" && parts[i + 1] === "replays") {
|
|
30011
30062
|
return true;
|
|
@@ -30018,10 +30069,10 @@ function sanitizeFilename(input) {
|
|
|
30018
30069
|
}
|
|
30019
30070
|
async function startReplayRecording(sessionID, directory) {
|
|
30020
30071
|
try {
|
|
30021
|
-
const replayDir =
|
|
30072
|
+
const replayDir = path59.join(directory, ".swarm", "replays");
|
|
30022
30073
|
const safeSessionID = sanitizeFilename(sessionID);
|
|
30023
30074
|
const filename = `${safeSessionID}-${Date.now()}.jsonl`;
|
|
30024
|
-
const filepath =
|
|
30075
|
+
const filepath = path59.join(replayDir, filename);
|
|
30025
30076
|
if (!isPathSafe(filepath, replayDir)) {
|
|
30026
30077
|
console.warn(`[replay] Invalid path detected - path traversal attempt blocked for session ${sessionID}`);
|
|
30027
30078
|
return null;
|
|
@@ -30091,8 +30142,9 @@ function errorMessage(err) {
|
|
|
30091
30142
|
}
|
|
30092
30143
|
async function handleResetSessionCommand(directory, _args) {
|
|
30093
30144
|
const results = [];
|
|
30145
|
+
let statePath;
|
|
30094
30146
|
try {
|
|
30095
|
-
|
|
30147
|
+
statePath = validateSwarmPath(directory, "session/state.json");
|
|
30096
30148
|
if (fs28.existsSync(statePath)) {
|
|
30097
30149
|
fs28.unlinkSync(statePath);
|
|
30098
30150
|
results.push("\u2705 Deleted .swarm/session/state.json");
|
|
@@ -30102,9 +30154,9 @@ async function handleResetSessionCommand(directory, _args) {
|
|
|
30102
30154
|
} catch {
|
|
30103
30155
|
results.push("\u274C Failed to delete state.json");
|
|
30104
30156
|
}
|
|
30105
|
-
const sessionDir =
|
|
30157
|
+
const sessionDir = statePath ? path60.dirname(statePath) : undefined;
|
|
30106
30158
|
let sessionFiles = [];
|
|
30107
|
-
if (fs28.existsSync(sessionDir)) {
|
|
30159
|
+
if (sessionDir && fs28.existsSync(sessionDir)) {
|
|
30108
30160
|
try {
|
|
30109
30161
|
sessionFiles = fs28.readdirSync(sessionDir);
|
|
30110
30162
|
} catch (err) {
|
|
@@ -30114,7 +30166,7 @@ async function handleResetSessionCommand(directory, _args) {
|
|
|
30114
30166
|
for (const file of sessionFiles) {
|
|
30115
30167
|
if (file === "state.json")
|
|
30116
30168
|
continue;
|
|
30117
|
-
const filePath =
|
|
30169
|
+
const filePath = path60.join(sessionDir, file);
|
|
30118
30170
|
try {
|
|
30119
30171
|
if (!fs28.existsSync(filePath))
|
|
30120
30172
|
continue;
|
|
@@ -30136,7 +30188,7 @@ async function handleResetSessionCommand(directory, _args) {
|
|
|
30136
30188
|
const chainCount = swarmState.delegationChains.size;
|
|
30137
30189
|
swarmState.delegationChains.clear();
|
|
30138
30190
|
results.push(`\u2705 Cleared ${chainCount} delegation chain(s)`);
|
|
30139
|
-
const worktreesDir =
|
|
30191
|
+
const worktreesDir = path60.resolve(path60.dirname(directory), ".swarm-worktrees");
|
|
30140
30192
|
try {
|
|
30141
30193
|
if (fs28.existsSync(worktreesDir)) {
|
|
30142
30194
|
fs28.rmSync(worktreesDir, { recursive: true, force: true });
|
|
@@ -30169,7 +30221,7 @@ async function handleResetSessionCommand(directory, _args) {
|
|
|
30169
30221
|
}
|
|
30170
30222
|
|
|
30171
30223
|
// src/summaries/manager.ts
|
|
30172
|
-
import * as
|
|
30224
|
+
import * as path61 from "path";
|
|
30173
30225
|
var SUMMARY_ID_REGEX = /^S\d+$/;
|
|
30174
30226
|
function sanitizeSummaryId(id) {
|
|
30175
30227
|
if (!id || id.length === 0) {
|
|
@@ -30193,7 +30245,7 @@ function sanitizeSummaryId(id) {
|
|
|
30193
30245
|
}
|
|
30194
30246
|
async function loadFullOutput(directory, id) {
|
|
30195
30247
|
const sanitizedId = sanitizeSummaryId(id);
|
|
30196
|
-
const relativePath =
|
|
30248
|
+
const relativePath = path61.join("summaries", `${sanitizedId}.json`);
|
|
30197
30249
|
validateSwarmPath(directory, relativePath);
|
|
30198
30250
|
const content = await readSwarmFileAsync(directory, relativePath);
|
|
30199
30251
|
if (content === null) {
|
|
@@ -30246,7 +30298,7 @@ ${error2 instanceof Error ? error2.message : String(error2)}`;
|
|
|
30246
30298
|
|
|
30247
30299
|
// src/commands/rollback.ts
|
|
30248
30300
|
import * as fs29 from "fs";
|
|
30249
|
-
import * as
|
|
30301
|
+
import * as path62 from "path";
|
|
30250
30302
|
function safeParseToolJson(result) {
|
|
30251
30303
|
try {
|
|
30252
30304
|
const jsonStr = typeof result === "string" ? result : result.output;
|
|
@@ -30401,8 +30453,8 @@ async function handleRollbackCommand(directory, args) {
|
|
|
30401
30453
|
if (EXCLUDE_FILES.has(file) || file.startsWith("plan-ledger.archived-")) {
|
|
30402
30454
|
continue;
|
|
30403
30455
|
}
|
|
30404
|
-
const src =
|
|
30405
|
-
const dest =
|
|
30456
|
+
const src = path62.join(checkpointDir, file);
|
|
30457
|
+
const dest = path62.join(swarmDir, file);
|
|
30406
30458
|
try {
|
|
30407
30459
|
fs29.cpSync(src, dest, { recursive: true, force: true });
|
|
30408
30460
|
successes.push(file);
|
|
@@ -30421,7 +30473,7 @@ async function handleRollbackCommand(directory, args) {
|
|
|
30421
30473
|
].join(`
|
|
30422
30474
|
`);
|
|
30423
30475
|
}
|
|
30424
|
-
const existingLedgerPath =
|
|
30476
|
+
const existingLedgerPath = path62.join(swarmDir, "plan-ledger.jsonl");
|
|
30425
30477
|
let ledgerDeletionFailed = false;
|
|
30426
30478
|
if (fs29.existsSync(existingLedgerPath)) {
|
|
30427
30479
|
try {
|
|
@@ -30434,7 +30486,7 @@ async function handleRollbackCommand(directory, args) {
|
|
|
30434
30486
|
}
|
|
30435
30487
|
if (!ledgerDeletionFailed) {
|
|
30436
30488
|
try {
|
|
30437
|
-
const planJsonPath =
|
|
30489
|
+
const planJsonPath = path62.join(swarmDir, "plan.json");
|
|
30438
30490
|
if (fs29.existsSync(planJsonPath)) {
|
|
30439
30491
|
const planRaw = fs29.readFileSync(planJsonPath, "utf-8");
|
|
30440
30492
|
const plan = PlanSchema.parse(JSON.parse(planRaw));
|
|
@@ -30482,8 +30534,8 @@ async function handleRollbackCommand(directory, args) {
|
|
|
30482
30534
|
|
|
30483
30535
|
// src/commands/sdd.ts
|
|
30484
30536
|
import * as fs30 from "fs";
|
|
30485
|
-
import * as
|
|
30486
|
-
var SWARM_SPEC_REL =
|
|
30537
|
+
import * as path63 from "path";
|
|
30538
|
+
var SWARM_SPEC_REL = path63.join(".swarm", "spec.md");
|
|
30487
30539
|
var USAGE9 = `Usage:
|
|
30488
30540
|
/swarm sdd status [--json] [--source <provider>]
|
|
30489
30541
|
/swarm sdd validate [--json] [--change <id>] [--source <provider>] [--feature <id>]
|
|
@@ -30599,7 +30651,7 @@ ${USAGE9}`;
|
|
|
30599
30651
|
}
|
|
30600
30652
|
const speckitDetection = detectSpeckit(directory);
|
|
30601
30653
|
const speckitPresent = speckitDetection.features.length > 0;
|
|
30602
|
-
const nativeSpecExists = fs30.existsSync(
|
|
30654
|
+
const nativeSpecExists = fs30.existsSync(path63.join(directory, SWARM_SPEC_REL));
|
|
30603
30655
|
if (speckitPresent && !parsed.source && !nativeSpecExists) {
|
|
30604
30656
|
const openspecProjection = buildOpenSpecProjectionSync(directory);
|
|
30605
30657
|
if (openspecProjection !== null) {
|
|
@@ -30669,7 +30721,7 @@ ${USAGE9}`;
|
|
|
30669
30721
|
${USAGE9}`;
|
|
30670
30722
|
}
|
|
30671
30723
|
let useSpeckit = false;
|
|
30672
|
-
const nativeSpecExists = fs30.existsSync(
|
|
30724
|
+
const nativeSpecExists = fs30.existsSync(path63.join(directory, SWARM_SPEC_REL));
|
|
30673
30725
|
if (parsed.source === "speckit") {
|
|
30674
30726
|
useSpeckit = true;
|
|
30675
30727
|
} else if (!parsed.source && !nativeSpecExists) {
|
|
@@ -30981,10 +31033,10 @@ Ensure this is a git repository with commit history.`;
|
|
|
30981
31033
|
`);
|
|
30982
31034
|
try {
|
|
30983
31035
|
const fs31 = await import("fs/promises");
|
|
30984
|
-
const
|
|
30985
|
-
const reportPath =
|
|
30986
|
-
await fs31.mkdir(
|
|
30987
|
-
const reportTempPath =
|
|
31036
|
+
const path64 = await import("path");
|
|
31037
|
+
const reportPath = path64.join(directory, ".swarm", "simulate-report.md");
|
|
31038
|
+
await fs31.mkdir(path64.dirname(reportPath), { recursive: true });
|
|
31039
|
+
const reportTempPath = path64.join(path64.dirname(reportPath), `${path64.basename(reportPath)}.tmp.${Date.now()}.${Math.floor(Math.random() * 1e9)}`);
|
|
30988
31040
|
try {
|
|
30989
31041
|
await fs31.writeFile(reportTempPath, report, "utf-8");
|
|
30990
31042
|
renameSync11(reportTempPath, reportPath);
|
|
@@ -31013,7 +31065,7 @@ async function handleSpecifyCommand(_directory, args) {
|
|
|
31013
31065
|
// src/services/status-service.ts
|
|
31014
31066
|
import * as fsSync2 from "fs";
|
|
31015
31067
|
import { readFile as readFile17 } from "fs/promises";
|
|
31016
|
-
import * as
|
|
31068
|
+
import * as path65 from "path";
|
|
31017
31069
|
|
|
31018
31070
|
// src/hooks/extractors.ts
|
|
31019
31071
|
function extractCurrentPhase(planContent) {
|
|
@@ -31058,13 +31110,13 @@ function extractCurrentPhaseFromPlan2(plan) {
|
|
|
31058
31110
|
// src/turbo/lean/state.ts
|
|
31059
31111
|
init_logger();
|
|
31060
31112
|
import * as fs31 from "fs";
|
|
31061
|
-
import * as
|
|
31113
|
+
import * as path64 from "path";
|
|
31062
31114
|
var STATE_FILE3 = "turbo-state.json";
|
|
31063
31115
|
function nowISO3() {
|
|
31064
31116
|
return new Date().toISOString();
|
|
31065
31117
|
}
|
|
31066
31118
|
function ensureSwarmDir2(directory) {
|
|
31067
|
-
const swarmDir =
|
|
31119
|
+
const swarmDir = path64.resolve(directory, ".swarm");
|
|
31068
31120
|
if (!fs31.existsSync(swarmDir)) {
|
|
31069
31121
|
fs31.mkdirSync(swarmDir, { recursive: true });
|
|
31070
31122
|
}
|
|
@@ -31109,7 +31161,7 @@ function markStateUnreadable2(directory, reason) {
|
|
|
31109
31161
|
}
|
|
31110
31162
|
function readPersisted2(directory) {
|
|
31111
31163
|
try {
|
|
31112
|
-
const filePath =
|
|
31164
|
+
const filePath = path64.join(directory, ".swarm", STATE_FILE3);
|
|
31113
31165
|
if (!fs31.existsSync(filePath)) {
|
|
31114
31166
|
const seed = emptyPersisted2();
|
|
31115
31167
|
try {
|
|
@@ -31145,7 +31197,7 @@ function writePersisted2(directory, persisted) {
|
|
|
31145
31197
|
let payload;
|
|
31146
31198
|
try {
|
|
31147
31199
|
ensureSwarmDir2(directory);
|
|
31148
|
-
filePath =
|
|
31200
|
+
filePath = path64.join(directory, ".swarm", STATE_FILE3);
|
|
31149
31201
|
tmpPath = `${filePath}.tmp.${Date.now()}`;
|
|
31150
31202
|
persisted.updatedAt = nowISO3();
|
|
31151
31203
|
payload = `${JSON.stringify(persisted, null, 2)}
|
|
@@ -31263,7 +31315,7 @@ var _internals47 = {
|
|
|
31263
31315
|
};
|
|
31264
31316
|
function readSpecStalenessSnapshot(directory) {
|
|
31265
31317
|
try {
|
|
31266
|
-
const p =
|
|
31318
|
+
const p = path65.join(directory, ".swarm", "spec-staleness.json");
|
|
31267
31319
|
if (!fsSync2.existsSync(p))
|
|
31268
31320
|
return { stale: false };
|
|
31269
31321
|
const raw = fsSync2.readFileSync(p, "utf-8");
|
|
@@ -31795,13 +31847,13 @@ function buildStatusMessage2(session, directory, sessionID) {
|
|
|
31795
31847
|
}
|
|
31796
31848
|
|
|
31797
31849
|
// src/commands/unlink.ts
|
|
31798
|
-
import { existsSync as
|
|
31799
|
-
import * as
|
|
31850
|
+
import { existsSync as existsSync40 } from "fs";
|
|
31851
|
+
import * as path66 from "path";
|
|
31800
31852
|
var DEDUP_THRESHOLD2 = 0.6;
|
|
31801
31853
|
async function copySharedKnowledgeToLocal(linkDir, localSwarmDir) {
|
|
31802
|
-
const sharedPath =
|
|
31803
|
-
const localPath =
|
|
31804
|
-
if (!
|
|
31854
|
+
const sharedPath = path66.join(linkDir, "knowledge.jsonl");
|
|
31855
|
+
const localPath = path66.join(localSwarmDir, "knowledge.jsonl");
|
|
31856
|
+
if (!existsSync40(sharedPath))
|
|
31805
31857
|
return 0;
|
|
31806
31858
|
const sharedEntries = await readKnowledge(sharedPath);
|
|
31807
31859
|
if (sharedEntries.length === 0)
|
|
@@ -31835,7 +31887,7 @@ async function handleUnlinkCommand(directory, args) {
|
|
|
31835
31887
|
let copied = 0;
|
|
31836
31888
|
if (copyBack) {
|
|
31837
31889
|
try {
|
|
31838
|
-
copied = await copySharedKnowledgeToLocal(linkDir,
|
|
31890
|
+
copied = await copySharedKnowledgeToLocal(linkDir, path66.join(directory, ".swarm"));
|
|
31839
31891
|
} catch (error2) {
|
|
31840
31892
|
return `\u274C Failed to copy shared knowledge back to local: ${error2 instanceof Error ? error2.message : String(error2)}`;
|
|
31841
31893
|
}
|
|
@@ -31997,7 +32049,7 @@ function buildDetailedHelp(commandName, entry) {
|
|
|
31997
32049
|
async function handleHelpCommand(ctx) {
|
|
31998
32050
|
const targetCommand = ctx.args.join(" ");
|
|
31999
32051
|
if (!targetCommand) {
|
|
32000
|
-
const { buildHelpText } = await import("./index-
|
|
32052
|
+
const { buildHelpText } = await import("./index-502f6np6.js");
|
|
32001
32053
|
return buildHelpText();
|
|
32002
32054
|
}
|
|
32003
32055
|
const tokens = targetCommand.split(/\s+/);
|
|
@@ -32006,7 +32058,7 @@ async function handleHelpCommand(ctx) {
|
|
|
32006
32058
|
return _internals49.buildDetailedHelp(resolved.key, resolved.entry);
|
|
32007
32059
|
}
|
|
32008
32060
|
const similar = _internals49.findSimilarCommands(targetCommand);
|
|
32009
|
-
const { buildHelpText: fullHelp } = await import("./index-
|
|
32061
|
+
const { buildHelpText: fullHelp } = await import("./index-502f6np6.js");
|
|
32010
32062
|
if (similar.length > 0) {
|
|
32011
32063
|
return `Command '/swarm ${targetCommand}' not found.
|
|
32012
32064
|
|
|
@@ -32139,7 +32191,7 @@ var COMMAND_REGISTRY = {
|
|
|
32139
32191
|
},
|
|
32140
32192
|
"guardrail explain": {
|
|
32141
32193
|
handler: async (ctx) => {
|
|
32142
|
-
const { handleGuardrailExplain } = await import("./guardrail-explain-
|
|
32194
|
+
const { handleGuardrailExplain } = await import("./guardrail-explain-etdrhd4d.js");
|
|
32143
32195
|
return handleGuardrailExplain(ctx.directory, ctx.args);
|
|
32144
32196
|
},
|
|
32145
32197
|
description: "Dry-run: show what the guardrails would do to a command or write target (executes nothing)",
|
|
@@ -32149,7 +32201,7 @@ var COMMAND_REGISTRY = {
|
|
|
32149
32201
|
},
|
|
32150
32202
|
"guardrail-log": {
|
|
32151
32203
|
handler: async (ctx) => {
|
|
32152
|
-
const { handleGuardrailLog } = await import("./guardrail-log-
|
|
32204
|
+
const { handleGuardrailLog } = await import("./guardrail-log-2rns4g6d.js");
|
|
32153
32205
|
return handleGuardrailLog(ctx.directory, ctx.args);
|
|
32154
32206
|
},
|
|
32155
32207
|
description: "Read the guardrail decision log (use --blocks-only for blocks)",
|
|
@@ -32922,24 +32974,24 @@ function validateAliases() {
|
|
|
32922
32974
|
continue;
|
|
32923
32975
|
}
|
|
32924
32976
|
const visited = new Set;
|
|
32925
|
-
const
|
|
32977
|
+
const path67 = [];
|
|
32926
32978
|
let current = target;
|
|
32927
32979
|
while (current) {
|
|
32928
32980
|
const currentEntry = COMMAND_REGISTRY[current];
|
|
32929
32981
|
if (!currentEntry)
|
|
32930
32982
|
break;
|
|
32931
32983
|
if (visited.has(current)) {
|
|
32932
|
-
const cycleStart =
|
|
32984
|
+
const cycleStart = path67.indexOf(current);
|
|
32933
32985
|
const fullChain = [
|
|
32934
32986
|
name,
|
|
32935
|
-
...
|
|
32987
|
+
...path67.slice(0, cycleStart > 0 ? cycleStart : path67.length),
|
|
32936
32988
|
current
|
|
32937
32989
|
].join(" \u2192 ");
|
|
32938
32990
|
errors.push(`Circular alias detected: ${fullChain}`);
|
|
32939
32991
|
break;
|
|
32940
32992
|
}
|
|
32941
32993
|
visited.add(current);
|
|
32942
|
-
|
|
32994
|
+
path67.push(current);
|
|
32943
32995
|
current = currentEntry.aliasOf || "";
|
|
32944
32996
|
}
|
|
32945
32997
|
}
|
|
@@ -34278,7 +34330,7 @@ init_logger();
|
|
|
34278
34330
|
|
|
34279
34331
|
// src/hooks/guardrails/destructive-command.ts
|
|
34280
34332
|
import * as fsSync3 from "fs";
|
|
34281
|
-
import * as
|
|
34333
|
+
import * as path67 from "path";
|
|
34282
34334
|
var DC_MAX_UNWRAP_DEPTH = 5;
|
|
34283
34335
|
var DC_SAFE_TARGETS = new Set([
|
|
34284
34336
|
"node_modules",
|
|
@@ -34442,16 +34494,16 @@ function dcIsRemotePath(p) {
|
|
|
34442
34494
|
return DC_REMOTE_PREFIXES.some((pfx) => p.startsWith(pfx));
|
|
34443
34495
|
}
|
|
34444
34496
|
function dcLstatAncestorWalk(targetPath, cwd) {
|
|
34445
|
-
const normalizedTarget =
|
|
34446
|
-
const normalizedCwd =
|
|
34497
|
+
const normalizedTarget = path67.resolve(cwd, targetPath);
|
|
34498
|
+
const normalizedCwd = path67.resolve(cwd);
|
|
34447
34499
|
const ancestors = [];
|
|
34448
34500
|
let current = normalizedTarget;
|
|
34449
34501
|
while (true) {
|
|
34450
34502
|
ancestors.push(current);
|
|
34451
|
-
const parent =
|
|
34503
|
+
const parent = path67.dirname(current);
|
|
34452
34504
|
if (parent === current)
|
|
34453
34505
|
break;
|
|
34454
|
-
const rel =
|
|
34506
|
+
const rel = path67.relative(normalizedCwd, current);
|
|
34455
34507
|
if (rel === "" || rel.startsWith(".."))
|
|
34456
34508
|
break;
|
|
34457
34509
|
current = parent;
|
|
@@ -34490,14 +34542,14 @@ function dcValidateTargets(targets, cwd) {
|
|
|
34490
34542
|
const lstatBlock = dcLstatAncestorWalk(t, cwd);
|
|
34491
34543
|
if (lstatBlock)
|
|
34492
34544
|
return lstatBlock;
|
|
34493
|
-
const basename12 =
|
|
34545
|
+
const basename12 = path67.basename(t);
|
|
34494
34546
|
if (t === basename12 && DC_SAFE_TARGETS.has(t)) {
|
|
34495
34547
|
continue;
|
|
34496
34548
|
}
|
|
34497
34549
|
if (DC_FS_ROOTS.has(t) || DC_FS_ROOTS.has(t.replace(/\//g, "\\"))) {
|
|
34498
34550
|
return `BLOCKED: Destructive command targets filesystem root "${t}"`;
|
|
34499
34551
|
}
|
|
34500
|
-
if (
|
|
34552
|
+
if (path67.isAbsolute(t) || /^[A-Za-z]:/.test(t)) {
|
|
34501
34553
|
for (const blocked of DC_BLOCKED_ABSOLUTE_PREFIXES) {
|
|
34502
34554
|
if (t.startsWith(blocked)) {
|
|
34503
34555
|
return `BLOCKED: Destructive command targets system path "${t}" which is under protected prefix "${blocked}"`;
|
|
@@ -34512,9 +34564,9 @@ function dcCheckJunctionCreation(segment, cwd) {
|
|
|
34512
34564
|
if (mklinkMatch) {
|
|
34513
34565
|
const target = mklinkMatch[2].trim();
|
|
34514
34566
|
if (!dcHasUnresolvableVars(target)) {
|
|
34515
|
-
const resolved =
|
|
34516
|
-
const rel =
|
|
34517
|
-
if (rel.startsWith("..") ||
|
|
34567
|
+
const resolved = path67.resolve(cwd, target);
|
|
34568
|
+
const rel = path67.relative(cwd, resolved);
|
|
34569
|
+
if (rel.startsWith("..") || path67.isAbsolute(rel)) {
|
|
34518
34570
|
return `BLOCKED: Junction/symlink creation targeting path outside working directory: mklink target "${target}" resolves to "${resolved}" which is outside "${cwd}". Creating junctions to external paths and then deleting them recursively can destroy data.`;
|
|
34519
34571
|
}
|
|
34520
34572
|
}
|
|
@@ -34526,9 +34578,9 @@ function dcCheckJunctionCreation(segment, cwd) {
|
|
|
34526
34578
|
if (newItemMatch) {
|
|
34527
34579
|
const target = newItemMatch[1].trim();
|
|
34528
34580
|
if (!dcHasUnresolvableVars(target)) {
|
|
34529
|
-
const resolved =
|
|
34530
|
-
const rel =
|
|
34531
|
-
if (rel.startsWith("..") ||
|
|
34581
|
+
const resolved = path67.resolve(cwd, target);
|
|
34582
|
+
const rel = path67.relative(cwd, resolved);
|
|
34583
|
+
if (rel.startsWith("..") || path67.isAbsolute(rel)) {
|
|
34532
34584
|
return `BLOCKED: Junction/symlink creation targeting path outside working directory: New-Item target "${target}" resolves to "${resolved}" which is outside "${cwd}". This pattern caused the K2.6 data-loss incident.`;
|
|
34533
34585
|
}
|
|
34534
34586
|
}
|
|
@@ -34538,9 +34590,9 @@ function dcCheckJunctionCreation(segment, cwd) {
|
|
|
34538
34590
|
if (lnMatch) {
|
|
34539
34591
|
const target = lnMatch[1].trim();
|
|
34540
34592
|
if (!dcHasUnresolvableVars(target)) {
|
|
34541
|
-
const resolved =
|
|
34542
|
-
const rel =
|
|
34543
|
-
if (rel.startsWith("..") ||
|
|
34593
|
+
const resolved = path67.resolve(cwd, target);
|
|
34594
|
+
const rel = path67.relative(cwd, resolved);
|
|
34595
|
+
if (rel.startsWith("..") || path67.isAbsolute(rel)) {
|
|
34544
34596
|
return `BLOCKED: Symlink creation targeting path outside working directory: ln -s target "${target}" resolves to "${resolved}" which is outside "${cwd}". Symlinks to external paths combined with recursive deletion can destroy data.`;
|
|
34545
34597
|
}
|
|
34546
34598
|
}
|
|
@@ -34911,10 +34963,10 @@ function classifySwarmCommandChatFallbackUse(resolved) {
|
|
|
34911
34963
|
init_executor();
|
|
34912
34964
|
|
|
34913
34965
|
// src/hooks/shell-write-detect.ts
|
|
34914
|
-
import * as
|
|
34966
|
+
import * as path68 from "path";
|
|
34915
34967
|
import parse from "bash-parser";
|
|
34916
|
-
function buildDedupeKey(category, operator,
|
|
34917
|
-
return `${category}|${operator}|${
|
|
34968
|
+
function buildDedupeKey(category, operator, path69) {
|
|
34969
|
+
return `${category}|${operator}|${path69 ?? "null"}`;
|
|
34918
34970
|
}
|
|
34919
34971
|
var REDIRECT_WRITE_TOKENS = new Set([
|
|
34920
34972
|
"GREAT",
|
|
@@ -34974,16 +35026,16 @@ function detectProcessSubstitutionWrites(command) {
|
|
|
34974
35026
|
results.push(builtinResult);
|
|
34975
35027
|
const appendMatch = stage.match(/^\s*(.*?)\s*>>(\s*)(\S+)\s*$/);
|
|
34976
35028
|
if (appendMatch) {
|
|
34977
|
-
const
|
|
34978
|
-
if (
|
|
34979
|
-
results.push({ category: "redirect", operator: ">>", path:
|
|
35029
|
+
const path69 = appendMatch[3];
|
|
35030
|
+
if (path69 && !isNullDevice(path69)) {
|
|
35031
|
+
results.push({ category: "redirect", operator: ">>", path: path69 });
|
|
34980
35032
|
}
|
|
34981
35033
|
} else {
|
|
34982
35034
|
const writeMatch = stage.match(/^\s*(.*?)\s*>(?!>)(\s*)(\S+)\s*$/);
|
|
34983
35035
|
if (writeMatch) {
|
|
34984
|
-
const
|
|
34985
|
-
if (
|
|
34986
|
-
results.push({ category: "redirect", operator: ">", path:
|
|
35036
|
+
const path69 = writeMatch[3];
|
|
35037
|
+
if (path69 && !isNullDevice(path69)) {
|
|
35038
|
+
results.push({ category: "redirect", operator: ">", path: path69 });
|
|
34987
35039
|
}
|
|
34988
35040
|
}
|
|
34989
35041
|
}
|
|
@@ -35157,8 +35209,8 @@ function extractRedirectPath(fileNode) {
|
|
|
35157
35209
|
return null;
|
|
35158
35210
|
return text;
|
|
35159
35211
|
}
|
|
35160
|
-
function isNullDevice(
|
|
35161
|
-
return
|
|
35212
|
+
function isNullDevice(path69) {
|
|
35213
|
+
return path69 === "/dev/null" || path69 === "/dev/zero" || path69 === "/dev/urandom";
|
|
35162
35214
|
}
|
|
35163
35215
|
function isNumeric(s) {
|
|
35164
35216
|
return /^\d+$/.test(s);
|
|
@@ -35178,12 +35230,12 @@ function detectRedirects(cmd) {
|
|
|
35178
35230
|
if (!opType || !REDIRECT_ALL_WRITE_TOKENS.has(opType))
|
|
35179
35231
|
continue;
|
|
35180
35232
|
const fileNode = r.file;
|
|
35181
|
-
const
|
|
35233
|
+
const path69 = extractRedirectPath(fileNode);
|
|
35182
35234
|
const opLabel = operatorLabel(opNode);
|
|
35183
35235
|
if (REDIRECT_WRITE_TOKENS.has(opType)) {
|
|
35184
|
-
results.push({ category: "redirect", operator: opLabel, path:
|
|
35236
|
+
results.push({ category: "redirect", operator: opLabel, path: path69 });
|
|
35185
35237
|
} else if (REDIRECT_HERE_TOKENS.has(opType)) {
|
|
35186
|
-
results.push({ category: "here_doc", operator: opLabel, path:
|
|
35238
|
+
results.push({ category: "here_doc", operator: opLabel, path: path69 });
|
|
35187
35239
|
}
|
|
35188
35240
|
}
|
|
35189
35241
|
return results;
|
|
@@ -35226,9 +35278,9 @@ function detectBuiltinWrites(cmd) {
|
|
|
35226
35278
|
const suffixWords2 = getSuffixWords(cmd);
|
|
35227
35279
|
for (const word of suffixWords2) {
|
|
35228
35280
|
if (word.startsWith("of=")) {
|
|
35229
|
-
const
|
|
35230
|
-
if (
|
|
35231
|
-
results.push({ category: "builtin_write", operator: "dd of=", path:
|
|
35281
|
+
const path69 = word.slice(3);
|
|
35282
|
+
if (path69 && !isNullDevice(path69)) {
|
|
35283
|
+
results.push({ category: "builtin_write", operator: "dd of=", path: path69 });
|
|
35232
35284
|
}
|
|
35233
35285
|
}
|
|
35234
35286
|
}
|
|
@@ -35347,12 +35399,12 @@ function detectNetworkDownloaders(cmd) {
|
|
|
35347
35399
|
for (let i = 0;i < suffixWords.length; i++) {
|
|
35348
35400
|
const word = suffixWords[i];
|
|
35349
35401
|
if (word === "-o" && i + 1 < suffixWords.length) {
|
|
35350
|
-
const
|
|
35351
|
-
if (!
|
|
35402
|
+
const path69 = suffixWords[i + 1];
|
|
35403
|
+
if (!path69.startsWith("-")) {
|
|
35352
35404
|
results.push({
|
|
35353
35405
|
category: "network_download",
|
|
35354
35406
|
operator: "curl -o",
|
|
35355
|
-
path:
|
|
35407
|
+
path: path69
|
|
35356
35408
|
});
|
|
35357
35409
|
}
|
|
35358
35410
|
} else if (word.startsWith("-o") && word.length > 2) {
|
|
@@ -35367,12 +35419,12 @@ function detectNetworkDownloaders(cmd) {
|
|
|
35367
35419
|
for (let i = 0;i < suffixWords.length; i++) {
|
|
35368
35420
|
const word = suffixWords[i];
|
|
35369
35421
|
if (word === "-O" && i + 1 < suffixWords.length) {
|
|
35370
|
-
const
|
|
35371
|
-
if (!
|
|
35422
|
+
const path69 = suffixWords[i + 1];
|
|
35423
|
+
if (!path69.startsWith("-")) {
|
|
35372
35424
|
results.push({
|
|
35373
35425
|
category: "network_download",
|
|
35374
35426
|
operator: "wget -O",
|
|
35375
|
-
path:
|
|
35427
|
+
path: path69
|
|
35376
35428
|
});
|
|
35377
35429
|
}
|
|
35378
35430
|
} else if (word.startsWith("-O") && word.length > 2) {
|
|
@@ -35481,9 +35533,9 @@ function detectGitDestructive(cmd) {
|
|
|
35481
35533
|
if (first === "checkout") {
|
|
35482
35534
|
const dashDashIdx = suffixWords.indexOf("--");
|
|
35483
35535
|
if (dashDashIdx !== -1 && dashDashIdx + 1 < suffixWords.length) {
|
|
35484
|
-
const
|
|
35485
|
-
const op =
|
|
35486
|
-
results.push({ category: "git_destructive", operator: op, path:
|
|
35536
|
+
const path69 = suffixWords[dashDashIdx + 1];
|
|
35537
|
+
const op = path69 === "." ? "git checkout -- ." : "git checkout --";
|
|
35538
|
+
results.push({ category: "git_destructive", operator: op, path: path69 });
|
|
35487
35539
|
}
|
|
35488
35540
|
} else if (first === "restore") {
|
|
35489
35541
|
const hasHard = suffixWords.some((w) => w === "--hard" || w === "-H" || w.startsWith("-") && w.includes("H"));
|
|
@@ -35603,10 +35655,10 @@ function detectPowerShellWrites(command) {
|
|
|
35603
35655
|
if (redirectMatch) {
|
|
35604
35656
|
const beforeRedirect = redirectMatch[1];
|
|
35605
35657
|
const op = redirectMatch[2];
|
|
35606
|
-
const
|
|
35658
|
+
const path69 = redirectMatch[3];
|
|
35607
35659
|
const fdRedirectPattern = /\d>\s*$|\s\d>&$/;
|
|
35608
35660
|
if (!fdRedirectPattern.test(`${beforeRedirect} ${op}`)) {
|
|
35609
|
-
results.push({ category: "redirect", operator: op, path:
|
|
35661
|
+
results.push({ category: "redirect", operator: op, path: path69 });
|
|
35610
35662
|
}
|
|
35611
35663
|
}
|
|
35612
35664
|
const leadingRedirect = innerCommand.match(/^((?:>){1,2})\s+(\S+)$/);
|
|
@@ -35619,12 +35671,12 @@ function detectPowerShellWrites(command) {
|
|
|
35619
35671
|
}
|
|
35620
35672
|
const iwrMatch = trimmed.match(/^(?:Invoke-WebRequest|curl)\s.*?(?:-OutFile\s+(\S+)|-o\s+(\S+))/i);
|
|
35621
35673
|
if (iwrMatch) {
|
|
35622
|
-
const
|
|
35623
|
-
if (
|
|
35674
|
+
const path69 = iwrMatch[1] || iwrMatch[2];
|
|
35675
|
+
if (path69) {
|
|
35624
35676
|
results.push({
|
|
35625
35677
|
category: "network_download",
|
|
35626
35678
|
operator: "Invoke-WebRequest -OutFile",
|
|
35627
|
-
path:
|
|
35679
|
+
path: path69
|
|
35628
35680
|
});
|
|
35629
35681
|
}
|
|
35630
35682
|
}
|
|
@@ -35636,15 +35688,15 @@ function detectPowerShellWrites(command) {
|
|
|
35636
35688
|
const rest = cmd.slice(cmdletMatch[0].length).trim();
|
|
35637
35689
|
const pathFlagMatch = rest.match(/(?:-Path|-FilePath|-LiteralPath)\s+("([^"]+)"|'([^']+)'|(\S+))/i);
|
|
35638
35690
|
if (pathFlagMatch) {
|
|
35639
|
-
const
|
|
35640
|
-
return { category: "redirect", operator: cmdletName, path:
|
|
35691
|
+
const path69 = pathFlagMatch[2] ?? pathFlagMatch[3] ?? pathFlagMatch[4] ?? "";
|
|
35692
|
+
return { category: "redirect", operator: cmdletName, path: path69 };
|
|
35641
35693
|
}
|
|
35642
35694
|
const tokens = rest.match(/(?:[^\s"-]+|"[^"]*"|'[^']*'|-[^\s]+)/g) ?? [];
|
|
35643
35695
|
for (const token of tokens) {
|
|
35644
35696
|
if (token.startsWith("-"))
|
|
35645
35697
|
continue;
|
|
35646
|
-
const
|
|
35647
|
-
return { category: "redirect", operator: cmdletName, path:
|
|
35698
|
+
const path69 = token.replace(/^["']|["']$/g, "");
|
|
35699
|
+
return { category: "redirect", operator: cmdletName, path: path69 };
|
|
35648
35700
|
}
|
|
35649
35701
|
return null;
|
|
35650
35702
|
}
|
|
@@ -35660,9 +35712,9 @@ function detectPowerShellWrites(command) {
|
|
|
35660
35712
|
for (const token of tokens) {
|
|
35661
35713
|
if (token.startsWith("-"))
|
|
35662
35714
|
continue;
|
|
35663
|
-
const
|
|
35664
|
-
if (
|
|
35665
|
-
results.push({ category: "redirect", operator: cmdletName, path:
|
|
35715
|
+
const path69 = token.replace(/^["']|["']$/g, "");
|
|
35716
|
+
if (path69) {
|
|
35717
|
+
results.push({ category: "redirect", operator: cmdletName, path: path69 });
|
|
35666
35718
|
break;
|
|
35667
35719
|
}
|
|
35668
35720
|
}
|
|
@@ -35675,8 +35727,8 @@ function detectPowerShellWrites(command) {
|
|
|
35675
35727
|
const rest = cmd.slice(opMatch[0].length).trim();
|
|
35676
35728
|
const destFlagMatch = rest.match(/-Destination\s+(\S+|"[^"]+"|'[^']+')/i);
|
|
35677
35729
|
if (destFlagMatch) {
|
|
35678
|
-
const
|
|
35679
|
-
return { category: "builtin_write", operator: cmdletName, path:
|
|
35730
|
+
const path69 = destFlagMatch[1].replace(/^["']|["']$/g, "");
|
|
35731
|
+
return { category: "builtin_write", operator: cmdletName, path: path69 };
|
|
35680
35732
|
}
|
|
35681
35733
|
const tokens = [];
|
|
35682
35734
|
const flagTakingValue = new Set([
|
|
@@ -35715,11 +35767,11 @@ function detectPowerShellWrites(command) {
|
|
|
35715
35767
|
}
|
|
35716
35768
|
}
|
|
35717
35769
|
if (tokens.length >= 2) {
|
|
35718
|
-
const
|
|
35719
|
-
return { category: "builtin_write", operator: cmdletName, path:
|
|
35770
|
+
const path69 = tokens[tokens.length - 1].replace(/^["']|["']$/g, "");
|
|
35771
|
+
return { category: "builtin_write", operator: cmdletName, path: path69 };
|
|
35720
35772
|
} else if (tokens.length === 1) {
|
|
35721
|
-
const
|
|
35722
|
-
return { category: "builtin_write", operator: cmdletName, path:
|
|
35773
|
+
const path69 = tokens[0].replace(/^["']|["']$/g, "");
|
|
35774
|
+
return { category: "builtin_write", operator: cmdletName, path: path69 };
|
|
35723
35775
|
}
|
|
35724
35776
|
return null;
|
|
35725
35777
|
}
|
|
@@ -35733,14 +35785,14 @@ function detectPowerShellWrites(command) {
|
|
|
35733
35785
|
const afterCmdlet = pipeFileOpMatch[2].trim();
|
|
35734
35786
|
const destFlagMatch = afterCmdlet.match(/-Destination\s+(\S+|"[^"]+"|'[^']+')/i);
|
|
35735
35787
|
if (destFlagMatch) {
|
|
35736
|
-
const
|
|
35737
|
-
results.push({ category: "builtin_write", operator: cmdletName, path:
|
|
35788
|
+
const path69 = destFlagMatch[1].replace(/^["']|["']$/g, "");
|
|
35789
|
+
results.push({ category: "builtin_write", operator: cmdletName, path: path69 });
|
|
35738
35790
|
} else {
|
|
35739
35791
|
const tokens = afterCmdlet.match(/(?:[^\s"-]+|"[^"]*"|'[^']*'|-[^\s]+)/g) ?? [];
|
|
35740
35792
|
const nonFlagTokens = tokens.filter((t) => !t.startsWith("-") && t.length > 0);
|
|
35741
35793
|
if (nonFlagTokens.length > 0) {
|
|
35742
|
-
const
|
|
35743
|
-
results.push({ category: "builtin_write", operator: cmdletName, path:
|
|
35794
|
+
const path69 = nonFlagTokens[nonFlagTokens.length - 1].replace(/^["']|["']$/g, "");
|
|
35795
|
+
results.push({ category: "builtin_write", operator: cmdletName, path: path69 });
|
|
35744
35796
|
}
|
|
35745
35797
|
}
|
|
35746
35798
|
}
|
|
@@ -35793,10 +35845,10 @@ function detectCmdWrites(command) {
|
|
|
35793
35845
|
if (redirectMatch) {
|
|
35794
35846
|
const beforeRedirect = redirectMatch[1];
|
|
35795
35847
|
const op = redirectMatch[2];
|
|
35796
|
-
const
|
|
35848
|
+
const path69 = redirectMatch[3];
|
|
35797
35849
|
const fdRedirectPattern = /\d>&?$/;
|
|
35798
35850
|
if (!fdRedirectPattern.test(beforeRedirect)) {
|
|
35799
|
-
results.push({ category: "redirect", operator: op, path:
|
|
35851
|
+
results.push({ category: "redirect", operator: op, path: path69 });
|
|
35800
35852
|
}
|
|
35801
35853
|
}
|
|
35802
35854
|
const leadingRedirect = innerCommand.match(/^((?:>){1,2})\s+(\S+)$/);
|
|
@@ -35854,8 +35906,8 @@ function detectCmdWrites(command) {
|
|
|
35854
35906
|
const rawTokens = rest.match(/(\/?[^\s]+|"[^"]*"|'[^']*')/g) ?? [];
|
|
35855
35907
|
const tokens = rawTokens.filter((t) => !t.startsWith("/"));
|
|
35856
35908
|
if (tokens.length > 0) {
|
|
35857
|
-
const
|
|
35858
|
-
return { category: "builtin_write", operator: "del", path:
|
|
35909
|
+
const path69 = tokens[0].replace(/^["']|["']$/g, "");
|
|
35910
|
+
return { category: "builtin_write", operator: "del", path: path69 };
|
|
35859
35911
|
}
|
|
35860
35912
|
return null;
|
|
35861
35913
|
}
|
|
@@ -35865,16 +35917,16 @@ function detectCmdWrites(command) {
|
|
|
35865
35917
|
}
|
|
35866
35918
|
const rdMatch = innerCommand.match(/^rd\s+(?:\/s\s+|\/q\s+)*(\S+)/i);
|
|
35867
35919
|
if (rdMatch) {
|
|
35868
|
-
const
|
|
35869
|
-
if (!
|
|
35870
|
-
results.push({ category: "builtin_write", operator: "rd", path:
|
|
35920
|
+
const path69 = rdMatch[1].replace(/^["']|["']$/g, "");
|
|
35921
|
+
if (!path69.startsWith("/")) {
|
|
35922
|
+
results.push({ category: "builtin_write", operator: "rd", path: path69 });
|
|
35871
35923
|
}
|
|
35872
35924
|
}
|
|
35873
35925
|
const mdMatch = trimmed.match(/^md\s+(\S+)/i);
|
|
35874
35926
|
if (mdMatch) {
|
|
35875
|
-
const
|
|
35876
|
-
if (!
|
|
35877
|
-
results.push({ category: "builtin_write", operator: "md", path:
|
|
35927
|
+
const path69 = mdMatch[1].replace(/^["']|["']$/g, "");
|
|
35928
|
+
if (!path69.startsWith("/")) {
|
|
35929
|
+
results.push({ category: "builtin_write", operator: "md", path: path69 });
|
|
35878
35930
|
}
|
|
35879
35931
|
}
|
|
35880
35932
|
const echoMatch = trimmed.match(/^echo\s+(\S+.*?)\s+((?:>){1,2})\s*(\S+)$/i);
|
|
@@ -35990,9 +36042,10 @@ function resolvePath(pathText, cwd) {
|
|
|
35990
36042
|
return null;
|
|
35991
36043
|
const isWindowsPath = /^[a-zA-Z]:[\\\\/]/.test(cwd) || cwd.includes("\\");
|
|
35992
36044
|
if (isWindowsPath) {
|
|
35993
|
-
return
|
|
36045
|
+
return path68.win32.resolve(cwd, pathText);
|
|
35994
36046
|
}
|
|
35995
|
-
|
|
36047
|
+
const normalizedRelativeWindowsPath = !path68.posix.isAbsolute(pathText) && !/^[a-zA-Z]:[\\/]/.test(pathText) ? pathText.replace(/\\/g, "/") : pathText;
|
|
36048
|
+
return path68.posix.resolve(cwd, normalizedRelativeWindowsPath);
|
|
35996
36049
|
}
|
|
35997
36050
|
function getCdTarget(cmd) {
|
|
35998
36051
|
if (!cmd || typeof cmd !== "object")
|
|
@@ -36059,7 +36112,7 @@ function collectWritesWithNodes(node, out, cwdStack) {
|
|
|
36059
36112
|
for (const cmd of node.commands) {
|
|
36060
36113
|
const cdTarget = getCdTarget(cmd);
|
|
36061
36114
|
if (cdTarget) {
|
|
36062
|
-
currentStack[0] =
|
|
36115
|
+
currentStack[0] = path68.posix.resolve(currentStack[0] ?? "/", cdTarget);
|
|
36063
36116
|
collectWritesWithNodes(cmd, out, currentStack);
|
|
36064
36117
|
} else {
|
|
36065
36118
|
collectWritesWithNodes(cmd, out, currentStack);
|
|
@@ -36105,7 +36158,7 @@ function collectWritesWithNodes(node, out, cwdStack) {
|
|
|
36105
36158
|
const effectiveCwd = cwdStack[0] ?? "/";
|
|
36106
36159
|
const cdTarget = getCdTarget(node);
|
|
36107
36160
|
if (cdTarget) {
|
|
36108
|
-
cwdStack[0] =
|
|
36161
|
+
cwdStack[0] = path68.posix.resolve(cwdStack[0] ?? "/", cdTarget);
|
|
36109
36162
|
return;
|
|
36110
36163
|
}
|
|
36111
36164
|
const writesFromRedirs = getWritesFromCommandRedirs(node, effectiveCwd);
|
|
@@ -36151,12 +36204,12 @@ function getWritesFromRedirectNode(redirect, _context) {
|
|
|
36151
36204
|
if (!opType || !REDIRECT_ALL_WRITE_TOKENS.has(opType))
|
|
36152
36205
|
return [];
|
|
36153
36206
|
const fileNode = r.file;
|
|
36154
|
-
const
|
|
36207
|
+
const path69 = extractRedirectPath(fileNode);
|
|
36155
36208
|
const opLabel = operatorLabel(opNode);
|
|
36156
36209
|
if (REDIRECT_WRITE_TOKENS.has(opType)) {
|
|
36157
|
-
return [{ category: "redirect", operator: opLabel, path:
|
|
36210
|
+
return [{ category: "redirect", operator: opLabel, path: path69 }];
|
|
36158
36211
|
} else if (REDIRECT_HERE_TOKENS.has(opType)) {
|
|
36159
|
-
return [{ category: "here_doc", operator: opLabel, path:
|
|
36212
|
+
return [{ category: "here_doc", operator: opLabel, path: path69 }];
|
|
36160
36213
|
}
|
|
36161
36214
|
return [];
|
|
36162
36215
|
}
|
|
@@ -36277,6 +36330,15 @@ var ACTIVE_PARALLEL_TASK_STATES = new Set([
|
|
|
36277
36330
|
"tests_run"
|
|
36278
36331
|
]);
|
|
36279
36332
|
|
|
36333
|
+
// src/hooks/realtime-learning-nudge.ts
|
|
36334
|
+
var realtimeLearningNudgeBySession = new Map;
|
|
36335
|
+
function resetRealtimeLearningNudgeState() {
|
|
36336
|
+
realtimeLearningNudgeBySession.clear();
|
|
36337
|
+
}
|
|
36338
|
+
function clearRealtimeLearningNudgeSession(sessionID) {
|
|
36339
|
+
realtimeLearningNudgeBySession.delete(sessionID);
|
|
36340
|
+
}
|
|
36341
|
+
|
|
36280
36342
|
// src/session/worktree-link-suggestion.ts
|
|
36281
36343
|
import { execFile as execFile3 } from "child_process";
|
|
36282
36344
|
var GIT_TIMEOUT_MS2 = 1500;
|
|
@@ -36419,6 +36481,7 @@ function resetSwarmState() {
|
|
|
36419
36481
|
swarmState.environmentProfiles.clear();
|
|
36420
36482
|
clearPendingCoderScope();
|
|
36421
36483
|
resetStandardWorktreeIsolationState();
|
|
36484
|
+
resetRealtimeLearningNudgeState();
|
|
36422
36485
|
_councilDisagreementWarned.clear();
|
|
36423
36486
|
}
|
|
36424
36487
|
function resetSwarmStatePreservingSingletons() {
|
|
@@ -36557,6 +36620,7 @@ function startAgentSession(sessionId, agentName, staleDurationMs = STALE_SESSION
|
|
|
36557
36620
|
}
|
|
36558
36621
|
function endAgentSession(sessionId) {
|
|
36559
36622
|
swarmState.agentSessions.delete(sessionId);
|
|
36623
|
+
clearRealtimeLearningNudgeSession(sessionId);
|
|
36560
36624
|
}
|
|
36561
36625
|
function getAgentSession(sessionId) {
|
|
36562
36626
|
return swarmState.agentSessions.get(sessionId);
|
|
@@ -36899,7 +36963,7 @@ function evidenceToWorkflowState(evidence) {
|
|
|
36899
36963
|
}
|
|
36900
36964
|
async function readPlanFromDisk(directory) {
|
|
36901
36965
|
try {
|
|
36902
|
-
const planPath =
|
|
36966
|
+
const planPath = path69.join(directory, ".swarm", "plan.json");
|
|
36903
36967
|
const content = await fs32.readFile(planPath, "utf-8");
|
|
36904
36968
|
const parsed = JSON.parse(content);
|
|
36905
36969
|
return PlanSchema.parse(parsed);
|
|
@@ -36910,7 +36974,7 @@ async function readPlanFromDisk(directory) {
|
|
|
36910
36974
|
async function readGateEvidenceFromDisk(directory) {
|
|
36911
36975
|
const evidenceMap = new Map;
|
|
36912
36976
|
try {
|
|
36913
|
-
const evidenceDir =
|
|
36977
|
+
const evidenceDir = path69.join(directory, ".swarm", "evidence");
|
|
36914
36978
|
const entries = await fs32.readdir(evidenceDir, { withFileTypes: true });
|
|
36915
36979
|
for (const entry of entries) {
|
|
36916
36980
|
if (!entry.isFile() || !entry.name.endsWith(".json")) {
|
|
@@ -36921,7 +36985,7 @@ async function readGateEvidenceFromDisk(directory) {
|
|
|
36921
36985
|
continue;
|
|
36922
36986
|
}
|
|
36923
36987
|
try {
|
|
36924
|
-
const filePath =
|
|
36988
|
+
const filePath = path69.join(evidenceDir, entry.name);
|
|
36925
36989
|
const content = await fs32.readFile(filePath, "utf-8");
|
|
36926
36990
|
const parsed = JSON.parse(content);
|
|
36927
36991
|
if (parsed && typeof parsed.taskId === "string" && Array.isArray(parsed.required_gates)) {
|
|
@@ -37063,7 +37127,7 @@ function hasActiveEpicMode(sessionID) {
|
|
|
37063
37127
|
async function rehydratePrSubscriptions(sessionID, directory) {
|
|
37064
37128
|
const map = new Map;
|
|
37065
37129
|
try {
|
|
37066
|
-
const { listActive: listActive2 } = await import("./pr-subscriptions-
|
|
37130
|
+
const { listActive: listActive2 } = await import("./pr-subscriptions-0dpn4epk.js");
|
|
37067
37131
|
const records = await listActive2(directory);
|
|
37068
37132
|
for (const record of records) {
|
|
37069
37133
|
if (record.sessionID !== sessionID)
|