opencode-swarm 6.46.0 → 6.47.1
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/index.js +450 -285
- package/dist/commands/close.d.ts +1 -1
- package/dist/commands/sync-plan.d.ts +3 -1
- package/dist/index.js +744 -578
- package/dist/plan/ledger.d.ts +2 -2
- package/dist/plan/manager.d.ts +12 -0
- package/dist/plan/manager.loadplan-validation-guard.test.d.ts +13 -0
- package/dist/plan/migration-revert.regression.test.d.ts +8 -0
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -16046,20 +16046,22 @@ async function readLedgerEvents(directory) {
|
|
|
16046
16046
|
return [];
|
|
16047
16047
|
}
|
|
16048
16048
|
}
|
|
16049
|
-
async function initLedger(directory, planId) {
|
|
16049
|
+
async function initLedger(directory, planId, initialPlanHash) {
|
|
16050
16050
|
const ledgerPath = getLedgerPath(directory);
|
|
16051
16051
|
const planJsonPath = getPlanJsonPath(directory);
|
|
16052
16052
|
if (fs6.existsSync(ledgerPath)) {
|
|
16053
16053
|
throw new Error("Ledger already initialized. Use appendLedgerEvent to add events.");
|
|
16054
16054
|
}
|
|
16055
|
-
let planHashAfter = "";
|
|
16056
|
-
|
|
16057
|
-
|
|
16058
|
-
|
|
16059
|
-
|
|
16060
|
-
|
|
16061
|
-
|
|
16062
|
-
|
|
16055
|
+
let planHashAfter = initialPlanHash ?? "";
|
|
16056
|
+
if (!initialPlanHash) {
|
|
16057
|
+
try {
|
|
16058
|
+
if (fs6.existsSync(planJsonPath)) {
|
|
16059
|
+
const content = fs6.readFileSync(planJsonPath, "utf8");
|
|
16060
|
+
const plan = JSON.parse(content);
|
|
16061
|
+
planHashAfter = computePlanHash(plan);
|
|
16062
|
+
}
|
|
16063
|
+
} catch {}
|
|
16064
|
+
}
|
|
16063
16065
|
const event = {
|
|
16064
16066
|
seq: 1,
|
|
16065
16067
|
timestamp: new Date().toISOString(),
|
|
@@ -16071,7 +16073,7 @@ async function initLedger(directory, planId) {
|
|
|
16071
16073
|
schema_version: LEDGER_SCHEMA_VERSION
|
|
16072
16074
|
};
|
|
16073
16075
|
fs6.mkdirSync(path6.join(directory, ".swarm"), { recursive: true });
|
|
16074
|
-
const tempPath = `${ledgerPath}.tmp`;
|
|
16076
|
+
const tempPath = `${ledgerPath}.tmp.${Date.now()}.${Math.floor(Math.random() * 1e9)}`;
|
|
16075
16077
|
const line = `${JSON.stringify(event)}
|
|
16076
16078
|
`;
|
|
16077
16079
|
fs6.writeFileSync(tempPath, line, "utf8");
|
|
@@ -16098,7 +16100,7 @@ async function appendLedgerEvent(directory, eventInput, options) {
|
|
|
16098
16100
|
schema_version: LEDGER_SCHEMA_VERSION
|
|
16099
16101
|
};
|
|
16100
16102
|
fs6.mkdirSync(path6.join(directory, ".swarm"), { recursive: true });
|
|
16101
|
-
const tempPath = `${ledgerPath}.tmp`;
|
|
16103
|
+
const tempPath = `${ledgerPath}.tmp.${Date.now()}.${Math.floor(Math.random() * 1e9)}`;
|
|
16102
16104
|
const line = `${JSON.stringify(event)}
|
|
16103
16105
|
`;
|
|
16104
16106
|
if (fs6.existsSync(ledgerPath)) {
|
|
@@ -16116,10 +16118,11 @@ async function takeSnapshotEvent(directory, plan, options) {
|
|
|
16116
16118
|
plan,
|
|
16117
16119
|
payload_hash: payloadHash
|
|
16118
16120
|
};
|
|
16121
|
+
const planId = `${plan.swarm}-${plan.title}`.replace(/[^a-zA-Z0-9-_]/g, "_");
|
|
16119
16122
|
return appendLedgerEvent(directory, {
|
|
16120
16123
|
event_type: "snapshot",
|
|
16121
16124
|
source: "takeSnapshotEvent",
|
|
16122
|
-
plan_id:
|
|
16125
|
+
plan_id: planId,
|
|
16123
16126
|
payload: snapshotPayload
|
|
16124
16127
|
}, options);
|
|
16125
16128
|
}
|
|
@@ -16128,13 +16131,15 @@ async function replayFromLedger(directory, options) {
|
|
|
16128
16131
|
if (events.length === 0) {
|
|
16129
16132
|
return null;
|
|
16130
16133
|
}
|
|
16134
|
+
const targetPlanId = events[0].plan_id;
|
|
16135
|
+
const relevantEvents = events.filter((e) => e.plan_id === targetPlanId);
|
|
16131
16136
|
{
|
|
16132
|
-
const snapshotEvents =
|
|
16137
|
+
const snapshotEvents = relevantEvents.filter((e) => e.event_type === "snapshot");
|
|
16133
16138
|
if (snapshotEvents.length > 0) {
|
|
16134
16139
|
const latestSnapshotEvent = snapshotEvents[snapshotEvents.length - 1];
|
|
16135
16140
|
const snapshotPayload = latestSnapshotEvent.payload;
|
|
16136
16141
|
let plan2 = snapshotPayload.plan;
|
|
16137
|
-
const eventsAfterSnapshot =
|
|
16142
|
+
const eventsAfterSnapshot = relevantEvents.filter((e) => e.seq > latestSnapshotEvent.seq);
|
|
16138
16143
|
for (const event of eventsAfterSnapshot) {
|
|
16139
16144
|
plan2 = applyEventToPlan(plan2, event);
|
|
16140
16145
|
if (plan2 === null) {
|
|
@@ -16155,7 +16160,7 @@ async function replayFromLedger(directory, options) {
|
|
|
16155
16160
|
} catch {
|
|
16156
16161
|
return null;
|
|
16157
16162
|
}
|
|
16158
|
-
for (const event of
|
|
16163
|
+
for (const event of relevantEvents) {
|
|
16159
16164
|
if (plan === null) {
|
|
16160
16165
|
return null;
|
|
16161
16166
|
}
|
|
@@ -16169,10 +16174,14 @@ function applyEventToPlan(plan, event) {
|
|
|
16169
16174
|
return plan;
|
|
16170
16175
|
case "task_status_changed":
|
|
16171
16176
|
if (event.task_id && event.to_status) {
|
|
16177
|
+
const parseResult = TaskStatusSchema.safeParse(event.to_status);
|
|
16178
|
+
if (!parseResult.success) {
|
|
16179
|
+
return plan;
|
|
16180
|
+
}
|
|
16172
16181
|
for (const phase of plan.phases) {
|
|
16173
16182
|
const task = phase.tasks.find((t) => t.id === event.task_id);
|
|
16174
16183
|
if (task) {
|
|
16175
|
-
task.status =
|
|
16184
|
+
task.status = parseResult.data;
|
|
16176
16185
|
break;
|
|
16177
16186
|
}
|
|
16178
16187
|
}
|
|
@@ -16206,6 +16215,7 @@ function applyEventToPlan(plan, event) {
|
|
|
16206
16215
|
}
|
|
16207
16216
|
var LEDGER_SCHEMA_VERSION = "1.0.0", LEDGER_FILENAME = "plan-ledger.jsonl", PLAN_JSON_FILENAME = "plan.json", LedgerStaleWriterError;
|
|
16208
16217
|
var init_ledger = __esm(() => {
|
|
16218
|
+
init_plan_schema();
|
|
16209
16219
|
LedgerStaleWriterError = class LedgerStaleWriterError extends Error {
|
|
16210
16220
|
constructor(message) {
|
|
16211
16221
|
super(message);
|
|
@@ -16215,7 +16225,7 @@ var init_ledger = __esm(() => {
|
|
|
16215
16225
|
});
|
|
16216
16226
|
|
|
16217
16227
|
// src/plan/manager.ts
|
|
16218
|
-
import { renameSync as renameSync3, unlinkSync } from "fs";
|
|
16228
|
+
import { existsSync as existsSync4, renameSync as renameSync3, unlinkSync } from "fs";
|
|
16219
16229
|
import * as path7 from "path";
|
|
16220
16230
|
async function loadPlanJsonOnly(directory) {
|
|
16221
16231
|
const planJsonContent = await readSwarmFileAsync(directory, "plan.json");
|
|
@@ -16346,28 +16356,49 @@ async function loadPlan(directory) {
|
|
|
16346
16356
|
const planHash = computePlanHash(validated);
|
|
16347
16357
|
const ledgerHash = await getLatestLedgerHash(directory);
|
|
16348
16358
|
if (ledgerHash !== "" && planHash !== ledgerHash) {
|
|
16349
|
-
|
|
16350
|
-
|
|
16351
|
-
|
|
16352
|
-
|
|
16353
|
-
|
|
16354
|
-
|
|
16355
|
-
|
|
16359
|
+
const currentPlanId = `${validated.swarm}-${validated.title}`.replace(/[^a-zA-Z0-9-_]/g, "_");
|
|
16360
|
+
const ledgerEvents = await readLedgerEvents(directory);
|
|
16361
|
+
const firstEvent = ledgerEvents.length > 0 ? ledgerEvents[0] : null;
|
|
16362
|
+
if (firstEvent && firstEvent.plan_id !== currentPlanId) {
|
|
16363
|
+
warn(`[loadPlan] Ledger identity mismatch (ledger: ${firstEvent.plan_id}, plan: ${currentPlanId}) \u2014 skipping ledger rebuild (migration detected). Use /swarm reset-session to reinitialize the ledger.`);
|
|
16364
|
+
} else {
|
|
16365
|
+
warn("[loadPlan] plan.json is stale (hash mismatch with ledger) \u2014 rebuilding from ledger. If this recurs, run /swarm reset-session to clear stale session state.");
|
|
16366
|
+
try {
|
|
16367
|
+
const rebuilt = await replayFromLedger(directory);
|
|
16368
|
+
if (rebuilt) {
|
|
16369
|
+
await rebuildPlan(directory, rebuilt);
|
|
16370
|
+
warn("[loadPlan] Rebuilt plan from ledger. Checkpoint available at SWARM_PLAN.md if it exists.");
|
|
16371
|
+
return rebuilt;
|
|
16372
|
+
}
|
|
16373
|
+
} catch (replayError) {
|
|
16374
|
+
warn(`[loadPlan] Ledger replay failed during hash-mismatch rebuild: ${replayError instanceof Error ? replayError.message : String(replayError)}. Returning stale plan.json. To recover: check SWARM_PLAN.md for a checkpoint, or run /swarm reset-session.`);
|
|
16356
16375
|
}
|
|
16357
|
-
} catch (replayError) {
|
|
16358
|
-
warn(`[loadPlan] Ledger replay failed during hash-mismatch rebuild: ${replayError instanceof Error ? replayError.message : String(replayError)}. Returning stale plan.json. To recover: check SWARM_PLAN.md for a checkpoint, or run /swarm reset-session.`);
|
|
16359
16376
|
}
|
|
16360
16377
|
}
|
|
16361
16378
|
}
|
|
16362
16379
|
return validated;
|
|
16363
16380
|
} catch (error49) {
|
|
16364
16381
|
warn(`[loadPlan] plan.json validation failed: ${error49 instanceof Error ? error49.message : String(error49)}. Attempting rebuild from ledger. If rebuild fails, check SWARM_PLAN.md for a checkpoint.`);
|
|
16382
|
+
let rawPlanId = null;
|
|
16383
|
+
try {
|
|
16384
|
+
const rawParsed = JSON.parse(planJsonContent);
|
|
16385
|
+
if (typeof rawParsed?.swarm === "string" && typeof rawParsed?.title === "string") {
|
|
16386
|
+
rawPlanId = `${rawParsed.swarm}-${rawParsed.title}`.replace(/[^a-zA-Z0-9-_]/g, "_");
|
|
16387
|
+
}
|
|
16388
|
+
} catch {}
|
|
16365
16389
|
if (await ledgerExists(directory)) {
|
|
16366
|
-
const
|
|
16367
|
-
|
|
16368
|
-
|
|
16369
|
-
|
|
16370
|
-
|
|
16390
|
+
const ledgerEventsForCatch = await readLedgerEvents(directory);
|
|
16391
|
+
const catchFirstEvent = ledgerEventsForCatch.length > 0 ? ledgerEventsForCatch[0] : null;
|
|
16392
|
+
const identityMatch = rawPlanId === null || catchFirstEvent === null || catchFirstEvent.plan_id === rawPlanId;
|
|
16393
|
+
if (!identityMatch) {
|
|
16394
|
+
warn(`[loadPlan] Ledger identity mismatch in validation-failure path (ledger: ${catchFirstEvent?.plan_id}, plan: ${rawPlanId}) \u2014 skipping ledger rebuild (migration detected).`);
|
|
16395
|
+
} else if (catchFirstEvent !== null && rawPlanId !== null) {
|
|
16396
|
+
const rebuilt = await replayFromLedger(directory);
|
|
16397
|
+
if (rebuilt) {
|
|
16398
|
+
await rebuildPlan(directory, rebuilt);
|
|
16399
|
+
warn("[loadPlan] Rebuilt plan from ledger after validation failure. Projection was stale.");
|
|
16400
|
+
return rebuilt;
|
|
16401
|
+
}
|
|
16371
16402
|
}
|
|
16372
16403
|
}
|
|
16373
16404
|
const planMdContent2 = await readSwarmFileAsync(directory, "plan.md");
|
|
@@ -16435,9 +16466,28 @@ async function savePlan(directory, plan, options) {
|
|
|
16435
16466
|
}
|
|
16436
16467
|
}
|
|
16437
16468
|
const currentPlan = await loadPlanJsonOnly(directory);
|
|
16469
|
+
const planId = `${validated.swarm}-${validated.title}`.replace(/[^a-zA-Z0-9-_]/g, "_");
|
|
16470
|
+
const planHashForInit = computePlanHash(validated);
|
|
16438
16471
|
if (!await ledgerExists(directory)) {
|
|
16439
|
-
|
|
16440
|
-
|
|
16472
|
+
await initLedger(directory, planId, planHashForInit);
|
|
16473
|
+
} else {
|
|
16474
|
+
const existingEvents = await readLedgerEvents(directory);
|
|
16475
|
+
if (existingEvents.length > 0 && existingEvents[0].plan_id !== planId) {
|
|
16476
|
+
const swarmDir2 = path7.resolve(directory, ".swarm");
|
|
16477
|
+
const oldLedgerPath = path7.join(swarmDir2, "plan-ledger.jsonl");
|
|
16478
|
+
const archivePath = path7.join(swarmDir2, `plan-ledger.archived-${Date.now()}-${Math.floor(Math.random() * 1e9)}.jsonl`);
|
|
16479
|
+
if (existsSync4(oldLedgerPath)) {
|
|
16480
|
+
renameSync3(oldLedgerPath, archivePath);
|
|
16481
|
+
warn(`[savePlan] Ledger identity mismatch (was "${existingEvents[0].plan_id}", now "${planId}") \u2014 archived old ledger to ${archivePath} and reinitializing.`);
|
|
16482
|
+
}
|
|
16483
|
+
try {
|
|
16484
|
+
await initLedger(directory, planId, planHashForInit);
|
|
16485
|
+
} catch (initErr) {
|
|
16486
|
+
if (!(initErr instanceof Error && initErr.message.includes("already initialized"))) {
|
|
16487
|
+
throw initErr;
|
|
16488
|
+
}
|
|
16489
|
+
}
|
|
16490
|
+
}
|
|
16441
16491
|
}
|
|
16442
16492
|
const currentHash = computeCurrentPlanHash(directory);
|
|
16443
16493
|
const hashAfter = computePlanHash(validated);
|
|
@@ -16530,10 +16580,24 @@ async function rebuildPlan(directory, plan) {
|
|
|
16530
16580
|
const tempPlanPath = path7.join(swarmDir, `plan.json.rebuild.${Date.now()}`);
|
|
16531
16581
|
await Bun.write(tempPlanPath, JSON.stringify(targetPlan, null, 2));
|
|
16532
16582
|
renameSync3(tempPlanPath, planPath);
|
|
16583
|
+
const contentHash = computePlanContentHash(targetPlan);
|
|
16533
16584
|
const markdown = derivePlanMarkdown(targetPlan);
|
|
16585
|
+
const markdownWithHash = `<!-- PLAN_HASH: ${contentHash} -->
|
|
16586
|
+
${markdown}`;
|
|
16534
16587
|
const tempMdPath = path7.join(swarmDir, `plan.md.rebuild.${Date.now()}`);
|
|
16535
|
-
await Bun.write(tempMdPath,
|
|
16588
|
+
await Bun.write(tempMdPath, markdownWithHash);
|
|
16536
16589
|
renameSync3(tempMdPath, mdPath);
|
|
16590
|
+
try {
|
|
16591
|
+
const markerPath = path7.join(swarmDir, ".plan-write-marker");
|
|
16592
|
+
const tasksCount = targetPlan.phases.reduce((sum, phase) => sum + phase.tasks.length, 0);
|
|
16593
|
+
const marker = JSON.stringify({
|
|
16594
|
+
source: "plan_manager",
|
|
16595
|
+
timestamp: new Date().toISOString(),
|
|
16596
|
+
phases_count: targetPlan.phases.length,
|
|
16597
|
+
tasks_count: tasksCount
|
|
16598
|
+
});
|
|
16599
|
+
await Bun.write(markerPath, marker);
|
|
16600
|
+
} catch {}
|
|
16537
16601
|
return targetPlan;
|
|
16538
16602
|
}
|
|
16539
16603
|
async function updateTaskStatus(directory, taskId, status) {
|
|
@@ -17134,11 +17198,11 @@ __export(exports_evidence_summary_integration, {
|
|
|
17134
17198
|
createEvidenceSummaryIntegration: () => createEvidenceSummaryIntegration,
|
|
17135
17199
|
EvidenceSummaryIntegration: () => EvidenceSummaryIntegration
|
|
17136
17200
|
});
|
|
17137
|
-
import { existsSync as
|
|
17201
|
+
import { existsSync as existsSync5, mkdirSync as mkdirSync4, writeFileSync as writeFileSync2 } from "fs";
|
|
17138
17202
|
import * as path8 from "path";
|
|
17139
17203
|
function persistSummary(swarmDir, artifact, filename) {
|
|
17140
17204
|
const swarmPath = path8.join(swarmDir, ".swarm");
|
|
17141
|
-
if (!
|
|
17205
|
+
if (!existsSync5(swarmPath)) {
|
|
17142
17206
|
mkdirSync4(swarmPath, { recursive: true });
|
|
17143
17207
|
}
|
|
17144
17208
|
const artifactPath = path8.join(swarmPath, filename);
|
|
@@ -32356,7 +32420,7 @@ var require_proper_lockfile = __commonJS((exports, module2) => {
|
|
|
32356
32420
|
});
|
|
32357
32421
|
|
|
32358
32422
|
// src/hooks/knowledge-store.ts
|
|
32359
|
-
import { existsSync as
|
|
32423
|
+
import { existsSync as existsSync9 } from "fs";
|
|
32360
32424
|
import { appendFile, mkdir, readFile as readFile2, writeFile } from "fs/promises";
|
|
32361
32425
|
import * as os3 from "os";
|
|
32362
32426
|
import * as path12 from "path";
|
|
@@ -32384,7 +32448,7 @@ function resolveHiveRejectedPath() {
|
|
|
32384
32448
|
return path12.join(path12.dirname(hivePath), "shared-learnings-rejected.jsonl");
|
|
32385
32449
|
}
|
|
32386
32450
|
async function readKnowledge(filePath) {
|
|
32387
|
-
if (!
|
|
32451
|
+
if (!existsSync9(filePath))
|
|
32388
32452
|
return [];
|
|
32389
32453
|
const content = await readFile2(filePath, "utf-8");
|
|
32390
32454
|
const results = [];
|
|
@@ -32533,7 +32597,7 @@ __export(exports_co_change_analyzer, {
|
|
|
32533
32597
|
import * as child_process2 from "child_process";
|
|
32534
32598
|
import { randomUUID as randomUUID2 } from "crypto";
|
|
32535
32599
|
import { readdir as readdir2, readFile as readFile4, stat } from "fs/promises";
|
|
32536
|
-
import * as
|
|
32600
|
+
import * as path20 from "path";
|
|
32537
32601
|
import { promisify } from "util";
|
|
32538
32602
|
function getExecFileAsync() {
|
|
32539
32603
|
return promisify(child_process2.execFile);
|
|
@@ -32635,7 +32699,7 @@ async function scanSourceFiles(dir) {
|
|
|
32635
32699
|
try {
|
|
32636
32700
|
const entries = await readdir2(dir, { withFileTypes: true });
|
|
32637
32701
|
for (const entry of entries) {
|
|
32638
|
-
const fullPath =
|
|
32702
|
+
const fullPath = path20.join(dir, entry.name);
|
|
32639
32703
|
if (entry.isDirectory()) {
|
|
32640
32704
|
if (skipDirs.has(entry.name)) {
|
|
32641
32705
|
continue;
|
|
@@ -32643,7 +32707,7 @@ async function scanSourceFiles(dir) {
|
|
|
32643
32707
|
const subFiles = await scanSourceFiles(fullPath);
|
|
32644
32708
|
results.push(...subFiles);
|
|
32645
32709
|
} else if (entry.isFile()) {
|
|
32646
|
-
const ext =
|
|
32710
|
+
const ext = path20.extname(entry.name);
|
|
32647
32711
|
if ([".ts", ".tsx", ".js", ".jsx", ".mjs"].includes(ext)) {
|
|
32648
32712
|
results.push(fullPath);
|
|
32649
32713
|
}
|
|
@@ -32665,8 +32729,8 @@ async function getStaticEdges(directory) {
|
|
|
32665
32729
|
continue;
|
|
32666
32730
|
}
|
|
32667
32731
|
try {
|
|
32668
|
-
const sourceDir =
|
|
32669
|
-
const resolvedPath =
|
|
32732
|
+
const sourceDir = path20.dirname(sourceFile);
|
|
32733
|
+
const resolvedPath = path20.resolve(sourceDir, importPath);
|
|
32670
32734
|
const extensions = [
|
|
32671
32735
|
"",
|
|
32672
32736
|
".ts",
|
|
@@ -32691,8 +32755,8 @@ async function getStaticEdges(directory) {
|
|
|
32691
32755
|
if (!targetFile) {
|
|
32692
32756
|
continue;
|
|
32693
32757
|
}
|
|
32694
|
-
const relSource =
|
|
32695
|
-
const relTarget =
|
|
32758
|
+
const relSource = path20.relative(directory, sourceFile).replace(/\\/g, "/");
|
|
32759
|
+
const relTarget = path20.relative(directory, targetFile).replace(/\\/g, "/");
|
|
32696
32760
|
const [key] = relSource < relTarget ? [`${relSource}::${relTarget}`, relSource, relTarget] : [`${relTarget}::${relSource}`, relTarget, relSource];
|
|
32697
32761
|
edges.add(key);
|
|
32698
32762
|
} catch {}
|
|
@@ -32704,7 +32768,7 @@ async function getStaticEdges(directory) {
|
|
|
32704
32768
|
function isTestImplementationPair(fileA, fileB) {
|
|
32705
32769
|
const testPatterns = [".test.ts", ".test.js", ".spec.ts", ".spec.js"];
|
|
32706
32770
|
const getBaseName = (filePath) => {
|
|
32707
|
-
const base =
|
|
32771
|
+
const base = path20.basename(filePath);
|
|
32708
32772
|
for (const pattern of testPatterns) {
|
|
32709
32773
|
if (base.endsWith(pattern)) {
|
|
32710
32774
|
return base.slice(0, -pattern.length);
|
|
@@ -32714,16 +32778,16 @@ function isTestImplementationPair(fileA, fileB) {
|
|
|
32714
32778
|
};
|
|
32715
32779
|
const baseA = getBaseName(fileA);
|
|
32716
32780
|
const baseB = getBaseName(fileB);
|
|
32717
|
-
return baseA === baseB && baseA !==
|
|
32781
|
+
return baseA === baseB && baseA !== path20.basename(fileA) && baseA !== path20.basename(fileB);
|
|
32718
32782
|
}
|
|
32719
32783
|
function hasSharedPrefix(fileA, fileB) {
|
|
32720
|
-
const dirA =
|
|
32721
|
-
const dirB =
|
|
32784
|
+
const dirA = path20.dirname(fileA);
|
|
32785
|
+
const dirB = path20.dirname(fileB);
|
|
32722
32786
|
if (dirA !== dirB) {
|
|
32723
32787
|
return false;
|
|
32724
32788
|
}
|
|
32725
|
-
const baseA =
|
|
32726
|
-
const baseB =
|
|
32789
|
+
const baseA = path20.basename(fileA).replace(/\.(ts|js|tsx|jsx|mjs)$/, "");
|
|
32790
|
+
const baseB = path20.basename(fileB).replace(/\.(ts|js|tsx|jsx|mjs)$/, "");
|
|
32727
32791
|
if (baseA.startsWith(baseB) || baseB.startsWith(baseA)) {
|
|
32728
32792
|
return true;
|
|
32729
32793
|
}
|
|
@@ -32777,8 +32841,8 @@ function darkMatterToKnowledgeEntries(pairs, projectName) {
|
|
|
32777
32841
|
const entries = [];
|
|
32778
32842
|
const now = new Date().toISOString();
|
|
32779
32843
|
for (const pair of pairs.slice(0, 10)) {
|
|
32780
|
-
const baseA =
|
|
32781
|
-
const baseB =
|
|
32844
|
+
const baseA = path20.basename(pair.fileA);
|
|
32845
|
+
const baseB = path20.basename(pair.fileB);
|
|
32782
32846
|
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.`;
|
|
32783
32847
|
if (lesson.length > 280) {
|
|
32784
32848
|
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.`;
|
|
@@ -32887,13 +32951,13 @@ __export(exports_config_doctor, {
|
|
|
32887
32951
|
import * as crypto3 from "crypto";
|
|
32888
32952
|
import * as fs13 from "fs";
|
|
32889
32953
|
import * as os5 from "os";
|
|
32890
|
-
import * as
|
|
32954
|
+
import * as path23 from "path";
|
|
32891
32955
|
function getUserConfigDir3() {
|
|
32892
|
-
return process.env.XDG_CONFIG_HOME ||
|
|
32956
|
+
return process.env.XDG_CONFIG_HOME || path23.join(os5.homedir(), ".config");
|
|
32893
32957
|
}
|
|
32894
32958
|
function getConfigPaths(directory) {
|
|
32895
|
-
const userConfigPath =
|
|
32896
|
-
const projectConfigPath =
|
|
32959
|
+
const userConfigPath = path23.join(getUserConfigDir3(), "opencode", "opencode-swarm.json");
|
|
32960
|
+
const projectConfigPath = path23.join(directory, ".opencode", "opencode-swarm.json");
|
|
32897
32961
|
return { userConfigPath, projectConfigPath };
|
|
32898
32962
|
}
|
|
32899
32963
|
function computeHash(content) {
|
|
@@ -32918,9 +32982,9 @@ function isValidConfigPath(configPath, directory) {
|
|
|
32918
32982
|
const normalizedUser = userConfigPath.replace(/\\/g, "/");
|
|
32919
32983
|
const normalizedProject = projectConfigPath.replace(/\\/g, "/");
|
|
32920
32984
|
try {
|
|
32921
|
-
const resolvedConfig =
|
|
32922
|
-
const resolvedUser =
|
|
32923
|
-
const resolvedProject =
|
|
32985
|
+
const resolvedConfig = path23.resolve(configPath);
|
|
32986
|
+
const resolvedUser = path23.resolve(normalizedUser);
|
|
32987
|
+
const resolvedProject = path23.resolve(normalizedProject);
|
|
32924
32988
|
return resolvedConfig === resolvedUser || resolvedConfig === resolvedProject;
|
|
32925
32989
|
} catch {
|
|
32926
32990
|
return false;
|
|
@@ -32960,12 +33024,12 @@ function createConfigBackup(directory) {
|
|
|
32960
33024
|
};
|
|
32961
33025
|
}
|
|
32962
33026
|
function writeBackupArtifact(directory, backup) {
|
|
32963
|
-
const swarmDir =
|
|
33027
|
+
const swarmDir = path23.join(directory, ".swarm");
|
|
32964
33028
|
if (!fs13.existsSync(swarmDir)) {
|
|
32965
33029
|
fs13.mkdirSync(swarmDir, { recursive: true });
|
|
32966
33030
|
}
|
|
32967
33031
|
const backupFilename = `config-backup-${backup.createdAt}.json`;
|
|
32968
|
-
const backupPath =
|
|
33032
|
+
const backupPath = path23.join(swarmDir, backupFilename);
|
|
32969
33033
|
const artifact = {
|
|
32970
33034
|
createdAt: backup.createdAt,
|
|
32971
33035
|
configPath: backup.configPath,
|
|
@@ -32995,7 +33059,7 @@ function restoreFromBackup(backupPath, directory) {
|
|
|
32995
33059
|
return null;
|
|
32996
33060
|
}
|
|
32997
33061
|
const targetPath = artifact.configPath;
|
|
32998
|
-
const targetDir =
|
|
33062
|
+
const targetDir = path23.dirname(targetPath);
|
|
32999
33063
|
if (!fs13.existsSync(targetDir)) {
|
|
33000
33064
|
fs13.mkdirSync(targetDir, { recursive: true });
|
|
33001
33065
|
}
|
|
@@ -33026,9 +33090,9 @@ function readConfigFromFile(directory) {
|
|
|
33026
33090
|
return null;
|
|
33027
33091
|
}
|
|
33028
33092
|
}
|
|
33029
|
-
function validateConfigKey(
|
|
33093
|
+
function validateConfigKey(path24, value, _config) {
|
|
33030
33094
|
const findings = [];
|
|
33031
|
-
switch (
|
|
33095
|
+
switch (path24) {
|
|
33032
33096
|
case "agents": {
|
|
33033
33097
|
if (value !== undefined) {
|
|
33034
33098
|
findings.push({
|
|
@@ -33275,27 +33339,27 @@ function validateConfigKey(path23, value, _config) {
|
|
|
33275
33339
|
}
|
|
33276
33340
|
return findings;
|
|
33277
33341
|
}
|
|
33278
|
-
function walkConfigAndValidate(obj,
|
|
33342
|
+
function walkConfigAndValidate(obj, path24, config3, findings) {
|
|
33279
33343
|
if (obj === null || obj === undefined) {
|
|
33280
33344
|
return;
|
|
33281
33345
|
}
|
|
33282
|
-
if (
|
|
33283
|
-
const keyFindings = validateConfigKey(
|
|
33346
|
+
if (path24 && typeof obj === "object" && !Array.isArray(obj)) {
|
|
33347
|
+
const keyFindings = validateConfigKey(path24, obj, config3);
|
|
33284
33348
|
findings.push(...keyFindings);
|
|
33285
33349
|
}
|
|
33286
33350
|
if (typeof obj !== "object") {
|
|
33287
|
-
const keyFindings = validateConfigKey(
|
|
33351
|
+
const keyFindings = validateConfigKey(path24, obj, config3);
|
|
33288
33352
|
findings.push(...keyFindings);
|
|
33289
33353
|
return;
|
|
33290
33354
|
}
|
|
33291
33355
|
if (Array.isArray(obj)) {
|
|
33292
33356
|
obj.forEach((item, index) => {
|
|
33293
|
-
walkConfigAndValidate(item, `${
|
|
33357
|
+
walkConfigAndValidate(item, `${path24}[${index}]`, config3, findings);
|
|
33294
33358
|
});
|
|
33295
33359
|
return;
|
|
33296
33360
|
}
|
|
33297
33361
|
for (const [key, value] of Object.entries(obj)) {
|
|
33298
|
-
const newPath =
|
|
33362
|
+
const newPath = path24 ? `${path24}.${key}` : key;
|
|
33299
33363
|
walkConfigAndValidate(value, newPath, config3, findings);
|
|
33300
33364
|
}
|
|
33301
33365
|
}
|
|
@@ -33415,7 +33479,7 @@ function applySafeAutoFixes(directory, result) {
|
|
|
33415
33479
|
}
|
|
33416
33480
|
}
|
|
33417
33481
|
if (appliedFixes.length > 0) {
|
|
33418
|
-
const configDir =
|
|
33482
|
+
const configDir = path23.dirname(configPath);
|
|
33419
33483
|
if (!fs13.existsSync(configDir)) {
|
|
33420
33484
|
fs13.mkdirSync(configDir, { recursive: true });
|
|
33421
33485
|
}
|
|
@@ -33425,12 +33489,12 @@ function applySafeAutoFixes(directory, result) {
|
|
|
33425
33489
|
return { appliedFixes, updatedConfigPath };
|
|
33426
33490
|
}
|
|
33427
33491
|
function writeDoctorArtifact(directory, result) {
|
|
33428
|
-
const swarmDir =
|
|
33492
|
+
const swarmDir = path23.join(directory, ".swarm");
|
|
33429
33493
|
if (!fs13.existsSync(swarmDir)) {
|
|
33430
33494
|
fs13.mkdirSync(swarmDir, { recursive: true });
|
|
33431
33495
|
}
|
|
33432
33496
|
const artifactFilename = "config-doctor.json";
|
|
33433
|
-
const artifactPath =
|
|
33497
|
+
const artifactPath = path23.join(swarmDir, artifactFilename);
|
|
33434
33498
|
const guiOutput = {
|
|
33435
33499
|
timestamp: result.timestamp,
|
|
33436
33500
|
summary: result.summary,
|
|
@@ -34484,7 +34548,7 @@ var init_detector = __esm(() => {
|
|
|
34484
34548
|
|
|
34485
34549
|
// src/build/discovery.ts
|
|
34486
34550
|
import * as fs14 from "fs";
|
|
34487
|
-
import * as
|
|
34551
|
+
import * as path25 from "path";
|
|
34488
34552
|
function isCommandAvailable(command) {
|
|
34489
34553
|
if (toolchainCache.has(command)) {
|
|
34490
34554
|
return toolchainCache.get(command);
|
|
@@ -34517,11 +34581,11 @@ function findBuildFiles(workingDir, patterns) {
|
|
|
34517
34581
|
const regex = simpleGlobToRegex(pattern);
|
|
34518
34582
|
const matches = files.filter((f) => regex.test(f));
|
|
34519
34583
|
if (matches.length > 0) {
|
|
34520
|
-
return
|
|
34584
|
+
return path25.join(dir, matches[0]);
|
|
34521
34585
|
}
|
|
34522
34586
|
} catch {}
|
|
34523
34587
|
} else {
|
|
34524
|
-
const filePath =
|
|
34588
|
+
const filePath = path25.join(workingDir, pattern);
|
|
34525
34589
|
if (fs14.existsSync(filePath)) {
|
|
34526
34590
|
return filePath;
|
|
34527
34591
|
}
|
|
@@ -34530,7 +34594,7 @@ function findBuildFiles(workingDir, patterns) {
|
|
|
34530
34594
|
return null;
|
|
34531
34595
|
}
|
|
34532
34596
|
function getRepoDefinedScripts(workingDir, scripts) {
|
|
34533
|
-
const packageJsonPath =
|
|
34597
|
+
const packageJsonPath = path25.join(workingDir, "package.json");
|
|
34534
34598
|
if (!fs14.existsSync(packageJsonPath)) {
|
|
34535
34599
|
return [];
|
|
34536
34600
|
}
|
|
@@ -34571,7 +34635,7 @@ function findAllBuildFiles(workingDir) {
|
|
|
34571
34635
|
const regex = simpleGlobToRegex(pattern);
|
|
34572
34636
|
findFilesRecursive(workingDir, regex, allBuildFiles);
|
|
34573
34637
|
} else {
|
|
34574
|
-
const filePath =
|
|
34638
|
+
const filePath = path25.join(workingDir, pattern);
|
|
34575
34639
|
if (fs14.existsSync(filePath)) {
|
|
34576
34640
|
allBuildFiles.add(filePath);
|
|
34577
34641
|
}
|
|
@@ -34584,7 +34648,7 @@ function findFilesRecursive(dir, regex, results) {
|
|
|
34584
34648
|
try {
|
|
34585
34649
|
const entries = fs14.readdirSync(dir, { withFileTypes: true });
|
|
34586
34650
|
for (const entry of entries) {
|
|
34587
|
-
const fullPath =
|
|
34651
|
+
const fullPath = path25.join(dir, entry.name);
|
|
34588
34652
|
if (entry.isDirectory() && !["node_modules", ".git", "dist", "build", "target"].includes(entry.name)) {
|
|
34589
34653
|
findFilesRecursive(fullPath, regex, results);
|
|
34590
34654
|
} else if (entry.isFile() && regex.test(entry.name)) {
|
|
@@ -34607,7 +34671,7 @@ async function discoverBuildCommandsFromProfiles(workingDir) {
|
|
|
34607
34671
|
let foundCommand = false;
|
|
34608
34672
|
for (const cmd of sortedCommands) {
|
|
34609
34673
|
if (cmd.detectFile) {
|
|
34610
|
-
const detectFilePath =
|
|
34674
|
+
const detectFilePath = path25.join(workingDir, cmd.detectFile);
|
|
34611
34675
|
if (!fs14.existsSync(detectFilePath)) {
|
|
34612
34676
|
continue;
|
|
34613
34677
|
}
|
|
@@ -34864,7 +34928,7 @@ function validateDirectory(directory) {
|
|
|
34864
34928
|
|
|
34865
34929
|
// src/tools/lint.ts
|
|
34866
34930
|
import * as fs15 from "fs";
|
|
34867
|
-
import * as
|
|
34931
|
+
import * as path26 from "path";
|
|
34868
34932
|
function validateArgs(args2) {
|
|
34869
34933
|
if (typeof args2 !== "object" || args2 === null)
|
|
34870
34934
|
return false;
|
|
@@ -34875,9 +34939,9 @@ function validateArgs(args2) {
|
|
|
34875
34939
|
}
|
|
34876
34940
|
function getLinterCommand(linter, mode, projectDir) {
|
|
34877
34941
|
const isWindows = process.platform === "win32";
|
|
34878
|
-
const binDir =
|
|
34879
|
-
const biomeBin = isWindows ?
|
|
34880
|
-
const eslintBin = isWindows ?
|
|
34942
|
+
const binDir = path26.join(projectDir, "node_modules", ".bin");
|
|
34943
|
+
const biomeBin = isWindows ? path26.join(binDir, "biome.EXE") : path26.join(binDir, "biome");
|
|
34944
|
+
const eslintBin = isWindows ? path26.join(binDir, "eslint.cmd") : path26.join(binDir, "eslint");
|
|
34881
34945
|
switch (linter) {
|
|
34882
34946
|
case "biome":
|
|
34883
34947
|
if (mode === "fix") {
|
|
@@ -34893,7 +34957,7 @@ function getLinterCommand(linter, mode, projectDir) {
|
|
|
34893
34957
|
}
|
|
34894
34958
|
function getAdditionalLinterCommand(linter, mode, cwd) {
|
|
34895
34959
|
const gradlewName = process.platform === "win32" ? "gradlew.bat" : "gradlew";
|
|
34896
|
-
const gradlew = fs15.existsSync(
|
|
34960
|
+
const gradlew = fs15.existsSync(path26.join(cwd, gradlewName)) ? path26.join(cwd, gradlewName) : null;
|
|
34897
34961
|
switch (linter) {
|
|
34898
34962
|
case "ruff":
|
|
34899
34963
|
return mode === "fix" ? ["ruff", "check", "--fix", "."] : ["ruff", "check", "."];
|
|
@@ -34927,10 +34991,10 @@ function getAdditionalLinterCommand(linter, mode, cwd) {
|
|
|
34927
34991
|
}
|
|
34928
34992
|
}
|
|
34929
34993
|
function detectRuff(cwd) {
|
|
34930
|
-
if (fs15.existsSync(
|
|
34994
|
+
if (fs15.existsSync(path26.join(cwd, "ruff.toml")))
|
|
34931
34995
|
return isCommandAvailable("ruff");
|
|
34932
34996
|
try {
|
|
34933
|
-
const pyproject =
|
|
34997
|
+
const pyproject = path26.join(cwd, "pyproject.toml");
|
|
34934
34998
|
if (fs15.existsSync(pyproject)) {
|
|
34935
34999
|
const content = fs15.readFileSync(pyproject, "utf-8");
|
|
34936
35000
|
if (content.includes("[tool.ruff]"))
|
|
@@ -34940,19 +35004,19 @@ function detectRuff(cwd) {
|
|
|
34940
35004
|
return false;
|
|
34941
35005
|
}
|
|
34942
35006
|
function detectClippy(cwd) {
|
|
34943
|
-
return fs15.existsSync(
|
|
35007
|
+
return fs15.existsSync(path26.join(cwd, "Cargo.toml")) && isCommandAvailable("cargo");
|
|
34944
35008
|
}
|
|
34945
35009
|
function detectGolangciLint(cwd) {
|
|
34946
|
-
return fs15.existsSync(
|
|
35010
|
+
return fs15.existsSync(path26.join(cwd, "go.mod")) && isCommandAvailable("golangci-lint");
|
|
34947
35011
|
}
|
|
34948
35012
|
function detectCheckstyle(cwd) {
|
|
34949
|
-
const hasMaven = fs15.existsSync(
|
|
34950
|
-
const hasGradle = fs15.existsSync(
|
|
34951
|
-
const hasBinary = hasMaven && isCommandAvailable("mvn") || hasGradle && (fs15.existsSync(
|
|
35013
|
+
const hasMaven = fs15.existsSync(path26.join(cwd, "pom.xml"));
|
|
35014
|
+
const hasGradle = fs15.existsSync(path26.join(cwd, "build.gradle")) || fs15.existsSync(path26.join(cwd, "build.gradle.kts"));
|
|
35015
|
+
const hasBinary = hasMaven && isCommandAvailable("mvn") || hasGradle && (fs15.existsSync(path26.join(cwd, "gradlew")) || isCommandAvailable("gradle"));
|
|
34952
35016
|
return (hasMaven || hasGradle) && hasBinary;
|
|
34953
35017
|
}
|
|
34954
35018
|
function detectKtlint(cwd) {
|
|
34955
|
-
const hasKotlin = fs15.existsSync(
|
|
35019
|
+
const hasKotlin = fs15.existsSync(path26.join(cwd, "build.gradle.kts")) || fs15.existsSync(path26.join(cwd, "build.gradle")) || (() => {
|
|
34956
35020
|
try {
|
|
34957
35021
|
return fs15.readdirSync(cwd).some((f) => f.endsWith(".kt") || f.endsWith(".kts"));
|
|
34958
35022
|
} catch {
|
|
@@ -34971,11 +35035,11 @@ function detectDotnetFormat(cwd) {
|
|
|
34971
35035
|
}
|
|
34972
35036
|
}
|
|
34973
35037
|
function detectCppcheck(cwd) {
|
|
34974
|
-
if (fs15.existsSync(
|
|
35038
|
+
if (fs15.existsSync(path26.join(cwd, "CMakeLists.txt"))) {
|
|
34975
35039
|
return isCommandAvailable("cppcheck");
|
|
34976
35040
|
}
|
|
34977
35041
|
try {
|
|
34978
|
-
const dirsToCheck = [cwd,
|
|
35042
|
+
const dirsToCheck = [cwd, path26.join(cwd, "src")];
|
|
34979
35043
|
const hasCpp = dirsToCheck.some((dir) => {
|
|
34980
35044
|
try {
|
|
34981
35045
|
return fs15.readdirSync(dir).some((f) => /\.(c|cpp|cc|cxx|h|hpp)$/.test(f));
|
|
@@ -34989,13 +35053,13 @@ function detectCppcheck(cwd) {
|
|
|
34989
35053
|
}
|
|
34990
35054
|
}
|
|
34991
35055
|
function detectSwiftlint(cwd) {
|
|
34992
|
-
return fs15.existsSync(
|
|
35056
|
+
return fs15.existsSync(path26.join(cwd, "Package.swift")) && isCommandAvailable("swiftlint");
|
|
34993
35057
|
}
|
|
34994
35058
|
function detectDartAnalyze(cwd) {
|
|
34995
|
-
return fs15.existsSync(
|
|
35059
|
+
return fs15.existsSync(path26.join(cwd, "pubspec.yaml")) && (isCommandAvailable("dart") || isCommandAvailable("flutter"));
|
|
34996
35060
|
}
|
|
34997
35061
|
function detectRubocop(cwd) {
|
|
34998
|
-
return (fs15.existsSync(
|
|
35062
|
+
return (fs15.existsSync(path26.join(cwd, "Gemfile")) || fs15.existsSync(path26.join(cwd, "gems.rb")) || fs15.existsSync(path26.join(cwd, ".rubocop.yml"))) && (isCommandAvailable("rubocop") || isCommandAvailable("bundle"));
|
|
34999
35063
|
}
|
|
35000
35064
|
function detectAdditionalLinter(cwd) {
|
|
35001
35065
|
if (detectRuff(cwd))
|
|
@@ -35023,10 +35087,10 @@ function detectAdditionalLinter(cwd) {
|
|
|
35023
35087
|
function resolveLinterBinPath(linter, projectDir) {
|
|
35024
35088
|
const isWindows = process.platform === "win32";
|
|
35025
35089
|
const binName = linter === "biome" ? isWindows ? "biome.EXE" : "biome" : isWindows ? "eslint.cmd" : "eslint";
|
|
35026
|
-
const localBin =
|
|
35090
|
+
const localBin = path26.join(projectDir, "node_modules", ".bin", binName);
|
|
35027
35091
|
if (fs15.existsSync(localBin))
|
|
35028
35092
|
return localBin;
|
|
35029
|
-
const ancestor = findBinInAncestors(
|
|
35093
|
+
const ancestor = findBinInAncestors(path26.dirname(projectDir), binName);
|
|
35030
35094
|
if (ancestor)
|
|
35031
35095
|
return ancestor;
|
|
35032
35096
|
const fromPath = findBinInEnvPath(binName);
|
|
@@ -35037,10 +35101,10 @@ function resolveLinterBinPath(linter, projectDir) {
|
|
|
35037
35101
|
function findBinInAncestors(startDir, binName) {
|
|
35038
35102
|
let dir = startDir;
|
|
35039
35103
|
while (true) {
|
|
35040
|
-
const candidate =
|
|
35104
|
+
const candidate = path26.join(dir, "node_modules", ".bin", binName);
|
|
35041
35105
|
if (fs15.existsSync(candidate))
|
|
35042
35106
|
return candidate;
|
|
35043
|
-
const parent =
|
|
35107
|
+
const parent = path26.dirname(dir);
|
|
35044
35108
|
if (parent === dir)
|
|
35045
35109
|
break;
|
|
35046
35110
|
dir = parent;
|
|
@@ -35049,10 +35113,10 @@ function findBinInAncestors(startDir, binName) {
|
|
|
35049
35113
|
}
|
|
35050
35114
|
function findBinInEnvPath(binName) {
|
|
35051
35115
|
const searchPath = process.env.PATH ?? "";
|
|
35052
|
-
for (const dir of searchPath.split(
|
|
35116
|
+
for (const dir of searchPath.split(path26.delimiter)) {
|
|
35053
35117
|
if (!dir)
|
|
35054
35118
|
continue;
|
|
35055
|
-
const candidate =
|
|
35119
|
+
const candidate = path26.join(dir, binName);
|
|
35056
35120
|
if (fs15.existsSync(candidate))
|
|
35057
35121
|
return candidate;
|
|
35058
35122
|
}
|
|
@@ -35065,13 +35129,13 @@ async function detectAvailableLinter(directory) {
|
|
|
35065
35129
|
return null;
|
|
35066
35130
|
const projectDir = directory;
|
|
35067
35131
|
const isWindows = process.platform === "win32";
|
|
35068
|
-
const biomeBin = isWindows ?
|
|
35069
|
-
const eslintBin = isWindows ?
|
|
35132
|
+
const biomeBin = isWindows ? path26.join(projectDir, "node_modules", ".bin", "biome.EXE") : path26.join(projectDir, "node_modules", ".bin", "biome");
|
|
35133
|
+
const eslintBin = isWindows ? path26.join(projectDir, "node_modules", ".bin", "eslint.cmd") : path26.join(projectDir, "node_modules", ".bin", "eslint");
|
|
35070
35134
|
const localResult = await _detectAvailableLinter(projectDir, biomeBin, eslintBin);
|
|
35071
35135
|
if (localResult)
|
|
35072
35136
|
return localResult;
|
|
35073
|
-
const biomeAncestor = findBinInAncestors(
|
|
35074
|
-
const eslintAncestor = findBinInAncestors(
|
|
35137
|
+
const biomeAncestor = findBinInAncestors(path26.dirname(projectDir), isWindows ? "biome.EXE" : "biome");
|
|
35138
|
+
const eslintAncestor = findBinInAncestors(path26.dirname(projectDir), isWindows ? "eslint.cmd" : "eslint");
|
|
35075
35139
|
if (biomeAncestor || eslintAncestor) {
|
|
35076
35140
|
return _detectAvailableLinter(projectDir, biomeAncestor ?? biomeBin, eslintAncestor ?? eslintBin);
|
|
35077
35141
|
}
|
|
@@ -35286,7 +35350,7 @@ For Rust: rustup component add clippy`
|
|
|
35286
35350
|
|
|
35287
35351
|
// src/tools/secretscan.ts
|
|
35288
35352
|
import * as fs16 from "fs";
|
|
35289
|
-
import * as
|
|
35353
|
+
import * as path27 from "path";
|
|
35290
35354
|
function calculateShannonEntropy(str) {
|
|
35291
35355
|
if (str.length === 0)
|
|
35292
35356
|
return 0;
|
|
@@ -35334,7 +35398,7 @@ function isGlobOrPathPattern(pattern) {
|
|
|
35334
35398
|
return pattern.includes("/") || pattern.includes("\\") || /[*?[\]{}]/.test(pattern);
|
|
35335
35399
|
}
|
|
35336
35400
|
function loadSecretScanIgnore(scanDir) {
|
|
35337
|
-
const ignorePath =
|
|
35401
|
+
const ignorePath = path27.join(scanDir, ".secretscanignore");
|
|
35338
35402
|
try {
|
|
35339
35403
|
if (!fs16.existsSync(ignorePath))
|
|
35340
35404
|
return [];
|
|
@@ -35357,7 +35421,7 @@ function isExcluded(entry, relPath, exactNames, globPatterns) {
|
|
|
35357
35421
|
if (exactNames.has(entry))
|
|
35358
35422
|
return true;
|
|
35359
35423
|
for (const pattern of globPatterns) {
|
|
35360
|
-
if (
|
|
35424
|
+
if (path27.matchesGlob(relPath, pattern))
|
|
35361
35425
|
return true;
|
|
35362
35426
|
}
|
|
35363
35427
|
return false;
|
|
@@ -35378,7 +35442,7 @@ function validateDirectoryInput(dir) {
|
|
|
35378
35442
|
return null;
|
|
35379
35443
|
}
|
|
35380
35444
|
function isBinaryFile(filePath, buffer) {
|
|
35381
|
-
const ext =
|
|
35445
|
+
const ext = path27.extname(filePath).toLowerCase();
|
|
35382
35446
|
if (DEFAULT_EXCLUDE_EXTENSIONS.has(ext)) {
|
|
35383
35447
|
return true;
|
|
35384
35448
|
}
|
|
@@ -35514,9 +35578,9 @@ function isSymlinkLoop(realPath, visited) {
|
|
|
35514
35578
|
return false;
|
|
35515
35579
|
}
|
|
35516
35580
|
function isPathWithinScope(realPath, scanDir) {
|
|
35517
|
-
const resolvedScanDir =
|
|
35518
|
-
const resolvedRealPath =
|
|
35519
|
-
return resolvedRealPath === resolvedScanDir || resolvedRealPath.startsWith(resolvedScanDir +
|
|
35581
|
+
const resolvedScanDir = path27.resolve(scanDir);
|
|
35582
|
+
const resolvedRealPath = path27.resolve(realPath);
|
|
35583
|
+
return resolvedRealPath === resolvedScanDir || resolvedRealPath.startsWith(resolvedScanDir + path27.sep) || resolvedRealPath.startsWith(`${resolvedScanDir}/`) || resolvedRealPath.startsWith(`${resolvedScanDir}\\`);
|
|
35520
35584
|
}
|
|
35521
35585
|
function findScannableFiles(dir, excludeExact, excludeGlobs, scanDir, visited, stats = {
|
|
35522
35586
|
skippedDirs: 0,
|
|
@@ -35542,8 +35606,8 @@ function findScannableFiles(dir, excludeExact, excludeGlobs, scanDir, visited, s
|
|
|
35542
35606
|
return a.localeCompare(b);
|
|
35543
35607
|
});
|
|
35544
35608
|
for (const entry of entries) {
|
|
35545
|
-
const fullPath =
|
|
35546
|
-
const relPath =
|
|
35609
|
+
const fullPath = path27.join(dir, entry);
|
|
35610
|
+
const relPath = path27.relative(scanDir, fullPath).replace(/\\/g, "/");
|
|
35547
35611
|
if (isExcluded(entry, relPath, excludeExact, excludeGlobs)) {
|
|
35548
35612
|
stats.skippedDirs++;
|
|
35549
35613
|
continue;
|
|
@@ -35578,7 +35642,7 @@ function findScannableFiles(dir, excludeExact, excludeGlobs, scanDir, visited, s
|
|
|
35578
35642
|
const subFiles = findScannableFiles(fullPath, excludeExact, excludeGlobs, scanDir, visited, stats);
|
|
35579
35643
|
files.push(...subFiles);
|
|
35580
35644
|
} else if (lstat.isFile()) {
|
|
35581
|
-
const ext =
|
|
35645
|
+
const ext = path27.extname(fullPath).toLowerCase();
|
|
35582
35646
|
if (!DEFAULT_EXCLUDE_EXTENSIONS.has(ext)) {
|
|
35583
35647
|
files.push(fullPath);
|
|
35584
35648
|
} else {
|
|
@@ -35836,7 +35900,7 @@ var init_secretscan = __esm(() => {
|
|
|
35836
35900
|
}
|
|
35837
35901
|
}
|
|
35838
35902
|
try {
|
|
35839
|
-
const _scanDirRaw =
|
|
35903
|
+
const _scanDirRaw = path27.resolve(directory);
|
|
35840
35904
|
const scanDir = (() => {
|
|
35841
35905
|
try {
|
|
35842
35906
|
return fs16.realpathSync(_scanDirRaw);
|
|
@@ -35979,7 +36043,7 @@ var init_secretscan = __esm(() => {
|
|
|
35979
36043
|
|
|
35980
36044
|
// src/tools/resolve-working-directory.ts
|
|
35981
36045
|
import * as fs17 from "fs";
|
|
35982
|
-
import * as
|
|
36046
|
+
import * as path28 from "path";
|
|
35983
36047
|
function resolveWorkingDirectory(workingDirectory, fallbackDirectory) {
|
|
35984
36048
|
if (workingDirectory == null || workingDirectory === "") {
|
|
35985
36049
|
return { success: true, directory: fallbackDirectory };
|
|
@@ -35999,15 +36063,15 @@ function resolveWorkingDirectory(workingDirectory, fallbackDirectory) {
|
|
|
35999
36063
|
};
|
|
36000
36064
|
}
|
|
36001
36065
|
}
|
|
36002
|
-
const normalizedDir =
|
|
36003
|
-
const pathParts = normalizedDir.split(
|
|
36066
|
+
const normalizedDir = path28.normalize(workingDirectory);
|
|
36067
|
+
const pathParts = normalizedDir.split(path28.sep);
|
|
36004
36068
|
if (pathParts.includes("..")) {
|
|
36005
36069
|
return {
|
|
36006
36070
|
success: false,
|
|
36007
36071
|
message: "Invalid working_directory: path traversal sequences (..) are not allowed"
|
|
36008
36072
|
};
|
|
36009
36073
|
}
|
|
36010
|
-
const resolvedDir =
|
|
36074
|
+
const resolvedDir = path28.resolve(normalizedDir);
|
|
36011
36075
|
try {
|
|
36012
36076
|
const realPath = fs17.realpathSync(resolvedDir);
|
|
36013
36077
|
return { success: true, directory: realPath };
|
|
@@ -36022,7 +36086,7 @@ var init_resolve_working_directory = () => {};
|
|
|
36022
36086
|
|
|
36023
36087
|
// src/tools/test-runner.ts
|
|
36024
36088
|
import * as fs18 from "fs";
|
|
36025
|
-
import * as
|
|
36089
|
+
import * as path29 from "path";
|
|
36026
36090
|
function isAbsolutePath(str) {
|
|
36027
36091
|
if (str.startsWith("/"))
|
|
36028
36092
|
return true;
|
|
@@ -36087,14 +36151,14 @@ function hasDevDependency(devDeps, ...patterns) {
|
|
|
36087
36151
|
return hasPackageJsonDependency(devDeps, ...patterns);
|
|
36088
36152
|
}
|
|
36089
36153
|
function detectGoTest(cwd) {
|
|
36090
|
-
return fs18.existsSync(
|
|
36154
|
+
return fs18.existsSync(path29.join(cwd, "go.mod")) && isCommandAvailable("go");
|
|
36091
36155
|
}
|
|
36092
36156
|
function detectJavaMaven(cwd) {
|
|
36093
|
-
return fs18.existsSync(
|
|
36157
|
+
return fs18.existsSync(path29.join(cwd, "pom.xml")) && isCommandAvailable("mvn");
|
|
36094
36158
|
}
|
|
36095
36159
|
function detectGradle(cwd) {
|
|
36096
|
-
const hasBuildFile = fs18.existsSync(
|
|
36097
|
-
const hasGradlew = fs18.existsSync(
|
|
36160
|
+
const hasBuildFile = fs18.existsSync(path29.join(cwd, "build.gradle")) || fs18.existsSync(path29.join(cwd, "build.gradle.kts"));
|
|
36161
|
+
const hasGradlew = fs18.existsSync(path29.join(cwd, "gradlew")) || fs18.existsSync(path29.join(cwd, "gradlew.bat"));
|
|
36098
36162
|
return hasBuildFile && (hasGradlew || isCommandAvailable("gradle"));
|
|
36099
36163
|
}
|
|
36100
36164
|
function detectDotnetTest(cwd) {
|
|
@@ -36107,30 +36171,30 @@ function detectDotnetTest(cwd) {
|
|
|
36107
36171
|
}
|
|
36108
36172
|
}
|
|
36109
36173
|
function detectCTest(cwd) {
|
|
36110
|
-
const hasSource = fs18.existsSync(
|
|
36111
|
-
const hasBuildCache = fs18.existsSync(
|
|
36174
|
+
const hasSource = fs18.existsSync(path29.join(cwd, "CMakeLists.txt"));
|
|
36175
|
+
const hasBuildCache = fs18.existsSync(path29.join(cwd, "CMakeCache.txt")) || fs18.existsSync(path29.join(cwd, "build", "CMakeCache.txt"));
|
|
36112
36176
|
return (hasSource || hasBuildCache) && isCommandAvailable("ctest");
|
|
36113
36177
|
}
|
|
36114
36178
|
function detectSwiftTest(cwd) {
|
|
36115
|
-
return fs18.existsSync(
|
|
36179
|
+
return fs18.existsSync(path29.join(cwd, "Package.swift")) && isCommandAvailable("swift");
|
|
36116
36180
|
}
|
|
36117
36181
|
function detectDartTest(cwd) {
|
|
36118
|
-
return fs18.existsSync(
|
|
36182
|
+
return fs18.existsSync(path29.join(cwd, "pubspec.yaml")) && (isCommandAvailable("dart") || isCommandAvailable("flutter"));
|
|
36119
36183
|
}
|
|
36120
36184
|
function detectRSpec(cwd) {
|
|
36121
|
-
const hasRSpecFile = fs18.existsSync(
|
|
36122
|
-
const hasGemfile = fs18.existsSync(
|
|
36123
|
-
const hasSpecDir = fs18.existsSync(
|
|
36185
|
+
const hasRSpecFile = fs18.existsSync(path29.join(cwd, ".rspec"));
|
|
36186
|
+
const hasGemfile = fs18.existsSync(path29.join(cwd, "Gemfile"));
|
|
36187
|
+
const hasSpecDir = fs18.existsSync(path29.join(cwd, "spec"));
|
|
36124
36188
|
const hasRSpec = hasRSpecFile || hasGemfile && hasSpecDir;
|
|
36125
36189
|
return hasRSpec && (isCommandAvailable("bundle") || isCommandAvailable("rspec"));
|
|
36126
36190
|
}
|
|
36127
36191
|
function detectMinitest(cwd) {
|
|
36128
|
-
return fs18.existsSync(
|
|
36192
|
+
return fs18.existsSync(path29.join(cwd, "test")) && (fs18.existsSync(path29.join(cwd, "Gemfile")) || fs18.existsSync(path29.join(cwd, "Rakefile"))) && isCommandAvailable("ruby");
|
|
36129
36193
|
}
|
|
36130
36194
|
async function detectTestFramework(cwd) {
|
|
36131
36195
|
const baseDir = cwd;
|
|
36132
36196
|
try {
|
|
36133
|
-
const packageJsonPath =
|
|
36197
|
+
const packageJsonPath = path29.join(baseDir, "package.json");
|
|
36134
36198
|
if (fs18.existsSync(packageJsonPath)) {
|
|
36135
36199
|
const content = fs18.readFileSync(packageJsonPath, "utf-8");
|
|
36136
36200
|
const pkg = JSON.parse(content);
|
|
@@ -36151,16 +36215,16 @@ async function detectTestFramework(cwd) {
|
|
|
36151
36215
|
return "jest";
|
|
36152
36216
|
if (hasDevDependency(devDeps, "mocha", "@types/mocha"))
|
|
36153
36217
|
return "mocha";
|
|
36154
|
-
if (fs18.existsSync(
|
|
36218
|
+
if (fs18.existsSync(path29.join(baseDir, "bun.lockb")) || fs18.existsSync(path29.join(baseDir, "bun.lock"))) {
|
|
36155
36219
|
if (scripts.test?.includes("bun"))
|
|
36156
36220
|
return "bun";
|
|
36157
36221
|
}
|
|
36158
36222
|
}
|
|
36159
36223
|
} catch {}
|
|
36160
36224
|
try {
|
|
36161
|
-
const pyprojectTomlPath =
|
|
36162
|
-
const setupCfgPath =
|
|
36163
|
-
const requirementsTxtPath =
|
|
36225
|
+
const pyprojectTomlPath = path29.join(baseDir, "pyproject.toml");
|
|
36226
|
+
const setupCfgPath = path29.join(baseDir, "setup.cfg");
|
|
36227
|
+
const requirementsTxtPath = path29.join(baseDir, "requirements.txt");
|
|
36164
36228
|
if (fs18.existsSync(pyprojectTomlPath)) {
|
|
36165
36229
|
const content = fs18.readFileSync(pyprojectTomlPath, "utf-8");
|
|
36166
36230
|
if (content.includes("[tool.pytest"))
|
|
@@ -36180,7 +36244,7 @@ async function detectTestFramework(cwd) {
|
|
|
36180
36244
|
}
|
|
36181
36245
|
} catch {}
|
|
36182
36246
|
try {
|
|
36183
|
-
const cargoTomlPath =
|
|
36247
|
+
const cargoTomlPath = path29.join(baseDir, "Cargo.toml");
|
|
36184
36248
|
if (fs18.existsSync(cargoTomlPath)) {
|
|
36185
36249
|
const content = fs18.readFileSync(cargoTomlPath, "utf-8");
|
|
36186
36250
|
if (content.includes("[dev-dependencies]")) {
|
|
@@ -36191,9 +36255,9 @@ async function detectTestFramework(cwd) {
|
|
|
36191
36255
|
}
|
|
36192
36256
|
} catch {}
|
|
36193
36257
|
try {
|
|
36194
|
-
const pesterConfigPath =
|
|
36195
|
-
const pesterConfigJsonPath =
|
|
36196
|
-
const pesterPs1Path =
|
|
36258
|
+
const pesterConfigPath = path29.join(baseDir, "pester.config.ps1");
|
|
36259
|
+
const pesterConfigJsonPath = path29.join(baseDir, "pester.config.ps1.json");
|
|
36260
|
+
const pesterPs1Path = path29.join(baseDir, "tests.ps1");
|
|
36197
36261
|
if (fs18.existsSync(pesterConfigPath) || fs18.existsSync(pesterConfigJsonPath) || fs18.existsSync(pesterPs1Path)) {
|
|
36198
36262
|
return "pester";
|
|
36199
36263
|
}
|
|
@@ -36226,8 +36290,8 @@ function getTestFilesFromConvention(sourceFiles) {
|
|
|
36226
36290
|
const testFiles = [];
|
|
36227
36291
|
for (const file3 of sourceFiles) {
|
|
36228
36292
|
const normalizedPath = file3.replace(/\\/g, "/");
|
|
36229
|
-
const basename5 =
|
|
36230
|
-
const dirname12 =
|
|
36293
|
+
const basename5 = path29.basename(file3);
|
|
36294
|
+
const dirname12 = path29.dirname(file3);
|
|
36231
36295
|
if (hasCompoundTestExtension(basename5) || basename5.includes(".spec.") || basename5.includes(".test.") || normalizedPath.includes("/__tests__/") || normalizedPath.includes("/tests/") || normalizedPath.includes("/test/")) {
|
|
36232
36296
|
if (!testFiles.includes(file3)) {
|
|
36233
36297
|
testFiles.push(file3);
|
|
@@ -36236,13 +36300,13 @@ function getTestFilesFromConvention(sourceFiles) {
|
|
|
36236
36300
|
}
|
|
36237
36301
|
for (const _pattern of TEST_PATTERNS) {
|
|
36238
36302
|
const nameWithoutExt = basename5.replace(/\.[^.]+$/, "");
|
|
36239
|
-
const ext =
|
|
36303
|
+
const ext = path29.extname(basename5);
|
|
36240
36304
|
const possibleTestFiles = [
|
|
36241
|
-
|
|
36242
|
-
|
|
36243
|
-
|
|
36244
|
-
|
|
36245
|
-
|
|
36305
|
+
path29.join(dirname12, `${nameWithoutExt}.spec${ext}`),
|
|
36306
|
+
path29.join(dirname12, `${nameWithoutExt}.test${ext}`),
|
|
36307
|
+
path29.join(dirname12, "__tests__", `${nameWithoutExt}${ext}`),
|
|
36308
|
+
path29.join(dirname12, "tests", `${nameWithoutExt}${ext}`),
|
|
36309
|
+
path29.join(dirname12, "test", `${nameWithoutExt}${ext}`)
|
|
36246
36310
|
];
|
|
36247
36311
|
for (const testFile of possibleTestFiles) {
|
|
36248
36312
|
if (fs18.existsSync(testFile) && !testFiles.includes(testFile)) {
|
|
@@ -36262,7 +36326,7 @@ async function getTestFilesFromGraph(sourceFiles) {
|
|
|
36262
36326
|
for (const testFile of candidateTestFiles) {
|
|
36263
36327
|
try {
|
|
36264
36328
|
const content = fs18.readFileSync(testFile, "utf-8");
|
|
36265
|
-
const testDir =
|
|
36329
|
+
const testDir = path29.dirname(testFile);
|
|
36266
36330
|
const importRegex = /import\s+.*?\s+from\s+['"]([^'"]+)['"]/g;
|
|
36267
36331
|
let match;
|
|
36268
36332
|
match = importRegex.exec(content);
|
|
@@ -36270,8 +36334,8 @@ async function getTestFilesFromGraph(sourceFiles) {
|
|
|
36270
36334
|
const importPath = match[1];
|
|
36271
36335
|
let resolvedImport;
|
|
36272
36336
|
if (importPath.startsWith(".")) {
|
|
36273
|
-
resolvedImport =
|
|
36274
|
-
const existingExt =
|
|
36337
|
+
resolvedImport = path29.resolve(testDir, importPath);
|
|
36338
|
+
const existingExt = path29.extname(resolvedImport);
|
|
36275
36339
|
if (!existingExt) {
|
|
36276
36340
|
for (const extToTry of [
|
|
36277
36341
|
".ts",
|
|
@@ -36291,12 +36355,12 @@ async function getTestFilesFromGraph(sourceFiles) {
|
|
|
36291
36355
|
} else {
|
|
36292
36356
|
continue;
|
|
36293
36357
|
}
|
|
36294
|
-
const importBasename =
|
|
36295
|
-
const importDir =
|
|
36358
|
+
const importBasename = path29.basename(resolvedImport, path29.extname(resolvedImport));
|
|
36359
|
+
const importDir = path29.dirname(resolvedImport);
|
|
36296
36360
|
for (const sourceFile of sourceFiles) {
|
|
36297
|
-
const sourceDir =
|
|
36298
|
-
const sourceBasename =
|
|
36299
|
-
const isRelatedDir = importDir === sourceDir || importDir ===
|
|
36361
|
+
const sourceDir = path29.dirname(sourceFile);
|
|
36362
|
+
const sourceBasename = path29.basename(sourceFile, path29.extname(sourceFile));
|
|
36363
|
+
const isRelatedDir = importDir === sourceDir || importDir === path29.join(sourceDir, "__tests__") || importDir === path29.join(sourceDir, "tests") || importDir === path29.join(sourceDir, "test");
|
|
36300
36364
|
if (resolvedImport === sourceFile || importBasename === sourceBasename && isRelatedDir) {
|
|
36301
36365
|
if (!testFiles.includes(testFile)) {
|
|
36302
36366
|
testFiles.push(testFile);
|
|
@@ -36311,8 +36375,8 @@ async function getTestFilesFromGraph(sourceFiles) {
|
|
|
36311
36375
|
while (match !== null) {
|
|
36312
36376
|
const importPath = match[1];
|
|
36313
36377
|
if (importPath.startsWith(".")) {
|
|
36314
|
-
let resolvedImport =
|
|
36315
|
-
const existingExt =
|
|
36378
|
+
let resolvedImport = path29.resolve(testDir, importPath);
|
|
36379
|
+
const existingExt = path29.extname(resolvedImport);
|
|
36316
36380
|
if (!existingExt) {
|
|
36317
36381
|
for (const extToTry of [
|
|
36318
36382
|
".ts",
|
|
@@ -36329,12 +36393,12 @@ async function getTestFilesFromGraph(sourceFiles) {
|
|
|
36329
36393
|
}
|
|
36330
36394
|
}
|
|
36331
36395
|
}
|
|
36332
|
-
const importDir =
|
|
36333
|
-
const importBasename =
|
|
36396
|
+
const importDir = path29.dirname(resolvedImport);
|
|
36397
|
+
const importBasename = path29.basename(resolvedImport, path29.extname(resolvedImport));
|
|
36334
36398
|
for (const sourceFile of sourceFiles) {
|
|
36335
|
-
const sourceDir =
|
|
36336
|
-
const sourceBasename =
|
|
36337
|
-
const isRelatedDir = importDir === sourceDir || importDir ===
|
|
36399
|
+
const sourceDir = path29.dirname(sourceFile);
|
|
36400
|
+
const sourceBasename = path29.basename(sourceFile, path29.extname(sourceFile));
|
|
36401
|
+
const isRelatedDir = importDir === sourceDir || importDir === path29.join(sourceDir, "__tests__") || importDir === path29.join(sourceDir, "tests") || importDir === path29.join(sourceDir, "test");
|
|
36338
36402
|
if (resolvedImport === sourceFile || importBasename === sourceBasename && isRelatedDir) {
|
|
36339
36403
|
if (!testFiles.includes(testFile)) {
|
|
36340
36404
|
testFiles.push(testFile);
|
|
@@ -36419,8 +36483,8 @@ function buildTestCommand(framework, scope, files, coverage, baseDir) {
|
|
|
36419
36483
|
return ["mvn", "test"];
|
|
36420
36484
|
case "gradle": {
|
|
36421
36485
|
const isWindows = process.platform === "win32";
|
|
36422
|
-
const hasGradlewBat = fs18.existsSync(
|
|
36423
|
-
const hasGradlew = fs18.existsSync(
|
|
36486
|
+
const hasGradlewBat = fs18.existsSync(path29.join(baseDir, "gradlew.bat"));
|
|
36487
|
+
const hasGradlew = fs18.existsSync(path29.join(baseDir, "gradlew"));
|
|
36424
36488
|
if (hasGradlewBat && isWindows)
|
|
36425
36489
|
return ["gradlew.bat", "test"];
|
|
36426
36490
|
if (hasGradlew)
|
|
@@ -36437,7 +36501,7 @@ function buildTestCommand(framework, scope, files, coverage, baseDir) {
|
|
|
36437
36501
|
"cmake-build-release",
|
|
36438
36502
|
"out"
|
|
36439
36503
|
];
|
|
36440
|
-
const actualBuildDir = buildDirCandidates.find((d) => fs18.existsSync(
|
|
36504
|
+
const actualBuildDir = buildDirCandidates.find((d) => fs18.existsSync(path29.join(baseDir, d, "CMakeCache.txt"))) ?? "build";
|
|
36441
36505
|
return ["ctest", "--test-dir", actualBuildDir];
|
|
36442
36506
|
}
|
|
36443
36507
|
case "swift-test":
|
|
@@ -37005,7 +37069,7 @@ var init_test_runner = __esm(() => {
|
|
|
37005
37069
|
let effectiveScope = scope;
|
|
37006
37070
|
if (scope === "all") {} else if (scope === "convention") {
|
|
37007
37071
|
const sourceFiles = args2.files.filter((f) => {
|
|
37008
|
-
const ext =
|
|
37072
|
+
const ext = path29.extname(f).toLowerCase();
|
|
37009
37073
|
return SOURCE_EXTENSIONS.has(ext);
|
|
37010
37074
|
});
|
|
37011
37075
|
if (sourceFiles.length === 0) {
|
|
@@ -37021,7 +37085,7 @@ var init_test_runner = __esm(() => {
|
|
|
37021
37085
|
testFiles = getTestFilesFromConvention(sourceFiles);
|
|
37022
37086
|
} else if (scope === "graph") {
|
|
37023
37087
|
const sourceFiles = args2.files.filter((f) => {
|
|
37024
|
-
const ext =
|
|
37088
|
+
const ext = path29.extname(f).toLowerCase();
|
|
37025
37089
|
return SOURCE_EXTENSIONS.has(ext);
|
|
37026
37090
|
});
|
|
37027
37091
|
if (sourceFiles.length === 0) {
|
|
@@ -37075,7 +37139,7 @@ var init_test_runner = __esm(() => {
|
|
|
37075
37139
|
|
|
37076
37140
|
// src/services/preflight-service.ts
|
|
37077
37141
|
import * as fs19 from "fs";
|
|
37078
|
-
import * as
|
|
37142
|
+
import * as path30 from "path";
|
|
37079
37143
|
function validateDirectoryPath(dir) {
|
|
37080
37144
|
if (!dir || typeof dir !== "string") {
|
|
37081
37145
|
throw new Error("Directory path is required");
|
|
@@ -37083,8 +37147,8 @@ function validateDirectoryPath(dir) {
|
|
|
37083
37147
|
if (dir.includes("..")) {
|
|
37084
37148
|
throw new Error("Directory path must not contain path traversal sequences");
|
|
37085
37149
|
}
|
|
37086
|
-
const normalized =
|
|
37087
|
-
const absolutePath =
|
|
37150
|
+
const normalized = path30.normalize(dir);
|
|
37151
|
+
const absolutePath = path30.isAbsolute(normalized) ? normalized : path30.resolve(normalized);
|
|
37088
37152
|
return absolutePath;
|
|
37089
37153
|
}
|
|
37090
37154
|
function validateTimeout(timeoutMs, defaultValue) {
|
|
@@ -37107,7 +37171,7 @@ function validateTimeout(timeoutMs, defaultValue) {
|
|
|
37107
37171
|
}
|
|
37108
37172
|
function getPackageVersion(dir) {
|
|
37109
37173
|
try {
|
|
37110
|
-
const packagePath =
|
|
37174
|
+
const packagePath = path30.join(dir, "package.json");
|
|
37111
37175
|
if (fs19.existsSync(packagePath)) {
|
|
37112
37176
|
const content = fs19.readFileSync(packagePath, "utf-8");
|
|
37113
37177
|
const pkg = JSON.parse(content);
|
|
@@ -37118,7 +37182,7 @@ function getPackageVersion(dir) {
|
|
|
37118
37182
|
}
|
|
37119
37183
|
function getChangelogVersion(dir) {
|
|
37120
37184
|
try {
|
|
37121
|
-
const changelogPath =
|
|
37185
|
+
const changelogPath = path30.join(dir, "CHANGELOG.md");
|
|
37122
37186
|
if (fs19.existsSync(changelogPath)) {
|
|
37123
37187
|
const content = fs19.readFileSync(changelogPath, "utf-8");
|
|
37124
37188
|
const match = content.match(/^##\s*\[?(\d+\.\d+\.\d+)\]?/m);
|
|
@@ -37132,7 +37196,7 @@ function getChangelogVersion(dir) {
|
|
|
37132
37196
|
function getVersionFileVersion(dir) {
|
|
37133
37197
|
const possibleFiles = ["VERSION.txt", "version.txt", "VERSION", "version"];
|
|
37134
37198
|
for (const file3 of possibleFiles) {
|
|
37135
|
-
const filePath =
|
|
37199
|
+
const filePath = path30.join(dir, file3);
|
|
37136
37200
|
if (fs19.existsSync(filePath)) {
|
|
37137
37201
|
try {
|
|
37138
37202
|
const content = fs19.readFileSync(filePath, "utf-8").trim();
|
|
@@ -37660,7 +37724,7 @@ __export(exports_gate_evidence, {
|
|
|
37660
37724
|
DEFAULT_REQUIRED_GATES: () => DEFAULT_REQUIRED_GATES
|
|
37661
37725
|
});
|
|
37662
37726
|
import { mkdirSync as mkdirSync12, readFileSync as readFileSync17, renameSync as renameSync10, unlinkSync as unlinkSync5 } from "fs";
|
|
37663
|
-
import * as
|
|
37727
|
+
import * as path37 from "path";
|
|
37664
37728
|
function isValidTaskId2(taskId) {
|
|
37665
37729
|
if (!taskId)
|
|
37666
37730
|
return false;
|
|
@@ -37707,10 +37771,10 @@ function expandRequiredGates(existingGates, newAgentType) {
|
|
|
37707
37771
|
return combined.sort();
|
|
37708
37772
|
}
|
|
37709
37773
|
function getEvidenceDir(directory) {
|
|
37710
|
-
return
|
|
37774
|
+
return path37.join(directory, ".swarm", "evidence");
|
|
37711
37775
|
}
|
|
37712
37776
|
function getEvidencePath(directory, taskId) {
|
|
37713
|
-
return
|
|
37777
|
+
return path37.join(getEvidenceDir(directory), `${taskId}.json`);
|
|
37714
37778
|
}
|
|
37715
37779
|
function readExisting(evidencePath) {
|
|
37716
37780
|
try {
|
|
@@ -37821,12 +37885,12 @@ __export(exports_review_receipt, {
|
|
|
37821
37885
|
});
|
|
37822
37886
|
import * as crypto5 from "crypto";
|
|
37823
37887
|
import * as fs28 from "fs";
|
|
37824
|
-
import * as
|
|
37888
|
+
import * as path39 from "path";
|
|
37825
37889
|
function resolveReceiptsDir(directory) {
|
|
37826
|
-
return
|
|
37890
|
+
return path39.join(directory, ".swarm", "review-receipts");
|
|
37827
37891
|
}
|
|
37828
37892
|
function resolveReceiptIndexPath(directory) {
|
|
37829
|
-
return
|
|
37893
|
+
return path39.join(resolveReceiptsDir(directory), "index.json");
|
|
37830
37894
|
}
|
|
37831
37895
|
function buildReceiptFilename(id, date9) {
|
|
37832
37896
|
const dateStr = date9.toISOString().slice(0, 10);
|
|
@@ -37865,7 +37929,7 @@ async function readReceiptIndex(directory) {
|
|
|
37865
37929
|
}
|
|
37866
37930
|
async function writeReceiptIndex(directory, index) {
|
|
37867
37931
|
const indexPath = resolveReceiptIndexPath(directory);
|
|
37868
|
-
const dir =
|
|
37932
|
+
const dir = path39.dirname(indexPath);
|
|
37869
37933
|
await fs28.promises.mkdir(dir, { recursive: true });
|
|
37870
37934
|
const tmpPath = `${indexPath}.tmp.${Date.now()}.${Math.random().toString(36).slice(2)}`;
|
|
37871
37935
|
await fs28.promises.writeFile(tmpPath, JSON.stringify(index, null, 2), "utf-8");
|
|
@@ -37876,7 +37940,7 @@ async function persistReviewReceipt(directory, receipt) {
|
|
|
37876
37940
|
await fs28.promises.mkdir(receiptsDir, { recursive: true });
|
|
37877
37941
|
const now = new Date(receipt.reviewed_at);
|
|
37878
37942
|
const filename = buildReceiptFilename(receipt.id, now);
|
|
37879
|
-
const receiptPath =
|
|
37943
|
+
const receiptPath = path39.join(receiptsDir, filename);
|
|
37880
37944
|
const tmpPath = `${receiptPath}.tmp.${Date.now()}.${Math.random().toString(36).slice(2)}`;
|
|
37881
37945
|
await fs28.promises.writeFile(tmpPath, JSON.stringify(receipt, null, 2), "utf-8");
|
|
37882
37946
|
fs28.renameSync(tmpPath, receiptPath);
|
|
@@ -37898,7 +37962,7 @@ async function readReceiptById(directory, receiptId) {
|
|
|
37898
37962
|
const entry = index.entries.find((e) => e.id === receiptId);
|
|
37899
37963
|
if (!entry)
|
|
37900
37964
|
return null;
|
|
37901
|
-
const receiptPath =
|
|
37965
|
+
const receiptPath = path39.join(resolveReceiptsDir(directory), entry.filename);
|
|
37902
37966
|
try {
|
|
37903
37967
|
const content = await fs28.promises.readFile(receiptPath, "utf-8");
|
|
37904
37968
|
return JSON.parse(content);
|
|
@@ -37911,7 +37975,7 @@ async function readReceiptsByScopeHash(directory, scopeHash) {
|
|
|
37911
37975
|
const matching = index.entries.filter((e) => e.scope_hash === scopeHash).sort((a, b) => b.reviewed_at.localeCompare(a.reviewed_at));
|
|
37912
37976
|
const receipts = [];
|
|
37913
37977
|
for (const entry of matching) {
|
|
37914
|
-
const receiptPath =
|
|
37978
|
+
const receiptPath = path39.join(resolveReceiptsDir(directory), entry.filename);
|
|
37915
37979
|
try {
|
|
37916
37980
|
const content = await fs28.promises.readFile(receiptPath, "utf-8");
|
|
37917
37981
|
receipts.push(JSON.parse(content));
|
|
@@ -37924,7 +37988,7 @@ async function readAllReceipts(directory) {
|
|
|
37924
37988
|
const sorted = [...index.entries].sort((a, b) => b.reviewed_at.localeCompare(a.reviewed_at));
|
|
37925
37989
|
const receipts = [];
|
|
37926
37990
|
for (const entry of sorted) {
|
|
37927
|
-
const receiptPath =
|
|
37991
|
+
const receiptPath = path39.join(resolveReceiptsDir(directory), entry.filename);
|
|
37928
37992
|
try {
|
|
37929
37993
|
const content = await fs28.promises.readFile(receiptPath, "utf-8");
|
|
37930
37994
|
receipts.push(JSON.parse(content));
|
|
@@ -38060,13 +38124,13 @@ __export(exports_doc_scan, {
|
|
|
38060
38124
|
import * as crypto6 from "crypto";
|
|
38061
38125
|
import * as fs31 from "fs";
|
|
38062
38126
|
import { mkdir as mkdir6, readFile as readFile6, writeFile as writeFile5 } from "fs/promises";
|
|
38063
|
-
import * as
|
|
38127
|
+
import * as path43 from "path";
|
|
38064
38128
|
function normalizeSeparators(filePath) {
|
|
38065
38129
|
return filePath.replace(/\\/g, "/");
|
|
38066
38130
|
}
|
|
38067
38131
|
function matchesDocPattern(filePath, patterns) {
|
|
38068
38132
|
const normalizedPath = normalizeSeparators(filePath);
|
|
38069
|
-
const basename6 =
|
|
38133
|
+
const basename6 = path43.basename(filePath);
|
|
38070
38134
|
for (const pattern of patterns) {
|
|
38071
38135
|
if (!pattern.includes("/") && !pattern.includes("\\")) {
|
|
38072
38136
|
if (basename6 === pattern) {
|
|
@@ -38122,7 +38186,7 @@ function stripMarkdown(text) {
|
|
|
38122
38186
|
return text.replace(/\[([^\]]+)\]\([^)]+\)/g, "$1").replace(/\*\*([^*]+)\*\*/g, "$1").replace(/`([^`]+)`/g, "$1").replace(/^\s*[-*\u2022]\s+/gm, "").replace(/^\s*\d+\.\s+/gm, "").trim();
|
|
38123
38187
|
}
|
|
38124
38188
|
async function scanDocIndex(directory) {
|
|
38125
|
-
const manifestPath =
|
|
38189
|
+
const manifestPath = path43.join(directory, ".swarm", "doc-manifest.json");
|
|
38126
38190
|
const defaultPatterns = DocsConfigSchema.parse({}).doc_patterns;
|
|
38127
38191
|
const extraPatterns = [
|
|
38128
38192
|
"ARCHITECTURE.md",
|
|
@@ -38139,7 +38203,7 @@ async function scanDocIndex(directory) {
|
|
|
38139
38203
|
let cacheValid = true;
|
|
38140
38204
|
for (const file3 of existingManifest.files) {
|
|
38141
38205
|
try {
|
|
38142
|
-
const fullPath =
|
|
38206
|
+
const fullPath = path43.join(directory, file3.path);
|
|
38143
38207
|
const stat2 = fs31.statSync(fullPath);
|
|
38144
38208
|
if (stat2.mtimeMs > new Date(existingManifest.scanned_at).getTime()) {
|
|
38145
38209
|
cacheValid = false;
|
|
@@ -38169,7 +38233,7 @@ async function scanDocIndex(directory) {
|
|
|
38169
38233
|
}
|
|
38170
38234
|
const entries = rawEntries.filter((e) => typeof e === "string");
|
|
38171
38235
|
for (const entry of entries) {
|
|
38172
|
-
const fullPath =
|
|
38236
|
+
const fullPath = path43.join(directory, entry);
|
|
38173
38237
|
let stat2;
|
|
38174
38238
|
try {
|
|
38175
38239
|
stat2 = fs31.statSync(fullPath);
|
|
@@ -38205,7 +38269,7 @@ async function scanDocIndex(directory) {
|
|
|
38205
38269
|
} catch {
|
|
38206
38270
|
continue;
|
|
38207
38271
|
}
|
|
38208
|
-
const { title, summary } = extractTitleAndSummary(content,
|
|
38272
|
+
const { title, summary } = extractTitleAndSummary(content, path43.basename(entry));
|
|
38209
38273
|
const lineCount = content.split(`
|
|
38210
38274
|
`).length;
|
|
38211
38275
|
discoveredFiles.push({
|
|
@@ -38231,7 +38295,7 @@ async function scanDocIndex(directory) {
|
|
|
38231
38295
|
files: discoveredFiles
|
|
38232
38296
|
};
|
|
38233
38297
|
try {
|
|
38234
|
-
await mkdir6(
|
|
38298
|
+
await mkdir6(path43.dirname(manifestPath), { recursive: true });
|
|
38235
38299
|
await writeFile5(manifestPath, JSON.stringify(manifest, null, 2), "utf-8");
|
|
38236
38300
|
} catch {}
|
|
38237
38301
|
return { manifest, cached: false };
|
|
@@ -38270,7 +38334,7 @@ function extractConstraintsFromContent(content) {
|
|
|
38270
38334
|
return constraints;
|
|
38271
38335
|
}
|
|
38272
38336
|
async function extractDocConstraints(directory, taskFiles, taskDescription) {
|
|
38273
|
-
const manifestPath =
|
|
38337
|
+
const manifestPath = path43.join(directory, ".swarm", "doc-manifest.json");
|
|
38274
38338
|
let manifest;
|
|
38275
38339
|
try {
|
|
38276
38340
|
const content = await readFile6(manifestPath, "utf-8");
|
|
@@ -38296,7 +38360,7 @@ async function extractDocConstraints(directory, taskFiles, taskDescription) {
|
|
|
38296
38360
|
}
|
|
38297
38361
|
let fullContent;
|
|
38298
38362
|
try {
|
|
38299
|
-
fullContent = await readFile6(
|
|
38363
|
+
fullContent = await readFile6(path43.join(directory, docFile.path), "utf-8");
|
|
38300
38364
|
} catch {
|
|
38301
38365
|
skippedCount++;
|
|
38302
38366
|
continue;
|
|
@@ -38319,7 +38383,7 @@ async function extractDocConstraints(directory, taskFiles, taskDescription) {
|
|
|
38319
38383
|
tier: "swarm",
|
|
38320
38384
|
lesson: constraint,
|
|
38321
38385
|
category: "architecture",
|
|
38322
|
-
tags: ["doc-scan",
|
|
38386
|
+
tags: ["doc-scan", path43.basename(docFile.path)],
|
|
38323
38387
|
scope: "global",
|
|
38324
38388
|
confidence: 0.5,
|
|
38325
38389
|
status: "candidate",
|
|
@@ -38392,7 +38456,7 @@ var init_doc_scan = __esm(() => {
|
|
|
38392
38456
|
}
|
|
38393
38457
|
} catch {}
|
|
38394
38458
|
if (force) {
|
|
38395
|
-
const manifestPath =
|
|
38459
|
+
const manifestPath = path43.join(directory, ".swarm", "doc-manifest.json");
|
|
38396
38460
|
try {
|
|
38397
38461
|
fs31.unlinkSync(manifestPath);
|
|
38398
38462
|
} catch {}
|
|
@@ -38447,9 +38511,9 @@ __export(exports_curator_drift, {
|
|
|
38447
38511
|
buildDriftInjectionText: () => buildDriftInjectionText
|
|
38448
38512
|
});
|
|
38449
38513
|
import * as fs34 from "fs";
|
|
38450
|
-
import * as
|
|
38514
|
+
import * as path46 from "path";
|
|
38451
38515
|
async function readPriorDriftReports(directory) {
|
|
38452
|
-
const swarmDir =
|
|
38516
|
+
const swarmDir = path46.join(directory, ".swarm");
|
|
38453
38517
|
const entries = await fs34.promises.readdir(swarmDir).catch(() => null);
|
|
38454
38518
|
if (entries === null)
|
|
38455
38519
|
return [];
|
|
@@ -38476,7 +38540,7 @@ async function readPriorDriftReports(directory) {
|
|
|
38476
38540
|
async function writeDriftReport(directory, report) {
|
|
38477
38541
|
const filename = `${DRIFT_REPORT_PREFIX}${report.phase}.json`;
|
|
38478
38542
|
const filePath = validateSwarmPath(directory, filename);
|
|
38479
|
-
const swarmDir =
|
|
38543
|
+
const swarmDir = path46.dirname(filePath);
|
|
38480
38544
|
await fs34.promises.mkdir(swarmDir, { recursive: true });
|
|
38481
38545
|
try {
|
|
38482
38546
|
await fs34.promises.writeFile(filePath, JSON.stringify(report, null, 2), "utf-8");
|
|
@@ -40069,11 +40133,11 @@ ${JSON.stringify(symbolNames, null, 2)}`);
|
|
|
40069
40133
|
throw toThrow;
|
|
40070
40134
|
}, "quit_");
|
|
40071
40135
|
var scriptDirectory = "";
|
|
40072
|
-
function locateFile(
|
|
40136
|
+
function locateFile(path56) {
|
|
40073
40137
|
if (Module["locateFile"]) {
|
|
40074
|
-
return Module["locateFile"](
|
|
40138
|
+
return Module["locateFile"](path56, scriptDirectory);
|
|
40075
40139
|
}
|
|
40076
|
-
return scriptDirectory +
|
|
40140
|
+
return scriptDirectory + path56;
|
|
40077
40141
|
}
|
|
40078
40142
|
__name(locateFile, "locateFile");
|
|
40079
40143
|
var readAsync, readBinary;
|
|
@@ -41813,13 +41877,13 @@ ${JSON.stringify(symbolNames, null, 2)}`);
|
|
|
41813
41877
|
});
|
|
41814
41878
|
|
|
41815
41879
|
// src/lang/runtime.ts
|
|
41816
|
-
import * as
|
|
41880
|
+
import * as path56 from "path";
|
|
41817
41881
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
41818
41882
|
async function initTreeSitter() {
|
|
41819
41883
|
if (treeSitterInitialized) {
|
|
41820
41884
|
return;
|
|
41821
41885
|
}
|
|
41822
|
-
const thisDir =
|
|
41886
|
+
const thisDir = path56.dirname(fileURLToPath2(import.meta.url));
|
|
41823
41887
|
const isSource = thisDir.replace(/\\/g, "/").endsWith("/src/lang");
|
|
41824
41888
|
if (isSource) {
|
|
41825
41889
|
await Parser.init();
|
|
@@ -41827,7 +41891,7 @@ async function initTreeSitter() {
|
|
|
41827
41891
|
const grammarsDir = getGrammarsDirAbsolute();
|
|
41828
41892
|
await Parser.init({
|
|
41829
41893
|
locateFile(scriptName) {
|
|
41830
|
-
return
|
|
41894
|
+
return path56.join(grammarsDir, scriptName);
|
|
41831
41895
|
}
|
|
41832
41896
|
});
|
|
41833
41897
|
}
|
|
@@ -41848,9 +41912,9 @@ function getWasmFileName(languageId) {
|
|
|
41848
41912
|
return `tree-sitter-${sanitized}.wasm`;
|
|
41849
41913
|
}
|
|
41850
41914
|
function getGrammarsDirAbsolute() {
|
|
41851
|
-
const thisDir =
|
|
41915
|
+
const thisDir = path56.dirname(fileURLToPath2(import.meta.url));
|
|
41852
41916
|
const isSource = thisDir.replace(/\\/g, "/").endsWith("/src/lang");
|
|
41853
|
-
return isSource ?
|
|
41917
|
+
return isSource ? path56.join(thisDir, "grammars") : path56.join(thisDir, "lang", "grammars");
|
|
41854
41918
|
}
|
|
41855
41919
|
async function loadGrammar(languageId) {
|
|
41856
41920
|
if (typeof languageId !== "string" || languageId.length > 100) {
|
|
@@ -41866,9 +41930,9 @@ async function loadGrammar(languageId) {
|
|
|
41866
41930
|
await initTreeSitter();
|
|
41867
41931
|
const parser = new Parser;
|
|
41868
41932
|
const wasmFileName = getWasmFileName(normalizedId);
|
|
41869
|
-
const wasmPath =
|
|
41870
|
-
const { existsSync:
|
|
41871
|
-
if (!
|
|
41933
|
+
const wasmPath = path56.join(getGrammarsDirAbsolute(), wasmFileName);
|
|
41934
|
+
const { existsSync: existsSync34 } = await import("fs");
|
|
41935
|
+
if (!existsSync34(wasmPath)) {
|
|
41872
41936
|
throw new Error(`Grammar file not found for ${languageId}: ${wasmPath}
|
|
41873
41937
|
Make sure to run 'bun run build' to copy grammar files to dist/lang/grammars/`);
|
|
41874
41938
|
}
|
|
@@ -41913,7 +41977,7 @@ var init_runtime = __esm(() => {
|
|
|
41913
41977
|
});
|
|
41914
41978
|
|
|
41915
41979
|
// src/index.ts
|
|
41916
|
-
import * as
|
|
41980
|
+
import * as path74 from "path";
|
|
41917
41981
|
|
|
41918
41982
|
// src/agents/index.ts
|
|
41919
41983
|
init_config();
|
|
@@ -46021,8 +46085,9 @@ class PlanSyncWorker {
|
|
|
46021
46085
|
try {
|
|
46022
46086
|
log("[PlanSyncWorker] Syncing plan...");
|
|
46023
46087
|
this.checkForUnauthorizedWrite();
|
|
46024
|
-
const plan = await this.withTimeout(
|
|
46088
|
+
const plan = await this.withTimeout(loadPlanJsonOnly(this.directory), this.syncTimeoutMs, "Sync operation timed out");
|
|
46025
46089
|
if (plan) {
|
|
46090
|
+
await regeneratePlanMarkdown(this.directory, plan);
|
|
46026
46091
|
log("[PlanSyncWorker] Sync complete", {
|
|
46027
46092
|
title: plan.title,
|
|
46028
46093
|
phase: plan.current_phase
|
|
@@ -46680,11 +46745,13 @@ async function handleClarifyCommand(_directory, args2) {
|
|
|
46680
46745
|
// src/commands/close.ts
|
|
46681
46746
|
init_schema();
|
|
46682
46747
|
init_manager();
|
|
46748
|
+
import { execFileSync } from "child_process";
|
|
46683
46749
|
import { promises as fs11 } from "fs";
|
|
46750
|
+
import path17 from "path";
|
|
46684
46751
|
|
|
46685
46752
|
// src/hooks/knowledge-reader.ts
|
|
46686
46753
|
init_knowledge_store();
|
|
46687
|
-
import { existsSync as
|
|
46754
|
+
import { existsSync as existsSync10 } from "fs";
|
|
46688
46755
|
import { mkdir as mkdir2, readFile as readFile3, writeFile as writeFile2 } from "fs/promises";
|
|
46689
46756
|
import * as path13 from "path";
|
|
46690
46757
|
var JACCARD_THRESHOLD = 0.6;
|
|
@@ -46737,7 +46804,7 @@ async function recordLessonsShown(directory, lessonIds, currentPhase) {
|
|
|
46737
46804
|
const shownFile = path13.join(directory, ".swarm", ".knowledge-shown.json");
|
|
46738
46805
|
try {
|
|
46739
46806
|
let shownData = {};
|
|
46740
|
-
if (
|
|
46807
|
+
if (existsSync10(shownFile)) {
|
|
46741
46808
|
const content = await readFile3(shownFile, "utf-8");
|
|
46742
46809
|
shownData = JSON.parse(content);
|
|
46743
46810
|
}
|
|
@@ -46843,7 +46910,7 @@ async function readMergedKnowledge(directory, config3, context) {
|
|
|
46843
46910
|
async function updateRetrievalOutcome(directory, phaseInfo, phaseSucceeded) {
|
|
46844
46911
|
const shownFile = path13.join(directory, ".swarm", ".knowledge-shown.json");
|
|
46845
46912
|
try {
|
|
46846
|
-
if (!
|
|
46913
|
+
if (!existsSync10(shownFile)) {
|
|
46847
46914
|
return;
|
|
46848
46915
|
}
|
|
46849
46916
|
const content = await readFile3(shownFile, "utf-8");
|
|
@@ -48065,87 +48132,183 @@ var write_retro = createSwarmTool({
|
|
|
48065
48132
|
});
|
|
48066
48133
|
|
|
48067
48134
|
// src/commands/close.ts
|
|
48068
|
-
async function handleCloseCommand(directory,
|
|
48135
|
+
async function handleCloseCommand(directory, args2) {
|
|
48069
48136
|
const planPath = validateSwarmPath(directory, "plan.json");
|
|
48070
|
-
let
|
|
48137
|
+
let planExists = false;
|
|
48138
|
+
let planData = {
|
|
48139
|
+
title: path17.basename(directory) || "Ad-hoc session",
|
|
48140
|
+
phases: []
|
|
48141
|
+
};
|
|
48071
48142
|
try {
|
|
48072
48143
|
const content = await fs11.readFile(planPath, "utf-8");
|
|
48073
48144
|
planData = JSON.parse(content);
|
|
48145
|
+
planExists = true;
|
|
48074
48146
|
} catch (error93) {
|
|
48075
|
-
|
|
48147
|
+
if (error93?.code !== "ENOENT") {
|
|
48148
|
+
return `\u274C Failed to read plan.json: ${error93 instanceof Error ? error93.message : String(error93)}`;
|
|
48149
|
+
}
|
|
48150
|
+
const swarmDirExists = await fs11.access(path17.join(directory, ".swarm")).then(() => true).catch(() => false);
|
|
48151
|
+
if (!swarmDirExists) {
|
|
48152
|
+
return `\u274C No .swarm/ directory found in ${directory}. Run /swarm close from the project root, or run /swarm plan first.`;
|
|
48153
|
+
}
|
|
48076
48154
|
}
|
|
48077
48155
|
const phases = planData.phases ?? [];
|
|
48078
48156
|
const inProgressPhases = phases.filter((p) => p.status === "in_progress");
|
|
48079
|
-
|
|
48080
|
-
if (
|
|
48081
|
-
|
|
48082
|
-
const blockedCount = phases.filter((p) => p.status === "blocked").length;
|
|
48083
|
-
const completeCount = phases.filter((p) => p.status === "complete" || p.status === "completed").length;
|
|
48084
|
-
return `\u2139\uFE0F Swarm already closed. ${completeCount} phases complete, ${closedCount} phases closed, ${blockedCount} phases blocked. No action taken.`;
|
|
48157
|
+
let planAlreadyDone = false;
|
|
48158
|
+
if (planExists) {
|
|
48159
|
+
planAlreadyDone = phases.length > 0 && phases.every((p) => p.status === "complete" || p.status === "completed" || p.status === "blocked" || p.status === "closed");
|
|
48085
48160
|
}
|
|
48086
48161
|
const config3 = KnowledgeConfigSchema.parse({});
|
|
48087
48162
|
const projectName = planData.title ?? "Unknown Project";
|
|
48088
48163
|
const closedPhases = [];
|
|
48089
48164
|
const closedTasks = [];
|
|
48090
48165
|
const warnings = [];
|
|
48091
|
-
|
|
48092
|
-
|
|
48093
|
-
|
|
48094
|
-
|
|
48095
|
-
|
|
48096
|
-
|
|
48097
|
-
|
|
48098
|
-
|
|
48099
|
-
|
|
48100
|
-
|
|
48101
|
-
|
|
48102
|
-
|
|
48103
|
-
|
|
48104
|
-
|
|
48105
|
-
|
|
48106
|
-
|
|
48107
|
-
|
|
48108
|
-
|
|
48166
|
+
if (!planAlreadyDone) {
|
|
48167
|
+
for (const phase of inProgressPhases) {
|
|
48168
|
+
closedPhases.push(phase.id);
|
|
48169
|
+
let retroResult;
|
|
48170
|
+
try {
|
|
48171
|
+
retroResult = await executeWriteRetro({
|
|
48172
|
+
phase: phase.id,
|
|
48173
|
+
summary: "Phase closed via /swarm close",
|
|
48174
|
+
task_count: Math.max(1, (phase.tasks ?? []).length),
|
|
48175
|
+
task_complexity: "simple",
|
|
48176
|
+
total_tool_calls: 0,
|
|
48177
|
+
coder_revisions: 0,
|
|
48178
|
+
reviewer_rejections: 0,
|
|
48179
|
+
test_failures: 0,
|
|
48180
|
+
security_findings: 0,
|
|
48181
|
+
integration_issues: 0
|
|
48182
|
+
}, directory);
|
|
48183
|
+
} catch (retroError) {
|
|
48184
|
+
warnings.push(`Retrospective write threw for phase ${phase.id}: ${retroError instanceof Error ? retroError.message : String(retroError)}`);
|
|
48185
|
+
}
|
|
48186
|
+
if (retroResult !== undefined) {
|
|
48187
|
+
try {
|
|
48188
|
+
const parsed = JSON.parse(retroResult);
|
|
48189
|
+
if (parsed.success !== true) {
|
|
48190
|
+
warnings.push(`Retrospective write failed for phase ${phase.id}`);
|
|
48191
|
+
}
|
|
48192
|
+
} catch {}
|
|
48109
48193
|
}
|
|
48110
|
-
|
|
48111
|
-
|
|
48112
|
-
|
|
48113
|
-
|
|
48194
|
+
for (const task of phase.tasks ?? []) {
|
|
48195
|
+
if (task.status !== "completed" && task.status !== "complete") {
|
|
48196
|
+
closedTasks.push(task.id);
|
|
48197
|
+
}
|
|
48114
48198
|
}
|
|
48115
48199
|
}
|
|
48116
48200
|
}
|
|
48201
|
+
const lessonsFilePath = path17.join(directory, ".swarm", "close-lessons.md");
|
|
48202
|
+
let explicitLessons = [];
|
|
48203
|
+
try {
|
|
48204
|
+
const lessonsText = await fs11.readFile(lessonsFilePath, "utf-8");
|
|
48205
|
+
explicitLessons = lessonsText.split(`
|
|
48206
|
+
`).map((line) => line.trim()).filter((line) => line.length > 0 && !line.startsWith("#"));
|
|
48207
|
+
} catch {}
|
|
48208
|
+
let curationSucceeded = false;
|
|
48117
48209
|
try {
|
|
48118
|
-
await curateAndStoreSwarm(
|
|
48210
|
+
await curateAndStoreSwarm(explicitLessons, projectName, { phase_number: 0 }, directory, config3);
|
|
48211
|
+
curationSucceeded = true;
|
|
48119
48212
|
} catch (error93) {
|
|
48120
48213
|
console.warn("[close-command] curateAndStoreSwarm error:", error93);
|
|
48121
48214
|
}
|
|
48122
|
-
|
|
48123
|
-
|
|
48124
|
-
|
|
48125
|
-
|
|
48126
|
-
|
|
48215
|
+
if (curationSucceeded && explicitLessons.length > 0) {
|
|
48216
|
+
await fs11.unlink(lessonsFilePath).catch(() => {});
|
|
48217
|
+
}
|
|
48218
|
+
if (planExists && !planAlreadyDone) {
|
|
48219
|
+
for (const phase of phases) {
|
|
48220
|
+
if (phase.status !== "complete" && phase.status !== "completed") {
|
|
48221
|
+
phase.status = "closed";
|
|
48222
|
+
if (!closedPhases.includes(phase.id)) {
|
|
48223
|
+
closedPhases.push(phase.id);
|
|
48224
|
+
}
|
|
48127
48225
|
}
|
|
48128
|
-
|
|
48129
|
-
|
|
48130
|
-
|
|
48131
|
-
|
|
48132
|
-
|
|
48133
|
-
|
|
48226
|
+
for (const task of phase.tasks ?? []) {
|
|
48227
|
+
if (task.status !== "completed" && task.status !== "complete") {
|
|
48228
|
+
task.status = "closed";
|
|
48229
|
+
if (!closedTasks.includes(task.id)) {
|
|
48230
|
+
closedTasks.push(task.id);
|
|
48231
|
+
}
|
|
48134
48232
|
}
|
|
48135
48233
|
}
|
|
48136
48234
|
}
|
|
48235
|
+
try {
|
|
48236
|
+
await fs11.writeFile(planPath, JSON.stringify(planData, null, 2), "utf-8");
|
|
48237
|
+
} catch (error93) {
|
|
48238
|
+
console.warn("[close-command] Failed to write plan.json:", error93);
|
|
48239
|
+
}
|
|
48137
48240
|
}
|
|
48138
48241
|
try {
|
|
48139
|
-
await
|
|
48242
|
+
await archiveEvidence(directory, 30, 10);
|
|
48140
48243
|
} catch (error93) {
|
|
48141
|
-
console.warn("[close-command]
|
|
48244
|
+
console.warn("[close-command] archiveEvidence error:", error93);
|
|
48142
48245
|
}
|
|
48246
|
+
const swarmDir = path17.join(directory, ".swarm");
|
|
48247
|
+
let configBackupsRemoved = 0;
|
|
48143
48248
|
try {
|
|
48144
|
-
await
|
|
48249
|
+
const swarmFiles = await fs11.readdir(swarmDir);
|
|
48250
|
+
const configBackups = swarmFiles.filter((f) => f.startsWith("config-backup-") && f.endsWith(".json"));
|
|
48251
|
+
for (const backup of configBackups) {
|
|
48252
|
+
try {
|
|
48253
|
+
await fs11.unlink(path17.join(swarmDir, backup));
|
|
48254
|
+
configBackupsRemoved++;
|
|
48255
|
+
} catch {}
|
|
48256
|
+
}
|
|
48257
|
+
} catch {}
|
|
48258
|
+
const contextPath = path17.join(directory, ".swarm", "context.md");
|
|
48259
|
+
const contextContent = [
|
|
48260
|
+
"# Context",
|
|
48261
|
+
"",
|
|
48262
|
+
"## Status",
|
|
48263
|
+
`Session closed after: ${projectName}`,
|
|
48264
|
+
`Closed: ${new Date().toISOString()}`,
|
|
48265
|
+
"No active plan. Next session starts fresh.",
|
|
48266
|
+
""
|
|
48267
|
+
].join(`
|
|
48268
|
+
`);
|
|
48269
|
+
try {
|
|
48270
|
+
await fs11.writeFile(contextPath, contextContent, "utf-8");
|
|
48145
48271
|
} catch (error93) {
|
|
48146
|
-
console.warn("[close-command]
|
|
48272
|
+
console.warn("[close-command] Failed to write context.md:", error93);
|
|
48273
|
+
}
|
|
48274
|
+
const pruneBranches = args2.includes("--prune-branches");
|
|
48275
|
+
const prunedBranches = [];
|
|
48276
|
+
const pruneErrors = [];
|
|
48277
|
+
if (pruneBranches) {
|
|
48278
|
+
try {
|
|
48279
|
+
const branchOutput = execFileSync("git", ["branch", "-vv"], {
|
|
48280
|
+
cwd: directory,
|
|
48281
|
+
encoding: "utf-8",
|
|
48282
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
48283
|
+
});
|
|
48284
|
+
const goneBranches = branchOutput.split(`
|
|
48285
|
+
`).filter((line) => line.includes(": gone]")).map((line) => line.trim().replace(/^[*+]\s+/, "").split(/\s+/)[0]).filter(Boolean);
|
|
48286
|
+
for (const branch of goneBranches) {
|
|
48287
|
+
try {
|
|
48288
|
+
execFileSync("git", ["branch", "-d", branch], {
|
|
48289
|
+
cwd: directory,
|
|
48290
|
+
encoding: "utf-8",
|
|
48291
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
48292
|
+
});
|
|
48293
|
+
prunedBranches.push(branch);
|
|
48294
|
+
} catch {
|
|
48295
|
+
pruneErrors.push(branch);
|
|
48296
|
+
}
|
|
48297
|
+
}
|
|
48298
|
+
} catch {}
|
|
48147
48299
|
}
|
|
48148
48300
|
const closeSummaryPath = validateSwarmPath(directory, "close-summary.md");
|
|
48301
|
+
const actionsPerformed = [
|
|
48302
|
+
...!planAlreadyDone && inProgressPhases.length > 0 ? ["- Wrote retrospectives for in-progress phases"] : [],
|
|
48303
|
+
"- Archived evidence bundles",
|
|
48304
|
+
"- Reset context.md for next session",
|
|
48305
|
+
...configBackupsRemoved > 0 ? [`- Removed ${configBackupsRemoved} stale config backup file(s)`] : [],
|
|
48306
|
+
...prunedBranches.length > 0 ? [
|
|
48307
|
+
`- Pruned ${prunedBranches.length} stale local git branch(es): ${prunedBranches.join(", ")}`
|
|
48308
|
+
] : [],
|
|
48309
|
+
"- Cleared agent sessions and delegation chains",
|
|
48310
|
+
...planExists && !planAlreadyDone ? ["- Set non-completed phases/tasks to closed status"] : []
|
|
48311
|
+
];
|
|
48149
48312
|
const summaryContent = [
|
|
48150
48313
|
"# Swarm Close Summary",
|
|
48151
48314
|
"",
|
|
@@ -48153,18 +48316,15 @@ async function handleCloseCommand(directory, _args) {
|
|
|
48153
48316
|
`**Closed:** ${new Date().toISOString()}`,
|
|
48154
48317
|
"",
|
|
48155
48318
|
`## Phases Closed: ${closedPhases.length}`,
|
|
48156
|
-
closedPhases.map((id) => `- Phase ${id}`).join(`
|
|
48157
|
-
`),
|
|
48319
|
+
!planExists ? "_No plan \u2014 ad-hoc session_" : closedPhases.length > 0 ? closedPhases.map((id) => `- Phase ${id}`).join(`
|
|
48320
|
+
`) : "_No phases to close_",
|
|
48158
48321
|
"",
|
|
48159
48322
|
`## Tasks Closed: ${closedTasks.length}`,
|
|
48160
48323
|
closedTasks.length > 0 ? closedTasks.map((id) => `- ${id}`).join(`
|
|
48161
48324
|
`) : "_No incomplete tasks_",
|
|
48162
48325
|
"",
|
|
48163
48326
|
"## Actions Performed",
|
|
48164
|
-
|
|
48165
|
-
"- Archived evidence bundles",
|
|
48166
|
-
"- Cleared agent sessions and delegation chains",
|
|
48167
|
-
"- Set non-completed phases/tasks to closed status"
|
|
48327
|
+
...actionsPerformed
|
|
48168
48328
|
].join(`
|
|
48169
48329
|
`);
|
|
48170
48330
|
try {
|
|
@@ -48180,21 +48340,27 @@ async function handleCloseCommand(directory, _args) {
|
|
|
48180
48340
|
await writeCheckpoint(directory).catch(() => {});
|
|
48181
48341
|
swarmState.agentSessions.clear();
|
|
48182
48342
|
swarmState.delegationChains.clear();
|
|
48343
|
+
if (pruneErrors.length > 0) {
|
|
48344
|
+
warnings.push(`Could not prune ${pruneErrors.length} branch(es) (unmerged or checked out): ${pruneErrors.join(", ")}`);
|
|
48345
|
+
}
|
|
48183
48346
|
const warningMsg = warnings.length > 0 ? ` Warnings: ${warnings.join("; ")}.` : "";
|
|
48347
|
+
if (planAlreadyDone) {
|
|
48348
|
+
return `\u2705 Session closed. Plan was already in a terminal state \u2014 cleanup steps applied.${warningMsg}`;
|
|
48349
|
+
}
|
|
48184
48350
|
return `\u2705 Swarm closed successfully. ${closedPhases.length} phase(s) closed, ${closedTasks.length} incomplete task(s) marked closed.${warningMsg}`;
|
|
48185
48351
|
}
|
|
48186
48352
|
|
|
48187
48353
|
// src/commands/config.ts
|
|
48188
48354
|
init_loader();
|
|
48189
48355
|
import * as os4 from "os";
|
|
48190
|
-
import * as
|
|
48356
|
+
import * as path18 from "path";
|
|
48191
48357
|
function getUserConfigDir2() {
|
|
48192
|
-
return process.env.XDG_CONFIG_HOME ||
|
|
48358
|
+
return process.env.XDG_CONFIG_HOME || path18.join(os4.homedir(), ".config");
|
|
48193
48359
|
}
|
|
48194
48360
|
async function handleConfigCommand(directory, _args) {
|
|
48195
48361
|
const config3 = loadPluginConfig(directory);
|
|
48196
|
-
const userConfigPath =
|
|
48197
|
-
const projectConfigPath =
|
|
48362
|
+
const userConfigPath = path18.join(getUserConfigDir2(), "opencode", "opencode-swarm.json");
|
|
48363
|
+
const projectConfigPath = path18.join(directory, ".opencode", "opencode-swarm.json");
|
|
48198
48364
|
const lines = [
|
|
48199
48365
|
"## Swarm Configuration",
|
|
48200
48366
|
"",
|
|
@@ -48217,7 +48383,7 @@ init_schema();
|
|
|
48217
48383
|
// src/hooks/curator.ts
|
|
48218
48384
|
import { randomUUID } from "crypto";
|
|
48219
48385
|
import * as fs12 from "fs";
|
|
48220
|
-
import * as
|
|
48386
|
+
import * as path19 from "path";
|
|
48221
48387
|
init_event_bus();
|
|
48222
48388
|
init_manager2();
|
|
48223
48389
|
init_knowledge_store();
|
|
@@ -48271,7 +48437,7 @@ async function readCuratorSummary(directory) {
|
|
|
48271
48437
|
}
|
|
48272
48438
|
async function writeCuratorSummary(directory, summary) {
|
|
48273
48439
|
const resolvedPath = validateSwarmPath(directory, "curator-summary.json");
|
|
48274
|
-
fs12.mkdirSync(
|
|
48440
|
+
fs12.mkdirSync(path19.dirname(resolvedPath), { recursive: true });
|
|
48275
48441
|
const tempPath = `${resolvedPath}.tmp.${Date.now()}.${Math.random().toString(36).slice(2)}`;
|
|
48276
48442
|
await Bun.write(tempPath, JSON.stringify(summary, null, 2));
|
|
48277
48443
|
fs12.renameSync(tempPath, resolvedPath);
|
|
@@ -48642,7 +48808,7 @@ ${phaseDigest.summary}`,
|
|
|
48642
48808
|
};
|
|
48643
48809
|
}
|
|
48644
48810
|
await writeCuratorSummary(directory, updatedSummary);
|
|
48645
|
-
const eventsPath =
|
|
48811
|
+
const eventsPath = path19.join(directory, ".swarm", "events.jsonl");
|
|
48646
48812
|
for (const obs of complianceObservations) {
|
|
48647
48813
|
await appendKnowledge(eventsPath, {
|
|
48648
48814
|
type: "curator_compliance",
|
|
@@ -48784,7 +48950,7 @@ async function applyCuratorKnowledgeUpdates(directory, recommendations, _knowled
|
|
|
48784
48950
|
created_at: now,
|
|
48785
48951
|
updated_at: now,
|
|
48786
48952
|
auto_generated: true,
|
|
48787
|
-
project_name:
|
|
48953
|
+
project_name: path19.basename(directory)
|
|
48788
48954
|
};
|
|
48789
48955
|
await appendKnowledge(knowledgePath, newEntry);
|
|
48790
48956
|
applied++;
|
|
@@ -49002,7 +49168,7 @@ function formatCurationSummary(summary) {
|
|
|
49002
49168
|
// src/commands/dark-matter.ts
|
|
49003
49169
|
init_knowledge_store();
|
|
49004
49170
|
init_co_change_analyzer();
|
|
49005
|
-
import
|
|
49171
|
+
import path21 from "path";
|
|
49006
49172
|
async function handleDarkMatterCommand(directory, args2) {
|
|
49007
49173
|
const options = {};
|
|
49008
49174
|
for (let i2 = 0;i2 < args2.length; i2++) {
|
|
@@ -49024,7 +49190,7 @@ async function handleDarkMatterCommand(directory, args2) {
|
|
|
49024
49190
|
const output = formatDarkMatterOutput(pairs);
|
|
49025
49191
|
if (pairs.length > 0) {
|
|
49026
49192
|
try {
|
|
49027
|
-
const projectName =
|
|
49193
|
+
const projectName = path21.basename(path21.resolve(directory));
|
|
49028
49194
|
const entries = darkMatterToKnowledgeEntries(pairs, projectName);
|
|
49029
49195
|
if (entries.length > 0) {
|
|
49030
49196
|
const knowledgePath = resolveSwarmKnowledgePath(directory);
|
|
@@ -49049,8 +49215,8 @@ init_manager();
|
|
|
49049
49215
|
init_utils2();
|
|
49050
49216
|
init_manager2();
|
|
49051
49217
|
import * as child_process3 from "child_process";
|
|
49052
|
-
import { existsSync as
|
|
49053
|
-
import
|
|
49218
|
+
import { existsSync as existsSync11, readdirSync as readdirSync2, readFileSync as readFileSync7, statSync as statSync5 } from "fs";
|
|
49219
|
+
import path22 from "path";
|
|
49054
49220
|
import { fileURLToPath } from "url";
|
|
49055
49221
|
function validateTaskDag(plan) {
|
|
49056
49222
|
const allTaskIds = new Set;
|
|
@@ -49283,7 +49449,7 @@ async function checkConfigBackups(directory) {
|
|
|
49283
49449
|
}
|
|
49284
49450
|
async function checkGitRepository(directory) {
|
|
49285
49451
|
try {
|
|
49286
|
-
if (!
|
|
49452
|
+
if (!existsSync11(directory) || !statSync5(directory).isDirectory()) {
|
|
49287
49453
|
return {
|
|
49288
49454
|
name: "Git Repository",
|
|
49289
49455
|
status: "\u274C",
|
|
@@ -49347,8 +49513,8 @@ async function checkSpecStaleness(directory, plan) {
|
|
|
49347
49513
|
};
|
|
49348
49514
|
}
|
|
49349
49515
|
async function checkConfigParseability(directory) {
|
|
49350
|
-
const configPath =
|
|
49351
|
-
if (!
|
|
49516
|
+
const configPath = path22.join(directory, ".opencode/opencode-swarm.json");
|
|
49517
|
+
if (!existsSync11(configPath)) {
|
|
49352
49518
|
return {
|
|
49353
49519
|
name: "Config Parseability",
|
|
49354
49520
|
status: "\u2705",
|
|
@@ -49394,15 +49560,15 @@ async function checkGrammarWasmFiles() {
|
|
|
49394
49560
|
"tree-sitter-ini.wasm",
|
|
49395
49561
|
"tree-sitter-regex.wasm"
|
|
49396
49562
|
];
|
|
49397
|
-
const thisDir =
|
|
49563
|
+
const thisDir = path22.dirname(fileURLToPath(import.meta.url));
|
|
49398
49564
|
const isSource = thisDir.replace(/\\/g, "/").endsWith("/src/services");
|
|
49399
|
-
const grammarDir = isSource ?
|
|
49565
|
+
const grammarDir = isSource ? path22.join(thisDir, "..", "lang", "grammars") : path22.join(thisDir, "lang", "grammars");
|
|
49400
49566
|
const missing = [];
|
|
49401
|
-
if (!
|
|
49567
|
+
if (!existsSync11(path22.join(grammarDir, "tree-sitter.wasm"))) {
|
|
49402
49568
|
missing.push("tree-sitter.wasm (core runtime)");
|
|
49403
49569
|
}
|
|
49404
49570
|
for (const file3 of grammarFiles) {
|
|
49405
|
-
if (!
|
|
49571
|
+
if (!existsSync11(path22.join(grammarDir, file3))) {
|
|
49406
49572
|
missing.push(file3);
|
|
49407
49573
|
}
|
|
49408
49574
|
}
|
|
@@ -49420,8 +49586,8 @@ async function checkGrammarWasmFiles() {
|
|
|
49420
49586
|
};
|
|
49421
49587
|
}
|
|
49422
49588
|
async function checkCheckpointManifest(directory) {
|
|
49423
|
-
const manifestPath =
|
|
49424
|
-
if (!
|
|
49589
|
+
const manifestPath = path22.join(directory, ".swarm/checkpoints.json");
|
|
49590
|
+
if (!existsSync11(manifestPath)) {
|
|
49425
49591
|
return {
|
|
49426
49592
|
name: "Checkpoint Manifest",
|
|
49427
49593
|
status: "\u2705",
|
|
@@ -49472,8 +49638,8 @@ async function checkCheckpointManifest(directory) {
|
|
|
49472
49638
|
}
|
|
49473
49639
|
}
|
|
49474
49640
|
async function checkEventStreamIntegrity(directory) {
|
|
49475
|
-
const eventsPath =
|
|
49476
|
-
if (!
|
|
49641
|
+
const eventsPath = path22.join(directory, ".swarm/events.jsonl");
|
|
49642
|
+
if (!existsSync11(eventsPath)) {
|
|
49477
49643
|
return {
|
|
49478
49644
|
name: "Event Stream",
|
|
49479
49645
|
status: "\u2705",
|
|
@@ -49513,8 +49679,8 @@ async function checkEventStreamIntegrity(directory) {
|
|
|
49513
49679
|
}
|
|
49514
49680
|
}
|
|
49515
49681
|
async function checkSteeringDirectives(directory) {
|
|
49516
|
-
const eventsPath =
|
|
49517
|
-
if (!
|
|
49682
|
+
const eventsPath = path22.join(directory, ".swarm/events.jsonl");
|
|
49683
|
+
if (!existsSync11(eventsPath)) {
|
|
49518
49684
|
return {
|
|
49519
49685
|
name: "Steering Directives",
|
|
49520
49686
|
status: "\u2705",
|
|
@@ -49569,8 +49735,8 @@ async function checkCurator(directory) {
|
|
|
49569
49735
|
detail: "Disabled (enable via curator.enabled)"
|
|
49570
49736
|
};
|
|
49571
49737
|
}
|
|
49572
|
-
const summaryPath =
|
|
49573
|
-
if (!
|
|
49738
|
+
const summaryPath = path22.join(directory, ".swarm/curator-summary.json");
|
|
49739
|
+
if (!existsSync11(summaryPath)) {
|
|
49574
49740
|
return {
|
|
49575
49741
|
name: "Curator",
|
|
49576
49742
|
status: "\u2705",
|
|
@@ -50469,14 +50635,14 @@ init_schema();
|
|
|
50469
50635
|
// src/hooks/knowledge-migrator.ts
|
|
50470
50636
|
init_knowledge_store();
|
|
50471
50637
|
import { randomUUID as randomUUID3 } from "crypto";
|
|
50472
|
-
import { existsSync as
|
|
50638
|
+
import { existsSync as existsSync13, readFileSync as readFileSync9 } from "fs";
|
|
50473
50639
|
import { mkdir as mkdir4, readFile as readFile5, writeFile as writeFile4 } from "fs/promises";
|
|
50474
|
-
import * as
|
|
50640
|
+
import * as path24 from "path";
|
|
50475
50641
|
async function migrateContextToKnowledge(directory, config3) {
|
|
50476
|
-
const sentinelPath =
|
|
50477
|
-
const contextPath =
|
|
50642
|
+
const sentinelPath = path24.join(directory, ".swarm", ".knowledge-migrated");
|
|
50643
|
+
const contextPath = path24.join(directory, ".swarm", "context.md");
|
|
50478
50644
|
const knowledgePath = resolveSwarmKnowledgePath(directory);
|
|
50479
|
-
if (
|
|
50645
|
+
if (existsSync13(sentinelPath)) {
|
|
50480
50646
|
return {
|
|
50481
50647
|
migrated: false,
|
|
50482
50648
|
entriesMigrated: 0,
|
|
@@ -50485,7 +50651,7 @@ async function migrateContextToKnowledge(directory, config3) {
|
|
|
50485
50651
|
skippedReason: "sentinel-exists"
|
|
50486
50652
|
};
|
|
50487
50653
|
}
|
|
50488
|
-
if (!
|
|
50654
|
+
if (!existsSync13(contextPath)) {
|
|
50489
50655
|
return {
|
|
50490
50656
|
migrated: false,
|
|
50491
50657
|
entriesMigrated: 0,
|
|
@@ -50670,8 +50836,8 @@ function truncateLesson(text) {
|
|
|
50670
50836
|
return `${text.slice(0, 277)}...`;
|
|
50671
50837
|
}
|
|
50672
50838
|
function inferProjectName(directory) {
|
|
50673
|
-
const packageJsonPath =
|
|
50674
|
-
if (
|
|
50839
|
+
const packageJsonPath = path24.join(directory, "package.json");
|
|
50840
|
+
if (existsSync13(packageJsonPath)) {
|
|
50675
50841
|
try {
|
|
50676
50842
|
const pkg = JSON.parse(readFileSync9(packageJsonPath, "utf-8"));
|
|
50677
50843
|
if (pkg.name && typeof pkg.name === "string") {
|
|
@@ -50679,7 +50845,7 @@ function inferProjectName(directory) {
|
|
|
50679
50845
|
}
|
|
50680
50846
|
} catch {}
|
|
50681
50847
|
}
|
|
50682
|
-
return
|
|
50848
|
+
return path24.basename(directory);
|
|
50683
50849
|
}
|
|
50684
50850
|
async function writeSentinel(sentinelPath, migrated, dropped) {
|
|
50685
50851
|
const sentinel = {
|
|
@@ -50691,7 +50857,7 @@ async function writeSentinel(sentinelPath, migrated, dropped) {
|
|
|
50691
50857
|
schema_version: 1,
|
|
50692
50858
|
migration_tool: "knowledge-migrator.ts"
|
|
50693
50859
|
};
|
|
50694
|
-
await mkdir4(
|
|
50860
|
+
await mkdir4(path24.dirname(sentinelPath), { recursive: true });
|
|
50695
50861
|
await writeFile4(sentinelPath, JSON.stringify(sentinel, null, 2), "utf-8");
|
|
50696
50862
|
}
|
|
50697
50863
|
|
|
@@ -50931,7 +51097,7 @@ init_preflight_service();
|
|
|
50931
51097
|
// src/knowledge/hive-promoter.ts
|
|
50932
51098
|
import * as fs20 from "fs";
|
|
50933
51099
|
import * as os6 from "os";
|
|
50934
|
-
import * as
|
|
51100
|
+
import * as path31 from "path";
|
|
50935
51101
|
var DANGEROUS_PATTERNS = [
|
|
50936
51102
|
[/rm\s+-rf/, "rm\\s+-rf"],
|
|
50937
51103
|
[/:\s*!\s*\|/, ":\\s*!\\s*\\|"],
|
|
@@ -50977,13 +51143,13 @@ function getHiveFilePath() {
|
|
|
50977
51143
|
const home = os6.homedir();
|
|
50978
51144
|
let dataDir;
|
|
50979
51145
|
if (platform === "win32") {
|
|
50980
|
-
dataDir =
|
|
51146
|
+
dataDir = path31.join(process.env.LOCALAPPDATA || path31.join(home, "AppData", "Local"), "opencode-swarm", "Data");
|
|
50981
51147
|
} else if (platform === "darwin") {
|
|
50982
|
-
dataDir =
|
|
51148
|
+
dataDir = path31.join(home, "Library", "Application Support", "opencode-swarm");
|
|
50983
51149
|
} else {
|
|
50984
|
-
dataDir =
|
|
51150
|
+
dataDir = path31.join(process.env.XDG_DATA_HOME || path31.join(home, ".local", "share"), "opencode-swarm");
|
|
50985
51151
|
}
|
|
50986
|
-
return
|
|
51152
|
+
return path31.join(dataDir, "hive-knowledge.jsonl");
|
|
50987
51153
|
}
|
|
50988
51154
|
async function promoteToHive(_directory, lesson, category) {
|
|
50989
51155
|
const trimmed = (lesson ?? "").trim();
|
|
@@ -50995,7 +51161,7 @@ async function promoteToHive(_directory, lesson, category) {
|
|
|
50995
51161
|
throw new Error(`Lesson rejected by validator: ${validation.reason}`);
|
|
50996
51162
|
}
|
|
50997
51163
|
const hivePath = getHiveFilePath();
|
|
50998
|
-
const hiveDir =
|
|
51164
|
+
const hiveDir = path31.dirname(hivePath);
|
|
50999
51165
|
if (!fs20.existsSync(hiveDir)) {
|
|
51000
51166
|
fs20.mkdirSync(hiveDir, { recursive: true });
|
|
51001
51167
|
}
|
|
@@ -51017,7 +51183,7 @@ async function promoteToHive(_directory, lesson, category) {
|
|
|
51017
51183
|
return `Promoted to hive: "${preview}" (confidence: 1.0, source: manual)`;
|
|
51018
51184
|
}
|
|
51019
51185
|
async function promoteFromSwarm(directory, lessonId) {
|
|
51020
|
-
const knowledgePath =
|
|
51186
|
+
const knowledgePath = path31.join(directory, ".swarm", "knowledge.jsonl");
|
|
51021
51187
|
const entries = [];
|
|
51022
51188
|
if (fs20.existsSync(knowledgePath)) {
|
|
51023
51189
|
const content = fs20.readFileSync(knowledgePath, "utf-8");
|
|
@@ -51044,7 +51210,7 @@ async function promoteFromSwarm(directory, lessonId) {
|
|
|
51044
51210
|
throw new Error(`Lesson rejected by validator: ${validation.reason}`);
|
|
51045
51211
|
}
|
|
51046
51212
|
const hivePath = getHiveFilePath();
|
|
51047
|
-
const hiveDir =
|
|
51213
|
+
const hiveDir = path31.dirname(hivePath);
|
|
51048
51214
|
if (!fs20.existsSync(hiveDir)) {
|
|
51049
51215
|
fs20.mkdirSync(hiveDir, { recursive: true });
|
|
51050
51216
|
}
|
|
@@ -51175,7 +51341,7 @@ async function handleResetCommand(directory, args2) {
|
|
|
51175
51341
|
// src/commands/reset-session.ts
|
|
51176
51342
|
init_utils2();
|
|
51177
51343
|
import * as fs22 from "fs";
|
|
51178
|
-
import * as
|
|
51344
|
+
import * as path32 from "path";
|
|
51179
51345
|
async function handleResetSessionCommand(directory, _args) {
|
|
51180
51346
|
const results = [];
|
|
51181
51347
|
try {
|
|
@@ -51190,13 +51356,13 @@ async function handleResetSessionCommand(directory, _args) {
|
|
|
51190
51356
|
results.push("\u274C Failed to delete state.json");
|
|
51191
51357
|
}
|
|
51192
51358
|
try {
|
|
51193
|
-
const sessionDir =
|
|
51359
|
+
const sessionDir = path32.dirname(validateSwarmPath(directory, "session/state.json"));
|
|
51194
51360
|
if (fs22.existsSync(sessionDir)) {
|
|
51195
51361
|
const files = fs22.readdirSync(sessionDir);
|
|
51196
51362
|
const otherFiles = files.filter((f) => f !== "state.json");
|
|
51197
51363
|
let deletedCount = 0;
|
|
51198
51364
|
for (const file3 of otherFiles) {
|
|
51199
|
-
const filePath =
|
|
51365
|
+
const filePath = path32.join(sessionDir, file3);
|
|
51200
51366
|
if (fs22.lstatSync(filePath).isFile()) {
|
|
51201
51367
|
fs22.unlinkSync(filePath);
|
|
51202
51368
|
deletedCount++;
|
|
@@ -51227,7 +51393,7 @@ async function handleResetSessionCommand(directory, _args) {
|
|
|
51227
51393
|
init_utils2();
|
|
51228
51394
|
init_utils();
|
|
51229
51395
|
import { mkdirSync as mkdirSync11, readdirSync as readdirSync8, renameSync as renameSync8, rmSync as rmSync3, statSync as statSync8 } from "fs";
|
|
51230
|
-
import * as
|
|
51396
|
+
import * as path33 from "path";
|
|
51231
51397
|
var SUMMARY_ID_REGEX = /^S\d+$/;
|
|
51232
51398
|
function sanitizeSummaryId(id) {
|
|
51233
51399
|
if (!id || id.length === 0) {
|
|
@@ -51262,9 +51428,9 @@ async function storeSummary(directory, id, fullOutput, summaryText, maxStoredByt
|
|
|
51262
51428
|
if (serializedSize > maxStoredBytes) {
|
|
51263
51429
|
throw new Error(`Summary entry size (${serializedSize} bytes) exceeds maximum (${maxStoredBytes} bytes)`);
|
|
51264
51430
|
}
|
|
51265
|
-
const relativePath =
|
|
51431
|
+
const relativePath = path33.join("summaries", `${sanitizedId}.json`);
|
|
51266
51432
|
const summaryPath = validateSwarmPath(directory, relativePath);
|
|
51267
|
-
const summaryDir =
|
|
51433
|
+
const summaryDir = path33.dirname(summaryPath);
|
|
51268
51434
|
const entry = {
|
|
51269
51435
|
id: sanitizedId,
|
|
51270
51436
|
summaryText,
|
|
@@ -51274,7 +51440,7 @@ async function storeSummary(directory, id, fullOutput, summaryText, maxStoredByt
|
|
|
51274
51440
|
};
|
|
51275
51441
|
const entryJson = JSON.stringify(entry);
|
|
51276
51442
|
mkdirSync11(summaryDir, { recursive: true });
|
|
51277
|
-
const tempPath =
|
|
51443
|
+
const tempPath = path33.join(summaryDir, `${sanitizedId}.json.tmp.${Date.now()}.${process.pid}`);
|
|
51278
51444
|
try {
|
|
51279
51445
|
await Bun.write(tempPath, entryJson);
|
|
51280
51446
|
renameSync8(tempPath, summaryPath);
|
|
@@ -51287,7 +51453,7 @@ async function storeSummary(directory, id, fullOutput, summaryText, maxStoredByt
|
|
|
51287
51453
|
}
|
|
51288
51454
|
async function loadFullOutput(directory, id) {
|
|
51289
51455
|
const sanitizedId = sanitizeSummaryId(id);
|
|
51290
|
-
const relativePath =
|
|
51456
|
+
const relativePath = path33.join("summaries", `${sanitizedId}.json`);
|
|
51291
51457
|
validateSwarmPath(directory, relativePath);
|
|
51292
51458
|
const content = await readSwarmFileAsync(directory, relativePath);
|
|
51293
51459
|
if (content === null) {
|
|
@@ -51341,7 +51507,7 @@ ${error93 instanceof Error ? error93.message : String(error93)}`;
|
|
|
51341
51507
|
// src/commands/rollback.ts
|
|
51342
51508
|
init_utils2();
|
|
51343
51509
|
import * as fs23 from "fs";
|
|
51344
|
-
import * as
|
|
51510
|
+
import * as path34 from "path";
|
|
51345
51511
|
async function handleRollbackCommand(directory, args2) {
|
|
51346
51512
|
const phaseArg = args2[0];
|
|
51347
51513
|
if (!phaseArg) {
|
|
@@ -51399,8 +51565,8 @@ async function handleRollbackCommand(directory, args2) {
|
|
|
51399
51565
|
const successes = [];
|
|
51400
51566
|
const failures = [];
|
|
51401
51567
|
for (const file3 of checkpointFiles) {
|
|
51402
|
-
const src =
|
|
51403
|
-
const dest =
|
|
51568
|
+
const src = path34.join(checkpointDir, file3);
|
|
51569
|
+
const dest = path34.join(swarmDir, file3);
|
|
51404
51570
|
try {
|
|
51405
51571
|
fs23.cpSync(src, dest, { recursive: true, force: true });
|
|
51406
51572
|
successes.push(file3);
|
|
@@ -51464,9 +51630,9 @@ async function handleSimulateCommand(directory, args2) {
|
|
|
51464
51630
|
const report = reportLines.filter(Boolean).join(`
|
|
51465
51631
|
`);
|
|
51466
51632
|
const fs24 = await import("fs/promises");
|
|
51467
|
-
const
|
|
51468
|
-
const reportPath =
|
|
51469
|
-
await fs24.mkdir(
|
|
51633
|
+
const path35 = await import("path");
|
|
51634
|
+
const reportPath = path35.join(directory, ".swarm", "simulate-report.md");
|
|
51635
|
+
await fs24.mkdir(path35.dirname(reportPath), { recursive: true });
|
|
51470
51636
|
await fs24.writeFile(reportPath, report, "utf-8");
|
|
51471
51637
|
return `${darkMatterPairs.length} hidden coupling pairs detected`;
|
|
51472
51638
|
}
|
|
@@ -51825,7 +51991,7 @@ init_manager2();
|
|
|
51825
51991
|
|
|
51826
51992
|
// src/services/compaction-service.ts
|
|
51827
51993
|
import * as fs24 from "fs";
|
|
51828
|
-
import * as
|
|
51994
|
+
import * as path35 from "path";
|
|
51829
51995
|
function makeInitialState() {
|
|
51830
51996
|
return {
|
|
51831
51997
|
lastObservationAt: 0,
|
|
@@ -51848,7 +52014,7 @@ function getSessionState(sessionId) {
|
|
|
51848
52014
|
}
|
|
51849
52015
|
function appendSnapshot(directory, tier, budgetPct, message) {
|
|
51850
52016
|
try {
|
|
51851
|
-
const snapshotPath =
|
|
52017
|
+
const snapshotPath = path35.join(directory, ".swarm", "context-snapshot.md");
|
|
51852
52018
|
const timestamp = new Date().toISOString();
|
|
51853
52019
|
const entry = `
|
|
51854
52020
|
## [${tier.toUpperCase()}] ${timestamp} \u2014 ${budgetPct.toFixed(1)}% used
|
|
@@ -52579,11 +52745,11 @@ async function doFlush(directory) {
|
|
|
52579
52745
|
const activitySection = renderActivitySection();
|
|
52580
52746
|
const updated = replaceOrAppendSection(existing, "## Agent Activity", activitySection);
|
|
52581
52747
|
const flushedCount = swarmState.pendingEvents;
|
|
52582
|
-
const
|
|
52583
|
-
const tempPath = `${
|
|
52748
|
+
const path36 = nodePath2.join(directory, ".swarm", "context.md");
|
|
52749
|
+
const tempPath = `${path36}.tmp`;
|
|
52584
52750
|
try {
|
|
52585
52751
|
await Bun.write(tempPath, updated);
|
|
52586
|
-
renameSync9(tempPath,
|
|
52752
|
+
renameSync9(tempPath, path36);
|
|
52587
52753
|
} catch (writeError) {
|
|
52588
52754
|
try {
|
|
52589
52755
|
unlinkSync4(tempPath);
|
|
@@ -53260,7 +53426,7 @@ function createCuratorLLMDelegate(directory, mode = "init", sessionId) {
|
|
|
53260
53426
|
// src/hooks/delegation-gate.ts
|
|
53261
53427
|
init_schema();
|
|
53262
53428
|
import * as fs26 from "fs";
|
|
53263
|
-
import * as
|
|
53429
|
+
import * as path38 from "path";
|
|
53264
53430
|
|
|
53265
53431
|
// src/parallel/review-router.ts
|
|
53266
53432
|
async function computeComplexity(directory, changedFiles) {
|
|
@@ -53273,8 +53439,8 @@ async function computeComplexity(directory, changedFiles) {
|
|
|
53273
53439
|
}
|
|
53274
53440
|
try {
|
|
53275
53441
|
const fs26 = await import("fs");
|
|
53276
|
-
const
|
|
53277
|
-
const filePath =
|
|
53442
|
+
const path36 = await import("path");
|
|
53443
|
+
const filePath = path36.join(directory, file3);
|
|
53278
53444
|
if (!fs26.existsSync(filePath)) {
|
|
53279
53445
|
continue;
|
|
53280
53446
|
}
|
|
@@ -53326,7 +53492,7 @@ function shouldParallelizeReview(routing) {
|
|
|
53326
53492
|
init_telemetry();
|
|
53327
53493
|
|
|
53328
53494
|
// src/hooks/guardrails.ts
|
|
53329
|
-
import * as
|
|
53495
|
+
import * as path36 from "path";
|
|
53330
53496
|
init_constants();
|
|
53331
53497
|
init_schema();
|
|
53332
53498
|
|
|
@@ -53490,10 +53656,10 @@ function isArchitect(sessionId) {
|
|
|
53490
53656
|
function isOutsideSwarmDir(filePath, directory) {
|
|
53491
53657
|
if (!filePath)
|
|
53492
53658
|
return false;
|
|
53493
|
-
const swarmDir =
|
|
53494
|
-
const resolved =
|
|
53495
|
-
const relative5 =
|
|
53496
|
-
return relative5.startsWith("..") ||
|
|
53659
|
+
const swarmDir = path36.resolve(directory, ".swarm");
|
|
53660
|
+
const resolved = path36.resolve(directory, filePath);
|
|
53661
|
+
const relative5 = path36.relative(swarmDir, resolved);
|
|
53662
|
+
return relative5.startsWith("..") || path36.isAbsolute(relative5);
|
|
53497
53663
|
}
|
|
53498
53664
|
function isSourceCodePath(filePath) {
|
|
53499
53665
|
if (!filePath)
|
|
@@ -53561,13 +53727,13 @@ function getCurrentTaskId(sessionId) {
|
|
|
53561
53727
|
}
|
|
53562
53728
|
function isInDeclaredScope(filePath, scopeEntries, cwd) {
|
|
53563
53729
|
const dir = cwd ?? process.cwd();
|
|
53564
|
-
const resolvedFile =
|
|
53730
|
+
const resolvedFile = path36.resolve(dir, filePath);
|
|
53565
53731
|
return scopeEntries.some((scope) => {
|
|
53566
|
-
const resolvedScope =
|
|
53732
|
+
const resolvedScope = path36.resolve(dir, scope);
|
|
53567
53733
|
if (resolvedFile === resolvedScope)
|
|
53568
53734
|
return true;
|
|
53569
|
-
const rel =
|
|
53570
|
-
return rel.length > 0 && !rel.startsWith("..") && !
|
|
53735
|
+
const rel = path36.relative(resolvedScope, resolvedFile);
|
|
53736
|
+
return rel.length > 0 && !rel.startsWith("..") && !path36.isAbsolute(rel);
|
|
53571
53737
|
});
|
|
53572
53738
|
}
|
|
53573
53739
|
function createGuardrailsHooks(directory, directoryOrConfig, config3, authorityConfig) {
|
|
@@ -53826,18 +53992,18 @@ function createGuardrailsHooks(directory, directoryOrConfig, config3, authorityC
|
|
|
53826
53992
|
const toolArgs = args2;
|
|
53827
53993
|
const targetPath = toolArgs?.filePath ?? toolArgs?.path ?? toolArgs?.file ?? toolArgs?.target;
|
|
53828
53994
|
if (typeof targetPath === "string" && targetPath.length > 0) {
|
|
53829
|
-
const resolvedTarget =
|
|
53830
|
-
const planMdPath =
|
|
53831
|
-
const planJsonPath =
|
|
53995
|
+
const resolvedTarget = path36.resolve(effectiveDirectory, targetPath).toLowerCase();
|
|
53996
|
+
const planMdPath = path36.resolve(effectiveDirectory, ".swarm", "plan.md").toLowerCase();
|
|
53997
|
+
const planJsonPath = path36.resolve(effectiveDirectory, ".swarm", "plan.json").toLowerCase();
|
|
53832
53998
|
if (resolvedTarget === planMdPath || resolvedTarget === planJsonPath) {
|
|
53833
53999
|
throw new Error("PLAN STATE VIOLATION: Direct writes to .swarm/plan.md and .swarm/plan.json are blocked. " + "plan.md is auto-regenerated from plan.json by PlanSyncWorker. " + "Use update_task_status() to mark tasks complete, " + "phase_complete() for phase transitions, or " + "save_plan to create/restructure plans.");
|
|
53834
54000
|
}
|
|
53835
54001
|
}
|
|
53836
54002
|
if (!targetPath && (tool3 === "apply_patch" || tool3 === "patch")) {
|
|
53837
54003
|
for (const p of extractPatchTargetPaths(tool3, args2)) {
|
|
53838
|
-
const resolvedP =
|
|
53839
|
-
const planMdPath =
|
|
53840
|
-
const planJsonPath =
|
|
54004
|
+
const resolvedP = path36.resolve(effectiveDirectory, p);
|
|
54005
|
+
const planMdPath = path36.resolve(effectiveDirectory, ".swarm", "plan.md").toLowerCase();
|
|
54006
|
+
const planJsonPath = path36.resolve(effectiveDirectory, ".swarm", "plan.json").toLowerCase();
|
|
53841
54007
|
if (resolvedP.toLowerCase() === planMdPath || resolvedP.toLowerCase() === planJsonPath) {
|
|
53842
54008
|
throw new Error("PLAN STATE VIOLATION: Direct writes to .swarm/plan.md and .swarm/plan.json are blocked. " + "plan.md is auto-regenerated from plan.json by PlanSyncWorker. " + "Use update_task_status() to mark tasks complete, " + "phase_complete() for phase transitions, or " + "save_plan to create/restructure plans.");
|
|
53843
54009
|
}
|
|
@@ -53856,7 +54022,7 @@ function createGuardrailsHooks(directory, directoryOrConfig, config3, authorityC
|
|
|
53856
54022
|
}
|
|
53857
54023
|
}
|
|
53858
54024
|
}
|
|
53859
|
-
if (typeof targetPath === "string" && targetPath.length > 0 && isOutsideSwarmDir(targetPath, effectiveDirectory) && isSourceCodePath(
|
|
54025
|
+
if (typeof targetPath === "string" && targetPath.length > 0 && isOutsideSwarmDir(targetPath, effectiveDirectory) && isSourceCodePath(path36.relative(effectiveDirectory, path36.resolve(effectiveDirectory, targetPath)))) {
|
|
53860
54026
|
const session = swarmState.agentSessions.get(sessionID);
|
|
53861
54027
|
if (session) {
|
|
53862
54028
|
session.architectWriteCount++;
|
|
@@ -54531,8 +54697,8 @@ function checkFileAuthorityWithRules(agentName, filePath, cwd, effectiveRules) {
|
|
|
54531
54697
|
const normalizedAgent = agentName.toLowerCase();
|
|
54532
54698
|
const strippedAgent = stripKnownSwarmPrefix(agentName).toLowerCase();
|
|
54533
54699
|
const dir = cwd || process.cwd();
|
|
54534
|
-
const resolved =
|
|
54535
|
-
const normalizedPath =
|
|
54700
|
+
const resolved = path36.resolve(dir, filePath);
|
|
54701
|
+
const normalizedPath = path36.relative(dir, resolved).replace(/\\/g, "/");
|
|
54536
54702
|
const rules = effectiveRules[normalizedAgent] ?? effectiveRules[strippedAgent];
|
|
54537
54703
|
if (!rules) {
|
|
54538
54704
|
return { allowed: false, reason: `Unknown agent: ${agentName}` };
|
|
@@ -54614,10 +54780,10 @@ async function getEvidenceTaskId(session, directory) {
|
|
|
54614
54780
|
if (typeof directory !== "string" || directory.length === 0) {
|
|
54615
54781
|
return null;
|
|
54616
54782
|
}
|
|
54617
|
-
const resolvedDirectory =
|
|
54618
|
-
const planPath =
|
|
54619
|
-
const resolvedPlanPath =
|
|
54620
|
-
if (!resolvedPlanPath.startsWith(resolvedDirectory +
|
|
54783
|
+
const resolvedDirectory = path38.resolve(directory);
|
|
54784
|
+
const planPath = path38.join(resolvedDirectory, ".swarm", "plan.json");
|
|
54785
|
+
const resolvedPlanPath = path38.resolve(planPath);
|
|
54786
|
+
if (!resolvedPlanPath.startsWith(resolvedDirectory + path38.sep) && resolvedPlanPath !== resolvedDirectory) {
|
|
54621
54787
|
return null;
|
|
54622
54788
|
}
|
|
54623
54789
|
const planContent = await fs26.promises.readFile(resolvedPlanPath, "utf-8");
|
|
@@ -55345,7 +55511,7 @@ function consolidateSystemMessages(messages) {
|
|
|
55345
55511
|
// src/hooks/phase-monitor.ts
|
|
55346
55512
|
init_schema();
|
|
55347
55513
|
init_manager2();
|
|
55348
|
-
import * as
|
|
55514
|
+
import * as path40 from "path";
|
|
55349
55515
|
init_utils2();
|
|
55350
55516
|
function createPhaseMonitorHook(directory, preflightManager, curatorRunner, delegateFactory) {
|
|
55351
55517
|
let lastKnownPhase = null;
|
|
@@ -55366,9 +55532,9 @@ function createPhaseMonitorHook(directory, preflightManager, curatorRunner, dele
|
|
|
55366
55532
|
const llmDelegate = delegateFactory?.(sessionId);
|
|
55367
55533
|
const initResult = await runner(directory, curatorConfig, llmDelegate);
|
|
55368
55534
|
if (initResult.briefing) {
|
|
55369
|
-
const briefingPath =
|
|
55535
|
+
const briefingPath = path40.join(directory, ".swarm", "curator-briefing.md");
|
|
55370
55536
|
const { mkdir: mkdir5, writeFile: writeFile5 } = await import("fs/promises");
|
|
55371
|
-
await mkdir5(
|
|
55537
|
+
await mkdir5(path40.dirname(briefingPath), { recursive: true });
|
|
55372
55538
|
await writeFile5(briefingPath, initResult.briefing, "utf-8");
|
|
55373
55539
|
const { buildApprovedReceipt: buildApprovedReceipt2, persistReviewReceipt: persistReviewReceipt2 } = await Promise.resolve().then(() => (init_review_receipt(), exports_review_receipt));
|
|
55374
55540
|
const initReceipt = buildApprovedReceipt2({
|
|
@@ -55502,14 +55668,14 @@ init_manager();
|
|
|
55502
55668
|
init_detector();
|
|
55503
55669
|
init_manager2();
|
|
55504
55670
|
import * as fs32 from "fs";
|
|
55505
|
-
import * as
|
|
55671
|
+
import * as path44 from "path";
|
|
55506
55672
|
|
|
55507
55673
|
// src/services/decision-drift-analyzer.ts
|
|
55508
55674
|
init_utils2();
|
|
55509
55675
|
init_manager2();
|
|
55510
55676
|
init_utils();
|
|
55511
55677
|
import * as fs29 from "fs";
|
|
55512
|
-
import * as
|
|
55678
|
+
import * as path41 from "path";
|
|
55513
55679
|
var DEFAULT_DRIFT_CONFIG = {
|
|
55514
55680
|
staleThresholdPhases: 1,
|
|
55515
55681
|
detectContradictions: true,
|
|
@@ -55663,7 +55829,7 @@ async function analyzeDecisionDrift(directory, config3 = {}) {
|
|
|
55663
55829
|
currentPhase = legacyPhase;
|
|
55664
55830
|
}
|
|
55665
55831
|
}
|
|
55666
|
-
const contextPath =
|
|
55832
|
+
const contextPath = path41.join(directory, ".swarm", "context.md");
|
|
55667
55833
|
let contextContent = "";
|
|
55668
55834
|
try {
|
|
55669
55835
|
if (fs29.existsSync(contextPath)) {
|
|
@@ -55793,7 +55959,7 @@ init_utils();
|
|
|
55793
55959
|
init_constants();
|
|
55794
55960
|
init_schema();
|
|
55795
55961
|
import * as fs30 from "fs/promises";
|
|
55796
|
-
import * as
|
|
55962
|
+
import * as path42 from "path";
|
|
55797
55963
|
function safeGet(obj, key) {
|
|
55798
55964
|
if (!obj || !Object.hasOwn(obj, key))
|
|
55799
55965
|
return;
|
|
@@ -56007,9 +56173,9 @@ async function handleDebuggingSpiral(match, taskId, directory) {
|
|
|
56007
56173
|
let eventLogged = false;
|
|
56008
56174
|
let checkpointCreated = false;
|
|
56009
56175
|
try {
|
|
56010
|
-
const swarmDir =
|
|
56176
|
+
const swarmDir = path42.join(directory, ".swarm");
|
|
56011
56177
|
await fs30.mkdir(swarmDir, { recursive: true });
|
|
56012
|
-
const eventsPath =
|
|
56178
|
+
const eventsPath = path42.join(swarmDir, "events.jsonl");
|
|
56013
56179
|
await fs30.appendFile(eventsPath, `${formatDebuggingSpiralEvent(match, taskId)}
|
|
56014
56180
|
`);
|
|
56015
56181
|
eventLogged = true;
|
|
@@ -56406,7 +56572,7 @@ function createSystemEnhancerHook(config3, directory) {
|
|
|
56406
56572
|
await fs32.promises.writeFile(darkMatterPath, darkMatterReport, "utf-8");
|
|
56407
56573
|
warn(`[system-enhancer] Dark matter scan complete: ${darkMatter.length} co-change patterns found`);
|
|
56408
56574
|
try {
|
|
56409
|
-
const projectName =
|
|
56575
|
+
const projectName = path44.basename(path44.resolve(directory));
|
|
56410
56576
|
const knowledgeEntries = darkMatterToKnowledgeEntries2(darkMatter, projectName);
|
|
56411
56577
|
const knowledgePath = resolveSwarmKnowledgePath(directory);
|
|
56412
56578
|
const existingEntries = await readKnowledge(knowledgePath);
|
|
@@ -57530,7 +57696,7 @@ function isReadTool(toolName) {
|
|
|
57530
57696
|
|
|
57531
57697
|
// src/hooks/incremental-verify.ts
|
|
57532
57698
|
import * as fs33 from "fs";
|
|
57533
|
-
import * as
|
|
57699
|
+
import * as path45 from "path";
|
|
57534
57700
|
|
|
57535
57701
|
// src/hooks/spawn-helper.ts
|
|
57536
57702
|
import * as child_process4 from "child_process";
|
|
@@ -57608,18 +57774,18 @@ function spawnAsync(command, cwd, timeoutMs) {
|
|
|
57608
57774
|
// src/hooks/incremental-verify.ts
|
|
57609
57775
|
var emittedSkipAdvisories = new Set;
|
|
57610
57776
|
function detectPackageManager(projectDir) {
|
|
57611
|
-
if (fs33.existsSync(
|
|
57777
|
+
if (fs33.existsSync(path45.join(projectDir, "bun.lockb")))
|
|
57612
57778
|
return "bun";
|
|
57613
|
-
if (fs33.existsSync(
|
|
57779
|
+
if (fs33.existsSync(path45.join(projectDir, "pnpm-lock.yaml")))
|
|
57614
57780
|
return "pnpm";
|
|
57615
|
-
if (fs33.existsSync(
|
|
57781
|
+
if (fs33.existsSync(path45.join(projectDir, "yarn.lock")))
|
|
57616
57782
|
return "yarn";
|
|
57617
|
-
if (fs33.existsSync(
|
|
57783
|
+
if (fs33.existsSync(path45.join(projectDir, "package-lock.json")))
|
|
57618
57784
|
return "npm";
|
|
57619
57785
|
return "bun";
|
|
57620
57786
|
}
|
|
57621
57787
|
function detectTypecheckCommand(projectDir) {
|
|
57622
|
-
const pkgPath =
|
|
57788
|
+
const pkgPath = path45.join(projectDir, "package.json");
|
|
57623
57789
|
if (fs33.existsSync(pkgPath)) {
|
|
57624
57790
|
try {
|
|
57625
57791
|
const pkg = JSON.parse(fs33.readFileSync(pkgPath, "utf8"));
|
|
@@ -57636,8 +57802,8 @@ function detectTypecheckCommand(projectDir) {
|
|
|
57636
57802
|
...pkg.dependencies,
|
|
57637
57803
|
...pkg.devDependencies
|
|
57638
57804
|
};
|
|
57639
|
-
if (!deps?.typescript && !fs33.existsSync(
|
|
57640
|
-
const hasTSMarkers = deps?.typescript || fs33.existsSync(
|
|
57805
|
+
if (!deps?.typescript && !fs33.existsSync(path45.join(projectDir, "tsconfig.json"))) {}
|
|
57806
|
+
const hasTSMarkers = deps?.typescript || fs33.existsSync(path45.join(projectDir, "tsconfig.json"));
|
|
57641
57807
|
if (hasTSMarkers) {
|
|
57642
57808
|
return { command: ["npx", "tsc", "--noEmit"], language: "typescript" };
|
|
57643
57809
|
}
|
|
@@ -57645,13 +57811,13 @@ function detectTypecheckCommand(projectDir) {
|
|
|
57645
57811
|
return null;
|
|
57646
57812
|
}
|
|
57647
57813
|
}
|
|
57648
|
-
if (fs33.existsSync(
|
|
57814
|
+
if (fs33.existsSync(path45.join(projectDir, "go.mod"))) {
|
|
57649
57815
|
return { command: ["go", "vet", "./..."], language: "go" };
|
|
57650
57816
|
}
|
|
57651
|
-
if (fs33.existsSync(
|
|
57817
|
+
if (fs33.existsSync(path45.join(projectDir, "Cargo.toml"))) {
|
|
57652
57818
|
return { command: ["cargo", "check"], language: "rust" };
|
|
57653
57819
|
}
|
|
57654
|
-
if (fs33.existsSync(
|
|
57820
|
+
if (fs33.existsSync(path45.join(projectDir, "pyproject.toml")) || fs33.existsSync(path45.join(projectDir, "requirements.txt")) || fs33.existsSync(path45.join(projectDir, "setup.py"))) {
|
|
57655
57821
|
return { command: null, language: "python" };
|
|
57656
57822
|
}
|
|
57657
57823
|
try {
|
|
@@ -57952,7 +58118,7 @@ ${injectionText}`;
|
|
|
57952
58118
|
// src/hooks/scope-guard.ts
|
|
57953
58119
|
init_constants();
|
|
57954
58120
|
init_schema();
|
|
57955
|
-
import * as
|
|
58121
|
+
import * as path47 from "path";
|
|
57956
58122
|
var WRITE_TOOLS = new Set(WRITE_TOOL_NAMES);
|
|
57957
58123
|
function createScopeGuardHook(config3, directory, injectAdvisory) {
|
|
57958
58124
|
const enabled = config3.enabled ?? true;
|
|
@@ -58004,13 +58170,13 @@ function createScopeGuardHook(config3, directory, injectAdvisory) {
|
|
|
58004
58170
|
}
|
|
58005
58171
|
function isFileInScope(filePath, scopeEntries, directory) {
|
|
58006
58172
|
const dir = directory ?? process.cwd();
|
|
58007
|
-
const resolvedFile =
|
|
58173
|
+
const resolvedFile = path47.resolve(dir, filePath);
|
|
58008
58174
|
return scopeEntries.some((scope) => {
|
|
58009
|
-
const resolvedScope =
|
|
58175
|
+
const resolvedScope = path47.resolve(dir, scope);
|
|
58010
58176
|
if (resolvedFile === resolvedScope)
|
|
58011
58177
|
return true;
|
|
58012
|
-
const rel =
|
|
58013
|
-
return rel.length > 0 && !rel.startsWith("..") && !
|
|
58178
|
+
const rel = path47.relative(resolvedScope, resolvedFile);
|
|
58179
|
+
return rel.length > 0 && !rel.startsWith("..") && !path47.isAbsolute(rel);
|
|
58014
58180
|
});
|
|
58015
58181
|
}
|
|
58016
58182
|
|
|
@@ -58060,7 +58226,7 @@ function createSelfReviewHook(config3, injectAdvisory) {
|
|
|
58060
58226
|
|
|
58061
58227
|
// src/hooks/slop-detector.ts
|
|
58062
58228
|
import * as fs35 from "fs";
|
|
58063
|
-
import * as
|
|
58229
|
+
import * as path48 from "path";
|
|
58064
58230
|
var WRITE_EDIT_TOOLS = new Set([
|
|
58065
58231
|
"write",
|
|
58066
58232
|
"edit",
|
|
@@ -58110,7 +58276,7 @@ function walkFiles(dir, exts, deadline) {
|
|
|
58110
58276
|
break;
|
|
58111
58277
|
if (entry.isSymbolicLink())
|
|
58112
58278
|
continue;
|
|
58113
|
-
const full =
|
|
58279
|
+
const full = path48.join(dir, entry.name);
|
|
58114
58280
|
if (entry.isDirectory()) {
|
|
58115
58281
|
if (entry.name === "node_modules" || entry.name === ".git")
|
|
58116
58282
|
continue;
|
|
@@ -58125,7 +58291,7 @@ function walkFiles(dir, exts, deadline) {
|
|
|
58125
58291
|
return results;
|
|
58126
58292
|
}
|
|
58127
58293
|
function checkDeadExports(content, projectDir, startTime) {
|
|
58128
|
-
const hasPackageJson = fs35.existsSync(
|
|
58294
|
+
const hasPackageJson = fs35.existsSync(path48.join(projectDir, "package.json"));
|
|
58129
58295
|
if (!hasPackageJson)
|
|
58130
58296
|
return null;
|
|
58131
58297
|
const exportMatches = content.matchAll(/^\+(?:export)\s+(?:function|class|const|type|interface)\s+(\w{3,})/gm);
|
|
@@ -58528,13 +58694,13 @@ init_telemetry();
|
|
|
58528
58694
|
init_tool();
|
|
58529
58695
|
init_create_tool();
|
|
58530
58696
|
import * as fs38 from "fs";
|
|
58531
|
-
import * as
|
|
58697
|
+
import * as path50 from "path";
|
|
58532
58698
|
|
|
58533
58699
|
// src/tools/symbols.ts
|
|
58534
58700
|
init_tool();
|
|
58535
58701
|
init_create_tool();
|
|
58536
58702
|
import * as fs37 from "fs";
|
|
58537
|
-
import * as
|
|
58703
|
+
import * as path49 from "path";
|
|
58538
58704
|
var MAX_FILE_SIZE_BYTES2 = 1024 * 1024;
|
|
58539
58705
|
var WINDOWS_RESERVED_NAMES = /^(con|prn|aux|nul|com[1-9]|lpt[1-9])(\.|:|$)/i;
|
|
58540
58706
|
function containsWindowsAttacks(str) {
|
|
@@ -58551,11 +58717,11 @@ function containsWindowsAttacks(str) {
|
|
|
58551
58717
|
}
|
|
58552
58718
|
function isPathInWorkspace(filePath, workspace) {
|
|
58553
58719
|
try {
|
|
58554
|
-
const resolvedPath =
|
|
58720
|
+
const resolvedPath = path49.resolve(workspace, filePath);
|
|
58555
58721
|
const realWorkspace = fs37.realpathSync(workspace);
|
|
58556
58722
|
const realResolvedPath = fs37.realpathSync(resolvedPath);
|
|
58557
|
-
const relativePath =
|
|
58558
|
-
if (relativePath.startsWith("..") ||
|
|
58723
|
+
const relativePath = path49.relative(realWorkspace, realResolvedPath);
|
|
58724
|
+
if (relativePath.startsWith("..") || path49.isAbsolute(relativePath)) {
|
|
58559
58725
|
return false;
|
|
58560
58726
|
}
|
|
58561
58727
|
return true;
|
|
@@ -58567,7 +58733,7 @@ function validatePathForRead(filePath, workspace) {
|
|
|
58567
58733
|
return isPathInWorkspace(filePath, workspace);
|
|
58568
58734
|
}
|
|
58569
58735
|
function extractTSSymbols(filePath, cwd) {
|
|
58570
|
-
const fullPath =
|
|
58736
|
+
const fullPath = path49.join(cwd, filePath);
|
|
58571
58737
|
if (!validatePathForRead(fullPath, cwd)) {
|
|
58572
58738
|
return [];
|
|
58573
58739
|
}
|
|
@@ -58719,7 +58885,7 @@ function extractTSSymbols(filePath, cwd) {
|
|
|
58719
58885
|
});
|
|
58720
58886
|
}
|
|
58721
58887
|
function extractPythonSymbols(filePath, cwd) {
|
|
58722
|
-
const fullPath =
|
|
58888
|
+
const fullPath = path49.join(cwd, filePath);
|
|
58723
58889
|
if (!validatePathForRead(fullPath, cwd)) {
|
|
58724
58890
|
return [];
|
|
58725
58891
|
}
|
|
@@ -58802,7 +58968,7 @@ var symbols = createSwarmTool({
|
|
|
58802
58968
|
}, null, 2);
|
|
58803
58969
|
}
|
|
58804
58970
|
const cwd = directory;
|
|
58805
|
-
const ext =
|
|
58971
|
+
const ext = path49.extname(file3);
|
|
58806
58972
|
if (containsControlChars(file3)) {
|
|
58807
58973
|
return JSON.stringify({
|
|
58808
58974
|
file: file3,
|
|
@@ -58878,14 +59044,14 @@ function containsWindowsAttacks2(str) {
|
|
|
58878
59044
|
}
|
|
58879
59045
|
function isPathInWorkspace2(filePath, workspace) {
|
|
58880
59046
|
try {
|
|
58881
|
-
const resolvedPath =
|
|
59047
|
+
const resolvedPath = path50.resolve(workspace, filePath);
|
|
58882
59048
|
if (!fs38.existsSync(resolvedPath)) {
|
|
58883
59049
|
return true;
|
|
58884
59050
|
}
|
|
58885
59051
|
const realWorkspace = fs38.realpathSync(workspace);
|
|
58886
59052
|
const realResolvedPath = fs38.realpathSync(resolvedPath);
|
|
58887
|
-
const relativePath =
|
|
58888
|
-
if (relativePath.startsWith("..") ||
|
|
59053
|
+
const relativePath = path50.relative(realWorkspace, realResolvedPath);
|
|
59054
|
+
if (relativePath.startsWith("..") || path50.isAbsolute(relativePath)) {
|
|
58889
59055
|
return false;
|
|
58890
59056
|
}
|
|
58891
59057
|
return true;
|
|
@@ -58894,7 +59060,7 @@ function isPathInWorkspace2(filePath, workspace) {
|
|
|
58894
59060
|
}
|
|
58895
59061
|
}
|
|
58896
59062
|
function processFile(file3, cwd, exportedOnly) {
|
|
58897
|
-
const ext =
|
|
59063
|
+
const ext = path50.extname(file3);
|
|
58898
59064
|
if (containsControlChars(file3)) {
|
|
58899
59065
|
return {
|
|
58900
59066
|
file: file3,
|
|
@@ -58927,7 +59093,7 @@ function processFile(file3, cwd, exportedOnly) {
|
|
|
58927
59093
|
errorType: "path-outside-workspace"
|
|
58928
59094
|
};
|
|
58929
59095
|
}
|
|
58930
|
-
const fullPath =
|
|
59096
|
+
const fullPath = path50.join(cwd, file3);
|
|
58931
59097
|
if (!fs38.existsSync(fullPath)) {
|
|
58932
59098
|
return {
|
|
58933
59099
|
file: file3,
|
|
@@ -59218,7 +59384,7 @@ init_manager();
|
|
|
59218
59384
|
init_create_tool();
|
|
59219
59385
|
init_resolve_working_directory();
|
|
59220
59386
|
import * as fs39 from "fs";
|
|
59221
|
-
import * as
|
|
59387
|
+
import * as path51 from "path";
|
|
59222
59388
|
var EVIDENCE_DIR = ".swarm/evidence";
|
|
59223
59389
|
var TASK_ID_PATTERN2 = /^\d+\.\d+(\.\d+)*$/;
|
|
59224
59390
|
function isValidTaskId3(taskId) {
|
|
@@ -59235,9 +59401,9 @@ function isValidTaskId3(taskId) {
|
|
|
59235
59401
|
return TASK_ID_PATTERN2.test(taskId);
|
|
59236
59402
|
}
|
|
59237
59403
|
function isPathWithinSwarm(filePath, workspaceRoot) {
|
|
59238
|
-
const normalizedWorkspace =
|
|
59239
|
-
const swarmPath =
|
|
59240
|
-
const normalizedPath =
|
|
59404
|
+
const normalizedWorkspace = path51.resolve(workspaceRoot);
|
|
59405
|
+
const swarmPath = path51.join(normalizedWorkspace, ".swarm", "evidence");
|
|
59406
|
+
const normalizedPath = path51.resolve(filePath);
|
|
59241
59407
|
return normalizedPath.startsWith(swarmPath);
|
|
59242
59408
|
}
|
|
59243
59409
|
function readEvidenceFile(evidencePath) {
|
|
@@ -59318,7 +59484,7 @@ var check_gate_status = createSwarmTool({
|
|
|
59318
59484
|
};
|
|
59319
59485
|
return JSON.stringify(errorResult, null, 2);
|
|
59320
59486
|
}
|
|
59321
|
-
const evidencePath =
|
|
59487
|
+
const evidencePath = path51.join(directory, EVIDENCE_DIR, `${taskIdInput}.json`);
|
|
59322
59488
|
if (!isPathWithinSwarm(evidencePath, directory)) {
|
|
59323
59489
|
const errorResult = {
|
|
59324
59490
|
taskId: taskIdInput,
|
|
@@ -59412,7 +59578,7 @@ init_co_change_analyzer();
|
|
|
59412
59578
|
init_dist();
|
|
59413
59579
|
init_utils2();
|
|
59414
59580
|
import * as fs40 from "fs";
|
|
59415
|
-
import * as
|
|
59581
|
+
import * as path52 from "path";
|
|
59416
59582
|
init_create_tool();
|
|
59417
59583
|
init_resolve_working_directory();
|
|
59418
59584
|
function extractMatches(regex, text) {
|
|
@@ -59566,10 +59732,10 @@ async function executeCompletionVerify(args2, directory) {
|
|
|
59566
59732
|
let hasFileReadFailure = false;
|
|
59567
59733
|
for (const filePath of fileTargets) {
|
|
59568
59734
|
const normalizedPath = filePath.replace(/\\/g, "/");
|
|
59569
|
-
const resolvedPath =
|
|
59570
|
-
const projectRoot =
|
|
59571
|
-
const relative9 =
|
|
59572
|
-
const withinProject = relative9 === "" || !relative9.startsWith("..") && !
|
|
59735
|
+
const resolvedPath = path52.resolve(directory, normalizedPath);
|
|
59736
|
+
const projectRoot = path52.resolve(directory);
|
|
59737
|
+
const relative9 = path52.relative(projectRoot, resolvedPath);
|
|
59738
|
+
const withinProject = relative9 === "" || !relative9.startsWith("..") && !path52.isAbsolute(relative9);
|
|
59573
59739
|
if (!withinProject) {
|
|
59574
59740
|
blockedTasks.push({
|
|
59575
59741
|
task_id: task.id,
|
|
@@ -59624,8 +59790,8 @@ async function executeCompletionVerify(args2, directory) {
|
|
|
59624
59790
|
blockedTasks
|
|
59625
59791
|
};
|
|
59626
59792
|
try {
|
|
59627
|
-
const evidenceDir =
|
|
59628
|
-
const evidencePath =
|
|
59793
|
+
const evidenceDir = path52.join(directory, ".swarm", "evidence", `${phase}`);
|
|
59794
|
+
const evidencePath = path52.join(evidenceDir, "completion-verify.json");
|
|
59629
59795
|
fs40.mkdirSync(evidenceDir, { recursive: true });
|
|
59630
59796
|
const evidenceBundle = {
|
|
59631
59797
|
schema_version: "1.0.0",
|
|
@@ -59702,11 +59868,11 @@ var completion_verify = createSwarmTool({
|
|
|
59702
59868
|
// src/tools/complexity-hotspots.ts
|
|
59703
59869
|
init_dist();
|
|
59704
59870
|
import * as fs42 from "fs";
|
|
59705
|
-
import * as
|
|
59871
|
+
import * as path54 from "path";
|
|
59706
59872
|
|
|
59707
59873
|
// src/quality/metrics.ts
|
|
59708
59874
|
import * as fs41 from "fs";
|
|
59709
|
-
import * as
|
|
59875
|
+
import * as path53 from "path";
|
|
59710
59876
|
var MAX_FILE_SIZE_BYTES3 = 256 * 1024;
|
|
59711
59877
|
var MIN_DUPLICATION_LINES = 10;
|
|
59712
59878
|
function estimateCyclomaticComplexity(content) {
|
|
@@ -59758,7 +59924,7 @@ async function computeComplexityDelta(files, workingDir) {
|
|
|
59758
59924
|
let totalComplexity = 0;
|
|
59759
59925
|
const analyzedFiles = [];
|
|
59760
59926
|
for (const file3 of files) {
|
|
59761
|
-
const fullPath =
|
|
59927
|
+
const fullPath = path53.isAbsolute(file3) ? file3 : path53.join(workingDir, file3);
|
|
59762
59928
|
if (!fs41.existsSync(fullPath)) {
|
|
59763
59929
|
continue;
|
|
59764
59930
|
}
|
|
@@ -59881,7 +60047,7 @@ function countGoExports(content) {
|
|
|
59881
60047
|
function getExportCountForFile(filePath) {
|
|
59882
60048
|
try {
|
|
59883
60049
|
const content = fs41.readFileSync(filePath, "utf-8");
|
|
59884
|
-
const ext =
|
|
60050
|
+
const ext = path53.extname(filePath).toLowerCase();
|
|
59885
60051
|
switch (ext) {
|
|
59886
60052
|
case ".ts":
|
|
59887
60053
|
case ".tsx":
|
|
@@ -59907,7 +60073,7 @@ async function computePublicApiDelta(files, workingDir) {
|
|
|
59907
60073
|
let totalExports = 0;
|
|
59908
60074
|
const analyzedFiles = [];
|
|
59909
60075
|
for (const file3 of files) {
|
|
59910
|
-
const fullPath =
|
|
60076
|
+
const fullPath = path53.isAbsolute(file3) ? file3 : path53.join(workingDir, file3);
|
|
59911
60077
|
if (!fs41.existsSync(fullPath)) {
|
|
59912
60078
|
continue;
|
|
59913
60079
|
}
|
|
@@ -59941,7 +60107,7 @@ async function computeDuplicationRatio(files, workingDir) {
|
|
|
59941
60107
|
let duplicateLines = 0;
|
|
59942
60108
|
const analyzedFiles = [];
|
|
59943
60109
|
for (const file3 of files) {
|
|
59944
|
-
const fullPath =
|
|
60110
|
+
const fullPath = path53.isAbsolute(file3) ? file3 : path53.join(workingDir, file3);
|
|
59945
60111
|
if (!fs41.existsSync(fullPath)) {
|
|
59946
60112
|
continue;
|
|
59947
60113
|
}
|
|
@@ -59974,8 +60140,8 @@ function countCodeLines(content) {
|
|
|
59974
60140
|
return lines.length;
|
|
59975
60141
|
}
|
|
59976
60142
|
function isTestFile(filePath) {
|
|
59977
|
-
const basename8 =
|
|
59978
|
-
const _ext =
|
|
60143
|
+
const basename8 = path53.basename(filePath);
|
|
60144
|
+
const _ext = path53.extname(filePath).toLowerCase();
|
|
59979
60145
|
const testPatterns = [
|
|
59980
60146
|
".test.",
|
|
59981
60147
|
".spec.",
|
|
@@ -60056,8 +60222,8 @@ function matchGlobSegment(globSegments, pathSegments) {
|
|
|
60056
60222
|
}
|
|
60057
60223
|
return gIndex === globSegments.length && pIndex === pathSegments.length;
|
|
60058
60224
|
}
|
|
60059
|
-
function matchesGlobSegment(
|
|
60060
|
-
const normalizedPath =
|
|
60225
|
+
function matchesGlobSegment(path54, glob) {
|
|
60226
|
+
const normalizedPath = path54.replace(/\\/g, "/");
|
|
60061
60227
|
const normalizedGlob = glob.replace(/\\/g, "/");
|
|
60062
60228
|
if (normalizedPath.includes("//")) {
|
|
60063
60229
|
return false;
|
|
@@ -60088,8 +60254,8 @@ function simpleGlobToRegex2(glob) {
|
|
|
60088
60254
|
function hasGlobstar(glob) {
|
|
60089
60255
|
return glob.includes("**");
|
|
60090
60256
|
}
|
|
60091
|
-
function globMatches(
|
|
60092
|
-
const normalizedPath =
|
|
60257
|
+
function globMatches(path54, glob) {
|
|
60258
|
+
const normalizedPath = path54.replace(/\\/g, "/");
|
|
60093
60259
|
if (!glob || glob === "") {
|
|
60094
60260
|
if (normalizedPath.includes("//")) {
|
|
60095
60261
|
return false;
|
|
@@ -60125,7 +60291,7 @@ function shouldExcludeFile(filePath, excludeGlobs) {
|
|
|
60125
60291
|
async function computeTestToCodeRatio(workingDir, enforceGlobs, excludeGlobs) {
|
|
60126
60292
|
let testLines = 0;
|
|
60127
60293
|
let codeLines = 0;
|
|
60128
|
-
const srcDir =
|
|
60294
|
+
const srcDir = path53.join(workingDir, "src");
|
|
60129
60295
|
if (fs41.existsSync(srcDir)) {
|
|
60130
60296
|
await scanDirectoryForLines(srcDir, enforceGlobs, excludeGlobs, false, (lines) => {
|
|
60131
60297
|
codeLines += lines;
|
|
@@ -60133,14 +60299,14 @@ async function computeTestToCodeRatio(workingDir, enforceGlobs, excludeGlobs) {
|
|
|
60133
60299
|
}
|
|
60134
60300
|
const possibleSrcDirs = ["lib", "app", "source", "core"];
|
|
60135
60301
|
for (const dir of possibleSrcDirs) {
|
|
60136
|
-
const dirPath =
|
|
60302
|
+
const dirPath = path53.join(workingDir, dir);
|
|
60137
60303
|
if (fs41.existsSync(dirPath)) {
|
|
60138
60304
|
await scanDirectoryForLines(dirPath, enforceGlobs, excludeGlobs, false, (lines) => {
|
|
60139
60305
|
codeLines += lines;
|
|
60140
60306
|
});
|
|
60141
60307
|
}
|
|
60142
60308
|
}
|
|
60143
|
-
const testsDir =
|
|
60309
|
+
const testsDir = path53.join(workingDir, "tests");
|
|
60144
60310
|
if (fs41.existsSync(testsDir)) {
|
|
60145
60311
|
await scanDirectoryForLines(testsDir, ["**"], ["node_modules", "dist"], true, (lines) => {
|
|
60146
60312
|
testLines += lines;
|
|
@@ -60148,7 +60314,7 @@ async function computeTestToCodeRatio(workingDir, enforceGlobs, excludeGlobs) {
|
|
|
60148
60314
|
}
|
|
60149
60315
|
const possibleTestDirs = ["test", "__tests__", "specs"];
|
|
60150
60316
|
for (const dir of possibleTestDirs) {
|
|
60151
|
-
const dirPath =
|
|
60317
|
+
const dirPath = path53.join(workingDir, dir);
|
|
60152
60318
|
if (fs41.existsSync(dirPath) && dirPath !== testsDir) {
|
|
60153
60319
|
await scanDirectoryForLines(dirPath, ["**"], ["node_modules", "dist"], true, (lines) => {
|
|
60154
60320
|
testLines += lines;
|
|
@@ -60163,7 +60329,7 @@ async function scanDirectoryForLines(dirPath, includeGlobs, excludeGlobs, isTest
|
|
|
60163
60329
|
try {
|
|
60164
60330
|
const entries = fs41.readdirSync(dirPath, { withFileTypes: true });
|
|
60165
60331
|
for (const entry of entries) {
|
|
60166
|
-
const fullPath =
|
|
60332
|
+
const fullPath = path53.join(dirPath, entry.name);
|
|
60167
60333
|
if (entry.isDirectory()) {
|
|
60168
60334
|
if (entry.name === "node_modules" || entry.name === "dist" || entry.name === "build" || entry.name === ".git") {
|
|
60169
60335
|
continue;
|
|
@@ -60171,7 +60337,7 @@ async function scanDirectoryForLines(dirPath, includeGlobs, excludeGlobs, isTest
|
|
|
60171
60337
|
await scanDirectoryForLines(fullPath, includeGlobs, excludeGlobs, isTestScan, callback);
|
|
60172
60338
|
} else if (entry.isFile()) {
|
|
60173
60339
|
const relativePath = fullPath.replace(`${dirPath}/`, "");
|
|
60174
|
-
const ext =
|
|
60340
|
+
const ext = path53.extname(entry.name).toLowerCase();
|
|
60175
60341
|
const validExts = [
|
|
60176
60342
|
".ts",
|
|
60177
60343
|
".tsx",
|
|
@@ -60423,7 +60589,7 @@ async function analyzeHotspots(days, topN, extensions, directory) {
|
|
|
60423
60589
|
const extSet = new Set(extensions.map((e) => e.startsWith(".") ? e : `.${e}`));
|
|
60424
60590
|
const filteredChurn = new Map;
|
|
60425
60591
|
for (const [file3, count] of churnMap) {
|
|
60426
|
-
const ext =
|
|
60592
|
+
const ext = path54.extname(file3).toLowerCase();
|
|
60427
60593
|
if (extSet.has(ext)) {
|
|
60428
60594
|
filteredChurn.set(file3, count);
|
|
60429
60595
|
}
|
|
@@ -60434,7 +60600,7 @@ async function analyzeHotspots(days, topN, extensions, directory) {
|
|
|
60434
60600
|
for (const [file3, churnCount] of filteredChurn) {
|
|
60435
60601
|
let fullPath = file3;
|
|
60436
60602
|
if (!fs42.existsSync(fullPath)) {
|
|
60437
|
-
fullPath =
|
|
60603
|
+
fullPath = path54.join(cwd, file3);
|
|
60438
60604
|
}
|
|
60439
60605
|
const complexity = getComplexityForFile2(fullPath);
|
|
60440
60606
|
if (complexity !== null) {
|
|
@@ -60682,7 +60848,7 @@ var curator_analyze = createSwarmTool({
|
|
|
60682
60848
|
// src/tools/declare-scope.ts
|
|
60683
60849
|
init_tool();
|
|
60684
60850
|
import * as fs43 from "fs";
|
|
60685
|
-
import * as
|
|
60851
|
+
import * as path55 from "path";
|
|
60686
60852
|
init_create_tool();
|
|
60687
60853
|
function validateTaskIdFormat(taskId) {
|
|
60688
60854
|
const taskIdPattern = /^\d+\.\d+(\.\d+)*$/;
|
|
@@ -60761,8 +60927,8 @@ async function executeDeclareScope(args2, fallbackDir) {
|
|
|
60761
60927
|
};
|
|
60762
60928
|
}
|
|
60763
60929
|
}
|
|
60764
|
-
normalizedDir =
|
|
60765
|
-
const pathParts = normalizedDir.split(
|
|
60930
|
+
normalizedDir = path55.normalize(args2.working_directory);
|
|
60931
|
+
const pathParts = normalizedDir.split(path55.sep);
|
|
60766
60932
|
if (pathParts.includes("..")) {
|
|
60767
60933
|
return {
|
|
60768
60934
|
success: false,
|
|
@@ -60772,10 +60938,10 @@ async function executeDeclareScope(args2, fallbackDir) {
|
|
|
60772
60938
|
]
|
|
60773
60939
|
};
|
|
60774
60940
|
}
|
|
60775
|
-
const resolvedDir =
|
|
60941
|
+
const resolvedDir = path55.resolve(normalizedDir);
|
|
60776
60942
|
try {
|
|
60777
60943
|
const realPath = fs43.realpathSync(resolvedDir);
|
|
60778
|
-
const planPath2 =
|
|
60944
|
+
const planPath2 = path55.join(realPath, ".swarm", "plan.json");
|
|
60779
60945
|
if (!fs43.existsSync(planPath2)) {
|
|
60780
60946
|
return {
|
|
60781
60947
|
success: false,
|
|
@@ -60799,7 +60965,7 @@ async function executeDeclareScope(args2, fallbackDir) {
|
|
|
60799
60965
|
console.warn("[declare-scope] fallbackDir is undefined, falling back to process.cwd()");
|
|
60800
60966
|
}
|
|
60801
60967
|
const directory = normalizedDir || fallbackDir;
|
|
60802
|
-
const planPath =
|
|
60968
|
+
const planPath = path55.resolve(directory, ".swarm", "plan.json");
|
|
60803
60969
|
if (!fs43.existsSync(planPath)) {
|
|
60804
60970
|
return {
|
|
60805
60971
|
success: false,
|
|
@@ -60841,8 +61007,8 @@ async function executeDeclareScope(args2, fallbackDir) {
|
|
|
60841
61007
|
const normalizeErrors = [];
|
|
60842
61008
|
const dir = normalizedDir || fallbackDir || process.cwd();
|
|
60843
61009
|
const mergedFiles = rawMergedFiles.map((file3) => {
|
|
60844
|
-
if (
|
|
60845
|
-
const relativePath =
|
|
61010
|
+
if (path55.isAbsolute(file3)) {
|
|
61011
|
+
const relativePath = path55.relative(dir, file3).replace(/\\/g, "/");
|
|
60846
61012
|
if (relativePath.startsWith("..")) {
|
|
60847
61013
|
normalizeErrors.push(`Path '${file3}' resolves outside the project directory`);
|
|
60848
61014
|
return file3;
|
|
@@ -61168,20 +61334,20 @@ function validateBase(base) {
|
|
|
61168
61334
|
function validatePaths(paths) {
|
|
61169
61335
|
if (!paths)
|
|
61170
61336
|
return null;
|
|
61171
|
-
for (const
|
|
61172
|
-
if (!
|
|
61337
|
+
for (const path57 of paths) {
|
|
61338
|
+
if (!path57 || path57.length === 0) {
|
|
61173
61339
|
return "empty path not allowed";
|
|
61174
61340
|
}
|
|
61175
|
-
if (
|
|
61341
|
+
if (path57.length > MAX_PATH_LENGTH) {
|
|
61176
61342
|
return `path exceeds maximum length of ${MAX_PATH_LENGTH}`;
|
|
61177
61343
|
}
|
|
61178
|
-
if (SHELL_METACHARACTERS2.test(
|
|
61344
|
+
if (SHELL_METACHARACTERS2.test(path57)) {
|
|
61179
61345
|
return "path contains shell metacharacters";
|
|
61180
61346
|
}
|
|
61181
|
-
if (
|
|
61347
|
+
if (path57.startsWith("-")) {
|
|
61182
61348
|
return 'path cannot start with "-" (option-like arguments not allowed)';
|
|
61183
61349
|
}
|
|
61184
|
-
if (CONTROL_CHAR_PATTERN2.test(
|
|
61350
|
+
if (CONTROL_CHAR_PATTERN2.test(path57)) {
|
|
61185
61351
|
return "path contains control characters";
|
|
61186
61352
|
}
|
|
61187
61353
|
}
|
|
@@ -61262,8 +61428,8 @@ var diff = createSwarmTool({
|
|
|
61262
61428
|
if (parts2.length >= 3) {
|
|
61263
61429
|
const additions = parseInt(parts2[0], 10) || 0;
|
|
61264
61430
|
const deletions = parseInt(parts2[1], 10) || 0;
|
|
61265
|
-
const
|
|
61266
|
-
files.push({ path:
|
|
61431
|
+
const path57 = parts2[2];
|
|
61432
|
+
files.push({ path: path57, additions, deletions });
|
|
61267
61433
|
}
|
|
61268
61434
|
}
|
|
61269
61435
|
const contractChanges = [];
|
|
@@ -61546,7 +61712,7 @@ Use these as DOMAIN values when delegating to @sme.`;
|
|
|
61546
61712
|
init_dist();
|
|
61547
61713
|
init_create_tool();
|
|
61548
61714
|
import * as fs44 from "fs";
|
|
61549
|
-
import * as
|
|
61715
|
+
import * as path57 from "path";
|
|
61550
61716
|
var MAX_FILE_SIZE_BYTES5 = 1024 * 1024;
|
|
61551
61717
|
var MAX_EVIDENCE_FILES = 1000;
|
|
61552
61718
|
var EVIDENCE_DIR2 = ".swarm/evidence";
|
|
@@ -61573,9 +61739,9 @@ function validateRequiredTypes(input) {
|
|
|
61573
61739
|
return null;
|
|
61574
61740
|
}
|
|
61575
61741
|
function isPathWithinSwarm2(filePath, cwd) {
|
|
61576
|
-
const normalizedCwd =
|
|
61577
|
-
const swarmPath =
|
|
61578
|
-
const normalizedPath =
|
|
61742
|
+
const normalizedCwd = path57.resolve(cwd);
|
|
61743
|
+
const swarmPath = path57.join(normalizedCwd, ".swarm");
|
|
61744
|
+
const normalizedPath = path57.resolve(filePath);
|
|
61579
61745
|
return normalizedPath.startsWith(swarmPath);
|
|
61580
61746
|
}
|
|
61581
61747
|
function parseCompletedTasks(planContent) {
|
|
@@ -61605,10 +61771,10 @@ function readEvidenceFiles(evidenceDir, _cwd) {
|
|
|
61605
61771
|
if (!VALID_EVIDENCE_FILENAME_REGEX.test(filename)) {
|
|
61606
61772
|
continue;
|
|
61607
61773
|
}
|
|
61608
|
-
const filePath =
|
|
61774
|
+
const filePath = path57.join(evidenceDir, filename);
|
|
61609
61775
|
try {
|
|
61610
|
-
const resolvedPath =
|
|
61611
|
-
const evidenceDirResolved =
|
|
61776
|
+
const resolvedPath = path57.resolve(filePath);
|
|
61777
|
+
const evidenceDirResolved = path57.resolve(evidenceDir);
|
|
61612
61778
|
if (!resolvedPath.startsWith(evidenceDirResolved)) {
|
|
61613
61779
|
continue;
|
|
61614
61780
|
}
|
|
@@ -61726,7 +61892,7 @@ var evidence_check = createSwarmTool({
|
|
|
61726
61892
|
return JSON.stringify(errorResult, null, 2);
|
|
61727
61893
|
}
|
|
61728
61894
|
const requiredTypes = requiredTypesValue.split(",").map((t) => t.trim()).filter((t) => t.length > 0).map(normalizeEvidenceType);
|
|
61729
|
-
const planPath =
|
|
61895
|
+
const planPath = path57.join(cwd, PLAN_FILE);
|
|
61730
61896
|
if (!isPathWithinSwarm2(planPath, cwd)) {
|
|
61731
61897
|
const errorResult = {
|
|
61732
61898
|
error: "plan file path validation failed",
|
|
@@ -61758,7 +61924,7 @@ var evidence_check = createSwarmTool({
|
|
|
61758
61924
|
};
|
|
61759
61925
|
return JSON.stringify(result2, null, 2);
|
|
61760
61926
|
}
|
|
61761
|
-
const evidenceDir =
|
|
61927
|
+
const evidenceDir = path57.join(cwd, EVIDENCE_DIR2);
|
|
61762
61928
|
const evidence = readEvidenceFiles(evidenceDir, cwd);
|
|
61763
61929
|
const { tasksWithFullEvidence, gaps } = analyzeGaps(completedTasks, evidence, requiredTypes);
|
|
61764
61930
|
const completeness = completedTasks.length > 0 ? Math.round(tasksWithFullEvidence.length / completedTasks.length * 100) / 100 : 1;
|
|
@@ -61776,7 +61942,7 @@ var evidence_check = createSwarmTool({
|
|
|
61776
61942
|
init_tool();
|
|
61777
61943
|
init_create_tool();
|
|
61778
61944
|
import * as fs45 from "fs";
|
|
61779
|
-
import * as
|
|
61945
|
+
import * as path58 from "path";
|
|
61780
61946
|
var EXT_MAP = {
|
|
61781
61947
|
python: ".py",
|
|
61782
61948
|
py: ".py",
|
|
@@ -61857,12 +62023,12 @@ var extract_code_blocks = createSwarmTool({
|
|
|
61857
62023
|
if (prefix) {
|
|
61858
62024
|
filename = `${prefix}_${filename}`;
|
|
61859
62025
|
}
|
|
61860
|
-
let filepath =
|
|
61861
|
-
const base =
|
|
61862
|
-
const ext =
|
|
62026
|
+
let filepath = path58.join(targetDir, filename);
|
|
62027
|
+
const base = path58.basename(filepath, path58.extname(filepath));
|
|
62028
|
+
const ext = path58.extname(filepath);
|
|
61863
62029
|
let counter = 1;
|
|
61864
62030
|
while (fs45.existsSync(filepath)) {
|
|
61865
|
-
filepath =
|
|
62031
|
+
filepath = path58.join(targetDir, `${base}_${counter}${ext}`);
|
|
61866
62032
|
counter++;
|
|
61867
62033
|
}
|
|
61868
62034
|
try {
|
|
@@ -61983,7 +62149,7 @@ var gitingest = createSwarmTool({
|
|
|
61983
62149
|
init_dist();
|
|
61984
62150
|
init_create_tool();
|
|
61985
62151
|
import * as fs46 from "fs";
|
|
61986
|
-
import * as
|
|
62152
|
+
import * as path59 from "path";
|
|
61987
62153
|
var MAX_FILE_PATH_LENGTH2 = 500;
|
|
61988
62154
|
var MAX_SYMBOL_LENGTH = 256;
|
|
61989
62155
|
var MAX_FILE_SIZE_BYTES6 = 1024 * 1024;
|
|
@@ -62031,7 +62197,7 @@ function validateSymbolInput(symbol3) {
|
|
|
62031
62197
|
return null;
|
|
62032
62198
|
}
|
|
62033
62199
|
function isBinaryFile2(filePath, buffer) {
|
|
62034
|
-
const ext =
|
|
62200
|
+
const ext = path59.extname(filePath).toLowerCase();
|
|
62035
62201
|
if (ext === ".json" || ext === ".md" || ext === ".txt") {
|
|
62036
62202
|
return false;
|
|
62037
62203
|
}
|
|
@@ -62055,15 +62221,15 @@ function parseImports(content, targetFile, targetSymbol) {
|
|
|
62055
62221
|
const imports = [];
|
|
62056
62222
|
let _resolvedTarget;
|
|
62057
62223
|
try {
|
|
62058
|
-
_resolvedTarget =
|
|
62224
|
+
_resolvedTarget = path59.resolve(targetFile);
|
|
62059
62225
|
} catch {
|
|
62060
62226
|
_resolvedTarget = targetFile;
|
|
62061
62227
|
}
|
|
62062
|
-
const targetBasename =
|
|
62228
|
+
const targetBasename = path59.basename(targetFile, path59.extname(targetFile));
|
|
62063
62229
|
const targetWithExt = targetFile;
|
|
62064
62230
|
const targetWithoutExt = targetFile.replace(/\.(ts|tsx|js|jsx|mjs|cjs)$/i, "");
|
|
62065
|
-
const normalizedTargetWithExt =
|
|
62066
|
-
const normalizedTargetWithoutExt =
|
|
62231
|
+
const normalizedTargetWithExt = path59.normalize(targetWithExt).replace(/\\/g, "/");
|
|
62232
|
+
const normalizedTargetWithoutExt = path59.normalize(targetWithoutExt).replace(/\\/g, "/");
|
|
62067
62233
|
const importRegex = /import\s+(?:\{[\s\S]*?\}|(?:\*\s+as\s+\w+)|\w+)\s+from\s+['"`]([^'"`]+)['"`]|import\s+['"`]([^'"`]+)['"`]|require\s*\(\s*['"`]([^'"`]+)['"`]\s*\)/g;
|
|
62068
62234
|
for (let match = importRegex.exec(content);match !== null; match = importRegex.exec(content)) {
|
|
62069
62235
|
const modulePath = match[1] || match[2] || match[3];
|
|
@@ -62086,9 +62252,9 @@ function parseImports(content, targetFile, targetSymbol) {
|
|
|
62086
62252
|
}
|
|
62087
62253
|
const _normalizedModule = modulePath.replace(/^\.\//, "").replace(/^\.\.\\/, "../");
|
|
62088
62254
|
let isMatch = false;
|
|
62089
|
-
const _targetDir =
|
|
62090
|
-
const targetExt =
|
|
62091
|
-
const targetBasenameNoExt =
|
|
62255
|
+
const _targetDir = path59.dirname(targetFile);
|
|
62256
|
+
const targetExt = path59.extname(targetFile);
|
|
62257
|
+
const targetBasenameNoExt = path59.basename(targetFile, targetExt);
|
|
62092
62258
|
const moduleNormalized = modulePath.replace(/\\/g, "/").replace(/^\.\//, "");
|
|
62093
62259
|
const moduleName = modulePath.split(/[/\\]/).pop() || "";
|
|
62094
62260
|
const moduleNameNoExt = moduleName.replace(/\.(ts|tsx|js|jsx|mjs|cjs)$/i, "");
|
|
@@ -62156,10 +62322,10 @@ function findSourceFiles(dir, files = [], stats = { skippedDirs: [], skippedFile
|
|
|
62156
62322
|
entries.sort((a, b) => a.toLowerCase().localeCompare(b.toLowerCase()));
|
|
62157
62323
|
for (const entry of entries) {
|
|
62158
62324
|
if (SKIP_DIRECTORIES3.has(entry)) {
|
|
62159
|
-
stats.skippedDirs.push(
|
|
62325
|
+
stats.skippedDirs.push(path59.join(dir, entry));
|
|
62160
62326
|
continue;
|
|
62161
62327
|
}
|
|
62162
|
-
const fullPath =
|
|
62328
|
+
const fullPath = path59.join(dir, entry);
|
|
62163
62329
|
let stat2;
|
|
62164
62330
|
try {
|
|
62165
62331
|
stat2 = fs46.statSync(fullPath);
|
|
@@ -62173,7 +62339,7 @@ function findSourceFiles(dir, files = [], stats = { skippedDirs: [], skippedFile
|
|
|
62173
62339
|
if (stat2.isDirectory()) {
|
|
62174
62340
|
findSourceFiles(fullPath, files, stats);
|
|
62175
62341
|
} else if (stat2.isFile()) {
|
|
62176
|
-
const ext =
|
|
62342
|
+
const ext = path59.extname(fullPath).toLowerCase();
|
|
62177
62343
|
if (SUPPORTED_EXTENSIONS.includes(ext)) {
|
|
62178
62344
|
files.push(fullPath);
|
|
62179
62345
|
}
|
|
@@ -62230,7 +62396,7 @@ var imports = createSwarmTool({
|
|
|
62230
62396
|
return JSON.stringify(errorResult, null, 2);
|
|
62231
62397
|
}
|
|
62232
62398
|
try {
|
|
62233
|
-
const targetFile =
|
|
62399
|
+
const targetFile = path59.resolve(file3);
|
|
62234
62400
|
if (!fs46.existsSync(targetFile)) {
|
|
62235
62401
|
const errorResult = {
|
|
62236
62402
|
error: `target file not found: ${file3}`,
|
|
@@ -62252,7 +62418,7 @@ var imports = createSwarmTool({
|
|
|
62252
62418
|
};
|
|
62253
62419
|
return JSON.stringify(errorResult, null, 2);
|
|
62254
62420
|
}
|
|
62255
|
-
const baseDir =
|
|
62421
|
+
const baseDir = path59.dirname(targetFile);
|
|
62256
62422
|
const scanStats = {
|
|
62257
62423
|
skippedDirs: [],
|
|
62258
62424
|
skippedFiles: 0,
|
|
@@ -62472,7 +62638,7 @@ init_dist();
|
|
|
62472
62638
|
init_config();
|
|
62473
62639
|
init_knowledge_store();
|
|
62474
62640
|
init_create_tool();
|
|
62475
|
-
import { existsSync as
|
|
62641
|
+
import { existsSync as existsSync37 } from "fs";
|
|
62476
62642
|
var DEFAULT_LIMIT = 10;
|
|
62477
62643
|
var MAX_LESSON_LENGTH = 200;
|
|
62478
62644
|
var VALID_CATEGORIES3 = [
|
|
@@ -62541,14 +62707,14 @@ function validateLimit(limit) {
|
|
|
62541
62707
|
}
|
|
62542
62708
|
async function readSwarmKnowledge(directory) {
|
|
62543
62709
|
const swarmPath = resolveSwarmKnowledgePath(directory);
|
|
62544
|
-
if (!
|
|
62710
|
+
if (!existsSync37(swarmPath)) {
|
|
62545
62711
|
return [];
|
|
62546
62712
|
}
|
|
62547
62713
|
return readKnowledge(swarmPath);
|
|
62548
62714
|
}
|
|
62549
62715
|
async function readHiveKnowledge() {
|
|
62550
62716
|
const hivePath = resolveHiveKnowledgePath();
|
|
62551
|
-
if (!
|
|
62717
|
+
if (!existsSync37(hivePath)) {
|
|
62552
62718
|
return [];
|
|
62553
62719
|
}
|
|
62554
62720
|
return readKnowledge(hivePath);
|
|
@@ -62862,7 +63028,7 @@ init_config();
|
|
|
62862
63028
|
init_schema();
|
|
62863
63029
|
init_manager();
|
|
62864
63030
|
import * as fs47 from "fs";
|
|
62865
|
-
import * as
|
|
63031
|
+
import * as path60 from "path";
|
|
62866
63032
|
init_review_receipt();
|
|
62867
63033
|
init_utils2();
|
|
62868
63034
|
init_ledger();
|
|
@@ -63086,7 +63252,7 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
|
|
|
63086
63252
|
safeWarn(`[phase_complete] Completion verify error (non-blocking):`, completionError);
|
|
63087
63253
|
}
|
|
63088
63254
|
try {
|
|
63089
|
-
const driftEvidencePath =
|
|
63255
|
+
const driftEvidencePath = path60.join(dir, ".swarm", "evidence", String(phase), "drift-verifier.json");
|
|
63090
63256
|
let driftVerdictFound = false;
|
|
63091
63257
|
let driftVerdictApproved = false;
|
|
63092
63258
|
try {
|
|
@@ -63120,7 +63286,7 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
|
|
|
63120
63286
|
driftVerdictFound = false;
|
|
63121
63287
|
}
|
|
63122
63288
|
if (!driftVerdictFound) {
|
|
63123
|
-
const specPath =
|
|
63289
|
+
const specPath = path60.join(dir, ".swarm", "spec.md");
|
|
63124
63290
|
const specExists = fs47.existsSync(specPath);
|
|
63125
63291
|
if (!specExists) {
|
|
63126
63292
|
let incompleteTaskCount = 0;
|
|
@@ -63172,7 +63338,7 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
|
|
|
63172
63338
|
const knowledgeConfig = KnowledgeConfigSchema.parse(config3.knowledge ?? {});
|
|
63173
63339
|
if (retroFound && retroEntry?.lessons_learned && retroEntry.lessons_learned.length > 0) {
|
|
63174
63340
|
try {
|
|
63175
|
-
const projectName =
|
|
63341
|
+
const projectName = path60.basename(dir);
|
|
63176
63342
|
const curationResult = await curateAndStoreSwarm(retroEntry.lessons_learned, projectName, { phase_number: phase }, dir, knowledgeConfig);
|
|
63177
63343
|
if (curationResult) {
|
|
63178
63344
|
const sessionState = swarmState.agentSessions.get(sessionID);
|
|
@@ -63492,7 +63658,7 @@ init_discovery();
|
|
|
63492
63658
|
init_utils();
|
|
63493
63659
|
init_create_tool();
|
|
63494
63660
|
import * as fs48 from "fs";
|
|
63495
|
-
import * as
|
|
63661
|
+
import * as path61 from "path";
|
|
63496
63662
|
var MAX_OUTPUT_BYTES5 = 52428800;
|
|
63497
63663
|
var AUDIT_TIMEOUT_MS = 120000;
|
|
63498
63664
|
function isValidEcosystem(value) {
|
|
@@ -63510,16 +63676,16 @@ function validateArgs3(args2) {
|
|
|
63510
63676
|
function detectEcosystems(directory) {
|
|
63511
63677
|
const ecosystems = [];
|
|
63512
63678
|
const cwd = directory;
|
|
63513
|
-
if (fs48.existsSync(
|
|
63679
|
+
if (fs48.existsSync(path61.join(cwd, "package.json"))) {
|
|
63514
63680
|
ecosystems.push("npm");
|
|
63515
63681
|
}
|
|
63516
|
-
if (fs48.existsSync(
|
|
63682
|
+
if (fs48.existsSync(path61.join(cwd, "pyproject.toml")) || fs48.existsSync(path61.join(cwd, "requirements.txt"))) {
|
|
63517
63683
|
ecosystems.push("pip");
|
|
63518
63684
|
}
|
|
63519
|
-
if (fs48.existsSync(
|
|
63685
|
+
if (fs48.existsSync(path61.join(cwd, "Cargo.toml"))) {
|
|
63520
63686
|
ecosystems.push("cargo");
|
|
63521
63687
|
}
|
|
63522
|
-
if (fs48.existsSync(
|
|
63688
|
+
if (fs48.existsSync(path61.join(cwd, "go.mod"))) {
|
|
63523
63689
|
ecosystems.push("go");
|
|
63524
63690
|
}
|
|
63525
63691
|
try {
|
|
@@ -63528,10 +63694,10 @@ function detectEcosystems(directory) {
|
|
|
63528
63694
|
ecosystems.push("dotnet");
|
|
63529
63695
|
}
|
|
63530
63696
|
} catch {}
|
|
63531
|
-
if (fs48.existsSync(
|
|
63697
|
+
if (fs48.existsSync(path61.join(cwd, "Gemfile")) || fs48.existsSync(path61.join(cwd, "Gemfile.lock"))) {
|
|
63532
63698
|
ecosystems.push("ruby");
|
|
63533
63699
|
}
|
|
63534
|
-
if (fs48.existsSync(
|
|
63700
|
+
if (fs48.existsSync(path61.join(cwd, "pubspec.yaml"))) {
|
|
63535
63701
|
ecosystems.push("dart");
|
|
63536
63702
|
}
|
|
63537
63703
|
return ecosystems;
|
|
@@ -64554,7 +64720,7 @@ var SUPPORTED_PARSER_EXTENSIONS = new Set([
|
|
|
64554
64720
|
// src/tools/pre-check-batch.ts
|
|
64555
64721
|
init_dist();
|
|
64556
64722
|
import * as fs50 from "fs";
|
|
64557
|
-
import * as
|
|
64723
|
+
import * as path63 from "path";
|
|
64558
64724
|
|
|
64559
64725
|
// node_modules/yocto-queue/index.js
|
|
64560
64726
|
class Node2 {
|
|
@@ -64829,7 +64995,7 @@ init_dist();
|
|
|
64829
64995
|
init_manager();
|
|
64830
64996
|
init_detector();
|
|
64831
64997
|
import * as fs49 from "fs";
|
|
64832
|
-
import * as
|
|
64998
|
+
import * as path62 from "path";
|
|
64833
64999
|
import { extname as extname12 } from "path";
|
|
64834
65000
|
|
|
64835
65001
|
// src/sast/rules/c.ts
|
|
@@ -65795,9 +65961,9 @@ async function sastScan(input, directory, config3) {
|
|
|
65795
65961
|
_filesSkipped++;
|
|
65796
65962
|
continue;
|
|
65797
65963
|
}
|
|
65798
|
-
const resolvedPath =
|
|
65799
|
-
const resolvedDirectory =
|
|
65800
|
-
if (!resolvedPath.startsWith(resolvedDirectory +
|
|
65964
|
+
const resolvedPath = path62.isAbsolute(filePath) ? filePath : path62.resolve(directory, filePath);
|
|
65965
|
+
const resolvedDirectory = path62.resolve(directory);
|
|
65966
|
+
if (!resolvedPath.startsWith(resolvedDirectory + path62.sep) && resolvedPath !== resolvedDirectory) {
|
|
65801
65967
|
_filesSkipped++;
|
|
65802
65968
|
continue;
|
|
65803
65969
|
}
|
|
@@ -65999,18 +66165,18 @@ function validatePath(inputPath, baseDir, workspaceDir) {
|
|
|
65999
66165
|
let resolved;
|
|
66000
66166
|
const isWinAbs = isWindowsAbsolutePath(inputPath);
|
|
66001
66167
|
if (isWinAbs) {
|
|
66002
|
-
resolved =
|
|
66003
|
-
} else if (
|
|
66004
|
-
resolved =
|
|
66168
|
+
resolved = path63.win32.resolve(inputPath);
|
|
66169
|
+
} else if (path63.isAbsolute(inputPath)) {
|
|
66170
|
+
resolved = path63.resolve(inputPath);
|
|
66005
66171
|
} else {
|
|
66006
|
-
resolved =
|
|
66172
|
+
resolved = path63.resolve(baseDir, inputPath);
|
|
66007
66173
|
}
|
|
66008
|
-
const workspaceResolved =
|
|
66174
|
+
const workspaceResolved = path63.resolve(workspaceDir);
|
|
66009
66175
|
let relative11;
|
|
66010
66176
|
if (isWinAbs) {
|
|
66011
|
-
relative11 =
|
|
66177
|
+
relative11 = path63.win32.relative(workspaceResolved, resolved);
|
|
66012
66178
|
} else {
|
|
66013
|
-
relative11 =
|
|
66179
|
+
relative11 = path63.relative(workspaceResolved, resolved);
|
|
66014
66180
|
}
|
|
66015
66181
|
if (relative11.startsWith("..")) {
|
|
66016
66182
|
return "path traversal detected";
|
|
@@ -66075,7 +66241,7 @@ async function runLintOnFiles(linter, files, workspaceDir) {
|
|
|
66075
66241
|
if (typeof file3 !== "string") {
|
|
66076
66242
|
continue;
|
|
66077
66243
|
}
|
|
66078
|
-
const resolvedPath =
|
|
66244
|
+
const resolvedPath = path63.resolve(file3);
|
|
66079
66245
|
const validationError = validatePath(resolvedPath, workspaceDir, workspaceDir);
|
|
66080
66246
|
if (validationError) {
|
|
66081
66247
|
continue;
|
|
@@ -66232,7 +66398,7 @@ async function runSecretscanWithFiles(files, directory) {
|
|
|
66232
66398
|
skippedFiles++;
|
|
66233
66399
|
continue;
|
|
66234
66400
|
}
|
|
66235
|
-
const resolvedPath =
|
|
66401
|
+
const resolvedPath = path63.resolve(file3);
|
|
66236
66402
|
const validationError = validatePath(resolvedPath, directory, directory);
|
|
66237
66403
|
if (validationError) {
|
|
66238
66404
|
skippedFiles++;
|
|
@@ -66250,7 +66416,7 @@ async function runSecretscanWithFiles(files, directory) {
|
|
|
66250
66416
|
};
|
|
66251
66417
|
}
|
|
66252
66418
|
for (const file3 of validatedFiles) {
|
|
66253
|
-
const ext =
|
|
66419
|
+
const ext = path63.extname(file3).toLowerCase();
|
|
66254
66420
|
if (DEFAULT_EXCLUDE_EXTENSIONS2.has(ext)) {
|
|
66255
66421
|
skippedFiles++;
|
|
66256
66422
|
continue;
|
|
@@ -66456,7 +66622,7 @@ function classifySastFindings(findings, changedLineRanges, directory) {
|
|
|
66456
66622
|
const preexistingFindings = [];
|
|
66457
66623
|
for (const finding of findings) {
|
|
66458
66624
|
const filePath = finding.location.file;
|
|
66459
|
-
const normalised =
|
|
66625
|
+
const normalised = path63.relative(directory, filePath).replace(/\\/g, "/");
|
|
66460
66626
|
const changedLines = changedLineRanges.get(normalised);
|
|
66461
66627
|
if (changedLines && changedLines.has(finding.location.line)) {
|
|
66462
66628
|
newFindings.push(finding);
|
|
@@ -66507,7 +66673,7 @@ async function runPreCheckBatch(input, workspaceDir, contextDir) {
|
|
|
66507
66673
|
warn(`pre_check_batch: Invalid file path: ${file3}`);
|
|
66508
66674
|
continue;
|
|
66509
66675
|
}
|
|
66510
|
-
changedFiles.push(
|
|
66676
|
+
changedFiles.push(path63.resolve(directory, file3));
|
|
66511
66677
|
}
|
|
66512
66678
|
if (changedFiles.length === 0) {
|
|
66513
66679
|
warn("pre_check_batch: No valid files after validation, skipping all tools (fail-closed)");
|
|
@@ -66695,7 +66861,7 @@ var pre_check_batch = createSwarmTool({
|
|
|
66695
66861
|
};
|
|
66696
66862
|
return JSON.stringify(errorResult, null, 2);
|
|
66697
66863
|
}
|
|
66698
|
-
const resolvedDirectory =
|
|
66864
|
+
const resolvedDirectory = path63.resolve(typedArgs.directory);
|
|
66699
66865
|
const workspaceAnchor = resolvedDirectory;
|
|
66700
66866
|
const dirError = validateDirectory2(resolvedDirectory, workspaceAnchor);
|
|
66701
66867
|
if (dirError) {
|
|
@@ -66802,25 +66968,25 @@ ${paginatedContent}`;
|
|
|
66802
66968
|
// src/tools/save-plan.ts
|
|
66803
66969
|
init_tool();
|
|
66804
66970
|
import * as fs52 from "fs";
|
|
66805
|
-
import * as
|
|
66971
|
+
import * as path65 from "path";
|
|
66806
66972
|
|
|
66807
66973
|
// src/parallel/file-locks.ts
|
|
66808
66974
|
var import_proper_lockfile3 = __toESM(require_proper_lockfile(), 1);
|
|
66809
66975
|
import * as fs51 from "fs";
|
|
66810
|
-
import * as
|
|
66976
|
+
import * as path64 from "path";
|
|
66811
66977
|
var LOCKS_DIR = ".swarm/locks";
|
|
66812
66978
|
var LOCK_TIMEOUT_MS = 5 * 60 * 1000;
|
|
66813
66979
|
function getLockFilePath(directory, filePath) {
|
|
66814
|
-
const normalized =
|
|
66815
|
-
if (!normalized.startsWith(
|
|
66980
|
+
const normalized = path64.resolve(directory, filePath);
|
|
66981
|
+
if (!normalized.startsWith(path64.resolve(directory))) {
|
|
66816
66982
|
throw new Error("Invalid file path: path traversal not allowed");
|
|
66817
66983
|
}
|
|
66818
66984
|
const hash3 = Buffer.from(normalized).toString("base64").replace(/[/+=]/g, "_");
|
|
66819
|
-
return
|
|
66985
|
+
return path64.join(directory, LOCKS_DIR, `${hash3}.lock`);
|
|
66820
66986
|
}
|
|
66821
66987
|
async function tryAcquireLock(directory, filePath, agent, taskId) {
|
|
66822
66988
|
const lockPath = getLockFilePath(directory, filePath);
|
|
66823
|
-
const locksDir =
|
|
66989
|
+
const locksDir = path64.dirname(lockPath);
|
|
66824
66990
|
if (!fs51.existsSync(locksDir)) {
|
|
66825
66991
|
fs51.mkdirSync(locksDir, { recursive: true });
|
|
66826
66992
|
}
|
|
@@ -66973,7 +67139,7 @@ async function executeSavePlan(args2, fallbackDir) {
|
|
|
66973
67139
|
await savePlan(dir, plan);
|
|
66974
67140
|
await writeCheckpoint(dir).catch(() => {});
|
|
66975
67141
|
try {
|
|
66976
|
-
const markerPath =
|
|
67142
|
+
const markerPath = path65.join(dir, ".swarm", ".plan-write-marker");
|
|
66977
67143
|
const marker = JSON.stringify({
|
|
66978
67144
|
source: "save_plan",
|
|
66979
67145
|
timestamp: new Date().toISOString(),
|
|
@@ -66996,7 +67162,7 @@ async function executeSavePlan(args2, fallbackDir) {
|
|
|
66996
67162
|
return {
|
|
66997
67163
|
success: true,
|
|
66998
67164
|
message: "Plan saved successfully",
|
|
66999
|
-
plan_path:
|
|
67165
|
+
plan_path: path65.join(dir, ".swarm", "plan.json"),
|
|
67000
67166
|
phases_count: plan.phases.length,
|
|
67001
67167
|
tasks_count: tasksCount,
|
|
67002
67168
|
...warnings.length > 0 ? { warnings } : {}
|
|
@@ -67041,7 +67207,7 @@ var save_plan = createSwarmTool({
|
|
|
67041
67207
|
init_dist();
|
|
67042
67208
|
init_manager();
|
|
67043
67209
|
import * as fs53 from "fs";
|
|
67044
|
-
import * as
|
|
67210
|
+
import * as path66 from "path";
|
|
67045
67211
|
|
|
67046
67212
|
// src/sbom/detectors/index.ts
|
|
67047
67213
|
init_utils();
|
|
@@ -67891,7 +68057,7 @@ function findManifestFiles(rootDir) {
|
|
|
67891
68057
|
try {
|
|
67892
68058
|
const entries = fs53.readdirSync(dir, { withFileTypes: true });
|
|
67893
68059
|
for (const entry of entries) {
|
|
67894
|
-
const fullPath =
|
|
68060
|
+
const fullPath = path66.join(dir, entry.name);
|
|
67895
68061
|
if (entry.name.startsWith(".") || entry.name === "node_modules" || entry.name === "dist" || entry.name === "build" || entry.name === "target") {
|
|
67896
68062
|
continue;
|
|
67897
68063
|
}
|
|
@@ -67900,7 +68066,7 @@ function findManifestFiles(rootDir) {
|
|
|
67900
68066
|
} else if (entry.isFile()) {
|
|
67901
68067
|
for (const pattern of patterns) {
|
|
67902
68068
|
if (simpleGlobToRegex(pattern).test(entry.name)) {
|
|
67903
|
-
manifestFiles.push(
|
|
68069
|
+
manifestFiles.push(path66.relative(rootDir, fullPath));
|
|
67904
68070
|
break;
|
|
67905
68071
|
}
|
|
67906
68072
|
}
|
|
@@ -67918,11 +68084,11 @@ function findManifestFilesInDirs(directories, workingDir) {
|
|
|
67918
68084
|
try {
|
|
67919
68085
|
const entries = fs53.readdirSync(dir, { withFileTypes: true });
|
|
67920
68086
|
for (const entry of entries) {
|
|
67921
|
-
const fullPath =
|
|
68087
|
+
const fullPath = path66.join(dir, entry.name);
|
|
67922
68088
|
if (entry.isFile()) {
|
|
67923
68089
|
for (const pattern of patterns) {
|
|
67924
68090
|
if (simpleGlobToRegex(pattern).test(entry.name)) {
|
|
67925
|
-
found.push(
|
|
68091
|
+
found.push(path66.relative(workingDir, fullPath));
|
|
67926
68092
|
break;
|
|
67927
68093
|
}
|
|
67928
68094
|
}
|
|
@@ -67935,11 +68101,11 @@ function findManifestFilesInDirs(directories, workingDir) {
|
|
|
67935
68101
|
function getDirectoriesFromChangedFiles(changedFiles, workingDir) {
|
|
67936
68102
|
const dirs = new Set;
|
|
67937
68103
|
for (const file3 of changedFiles) {
|
|
67938
|
-
let currentDir =
|
|
68104
|
+
let currentDir = path66.dirname(file3);
|
|
67939
68105
|
while (true) {
|
|
67940
|
-
if (currentDir && currentDir !== "." && currentDir !==
|
|
67941
|
-
dirs.add(
|
|
67942
|
-
const parent =
|
|
68106
|
+
if (currentDir && currentDir !== "." && currentDir !== path66.sep) {
|
|
68107
|
+
dirs.add(path66.join(workingDir, currentDir));
|
|
68108
|
+
const parent = path66.dirname(currentDir);
|
|
67943
68109
|
if (parent === currentDir)
|
|
67944
68110
|
break;
|
|
67945
68111
|
currentDir = parent;
|
|
@@ -68023,7 +68189,7 @@ var sbom_generate = createSwarmTool({
|
|
|
68023
68189
|
const changedFiles = obj.changed_files;
|
|
68024
68190
|
const relativeOutputDir = obj.output_dir || DEFAULT_OUTPUT_DIR;
|
|
68025
68191
|
const workingDir = directory;
|
|
68026
|
-
const outputDir =
|
|
68192
|
+
const outputDir = path66.isAbsolute(relativeOutputDir) ? relativeOutputDir : path66.join(workingDir, relativeOutputDir);
|
|
68027
68193
|
let manifestFiles = [];
|
|
68028
68194
|
if (scope === "all") {
|
|
68029
68195
|
manifestFiles = findManifestFiles(workingDir);
|
|
@@ -68046,7 +68212,7 @@ var sbom_generate = createSwarmTool({
|
|
|
68046
68212
|
const processedFiles = [];
|
|
68047
68213
|
for (const manifestFile of manifestFiles) {
|
|
68048
68214
|
try {
|
|
68049
|
-
const fullPath =
|
|
68215
|
+
const fullPath = path66.isAbsolute(manifestFile) ? manifestFile : path66.join(workingDir, manifestFile);
|
|
68050
68216
|
if (!fs53.existsSync(fullPath)) {
|
|
68051
68217
|
continue;
|
|
68052
68218
|
}
|
|
@@ -68063,7 +68229,7 @@ var sbom_generate = createSwarmTool({
|
|
|
68063
68229
|
const bom = generateCycloneDX(allComponents);
|
|
68064
68230
|
const bomJson = serializeCycloneDX(bom);
|
|
68065
68231
|
const filename = generateSbomFilename();
|
|
68066
|
-
const outputPath =
|
|
68232
|
+
const outputPath = path66.join(outputDir, filename);
|
|
68067
68233
|
fs53.writeFileSync(outputPath, bomJson, "utf-8");
|
|
68068
68234
|
const verdict = processedFiles.length > 0 ? "pass" : "pass";
|
|
68069
68235
|
try {
|
|
@@ -68107,7 +68273,7 @@ var sbom_generate = createSwarmTool({
|
|
|
68107
68273
|
init_dist();
|
|
68108
68274
|
init_create_tool();
|
|
68109
68275
|
import * as fs54 from "fs";
|
|
68110
|
-
import * as
|
|
68276
|
+
import * as path67 from "path";
|
|
68111
68277
|
var SPEC_CANDIDATES = [
|
|
68112
68278
|
"openapi.json",
|
|
68113
68279
|
"openapi.yaml",
|
|
@@ -68139,12 +68305,12 @@ function normalizePath2(p) {
|
|
|
68139
68305
|
}
|
|
68140
68306
|
function discoverSpecFile(cwd, specFileArg) {
|
|
68141
68307
|
if (specFileArg) {
|
|
68142
|
-
const resolvedPath =
|
|
68143
|
-
const normalizedCwd = cwd.endsWith(
|
|
68308
|
+
const resolvedPath = path67.resolve(cwd, specFileArg);
|
|
68309
|
+
const normalizedCwd = cwd.endsWith(path67.sep) ? cwd : cwd + path67.sep;
|
|
68144
68310
|
if (!resolvedPath.startsWith(normalizedCwd) && resolvedPath !== cwd) {
|
|
68145
68311
|
throw new Error("Invalid spec_file: path traversal detected");
|
|
68146
68312
|
}
|
|
68147
|
-
const ext =
|
|
68313
|
+
const ext = path67.extname(resolvedPath).toLowerCase();
|
|
68148
68314
|
if (!ALLOWED_EXTENSIONS.includes(ext)) {
|
|
68149
68315
|
throw new Error(`Invalid spec_file: must end in .json, .yaml, or .yml, got ${ext}`);
|
|
68150
68316
|
}
|
|
@@ -68158,7 +68324,7 @@ function discoverSpecFile(cwd, specFileArg) {
|
|
|
68158
68324
|
return resolvedPath;
|
|
68159
68325
|
}
|
|
68160
68326
|
for (const candidate of SPEC_CANDIDATES) {
|
|
68161
|
-
const candidatePath =
|
|
68327
|
+
const candidatePath = path67.resolve(cwd, candidate);
|
|
68162
68328
|
if (fs54.existsSync(candidatePath)) {
|
|
68163
68329
|
const stats = fs54.statSync(candidatePath);
|
|
68164
68330
|
if (stats.size <= MAX_SPEC_SIZE) {
|
|
@@ -68170,7 +68336,7 @@ function discoverSpecFile(cwd, specFileArg) {
|
|
|
68170
68336
|
}
|
|
68171
68337
|
function parseSpec(specFile) {
|
|
68172
68338
|
const content = fs54.readFileSync(specFile, "utf-8");
|
|
68173
|
-
const ext =
|
|
68339
|
+
const ext = path67.extname(specFile).toLowerCase();
|
|
68174
68340
|
if (ext === ".json") {
|
|
68175
68341
|
return parseJsonSpec(content);
|
|
68176
68342
|
}
|
|
@@ -68246,7 +68412,7 @@ function extractRoutes(cwd) {
|
|
|
68246
68412
|
return;
|
|
68247
68413
|
}
|
|
68248
68414
|
for (const entry of entries) {
|
|
68249
|
-
const fullPath =
|
|
68415
|
+
const fullPath = path67.join(dir, entry.name);
|
|
68250
68416
|
if (entry.isSymbolicLink()) {
|
|
68251
68417
|
continue;
|
|
68252
68418
|
}
|
|
@@ -68256,7 +68422,7 @@ function extractRoutes(cwd) {
|
|
|
68256
68422
|
}
|
|
68257
68423
|
walkDir(fullPath);
|
|
68258
68424
|
} else if (entry.isFile()) {
|
|
68259
|
-
const ext =
|
|
68425
|
+
const ext = path67.extname(entry.name).toLowerCase();
|
|
68260
68426
|
const baseName = entry.name.toLowerCase();
|
|
68261
68427
|
if (![".ts", ".js", ".mjs"].includes(ext)) {
|
|
68262
68428
|
continue;
|
|
@@ -68422,7 +68588,7 @@ var schema_drift = createSwarmTool({
|
|
|
68422
68588
|
init_tool();
|
|
68423
68589
|
init_create_tool();
|
|
68424
68590
|
import * as fs55 from "fs";
|
|
68425
|
-
import * as
|
|
68591
|
+
import * as path68 from "path";
|
|
68426
68592
|
var DEFAULT_MAX_RESULTS = 100;
|
|
68427
68593
|
var DEFAULT_MAX_LINES = 200;
|
|
68428
68594
|
var REGEX_TIMEOUT_MS = 5000;
|
|
@@ -68458,11 +68624,11 @@ function containsWindowsAttacks3(str) {
|
|
|
68458
68624
|
}
|
|
68459
68625
|
function isPathInWorkspace3(filePath, workspace) {
|
|
68460
68626
|
try {
|
|
68461
|
-
const resolvedPath =
|
|
68627
|
+
const resolvedPath = path68.resolve(workspace, filePath);
|
|
68462
68628
|
const realWorkspace = fs55.realpathSync(workspace);
|
|
68463
68629
|
const realResolvedPath = fs55.realpathSync(resolvedPath);
|
|
68464
|
-
const relativePath =
|
|
68465
|
-
if (relativePath.startsWith("..") ||
|
|
68630
|
+
const relativePath = path68.relative(realWorkspace, realResolvedPath);
|
|
68631
|
+
if (relativePath.startsWith("..") || path68.isAbsolute(relativePath)) {
|
|
68466
68632
|
return false;
|
|
68467
68633
|
}
|
|
68468
68634
|
return true;
|
|
@@ -68475,11 +68641,11 @@ function validatePathForRead2(filePath, workspace) {
|
|
|
68475
68641
|
}
|
|
68476
68642
|
function findRgInEnvPath() {
|
|
68477
68643
|
const searchPath = process.env.PATH ?? "";
|
|
68478
|
-
for (const dir of searchPath.split(
|
|
68644
|
+
for (const dir of searchPath.split(path68.delimiter)) {
|
|
68479
68645
|
if (!dir)
|
|
68480
68646
|
continue;
|
|
68481
68647
|
const isWindows = process.platform === "win32";
|
|
68482
|
-
const candidate =
|
|
68648
|
+
const candidate = path68.join(dir, isWindows ? "rg.exe" : "rg");
|
|
68483
68649
|
if (fs55.existsSync(candidate))
|
|
68484
68650
|
return candidate;
|
|
68485
68651
|
}
|
|
@@ -68609,8 +68775,8 @@ function collectFiles(dir, workspace, includeGlobs, excludeGlobs) {
|
|
|
68609
68775
|
try {
|
|
68610
68776
|
const entries = fs55.readdirSync(dir, { withFileTypes: true });
|
|
68611
68777
|
for (const entry of entries) {
|
|
68612
|
-
const fullPath =
|
|
68613
|
-
const relativePath =
|
|
68778
|
+
const fullPath = path68.join(dir, entry.name);
|
|
68779
|
+
const relativePath = path68.relative(workspace, fullPath);
|
|
68614
68780
|
if (!validatePathForRead2(fullPath, workspace)) {
|
|
68615
68781
|
continue;
|
|
68616
68782
|
}
|
|
@@ -68651,7 +68817,7 @@ async function fallbackSearch(opts) {
|
|
|
68651
68817
|
const matches = [];
|
|
68652
68818
|
let total = 0;
|
|
68653
68819
|
for (const file3 of files) {
|
|
68654
|
-
const fullPath =
|
|
68820
|
+
const fullPath = path68.join(opts.workspace, file3);
|
|
68655
68821
|
if (!validatePathForRead2(fullPath, opts.workspace)) {
|
|
68656
68822
|
continue;
|
|
68657
68823
|
}
|
|
@@ -68822,7 +68988,7 @@ init_secretscan();
|
|
|
68822
68988
|
init_tool();
|
|
68823
68989
|
init_create_tool();
|
|
68824
68990
|
import * as fs56 from "fs";
|
|
68825
|
-
import * as
|
|
68991
|
+
import * as path69 from "path";
|
|
68826
68992
|
var WINDOWS_RESERVED_NAMES4 = /^(con|prn|aux|nul|com[1-9]|lpt[1-9])(\.|:|$)/i;
|
|
68827
68993
|
function containsWindowsAttacks4(str) {
|
|
68828
68994
|
if (/:[^\\/]/.test(str))
|
|
@@ -68836,14 +69002,14 @@ function containsWindowsAttacks4(str) {
|
|
|
68836
69002
|
}
|
|
68837
69003
|
function isPathInWorkspace4(filePath, workspace) {
|
|
68838
69004
|
try {
|
|
68839
|
-
const resolvedPath =
|
|
69005
|
+
const resolvedPath = path69.resolve(workspace, filePath);
|
|
68840
69006
|
if (!fs56.existsSync(resolvedPath)) {
|
|
68841
69007
|
return true;
|
|
68842
69008
|
}
|
|
68843
69009
|
const realWorkspace = fs56.realpathSync(workspace);
|
|
68844
69010
|
const realResolvedPath = fs56.realpathSync(resolvedPath);
|
|
68845
|
-
const relativePath =
|
|
68846
|
-
if (relativePath.startsWith("..") ||
|
|
69011
|
+
const relativePath = path69.relative(realWorkspace, realResolvedPath);
|
|
69012
|
+
if (relativePath.startsWith("..") || path69.isAbsolute(relativePath)) {
|
|
68847
69013
|
return false;
|
|
68848
69014
|
}
|
|
68849
69015
|
return true;
|
|
@@ -69051,7 +69217,7 @@ var suggestPatch = createSwarmTool({
|
|
|
69051
69217
|
});
|
|
69052
69218
|
continue;
|
|
69053
69219
|
}
|
|
69054
|
-
const fullPath =
|
|
69220
|
+
const fullPath = path69.resolve(directory, change.file);
|
|
69055
69221
|
if (!fs56.existsSync(fullPath)) {
|
|
69056
69222
|
errors5.push({
|
|
69057
69223
|
success: false,
|
|
@@ -69155,7 +69321,7 @@ init_dist();
|
|
|
69155
69321
|
init_utils();
|
|
69156
69322
|
init_create_tool();
|
|
69157
69323
|
import * as fs57 from "fs";
|
|
69158
|
-
import * as
|
|
69324
|
+
import * as path70 from "path";
|
|
69159
69325
|
var MAX_TEXT_LENGTH = 200;
|
|
69160
69326
|
var MAX_FILE_SIZE_BYTES9 = 1024 * 1024;
|
|
69161
69327
|
var SUPPORTED_EXTENSIONS2 = new Set([
|
|
@@ -69220,9 +69386,9 @@ function validatePathsInput(paths, cwd) {
|
|
|
69220
69386
|
return { error: "paths contains path traversal", resolvedPath: null };
|
|
69221
69387
|
}
|
|
69222
69388
|
try {
|
|
69223
|
-
const resolvedPath =
|
|
69224
|
-
const normalizedCwd =
|
|
69225
|
-
const normalizedResolved =
|
|
69389
|
+
const resolvedPath = path70.resolve(paths);
|
|
69390
|
+
const normalizedCwd = path70.resolve(cwd);
|
|
69391
|
+
const normalizedResolved = path70.resolve(resolvedPath);
|
|
69226
69392
|
if (!normalizedResolved.startsWith(normalizedCwd)) {
|
|
69227
69393
|
return {
|
|
69228
69394
|
error: "paths must be within the current working directory",
|
|
@@ -69238,7 +69404,7 @@ function validatePathsInput(paths, cwd) {
|
|
|
69238
69404
|
}
|
|
69239
69405
|
}
|
|
69240
69406
|
function isSupportedExtension(filePath) {
|
|
69241
|
-
const ext =
|
|
69407
|
+
const ext = path70.extname(filePath).toLowerCase();
|
|
69242
69408
|
return SUPPORTED_EXTENSIONS2.has(ext);
|
|
69243
69409
|
}
|
|
69244
69410
|
function findSourceFiles2(dir, files = []) {
|
|
@@ -69253,7 +69419,7 @@ function findSourceFiles2(dir, files = []) {
|
|
|
69253
69419
|
if (SKIP_DIRECTORIES4.has(entry)) {
|
|
69254
69420
|
continue;
|
|
69255
69421
|
}
|
|
69256
|
-
const fullPath =
|
|
69422
|
+
const fullPath = path70.join(dir, entry);
|
|
69257
69423
|
let stat2;
|
|
69258
69424
|
try {
|
|
69259
69425
|
stat2 = fs57.statSync(fullPath);
|
|
@@ -69365,7 +69531,7 @@ var todo_extract = createSwarmTool({
|
|
|
69365
69531
|
filesToScan.push(scanPath);
|
|
69366
69532
|
} else {
|
|
69367
69533
|
const errorResult = {
|
|
69368
|
-
error: `unsupported file extension: ${
|
|
69534
|
+
error: `unsupported file extension: ${path70.extname(scanPath)}`,
|
|
69369
69535
|
total: 0,
|
|
69370
69536
|
byPriority: { high: 0, medium: 0, low: 0 },
|
|
69371
69537
|
entries: []
|
|
@@ -69412,14 +69578,14 @@ init_tool();
|
|
|
69412
69578
|
init_schema();
|
|
69413
69579
|
init_gate_evidence();
|
|
69414
69580
|
import * as fs59 from "fs";
|
|
69415
|
-
import * as
|
|
69581
|
+
import * as path72 from "path";
|
|
69416
69582
|
|
|
69417
69583
|
// src/hooks/diff-scope.ts
|
|
69418
69584
|
import * as fs58 from "fs";
|
|
69419
|
-
import * as
|
|
69585
|
+
import * as path71 from "path";
|
|
69420
69586
|
function getDeclaredScope(taskId, directory) {
|
|
69421
69587
|
try {
|
|
69422
|
-
const planPath =
|
|
69588
|
+
const planPath = path71.join(directory, ".swarm", "plan.json");
|
|
69423
69589
|
if (!fs58.existsSync(planPath))
|
|
69424
69590
|
return null;
|
|
69425
69591
|
const raw = fs58.readFileSync(planPath, "utf-8");
|
|
@@ -69535,7 +69701,7 @@ var TIER_3_PATTERNS = [
|
|
|
69535
69701
|
];
|
|
69536
69702
|
function matchesTier3Pattern(files) {
|
|
69537
69703
|
for (const file3 of files) {
|
|
69538
|
-
const fileName =
|
|
69704
|
+
const fileName = path72.basename(file3);
|
|
69539
69705
|
for (const pattern of TIER_3_PATTERNS) {
|
|
69540
69706
|
if (pattern.test(fileName)) {
|
|
69541
69707
|
return true;
|
|
@@ -69549,7 +69715,7 @@ function checkReviewerGate(taskId, workingDirectory) {
|
|
|
69549
69715
|
if (hasActiveTurboMode()) {
|
|
69550
69716
|
const resolvedDir2 = workingDirectory;
|
|
69551
69717
|
try {
|
|
69552
|
-
const planPath =
|
|
69718
|
+
const planPath = path72.join(resolvedDir2, ".swarm", "plan.json");
|
|
69553
69719
|
const planRaw = fs59.readFileSync(planPath, "utf-8");
|
|
69554
69720
|
const plan = JSON.parse(planRaw);
|
|
69555
69721
|
for (const planPhase of plan.phases ?? []) {
|
|
@@ -69616,7 +69782,7 @@ function checkReviewerGate(taskId, workingDirectory) {
|
|
|
69616
69782
|
}
|
|
69617
69783
|
try {
|
|
69618
69784
|
const resolvedDir2 = workingDirectory;
|
|
69619
|
-
const planPath =
|
|
69785
|
+
const planPath = path72.join(resolvedDir2, ".swarm", "plan.json");
|
|
69620
69786
|
const planRaw = fs59.readFileSync(planPath, "utf-8");
|
|
69621
69787
|
const plan = JSON.parse(planRaw);
|
|
69622
69788
|
for (const planPhase of plan.phases ?? []) {
|
|
@@ -69799,8 +69965,8 @@ async function executeUpdateTaskStatus(args2, fallbackDir) {
|
|
|
69799
69965
|
};
|
|
69800
69966
|
}
|
|
69801
69967
|
}
|
|
69802
|
-
normalizedDir =
|
|
69803
|
-
const pathParts = normalizedDir.split(
|
|
69968
|
+
normalizedDir = path72.normalize(args2.working_directory);
|
|
69969
|
+
const pathParts = normalizedDir.split(path72.sep);
|
|
69804
69970
|
if (pathParts.includes("..")) {
|
|
69805
69971
|
return {
|
|
69806
69972
|
success: false,
|
|
@@ -69810,10 +69976,10 @@ async function executeUpdateTaskStatus(args2, fallbackDir) {
|
|
|
69810
69976
|
]
|
|
69811
69977
|
};
|
|
69812
69978
|
}
|
|
69813
|
-
const resolvedDir =
|
|
69979
|
+
const resolvedDir = path72.resolve(normalizedDir);
|
|
69814
69980
|
try {
|
|
69815
69981
|
const realPath = fs59.realpathSync(resolvedDir);
|
|
69816
|
-
const planPath =
|
|
69982
|
+
const planPath = path72.join(realPath, ".swarm", "plan.json");
|
|
69817
69983
|
if (!fs59.existsSync(planPath)) {
|
|
69818
69984
|
return {
|
|
69819
69985
|
success: false,
|
|
@@ -69847,7 +70013,7 @@ async function executeUpdateTaskStatus(args2, fallbackDir) {
|
|
|
69847
70013
|
recoverTaskStateFromDelegations(args2.task_id);
|
|
69848
70014
|
let phaseRequiresReviewer = true;
|
|
69849
70015
|
try {
|
|
69850
|
-
const planPath =
|
|
70016
|
+
const planPath = path72.join(directory, ".swarm", "plan.json");
|
|
69851
70017
|
const planRaw = fs59.readFileSync(planPath, "utf-8");
|
|
69852
70018
|
const plan = JSON.parse(planRaw);
|
|
69853
70019
|
const taskPhase = plan.phases.find((p) => p.tasks.some((t) => t.id === args2.task_id));
|
|
@@ -69912,7 +70078,7 @@ init_tool();
|
|
|
69912
70078
|
init_utils2();
|
|
69913
70079
|
init_create_tool();
|
|
69914
70080
|
import fs60 from "fs";
|
|
69915
|
-
import
|
|
70081
|
+
import path73 from "path";
|
|
69916
70082
|
function normalizeVerdict(verdict) {
|
|
69917
70083
|
switch (verdict) {
|
|
69918
70084
|
case "APPROVED":
|
|
@@ -69959,7 +70125,7 @@ async function executeWriteDriftEvidence(args2, directory) {
|
|
|
69959
70125
|
entries: [evidenceEntry]
|
|
69960
70126
|
};
|
|
69961
70127
|
const filename = "drift-verifier.json";
|
|
69962
|
-
const relativePath =
|
|
70128
|
+
const relativePath = path73.join("evidence", String(phase), filename);
|
|
69963
70129
|
let validatedPath;
|
|
69964
70130
|
try {
|
|
69965
70131
|
validatedPath = validateSwarmPath(directory, relativePath);
|
|
@@ -69970,10 +70136,10 @@ async function executeWriteDriftEvidence(args2, directory) {
|
|
|
69970
70136
|
message: error93 instanceof Error ? error93.message : "Failed to validate path"
|
|
69971
70137
|
}, null, 2);
|
|
69972
70138
|
}
|
|
69973
|
-
const evidenceDir =
|
|
70139
|
+
const evidenceDir = path73.dirname(validatedPath);
|
|
69974
70140
|
try {
|
|
69975
70141
|
await fs60.promises.mkdir(evidenceDir, { recursive: true });
|
|
69976
|
-
const tempPath =
|
|
70142
|
+
const tempPath = path73.join(evidenceDir, `.${filename}.tmp`);
|
|
69977
70143
|
await fs60.promises.writeFile(tempPath, JSON.stringify(evidenceContent, null, 2), "utf-8");
|
|
69978
70144
|
await fs60.promises.rename(tempPath, validatedPath);
|
|
69979
70145
|
return JSON.stringify({
|
|
@@ -70167,7 +70333,7 @@ var OpenCodeSwarm = async (ctx) => {
|
|
|
70167
70333
|
const { PreflightTriggerManager: PTM } = await Promise.resolve().then(() => (init_trigger(), exports_trigger));
|
|
70168
70334
|
preflightTriggerManager = new PTM(automationConfig);
|
|
70169
70335
|
const { AutomationStatusArtifact: ASA } = await Promise.resolve().then(() => (init_status_artifact(), exports_status_artifact));
|
|
70170
|
-
const swarmDir =
|
|
70336
|
+
const swarmDir = path74.resolve(ctx.directory, ".swarm");
|
|
70171
70337
|
statusArtifact = new ASA(swarmDir);
|
|
70172
70338
|
statusArtifact.updateConfig(automationConfig.mode, automationConfig.capabilities);
|
|
70173
70339
|
if (automationConfig.capabilities?.evidence_auto_summaries === true) {
|