opencode-swarm 6.41.4 → 6.42.0
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 +13 -1
- package/dist/hooks/curator-llm-factory.d.ts +11 -0
- package/dist/hooks/index.d.ts +2 -0
- package/dist/hooks/knowledge-store.d.ts +1 -0
- package/dist/hooks/phase-monitor.d.ts +1 -1
- package/dist/hooks/review-receipt.d.ts +189 -0
- package/dist/index.js +726 -438
- package/dist/state.d.ts +3 -0
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -14961,7 +14961,7 @@ var init_schema = __esm(() => {
|
|
|
14961
14961
|
max_encounter_score: exports_external.number().min(1).max(20).default(10)
|
|
14962
14962
|
});
|
|
14963
14963
|
CuratorConfigSchema = exports_external.object({
|
|
14964
|
-
enabled: exports_external.boolean().default(
|
|
14964
|
+
enabled: exports_external.boolean().default(true),
|
|
14965
14965
|
init_enabled: exports_external.boolean().default(true),
|
|
14966
14966
|
phase_enabled: exports_external.boolean().default(true),
|
|
14967
14967
|
max_summary_tokens: exports_external.number().min(500).max(8000).default(2000),
|
|
@@ -31982,6 +31982,13 @@ async function rewriteKnowledge(filePath, entries) {
|
|
|
31982
31982
|
}
|
|
31983
31983
|
}
|
|
31984
31984
|
}
|
|
31985
|
+
async function enforceKnowledgeCap(filePath, maxEntries) {
|
|
31986
|
+
const entries = await readKnowledge(filePath);
|
|
31987
|
+
if (entries.length > maxEntries) {
|
|
31988
|
+
const trimmed = entries.slice(entries.length - maxEntries);
|
|
31989
|
+
await rewriteKnowledge(filePath, trimmed);
|
|
31990
|
+
}
|
|
31991
|
+
}
|
|
31985
31992
|
async function appendRejectedLesson(directory, lesson) {
|
|
31986
31993
|
const filePath = resolveSwarmRejectedPath(directory);
|
|
31987
31994
|
const existing = await readRejectedLessons(directory);
|
|
@@ -37293,6 +37300,184 @@ var init_gate_evidence = __esm(() => {
|
|
|
37293
37300
|
TASK_ID_PATTERN = /^\d+\.\d+(\.\d+)*$/;
|
|
37294
37301
|
});
|
|
37295
37302
|
|
|
37303
|
+
// src/hooks/review-receipt.ts
|
|
37304
|
+
var exports_review_receipt = {};
|
|
37305
|
+
__export(exports_review_receipt, {
|
|
37306
|
+
resolveReceiptsDir: () => resolveReceiptsDir,
|
|
37307
|
+
resolveReceiptIndexPath: () => resolveReceiptIndexPath,
|
|
37308
|
+
readReceiptsByScopeHash: () => readReceiptsByScopeHash,
|
|
37309
|
+
readReceiptById: () => readReceiptById,
|
|
37310
|
+
readAllReceipts: () => readAllReceipts,
|
|
37311
|
+
persistReviewReceipt: () => persistReviewReceipt,
|
|
37312
|
+
isScopeStale: () => isScopeStale,
|
|
37313
|
+
computeScopeFingerprint: () => computeScopeFingerprint,
|
|
37314
|
+
buildRejectedReceipt: () => buildRejectedReceipt,
|
|
37315
|
+
buildReceiptContextForDrift: () => buildReceiptContextForDrift,
|
|
37316
|
+
buildApprovedReceipt: () => buildApprovedReceipt
|
|
37317
|
+
});
|
|
37318
|
+
import * as crypto4 from "crypto";
|
|
37319
|
+
import * as fs25 from "fs";
|
|
37320
|
+
import * as path36 from "path";
|
|
37321
|
+
function resolveReceiptsDir(directory) {
|
|
37322
|
+
return path36.join(directory, ".swarm", "review-receipts");
|
|
37323
|
+
}
|
|
37324
|
+
function resolveReceiptIndexPath(directory) {
|
|
37325
|
+
return path36.join(resolveReceiptsDir(directory), "index.json");
|
|
37326
|
+
}
|
|
37327
|
+
function buildReceiptFilename(id, date9) {
|
|
37328
|
+
const dateStr = date9.toISOString().slice(0, 10);
|
|
37329
|
+
return `${dateStr}-${id}.json`;
|
|
37330
|
+
}
|
|
37331
|
+
function computeScopeFingerprint(content, scopeDescription) {
|
|
37332
|
+
const hash3 = crypto4.createHash("sha256").update(content, "utf-8").digest("hex");
|
|
37333
|
+
return {
|
|
37334
|
+
hash: hash3,
|
|
37335
|
+
scope_description: scopeDescription,
|
|
37336
|
+
content_length: content.length
|
|
37337
|
+
};
|
|
37338
|
+
}
|
|
37339
|
+
function isScopeStale(receipt, currentContent) {
|
|
37340
|
+
if (currentContent === undefined) {
|
|
37341
|
+
return true;
|
|
37342
|
+
}
|
|
37343
|
+
const currentHash = crypto4.createHash("sha256").update(currentContent, "utf-8").digest("hex");
|
|
37344
|
+
return currentHash !== receipt.scope_fingerprint.hash;
|
|
37345
|
+
}
|
|
37346
|
+
async function readReceiptIndex(directory) {
|
|
37347
|
+
const indexPath = resolveReceiptIndexPath(directory);
|
|
37348
|
+
if (!fs25.existsSync(indexPath)) {
|
|
37349
|
+
return { schema_version: 1, entries: [] };
|
|
37350
|
+
}
|
|
37351
|
+
try {
|
|
37352
|
+
const content = await fs25.promises.readFile(indexPath, "utf-8");
|
|
37353
|
+
const parsed = JSON.parse(content);
|
|
37354
|
+
if (parsed.schema_version !== 1 || !Array.isArray(parsed.entries)) {
|
|
37355
|
+
return { schema_version: 1, entries: [] };
|
|
37356
|
+
}
|
|
37357
|
+
return parsed;
|
|
37358
|
+
} catch {
|
|
37359
|
+
return { schema_version: 1, entries: [] };
|
|
37360
|
+
}
|
|
37361
|
+
}
|
|
37362
|
+
async function writeReceiptIndex(directory, index) {
|
|
37363
|
+
const indexPath = resolveReceiptIndexPath(directory);
|
|
37364
|
+
const dir = path36.dirname(indexPath);
|
|
37365
|
+
await fs25.promises.mkdir(dir, { recursive: true });
|
|
37366
|
+
const tmpPath = `${indexPath}.tmp.${Date.now()}.${Math.random().toString(36).slice(2)}`;
|
|
37367
|
+
await fs25.promises.writeFile(tmpPath, JSON.stringify(index, null, 2), "utf-8");
|
|
37368
|
+
fs25.renameSync(tmpPath, indexPath);
|
|
37369
|
+
}
|
|
37370
|
+
async function persistReviewReceipt(directory, receipt) {
|
|
37371
|
+
const receiptsDir = resolveReceiptsDir(directory);
|
|
37372
|
+
await fs25.promises.mkdir(receiptsDir, { recursive: true });
|
|
37373
|
+
const now = new Date(receipt.reviewed_at);
|
|
37374
|
+
const filename = buildReceiptFilename(receipt.id, now);
|
|
37375
|
+
const receiptPath = path36.join(receiptsDir, filename);
|
|
37376
|
+
const tmpPath = `${receiptPath}.tmp.${Date.now()}.${Math.random().toString(36).slice(2)}`;
|
|
37377
|
+
await fs25.promises.writeFile(tmpPath, JSON.stringify(receipt, null, 2), "utf-8");
|
|
37378
|
+
fs25.renameSync(tmpPath, receiptPath);
|
|
37379
|
+
const index = await readReceiptIndex(directory);
|
|
37380
|
+
const entry = {
|
|
37381
|
+
id: receipt.id,
|
|
37382
|
+
verdict: receipt.verdict,
|
|
37383
|
+
reviewed_at: receipt.reviewed_at,
|
|
37384
|
+
scope_hash: receipt.scope_fingerprint.hash,
|
|
37385
|
+
agent: receipt.reviewer.agent,
|
|
37386
|
+
filename
|
|
37387
|
+
};
|
|
37388
|
+
index.entries.push(entry);
|
|
37389
|
+
await writeReceiptIndex(directory, index);
|
|
37390
|
+
return receiptPath;
|
|
37391
|
+
}
|
|
37392
|
+
async function readReceiptById(directory, receiptId) {
|
|
37393
|
+
const index = await readReceiptIndex(directory);
|
|
37394
|
+
const entry = index.entries.find((e) => e.id === receiptId);
|
|
37395
|
+
if (!entry)
|
|
37396
|
+
return null;
|
|
37397
|
+
const receiptPath = path36.join(resolveReceiptsDir(directory), entry.filename);
|
|
37398
|
+
try {
|
|
37399
|
+
const content = await fs25.promises.readFile(receiptPath, "utf-8");
|
|
37400
|
+
return JSON.parse(content);
|
|
37401
|
+
} catch {
|
|
37402
|
+
return null;
|
|
37403
|
+
}
|
|
37404
|
+
}
|
|
37405
|
+
async function readReceiptsByScopeHash(directory, scopeHash) {
|
|
37406
|
+
const index = await readReceiptIndex(directory);
|
|
37407
|
+
const matching = index.entries.filter((e) => e.scope_hash === scopeHash).sort((a, b) => b.reviewed_at.localeCompare(a.reviewed_at));
|
|
37408
|
+
const receipts = [];
|
|
37409
|
+
for (const entry of matching) {
|
|
37410
|
+
const receiptPath = path36.join(resolveReceiptsDir(directory), entry.filename);
|
|
37411
|
+
try {
|
|
37412
|
+
const content = await fs25.promises.readFile(receiptPath, "utf-8");
|
|
37413
|
+
receipts.push(JSON.parse(content));
|
|
37414
|
+
} catch {}
|
|
37415
|
+
}
|
|
37416
|
+
return receipts;
|
|
37417
|
+
}
|
|
37418
|
+
async function readAllReceipts(directory) {
|
|
37419
|
+
const index = await readReceiptIndex(directory);
|
|
37420
|
+
const sorted = [...index.entries].sort((a, b) => b.reviewed_at.localeCompare(a.reviewed_at));
|
|
37421
|
+
const receipts = [];
|
|
37422
|
+
for (const entry of sorted) {
|
|
37423
|
+
const receiptPath = path36.join(resolveReceiptsDir(directory), entry.filename);
|
|
37424
|
+
try {
|
|
37425
|
+
const content = await fs25.promises.readFile(receiptPath, "utf-8");
|
|
37426
|
+
receipts.push(JSON.parse(content));
|
|
37427
|
+
} catch {}
|
|
37428
|
+
}
|
|
37429
|
+
return receipts;
|
|
37430
|
+
}
|
|
37431
|
+
function buildRejectedReceipt(opts) {
|
|
37432
|
+
return {
|
|
37433
|
+
schema_version: 1,
|
|
37434
|
+
id: crypto4.randomUUID(),
|
|
37435
|
+
receipt_type: "rejected",
|
|
37436
|
+
verdict: "rejected",
|
|
37437
|
+
reviewer: { agent: opts.agent, session_id: opts.sessionId },
|
|
37438
|
+
reviewed_at: new Date().toISOString(),
|
|
37439
|
+
scope_fingerprint: computeScopeFingerprint(opts.scopeContent, opts.scopeDescription),
|
|
37440
|
+
blocking_findings: opts.blockingFindings,
|
|
37441
|
+
evidence_references: opts.evidenceReferences,
|
|
37442
|
+
pass_conditions: opts.passConditions,
|
|
37443
|
+
summary: opts.summary
|
|
37444
|
+
};
|
|
37445
|
+
}
|
|
37446
|
+
function buildApprovedReceipt(opts) {
|
|
37447
|
+
return {
|
|
37448
|
+
schema_version: 1,
|
|
37449
|
+
id: crypto4.randomUUID(),
|
|
37450
|
+
receipt_type: "approved",
|
|
37451
|
+
verdict: "approved",
|
|
37452
|
+
reviewer: { agent: opts.agent, session_id: opts.sessionId },
|
|
37453
|
+
reviewed_at: new Date().toISOString(),
|
|
37454
|
+
scope_fingerprint: computeScopeFingerprint(opts.scopeContent, opts.scopeDescription),
|
|
37455
|
+
checked_aspects: opts.checkedAspects,
|
|
37456
|
+
validated_claims: opts.validatedClaims,
|
|
37457
|
+
caveats: opts.caveats
|
|
37458
|
+
};
|
|
37459
|
+
}
|
|
37460
|
+
function buildReceiptContextForDrift(receipts, currentScopeContent, maxChars = 1000) {
|
|
37461
|
+
if (receipts.length === 0)
|
|
37462
|
+
return "";
|
|
37463
|
+
const lines = ["## Prior Review Receipts (supporting context)"];
|
|
37464
|
+
for (const receipt of receipts) {
|
|
37465
|
+
const stale = receipt.verdict === "approved" ? isScopeStale(receipt, currentScopeContent) : false;
|
|
37466
|
+
const staleTag = stale ? " [SCOPE-STALE \u2014 treat as context only]" : "";
|
|
37467
|
+
if (receipt.verdict === "rejected") {
|
|
37468
|
+
const r = receipt;
|
|
37469
|
+
lines.push(`- REJECTED by ${r.reviewer.agent} at ${r.reviewed_at.slice(0, 10)}: ` + `${r.blocking_findings.length} blocking finding(s). ` + `Pass conditions: ${r.pass_conditions.slice(0, 2).join("; ")}.`);
|
|
37470
|
+
} else {
|
|
37471
|
+
const a = receipt;
|
|
37472
|
+
lines.push(`- APPROVED by ${a.reviewer.agent} at ${a.reviewed_at.slice(0, 10)}${staleTag}: ` + `checked [${a.checked_aspects.join(", ")}]. ` + (a.caveats && a.caveats.length > 0 ? `Caveats: ${a.caveats[0]}.` : "No caveats recorded."));
|
|
37473
|
+
}
|
|
37474
|
+
}
|
|
37475
|
+
lines.push("Note: Approved receipts are supporting evidence only. Stale receipts must not be blindly trusted.");
|
|
37476
|
+
return lines.join(`
|
|
37477
|
+
`).slice(0, maxChars);
|
|
37478
|
+
}
|
|
37479
|
+
var init_review_receipt = () => {};
|
|
37480
|
+
|
|
37296
37481
|
// src/services/preflight-integration.ts
|
|
37297
37482
|
var exports_preflight_integration = {};
|
|
37298
37483
|
__export(exports_preflight_integration, {
|
|
@@ -37368,16 +37553,16 @@ __export(exports_doc_scan, {
|
|
|
37368
37553
|
doc_scan: () => doc_scan,
|
|
37369
37554
|
doc_extract: () => doc_extract
|
|
37370
37555
|
});
|
|
37371
|
-
import * as
|
|
37372
|
-
import * as
|
|
37556
|
+
import * as crypto5 from "crypto";
|
|
37557
|
+
import * as fs28 from "fs";
|
|
37373
37558
|
import { mkdir as mkdir6, readFile as readFile6, writeFile as writeFile5 } from "fs/promises";
|
|
37374
|
-
import * as
|
|
37559
|
+
import * as path40 from "path";
|
|
37375
37560
|
function normalizeSeparators(filePath) {
|
|
37376
37561
|
return filePath.replace(/\\/g, "/");
|
|
37377
37562
|
}
|
|
37378
37563
|
function matchesDocPattern(filePath, patterns) {
|
|
37379
37564
|
const normalizedPath = normalizeSeparators(filePath);
|
|
37380
|
-
const basename5 =
|
|
37565
|
+
const basename5 = path40.basename(filePath);
|
|
37381
37566
|
for (const pattern of patterns) {
|
|
37382
37567
|
if (!pattern.includes("/") && !pattern.includes("\\")) {
|
|
37383
37568
|
if (basename5 === pattern) {
|
|
@@ -37433,7 +37618,7 @@ function stripMarkdown(text) {
|
|
|
37433
37618
|
return text.replace(/\[([^\]]+)\]\([^)]+\)/g, "$1").replace(/\*\*([^*]+)\*\*/g, "$1").replace(/`([^`]+)`/g, "$1").replace(/^\s*[-*\u2022]\s+/gm, "").replace(/^\s*\d+\.\s+/gm, "").trim();
|
|
37434
37619
|
}
|
|
37435
37620
|
async function scanDocIndex(directory) {
|
|
37436
|
-
const manifestPath =
|
|
37621
|
+
const manifestPath = path40.join(directory, ".swarm", "doc-manifest.json");
|
|
37437
37622
|
const defaultPatterns = DocsConfigSchema.parse({}).doc_patterns;
|
|
37438
37623
|
const extraPatterns = [
|
|
37439
37624
|
"ARCHITECTURE.md",
|
|
@@ -37450,8 +37635,8 @@ async function scanDocIndex(directory) {
|
|
|
37450
37635
|
let cacheValid = true;
|
|
37451
37636
|
for (const file3 of existingManifest.files) {
|
|
37452
37637
|
try {
|
|
37453
|
-
const fullPath =
|
|
37454
|
-
const stat2 =
|
|
37638
|
+
const fullPath = path40.join(directory, file3.path);
|
|
37639
|
+
const stat2 = fs28.statSync(fullPath);
|
|
37455
37640
|
if (stat2.mtimeMs > new Date(existingManifest.scanned_at).getTime()) {
|
|
37456
37641
|
cacheValid = false;
|
|
37457
37642
|
break;
|
|
@@ -37469,7 +37654,7 @@ async function scanDocIndex(directory) {
|
|
|
37469
37654
|
const discoveredFiles = [];
|
|
37470
37655
|
let rawEntries;
|
|
37471
37656
|
try {
|
|
37472
|
-
rawEntries =
|
|
37657
|
+
rawEntries = fs28.readdirSync(directory, { recursive: true });
|
|
37473
37658
|
} catch {
|
|
37474
37659
|
const manifest2 = {
|
|
37475
37660
|
schema_version: 1,
|
|
@@ -37480,10 +37665,10 @@ async function scanDocIndex(directory) {
|
|
|
37480
37665
|
}
|
|
37481
37666
|
const entries = rawEntries.filter((e) => typeof e === "string");
|
|
37482
37667
|
for (const entry of entries) {
|
|
37483
|
-
const fullPath =
|
|
37668
|
+
const fullPath = path40.join(directory, entry);
|
|
37484
37669
|
let stat2;
|
|
37485
37670
|
try {
|
|
37486
|
-
stat2 =
|
|
37671
|
+
stat2 = fs28.statSync(fullPath);
|
|
37487
37672
|
} catch {
|
|
37488
37673
|
continue;
|
|
37489
37674
|
}
|
|
@@ -37512,11 +37697,11 @@ async function scanDocIndex(directory) {
|
|
|
37512
37697
|
}
|
|
37513
37698
|
let content;
|
|
37514
37699
|
try {
|
|
37515
|
-
content =
|
|
37700
|
+
content = fs28.readFileSync(fullPath, "utf-8");
|
|
37516
37701
|
} catch {
|
|
37517
37702
|
continue;
|
|
37518
37703
|
}
|
|
37519
|
-
const { title, summary } = extractTitleAndSummary(content,
|
|
37704
|
+
const { title, summary } = extractTitleAndSummary(content, path40.basename(entry));
|
|
37520
37705
|
const lineCount = content.split(`
|
|
37521
37706
|
`).length;
|
|
37522
37707
|
discoveredFiles.push({
|
|
@@ -37542,7 +37727,7 @@ async function scanDocIndex(directory) {
|
|
|
37542
37727
|
files: discoveredFiles
|
|
37543
37728
|
};
|
|
37544
37729
|
try {
|
|
37545
|
-
await mkdir6(
|
|
37730
|
+
await mkdir6(path40.dirname(manifestPath), { recursive: true });
|
|
37546
37731
|
await writeFile5(manifestPath, JSON.stringify(manifest, null, 2), "utf-8");
|
|
37547
37732
|
} catch {}
|
|
37548
37733
|
return { manifest, cached: false };
|
|
@@ -37581,7 +37766,7 @@ function extractConstraintsFromContent(content) {
|
|
|
37581
37766
|
return constraints;
|
|
37582
37767
|
}
|
|
37583
37768
|
async function extractDocConstraints(directory, taskFiles, taskDescription) {
|
|
37584
|
-
const manifestPath =
|
|
37769
|
+
const manifestPath = path40.join(directory, ".swarm", "doc-manifest.json");
|
|
37585
37770
|
let manifest;
|
|
37586
37771
|
try {
|
|
37587
37772
|
const content = await readFile6(manifestPath, "utf-8");
|
|
@@ -37607,7 +37792,7 @@ async function extractDocConstraints(directory, taskFiles, taskDescription) {
|
|
|
37607
37792
|
}
|
|
37608
37793
|
let fullContent;
|
|
37609
37794
|
try {
|
|
37610
|
-
fullContent = await readFile6(
|
|
37795
|
+
fullContent = await readFile6(path40.join(directory, docFile.path), "utf-8");
|
|
37611
37796
|
} catch {
|
|
37612
37797
|
skippedCount++;
|
|
37613
37798
|
continue;
|
|
@@ -37626,11 +37811,11 @@ async function extractDocConstraints(directory, taskFiles, taskDescription) {
|
|
|
37626
37811
|
const duplicate = findNearDuplicate(constraint, existingEntries, DEDUP_THRESHOLD);
|
|
37627
37812
|
if (!duplicate) {
|
|
37628
37813
|
const entry = {
|
|
37629
|
-
id:
|
|
37814
|
+
id: crypto5.randomUUID(),
|
|
37630
37815
|
tier: "swarm",
|
|
37631
37816
|
lesson: constraint,
|
|
37632
37817
|
category: "architecture",
|
|
37633
|
-
tags: ["doc-scan",
|
|
37818
|
+
tags: ["doc-scan", path40.basename(docFile.path)],
|
|
37634
37819
|
scope: "global",
|
|
37635
37820
|
confidence: 0.5,
|
|
37636
37821
|
status: "candidate",
|
|
@@ -37703,9 +37888,9 @@ var init_doc_scan = __esm(() => {
|
|
|
37703
37888
|
}
|
|
37704
37889
|
} catch {}
|
|
37705
37890
|
if (force) {
|
|
37706
|
-
const manifestPath =
|
|
37891
|
+
const manifestPath = path40.join(directory, ".swarm", "doc-manifest.json");
|
|
37707
37892
|
try {
|
|
37708
|
-
|
|
37893
|
+
fs28.unlinkSync(manifestPath);
|
|
37709
37894
|
} catch {}
|
|
37710
37895
|
}
|
|
37711
37896
|
const { manifest, cached: cached3 } = await scanDocIndex(directory);
|
|
@@ -37757,11 +37942,11 @@ __export(exports_curator_drift, {
|
|
|
37757
37942
|
readPriorDriftReports: () => readPriorDriftReports,
|
|
37758
37943
|
buildDriftInjectionText: () => buildDriftInjectionText
|
|
37759
37944
|
});
|
|
37760
|
-
import * as
|
|
37761
|
-
import * as
|
|
37945
|
+
import * as fs31 from "fs";
|
|
37946
|
+
import * as path43 from "path";
|
|
37762
37947
|
async function readPriorDriftReports(directory) {
|
|
37763
|
-
const swarmDir =
|
|
37764
|
-
const entries = await
|
|
37948
|
+
const swarmDir = path43.join(directory, ".swarm");
|
|
37949
|
+
const entries = await fs31.promises.readdir(swarmDir).catch(() => null);
|
|
37765
37950
|
if (entries === null)
|
|
37766
37951
|
return [];
|
|
37767
37952
|
const reportFiles = entries.filter((name2) => name2.startsWith(DRIFT_REPORT_PREFIX) && name2.endsWith(".json")).sort();
|
|
@@ -37787,10 +37972,10 @@ async function readPriorDriftReports(directory) {
|
|
|
37787
37972
|
async function writeDriftReport(directory, report) {
|
|
37788
37973
|
const filename = `${DRIFT_REPORT_PREFIX}${report.phase}.json`;
|
|
37789
37974
|
const filePath = validateSwarmPath(directory, filename);
|
|
37790
|
-
const swarmDir =
|
|
37791
|
-
await
|
|
37975
|
+
const swarmDir = path43.dirname(filePath);
|
|
37976
|
+
await fs31.promises.mkdir(swarmDir, { recursive: true });
|
|
37792
37977
|
try {
|
|
37793
|
-
await
|
|
37978
|
+
await fs31.promises.writeFile(filePath, JSON.stringify(report, null, 2), "utf-8");
|
|
37794
37979
|
} catch (err2) {
|
|
37795
37980
|
throw new Error(`[curator-drift] Failed to write drift report to ${filePath}: ${String(err2)}`);
|
|
37796
37981
|
}
|
|
@@ -39380,11 +39565,11 @@ ${JSON.stringify(symbolNames, null, 2)}`);
|
|
|
39380
39565
|
throw toThrow;
|
|
39381
39566
|
}, "quit_");
|
|
39382
39567
|
var scriptDirectory = "";
|
|
39383
|
-
function locateFile(
|
|
39568
|
+
function locateFile(path51) {
|
|
39384
39569
|
if (Module["locateFile"]) {
|
|
39385
|
-
return Module["locateFile"](
|
|
39570
|
+
return Module["locateFile"](path51, scriptDirectory);
|
|
39386
39571
|
}
|
|
39387
|
-
return scriptDirectory +
|
|
39572
|
+
return scriptDirectory + path51;
|
|
39388
39573
|
}
|
|
39389
39574
|
__name(locateFile, "locateFile");
|
|
39390
39575
|
var readAsync, readBinary;
|
|
@@ -41124,13 +41309,13 @@ ${JSON.stringify(symbolNames, null, 2)}`);
|
|
|
41124
41309
|
});
|
|
41125
41310
|
|
|
41126
41311
|
// src/lang/runtime.ts
|
|
41127
|
-
import * as
|
|
41312
|
+
import * as path51 from "path";
|
|
41128
41313
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
41129
41314
|
async function initTreeSitter() {
|
|
41130
41315
|
if (treeSitterInitialized) {
|
|
41131
41316
|
return;
|
|
41132
41317
|
}
|
|
41133
|
-
const thisDir =
|
|
41318
|
+
const thisDir = path51.dirname(fileURLToPath2(import.meta.url));
|
|
41134
41319
|
const isSource = thisDir.replace(/\\/g, "/").endsWith("/src/lang");
|
|
41135
41320
|
if (isSource) {
|
|
41136
41321
|
await Parser.init();
|
|
@@ -41138,7 +41323,7 @@ async function initTreeSitter() {
|
|
|
41138
41323
|
const grammarsDir = getGrammarsDirAbsolute();
|
|
41139
41324
|
await Parser.init({
|
|
41140
41325
|
locateFile(scriptName) {
|
|
41141
|
-
return
|
|
41326
|
+
return path51.join(grammarsDir, scriptName);
|
|
41142
41327
|
}
|
|
41143
41328
|
});
|
|
41144
41329
|
}
|
|
@@ -41159,9 +41344,9 @@ function getWasmFileName(languageId) {
|
|
|
41159
41344
|
return `tree-sitter-${sanitized}.wasm`;
|
|
41160
41345
|
}
|
|
41161
41346
|
function getGrammarsDirAbsolute() {
|
|
41162
|
-
const thisDir =
|
|
41347
|
+
const thisDir = path51.dirname(fileURLToPath2(import.meta.url));
|
|
41163
41348
|
const isSource = thisDir.replace(/\\/g, "/").endsWith("/src/lang");
|
|
41164
|
-
return isSource ?
|
|
41349
|
+
return isSource ? path51.join(thisDir, "grammars") : path51.join(thisDir, "lang", "grammars");
|
|
41165
41350
|
}
|
|
41166
41351
|
async function loadGrammar(languageId) {
|
|
41167
41352
|
if (typeof languageId !== "string" || languageId.length > 100) {
|
|
@@ -41177,9 +41362,9 @@ async function loadGrammar(languageId) {
|
|
|
41177
41362
|
await initTreeSitter();
|
|
41178
41363
|
const parser = new Parser;
|
|
41179
41364
|
const wasmFileName = getWasmFileName(normalizedId);
|
|
41180
|
-
const wasmPath =
|
|
41181
|
-
const { existsSync:
|
|
41182
|
-
if (!
|
|
41365
|
+
const wasmPath = path51.join(getGrammarsDirAbsolute(), wasmFileName);
|
|
41366
|
+
const { existsSync: existsSync30 } = await import("fs");
|
|
41367
|
+
if (!existsSync30(wasmPath)) {
|
|
41183
41368
|
throw new Error(`Grammar file not found for ${languageId}: ${wasmPath}
|
|
41184
41369
|
Make sure to run 'bun run build' to copy grammar files to dist/lang/grammars/`);
|
|
41185
41370
|
}
|
|
@@ -41224,7 +41409,7 @@ var init_runtime = __esm(() => {
|
|
|
41224
41409
|
});
|
|
41225
41410
|
|
|
41226
41411
|
// src/index.ts
|
|
41227
|
-
import * as
|
|
41412
|
+
import * as path68 from "path";
|
|
41228
41413
|
|
|
41229
41414
|
// src/agents/index.ts
|
|
41230
41415
|
init_config();
|
|
@@ -41245,6 +41430,7 @@ var swarmState = {
|
|
|
41245
41430
|
activeAgent: new Map,
|
|
41246
41431
|
delegationChains: new Map,
|
|
41247
41432
|
pendingEvents: 0,
|
|
41433
|
+
opencodeClient: null,
|
|
41248
41434
|
lastBudgetPct: 0,
|
|
41249
41435
|
agentSessions: new Map,
|
|
41250
41436
|
pendingRehydrations: new Set
|
|
@@ -41750,7 +41936,7 @@ Output to .swarm/plan.md MUST use "## Phase N" headers. Do not write MODE labels
|
|
|
41750
41936
|
1. DELEGATE all coding to {{AGENT_PREFIX}}coder. You do NOT write code.
|
|
41751
41937
|
// IMPORTANT: This list MUST match AGENT_TOOL_MAP['architect'] in src/config/constants.ts
|
|
41752
41938
|
// If you add a tool to the map, add it here. If you remove it from the map, remove it here.
|
|
41753
|
-
YOUR TOOLS: Task (delegation),
|
|
41939
|
+
YOUR TOOLS: Task (delegation), build_check, check_gate_status, checkpoint, co_change_analyzer, completion_verify, complexity_hotspots, curator_analyze, declare_scope, detect_domains, diff, doc_extract, doc_scan, evidence_check, extract_code_blocks, gitingest, imports, knowledgeAdd, knowledge_query, knowledgeRecall, knowledgeRemove, lint, phase_complete, pkg_audit, placeholder_scan, pre_check_batch, quality_budget, retrieve_summary, sast_scan, save_plan, sbom_generate, schema_drift, secretscan, symbols, syntax_check, test_runner, todo_extract, update_task_status, write_drift_evidence, write_retro.
|
|
41754
41940
|
CODER'S TOOLS: write, edit, patch, apply_patch, create_file, insert, replace \u2014 any tool that modifies file contents.
|
|
41755
41941
|
If a tool modifies a file, it is a CODER tool. Delegate.
|
|
41756
41942
|
2. ONE agent per message. Send, STOP, wait for response.
|
|
@@ -45913,7 +46099,9 @@ async function recordLessonsShown(directory, lessonIds, currentPhase) {
|
|
|
45913
46099
|
const content = await readFile3(shownFile, "utf-8");
|
|
45914
46100
|
shownData = JSON.parse(content);
|
|
45915
46101
|
}
|
|
45916
|
-
|
|
46102
|
+
const phaseMatch = /^Phase\s+(\d+)/i.exec(currentPhase);
|
|
46103
|
+
const canonicalKey = phaseMatch ? `Phase ${phaseMatch[1]}` : currentPhase;
|
|
46104
|
+
shownData[canonicalKey] = lessonIds;
|
|
45917
46105
|
await mkdir2(path12.dirname(shownFile), { recursive: true });
|
|
45918
46106
|
await writeFile2(shownFile, JSON.stringify(shownData, null, 2), "utf-8");
|
|
45919
46107
|
} catch {
|
|
@@ -46637,6 +46825,7 @@ async function curateAndStoreSwarm(lessons, projectName, phaseInfo, directory, c
|
|
|
46637
46825
|
stored++;
|
|
46638
46826
|
existingEntries.push(entry);
|
|
46639
46827
|
}
|
|
46828
|
+
await enforceKnowledgeCap(knowledgePath, config3.swarm_max_entries);
|
|
46640
46829
|
await runAutoPromotion(directory, config3);
|
|
46641
46830
|
return { stored, skipped, rejected };
|
|
46642
46831
|
}
|
|
@@ -48003,6 +48192,9 @@ async function checkHivePromotions(swarmEntries, config3) {
|
|
|
48003
48192
|
if (hiveModified) {
|
|
48004
48193
|
await rewriteKnowledge(resolveHiveKnowledgePath(), hiveEntries);
|
|
48005
48194
|
}
|
|
48195
|
+
if (newPromotions > 0 || hiveModified) {
|
|
48196
|
+
await enforceKnowledgeCap(resolveHiveKnowledgePath(), config3.hive_max_entries);
|
|
48197
|
+
}
|
|
48006
48198
|
return {
|
|
48007
48199
|
timestamp: new Date().toISOString(),
|
|
48008
48200
|
new_promotions: newPromotions,
|
|
@@ -52176,6 +52368,43 @@ function maskToolOutput(msg, _threshold) {
|
|
|
52176
52368
|
}
|
|
52177
52369
|
return freedTokens;
|
|
52178
52370
|
}
|
|
52371
|
+
// src/hooks/curator-llm-factory.ts
|
|
52372
|
+
function createCuratorLLMDelegate(directory) {
|
|
52373
|
+
const client = swarmState.opencodeClient;
|
|
52374
|
+
if (!client)
|
|
52375
|
+
return;
|
|
52376
|
+
return async (systemPrompt, userInput) => {
|
|
52377
|
+
let ephemeralSessionId;
|
|
52378
|
+
try {
|
|
52379
|
+
const createResult = await client.session.create({
|
|
52380
|
+
query: { directory }
|
|
52381
|
+
});
|
|
52382
|
+
if (!createResult.data) {
|
|
52383
|
+
throw new Error(`Failed to create curator session: ${JSON.stringify(createResult.error)}`);
|
|
52384
|
+
}
|
|
52385
|
+
ephemeralSessionId = createResult.data.id;
|
|
52386
|
+
const promptResult = await client.session.prompt({
|
|
52387
|
+
path: { id: ephemeralSessionId },
|
|
52388
|
+
body: {
|
|
52389
|
+
agent: "explorer",
|
|
52390
|
+
system: systemPrompt,
|
|
52391
|
+
tools: { write: false, edit: false, patch: false },
|
|
52392
|
+
parts: [{ type: "text", text: userInput }]
|
|
52393
|
+
}
|
|
52394
|
+
});
|
|
52395
|
+
if (!promptResult.data) {
|
|
52396
|
+
throw new Error(`Curator LLM prompt failed: ${JSON.stringify(promptResult.error)}`);
|
|
52397
|
+
}
|
|
52398
|
+
const textParts = promptResult.data.parts.filter((p) => p.type === "text");
|
|
52399
|
+
return textParts.map((p) => p.text).join(`
|
|
52400
|
+
`);
|
|
52401
|
+
} finally {
|
|
52402
|
+
if (ephemeralSessionId) {
|
|
52403
|
+
client.session.delete({ path: { id: ephemeralSessionId } }).catch(() => {});
|
|
52404
|
+
}
|
|
52405
|
+
}
|
|
52406
|
+
};
|
|
52407
|
+
}
|
|
52179
52408
|
// src/hooks/delegation-gate.ts
|
|
52180
52409
|
init_schema();
|
|
52181
52410
|
import * as fs23 from "fs";
|
|
@@ -54198,11 +54427,12 @@ function consolidateSystemMessages(messages) {
|
|
|
54198
54427
|
// src/hooks/phase-monitor.ts
|
|
54199
54428
|
init_schema();
|
|
54200
54429
|
init_manager2();
|
|
54201
|
-
import * as
|
|
54430
|
+
import * as path37 from "path";
|
|
54202
54431
|
init_utils2();
|
|
54203
|
-
function createPhaseMonitorHook(directory, preflightManager, curatorRunner
|
|
54432
|
+
function createPhaseMonitorHook(directory, preflightManager, curatorRunner, llmDelegate) {
|
|
54204
54433
|
let lastKnownPhase = null;
|
|
54205
54434
|
const handler = async (_input, _output) => {
|
|
54435
|
+
const runner = curatorRunner ?? runCuratorInit;
|
|
54206
54436
|
const plan = await loadPlan(directory);
|
|
54207
54437
|
if (!plan)
|
|
54208
54438
|
return;
|
|
@@ -54214,12 +54444,29 @@ function createPhaseMonitorHook(directory, preflightManager, curatorRunner = run
|
|
|
54214
54444
|
const { config: config3 } = loadPluginConfigWithMeta2(directory);
|
|
54215
54445
|
const curatorConfig = CuratorConfigSchema.parse(config3.curator ?? {});
|
|
54216
54446
|
if (curatorConfig.enabled && curatorConfig.init_enabled) {
|
|
54217
|
-
const initResult = await
|
|
54447
|
+
const initResult = await runner(directory, curatorConfig, llmDelegate);
|
|
54218
54448
|
if (initResult.briefing) {
|
|
54219
|
-
const briefingPath =
|
|
54449
|
+
const briefingPath = path37.join(directory, ".swarm", "curator-briefing.md");
|
|
54220
54450
|
const { mkdir: mkdir5, writeFile: writeFile5 } = await import("fs/promises");
|
|
54221
|
-
await mkdir5(
|
|
54451
|
+
await mkdir5(path37.dirname(briefingPath), { recursive: true });
|
|
54222
54452
|
await writeFile5(briefingPath, initResult.briefing, "utf-8");
|
|
54453
|
+
const { buildApprovedReceipt: buildApprovedReceipt2, persistReviewReceipt: persistReviewReceipt2 } = await Promise.resolve().then(() => (init_review_receipt(), exports_review_receipt));
|
|
54454
|
+
const initReceipt = buildApprovedReceipt2({
|
|
54455
|
+
agent: "curator",
|
|
54456
|
+
scopeContent: initResult.briefing,
|
|
54457
|
+
scopeDescription: "curator-init-briefing",
|
|
54458
|
+
checkedAspects: [
|
|
54459
|
+
"knowledge_entries",
|
|
54460
|
+
"prior_phase_summaries",
|
|
54461
|
+
"contradiction_detection"
|
|
54462
|
+
],
|
|
54463
|
+
validatedClaims: [
|
|
54464
|
+
`knowledge_entries_reviewed: ${initResult.knowledge_entries_reviewed}`,
|
|
54465
|
+
`prior_phases_covered: ${initResult.prior_phases_covered}`,
|
|
54466
|
+
`contradictions: ${initResult.contradictions.length}`
|
|
54467
|
+
]
|
|
54468
|
+
});
|
|
54469
|
+
persistReviewReceipt2(directory, initReceipt).catch(() => {});
|
|
54223
54470
|
}
|
|
54224
54471
|
}
|
|
54225
54472
|
} catch {}
|
|
@@ -54324,21 +54571,25 @@ ${originalText}`;
|
|
|
54324
54571
|
})
|
|
54325
54572
|
};
|
|
54326
54573
|
}
|
|
54574
|
+
|
|
54575
|
+
// src/hooks/index.ts
|
|
54576
|
+
init_review_receipt();
|
|
54577
|
+
|
|
54327
54578
|
// src/hooks/system-enhancer.ts
|
|
54328
54579
|
init_constants();
|
|
54329
54580
|
init_schema();
|
|
54330
54581
|
init_manager();
|
|
54331
54582
|
init_detector();
|
|
54332
54583
|
init_manager2();
|
|
54333
|
-
import * as
|
|
54334
|
-
import * as
|
|
54584
|
+
import * as fs29 from "fs";
|
|
54585
|
+
import * as path41 from "path";
|
|
54335
54586
|
|
|
54336
54587
|
// src/services/decision-drift-analyzer.ts
|
|
54337
54588
|
init_utils2();
|
|
54338
54589
|
init_manager2();
|
|
54339
54590
|
init_utils();
|
|
54340
|
-
import * as
|
|
54341
|
-
import * as
|
|
54591
|
+
import * as fs26 from "fs";
|
|
54592
|
+
import * as path38 from "path";
|
|
54342
54593
|
var DEFAULT_DRIFT_CONFIG = {
|
|
54343
54594
|
staleThresholdPhases: 1,
|
|
54344
54595
|
detectContradictions: true,
|
|
@@ -54492,11 +54743,11 @@ async function analyzeDecisionDrift(directory, config3 = {}) {
|
|
|
54492
54743
|
currentPhase = legacyPhase;
|
|
54493
54744
|
}
|
|
54494
54745
|
}
|
|
54495
|
-
const contextPath =
|
|
54746
|
+
const contextPath = path38.join(directory, ".swarm", "context.md");
|
|
54496
54747
|
let contextContent = "";
|
|
54497
54748
|
try {
|
|
54498
|
-
if (
|
|
54499
|
-
contextContent =
|
|
54749
|
+
if (fs26.existsSync(contextPath)) {
|
|
54750
|
+
contextContent = fs26.readFileSync(contextPath, "utf-8");
|
|
54500
54751
|
}
|
|
54501
54752
|
} catch (error93) {
|
|
54502
54753
|
log("[DecisionDriftAnalyzer] context file read failed", {
|
|
@@ -54621,8 +54872,8 @@ init_utils();
|
|
|
54621
54872
|
// src/hooks/adversarial-detector.ts
|
|
54622
54873
|
init_constants();
|
|
54623
54874
|
init_schema();
|
|
54624
|
-
import * as
|
|
54625
|
-
import * as
|
|
54875
|
+
import * as fs27 from "fs/promises";
|
|
54876
|
+
import * as path39 from "path";
|
|
54626
54877
|
function safeGet(obj, key) {
|
|
54627
54878
|
if (!obj || !Object.hasOwn(obj, key))
|
|
54628
54879
|
return;
|
|
@@ -54836,10 +55087,10 @@ async function handleDebuggingSpiral(match, taskId, directory) {
|
|
|
54836
55087
|
let eventLogged = false;
|
|
54837
55088
|
let checkpointCreated = false;
|
|
54838
55089
|
try {
|
|
54839
|
-
const swarmDir =
|
|
54840
|
-
await
|
|
54841
|
-
const eventsPath =
|
|
54842
|
-
await
|
|
55090
|
+
const swarmDir = path39.join(directory, ".swarm");
|
|
55091
|
+
await fs27.mkdir(swarmDir, { recursive: true });
|
|
55092
|
+
const eventsPath = path39.join(swarmDir, "events.jsonl");
|
|
55093
|
+
await fs27.appendFile(eventsPath, `${formatDebuggingSpiralEvent(match, taskId)}
|
|
54843
55094
|
`);
|
|
54844
55095
|
eventLogged = true;
|
|
54845
55096
|
} catch {}
|
|
@@ -55220,7 +55471,7 @@ function createSystemEnhancerHook(config3, directory) {
|
|
|
55220
55471
|
} catch {}
|
|
55221
55472
|
try {
|
|
55222
55473
|
const darkMatterPath = validateSwarmPath(directory, "dark-matter.md");
|
|
55223
|
-
if (!
|
|
55474
|
+
if (!fs29.existsSync(darkMatterPath)) {
|
|
55224
55475
|
const {
|
|
55225
55476
|
detectDarkMatter: detectDarkMatter2,
|
|
55226
55477
|
formatDarkMatterOutput: formatDarkMatterOutput2,
|
|
@@ -55232,10 +55483,10 @@ function createSystemEnhancerHook(config3, directory) {
|
|
|
55232
55483
|
});
|
|
55233
55484
|
if (darkMatter && darkMatter.length > 0) {
|
|
55234
55485
|
const darkMatterReport = formatDarkMatterOutput2(darkMatter);
|
|
55235
|
-
await
|
|
55486
|
+
await fs29.promises.writeFile(darkMatterPath, darkMatterReport, "utf-8");
|
|
55236
55487
|
warn(`[system-enhancer] Dark matter scan complete: ${darkMatter.length} co-change patterns found`);
|
|
55237
55488
|
try {
|
|
55238
|
-
const projectName =
|
|
55489
|
+
const projectName = path41.basename(path41.resolve(directory));
|
|
55239
55490
|
const knowledgeEntries = darkMatterToKnowledgeEntries2(darkMatter, projectName);
|
|
55240
55491
|
const knowledgePath = resolveSwarmKnowledgePath(directory);
|
|
55241
55492
|
const existingEntries = await readKnowledge(knowledgePath);
|
|
@@ -55299,11 +55550,11 @@ function createSystemEnhancerHook(config3, directory) {
|
|
|
55299
55550
|
if (handoffContent) {
|
|
55300
55551
|
const handoffPath = validateSwarmPath(directory, "handoff.md");
|
|
55301
55552
|
const consumedPath = validateSwarmPath(directory, "handoff-consumed.md");
|
|
55302
|
-
if (
|
|
55553
|
+
if (fs29.existsSync(consumedPath)) {
|
|
55303
55554
|
warn("Duplicate handoff detected: handoff-consumed.md already exists");
|
|
55304
|
-
|
|
55555
|
+
fs29.unlinkSync(consumedPath);
|
|
55305
55556
|
}
|
|
55306
|
-
|
|
55557
|
+
fs29.renameSync(handoffPath, consumedPath);
|
|
55307
55558
|
const handoffBlock = `## HANDOFF \u2014 Resuming from model switch
|
|
55308
55559
|
The previous model's session ended. Here is your starting context:
|
|
55309
55560
|
|
|
@@ -55584,11 +55835,11 @@ ${budgetWarning}`);
|
|
|
55584
55835
|
if (handoffContent) {
|
|
55585
55836
|
const handoffPath = validateSwarmPath(directory, "handoff.md");
|
|
55586
55837
|
const consumedPath = validateSwarmPath(directory, "handoff-consumed.md");
|
|
55587
|
-
if (
|
|
55838
|
+
if (fs29.existsSync(consumedPath)) {
|
|
55588
55839
|
warn("Duplicate handoff detected: handoff-consumed.md already exists");
|
|
55589
|
-
|
|
55840
|
+
fs29.unlinkSync(consumedPath);
|
|
55590
55841
|
}
|
|
55591
|
-
|
|
55842
|
+
fs29.renameSync(handoffPath, consumedPath);
|
|
55592
55843
|
const handoffBlock = `## HANDOFF \u2014 Resuming from model switch
|
|
55593
55844
|
The previous model's session ended. Here is your starting context:
|
|
55594
55845
|
|
|
@@ -56358,8 +56609,8 @@ function isReadTool(toolName) {
|
|
|
56358
56609
|
}
|
|
56359
56610
|
|
|
56360
56611
|
// src/hooks/incremental-verify.ts
|
|
56361
|
-
import * as
|
|
56362
|
-
import * as
|
|
56612
|
+
import * as fs30 from "fs";
|
|
56613
|
+
import * as path42 from "path";
|
|
56363
56614
|
|
|
56364
56615
|
// src/hooks/spawn-helper.ts
|
|
56365
56616
|
import { spawn } from "child_process";
|
|
@@ -56434,21 +56685,21 @@ function spawnAsync(command, cwd, timeoutMs) {
|
|
|
56434
56685
|
// src/hooks/incremental-verify.ts
|
|
56435
56686
|
var emittedSkipAdvisories = new Set;
|
|
56436
56687
|
function detectPackageManager(projectDir) {
|
|
56437
|
-
if (
|
|
56688
|
+
if (fs30.existsSync(path42.join(projectDir, "bun.lockb")))
|
|
56438
56689
|
return "bun";
|
|
56439
|
-
if (
|
|
56690
|
+
if (fs30.existsSync(path42.join(projectDir, "pnpm-lock.yaml")))
|
|
56440
56691
|
return "pnpm";
|
|
56441
|
-
if (
|
|
56692
|
+
if (fs30.existsSync(path42.join(projectDir, "yarn.lock")))
|
|
56442
56693
|
return "yarn";
|
|
56443
|
-
if (
|
|
56694
|
+
if (fs30.existsSync(path42.join(projectDir, "package-lock.json")))
|
|
56444
56695
|
return "npm";
|
|
56445
56696
|
return "bun";
|
|
56446
56697
|
}
|
|
56447
56698
|
function detectTypecheckCommand(projectDir) {
|
|
56448
|
-
const pkgPath =
|
|
56449
|
-
if (
|
|
56699
|
+
const pkgPath = path42.join(projectDir, "package.json");
|
|
56700
|
+
if (fs30.existsSync(pkgPath)) {
|
|
56450
56701
|
try {
|
|
56451
|
-
const pkg = JSON.parse(
|
|
56702
|
+
const pkg = JSON.parse(fs30.readFileSync(pkgPath, "utf8"));
|
|
56452
56703
|
const scripts = pkg.scripts;
|
|
56453
56704
|
if (scripts?.typecheck) {
|
|
56454
56705
|
const pm = detectPackageManager(projectDir);
|
|
@@ -56462,8 +56713,8 @@ function detectTypecheckCommand(projectDir) {
|
|
|
56462
56713
|
...pkg.dependencies,
|
|
56463
56714
|
...pkg.devDependencies
|
|
56464
56715
|
};
|
|
56465
|
-
if (!deps?.typescript && !
|
|
56466
|
-
const hasTSMarkers = deps?.typescript ||
|
|
56716
|
+
if (!deps?.typescript && !fs30.existsSync(path42.join(projectDir, "tsconfig.json"))) {}
|
|
56717
|
+
const hasTSMarkers = deps?.typescript || fs30.existsSync(path42.join(projectDir, "tsconfig.json"));
|
|
56467
56718
|
if (hasTSMarkers) {
|
|
56468
56719
|
return { command: ["npx", "tsc", "--noEmit"], language: "typescript" };
|
|
56469
56720
|
}
|
|
@@ -56471,17 +56722,17 @@ function detectTypecheckCommand(projectDir) {
|
|
|
56471
56722
|
return null;
|
|
56472
56723
|
}
|
|
56473
56724
|
}
|
|
56474
|
-
if (
|
|
56725
|
+
if (fs30.existsSync(path42.join(projectDir, "go.mod"))) {
|
|
56475
56726
|
return { command: ["go", "vet", "./..."], language: "go" };
|
|
56476
56727
|
}
|
|
56477
|
-
if (
|
|
56728
|
+
if (fs30.existsSync(path42.join(projectDir, "Cargo.toml"))) {
|
|
56478
56729
|
return { command: ["cargo", "check"], language: "rust" };
|
|
56479
56730
|
}
|
|
56480
|
-
if (
|
|
56731
|
+
if (fs30.existsSync(path42.join(projectDir, "pyproject.toml")) || fs30.existsSync(path42.join(projectDir, "requirements.txt")) || fs30.existsSync(path42.join(projectDir, "setup.py"))) {
|
|
56481
56732
|
return { command: null, language: "python" };
|
|
56482
56733
|
}
|
|
56483
56734
|
try {
|
|
56484
|
-
const entries =
|
|
56735
|
+
const entries = fs30.readdirSync(projectDir);
|
|
56485
56736
|
if (entries.some((f) => f.endsWith(".csproj") || f.endsWith(".sln"))) {
|
|
56486
56737
|
return {
|
|
56487
56738
|
command: ["dotnet", "build", "--no-restore"],
|
|
@@ -56661,19 +56912,7 @@ function sanitizeLessonForContext(text) {
|
|
|
56661
56912
|
}
|
|
56662
56913
|
function isOrchestratorAgent(agentName) {
|
|
56663
56914
|
const stripped = stripKnownSwarmPrefix(agentName);
|
|
56664
|
-
|
|
56665
|
-
"coder",
|
|
56666
|
-
"reviewer",
|
|
56667
|
-
"test_engineer",
|
|
56668
|
-
"security_reviewer",
|
|
56669
|
-
"integration_analyst",
|
|
56670
|
-
"docs_writer",
|
|
56671
|
-
"designer",
|
|
56672
|
-
"critic",
|
|
56673
|
-
"docs",
|
|
56674
|
-
"explorer"
|
|
56675
|
-
]);
|
|
56676
|
-
return !nonOrchestratorAgents.has(stripped.toLowerCase());
|
|
56915
|
+
return stripped.toLowerCase() === "architect";
|
|
56677
56916
|
}
|
|
56678
56917
|
function injectKnowledgeMessage(output, text) {
|
|
56679
56918
|
if (!output.messages)
|
|
@@ -56790,7 +57029,7 @@ ${injectionText}`;
|
|
|
56790
57029
|
// src/hooks/scope-guard.ts
|
|
56791
57030
|
init_constants();
|
|
56792
57031
|
init_schema();
|
|
56793
|
-
import * as
|
|
57032
|
+
import * as path44 from "path";
|
|
56794
57033
|
var WRITE_TOOLS = new Set([
|
|
56795
57034
|
"write",
|
|
56796
57035
|
"edit",
|
|
@@ -56852,13 +57091,13 @@ function createScopeGuardHook(config3, directory, injectAdvisory) {
|
|
|
56852
57091
|
}
|
|
56853
57092
|
function isFileInScope(filePath, scopeEntries, directory) {
|
|
56854
57093
|
const dir = directory ?? process.cwd();
|
|
56855
|
-
const resolvedFile =
|
|
57094
|
+
const resolvedFile = path44.resolve(dir, filePath);
|
|
56856
57095
|
return scopeEntries.some((scope) => {
|
|
56857
|
-
const resolvedScope =
|
|
57096
|
+
const resolvedScope = path44.resolve(dir, scope);
|
|
56858
57097
|
if (resolvedFile === resolvedScope)
|
|
56859
57098
|
return true;
|
|
56860
|
-
const rel =
|
|
56861
|
-
return rel.length > 0 && !rel.startsWith("..") && !
|
|
57099
|
+
const rel = path44.relative(resolvedScope, resolvedFile);
|
|
57100
|
+
return rel.length > 0 && !rel.startsWith("..") && !path44.isAbsolute(rel);
|
|
56862
57101
|
});
|
|
56863
57102
|
}
|
|
56864
57103
|
|
|
@@ -56907,8 +57146,8 @@ function createSelfReviewHook(config3, injectAdvisory) {
|
|
|
56907
57146
|
}
|
|
56908
57147
|
|
|
56909
57148
|
// src/hooks/slop-detector.ts
|
|
56910
|
-
import * as
|
|
56911
|
-
import * as
|
|
57149
|
+
import * as fs32 from "fs";
|
|
57150
|
+
import * as path45 from "path";
|
|
56912
57151
|
var WRITE_EDIT_TOOLS = new Set([
|
|
56913
57152
|
"write",
|
|
56914
57153
|
"edit",
|
|
@@ -56953,12 +57192,12 @@ function checkBoilerplateExplosion(content, taskDescription, threshold) {
|
|
|
56953
57192
|
function walkFiles(dir, exts, deadline) {
|
|
56954
57193
|
const results = [];
|
|
56955
57194
|
try {
|
|
56956
|
-
for (const entry of
|
|
57195
|
+
for (const entry of fs32.readdirSync(dir, { withFileTypes: true })) {
|
|
56957
57196
|
if (deadline !== undefined && Date.now() > deadline)
|
|
56958
57197
|
break;
|
|
56959
57198
|
if (entry.isSymbolicLink())
|
|
56960
57199
|
continue;
|
|
56961
|
-
const full =
|
|
57200
|
+
const full = path45.join(dir, entry.name);
|
|
56962
57201
|
if (entry.isDirectory()) {
|
|
56963
57202
|
if (entry.name === "node_modules" || entry.name === ".git")
|
|
56964
57203
|
continue;
|
|
@@ -56973,7 +57212,7 @@ function walkFiles(dir, exts, deadline) {
|
|
|
56973
57212
|
return results;
|
|
56974
57213
|
}
|
|
56975
57214
|
function checkDeadExports(content, projectDir, startTime) {
|
|
56976
|
-
const hasPackageJson =
|
|
57215
|
+
const hasPackageJson = fs32.existsSync(path45.join(projectDir, "package.json"));
|
|
56977
57216
|
if (!hasPackageJson)
|
|
56978
57217
|
return null;
|
|
56979
57218
|
const exportMatches = content.matchAll(/^\+(?:export)\s+(?:function|class|const|type|interface)\s+(\w{3,})/gm);
|
|
@@ -56996,7 +57235,7 @@ function checkDeadExports(content, projectDir, startTime) {
|
|
|
56996
57235
|
if (found || Date.now() - startTime > 480)
|
|
56997
57236
|
break;
|
|
56998
57237
|
try {
|
|
56999
|
-
const text =
|
|
57238
|
+
const text = fs32.readFileSync(file3, "utf-8");
|
|
57000
57239
|
if (importPattern.test(text))
|
|
57001
57240
|
found = true;
|
|
57002
57241
|
importPattern.lastIndex = 0;
|
|
@@ -57129,7 +57368,7 @@ Review before proceeding.`;
|
|
|
57129
57368
|
|
|
57130
57369
|
// src/hooks/steering-consumed.ts
|
|
57131
57370
|
init_utils2();
|
|
57132
|
-
import * as
|
|
57371
|
+
import * as fs33 from "fs";
|
|
57133
57372
|
function recordSteeringConsumed(directory, directiveId) {
|
|
57134
57373
|
try {
|
|
57135
57374
|
const eventsPath = validateSwarmPath(directory, "events.jsonl");
|
|
@@ -57138,7 +57377,7 @@ function recordSteeringConsumed(directory, directiveId) {
|
|
|
57138
57377
|
directiveId,
|
|
57139
57378
|
timestamp: new Date().toISOString()
|
|
57140
57379
|
};
|
|
57141
|
-
|
|
57380
|
+
fs33.appendFileSync(eventsPath, `${JSON.stringify(event)}
|
|
57142
57381
|
`, "utf-8");
|
|
57143
57382
|
} catch {}
|
|
57144
57383
|
}
|
|
@@ -57183,7 +57422,7 @@ init_config_doctor();
|
|
|
57183
57422
|
|
|
57184
57423
|
// src/session/snapshot-reader.ts
|
|
57185
57424
|
init_utils2();
|
|
57186
|
-
import { renameSync as
|
|
57425
|
+
import { renameSync as renameSync12 } from "fs";
|
|
57187
57426
|
var TRANSIENT_SESSION_FIELDS = [
|
|
57188
57427
|
{ name: "revisionLimitHit", resetValue: false },
|
|
57189
57428
|
{ name: "coderRevisions", resetValue: 0 },
|
|
@@ -57294,7 +57533,7 @@ async function readSnapshot(directory) {
|
|
|
57294
57533
|
if (parsed.version !== 1 && parsed.version !== 2) {
|
|
57295
57534
|
try {
|
|
57296
57535
|
const quarantinePath = validateSwarmPath(directory, "session/state.json.quarantine");
|
|
57297
|
-
|
|
57536
|
+
renameSync12(resolvedPath, quarantinePath);
|
|
57298
57537
|
} catch {}
|
|
57299
57538
|
return null;
|
|
57300
57539
|
}
|
|
@@ -57551,8 +57790,8 @@ init_dist();
|
|
|
57551
57790
|
init_manager();
|
|
57552
57791
|
init_create_tool();
|
|
57553
57792
|
init_resolve_working_directory();
|
|
57554
|
-
import * as
|
|
57555
|
-
import * as
|
|
57793
|
+
import * as fs34 from "fs";
|
|
57794
|
+
import * as path46 from "path";
|
|
57556
57795
|
var EVIDENCE_DIR = ".swarm/evidence";
|
|
57557
57796
|
var TASK_ID_PATTERN2 = /^\d+\.\d+(\.\d+)*$/;
|
|
57558
57797
|
function isValidTaskId3(taskId) {
|
|
@@ -57569,18 +57808,18 @@ function isValidTaskId3(taskId) {
|
|
|
57569
57808
|
return TASK_ID_PATTERN2.test(taskId);
|
|
57570
57809
|
}
|
|
57571
57810
|
function isPathWithinSwarm(filePath, workspaceRoot) {
|
|
57572
|
-
const normalizedWorkspace =
|
|
57573
|
-
const swarmPath =
|
|
57574
|
-
const normalizedPath =
|
|
57811
|
+
const normalizedWorkspace = path46.resolve(workspaceRoot);
|
|
57812
|
+
const swarmPath = path46.join(normalizedWorkspace, ".swarm", "evidence");
|
|
57813
|
+
const normalizedPath = path46.resolve(filePath);
|
|
57575
57814
|
return normalizedPath.startsWith(swarmPath);
|
|
57576
57815
|
}
|
|
57577
57816
|
function readEvidenceFile(evidencePath) {
|
|
57578
|
-
if (!
|
|
57817
|
+
if (!fs34.existsSync(evidencePath)) {
|
|
57579
57818
|
return null;
|
|
57580
57819
|
}
|
|
57581
57820
|
let content;
|
|
57582
57821
|
try {
|
|
57583
|
-
content =
|
|
57822
|
+
content = fs34.readFileSync(evidencePath, "utf-8");
|
|
57584
57823
|
} catch {
|
|
57585
57824
|
return null;
|
|
57586
57825
|
}
|
|
@@ -57652,7 +57891,7 @@ var check_gate_status = createSwarmTool({
|
|
|
57652
57891
|
};
|
|
57653
57892
|
return JSON.stringify(errorResult, null, 2);
|
|
57654
57893
|
}
|
|
57655
|
-
const evidencePath =
|
|
57894
|
+
const evidencePath = path46.join(directory, EVIDENCE_DIR, `${taskIdInput}.json`);
|
|
57656
57895
|
if (!isPathWithinSwarm(evidencePath, directory)) {
|
|
57657
57896
|
const errorResult = {
|
|
57658
57897
|
taskId: taskIdInput,
|
|
@@ -57745,8 +57984,8 @@ init_co_change_analyzer();
|
|
|
57745
57984
|
// src/tools/completion-verify.ts
|
|
57746
57985
|
init_dist();
|
|
57747
57986
|
init_utils2();
|
|
57748
|
-
import * as
|
|
57749
|
-
import * as
|
|
57987
|
+
import * as fs35 from "fs";
|
|
57988
|
+
import * as path47 from "path";
|
|
57750
57989
|
init_create_tool();
|
|
57751
57990
|
init_resolve_working_directory();
|
|
57752
57991
|
function extractMatches(regex, text) {
|
|
@@ -57842,7 +58081,7 @@ async function executeCompletionVerify(args2, directory) {
|
|
|
57842
58081
|
let plan;
|
|
57843
58082
|
try {
|
|
57844
58083
|
const planPath = validateSwarmPath(directory, "plan.json");
|
|
57845
|
-
const planRaw =
|
|
58084
|
+
const planRaw = fs35.readFileSync(planPath, "utf-8");
|
|
57846
58085
|
plan = JSON.parse(planRaw);
|
|
57847
58086
|
} catch {
|
|
57848
58087
|
const result2 = {
|
|
@@ -57900,10 +58139,10 @@ async function executeCompletionVerify(args2, directory) {
|
|
|
57900
58139
|
let hasFileReadFailure = false;
|
|
57901
58140
|
for (const filePath of fileTargets) {
|
|
57902
58141
|
const normalizedPath = filePath.replace(/\\/g, "/");
|
|
57903
|
-
const resolvedPath =
|
|
57904
|
-
const projectRoot =
|
|
57905
|
-
const relative6 =
|
|
57906
|
-
const withinProject = relative6 === "" || !relative6.startsWith("..") && !
|
|
58142
|
+
const resolvedPath = path47.resolve(directory, normalizedPath);
|
|
58143
|
+
const projectRoot = path47.resolve(directory);
|
|
58144
|
+
const relative6 = path47.relative(projectRoot, resolvedPath);
|
|
58145
|
+
const withinProject = relative6 === "" || !relative6.startsWith("..") && !path47.isAbsolute(relative6);
|
|
57907
58146
|
if (!withinProject) {
|
|
57908
58147
|
blockedTasks.push({
|
|
57909
58148
|
task_id: task.id,
|
|
@@ -57916,7 +58155,7 @@ async function executeCompletionVerify(args2, directory) {
|
|
|
57916
58155
|
}
|
|
57917
58156
|
let fileContent;
|
|
57918
58157
|
try {
|
|
57919
|
-
fileContent =
|
|
58158
|
+
fileContent = fs35.readFileSync(resolvedPath, "utf-8");
|
|
57920
58159
|
} catch {
|
|
57921
58160
|
blockedTasks.push({
|
|
57922
58161
|
task_id: task.id,
|
|
@@ -57958,9 +58197,9 @@ async function executeCompletionVerify(args2, directory) {
|
|
|
57958
58197
|
blockedTasks
|
|
57959
58198
|
};
|
|
57960
58199
|
try {
|
|
57961
|
-
const evidenceDir =
|
|
57962
|
-
const evidencePath =
|
|
57963
|
-
|
|
58200
|
+
const evidenceDir = path47.join(directory, ".swarm", "evidence", `${phase}`);
|
|
58201
|
+
const evidencePath = path47.join(evidenceDir, "completion-verify.json");
|
|
58202
|
+
fs35.mkdirSync(evidenceDir, { recursive: true });
|
|
57964
58203
|
const evidenceBundle = {
|
|
57965
58204
|
schema_version: "1.0.0",
|
|
57966
58205
|
task_id: "completion-verify",
|
|
@@ -57981,7 +58220,7 @@ async function executeCompletionVerify(args2, directory) {
|
|
|
57981
58220
|
}
|
|
57982
58221
|
]
|
|
57983
58222
|
};
|
|
57984
|
-
|
|
58223
|
+
fs35.writeFileSync(evidencePath, JSON.stringify(evidenceBundle, null, 2), "utf-8");
|
|
57985
58224
|
} catch {}
|
|
57986
58225
|
return JSON.stringify(result, null, 2);
|
|
57987
58226
|
}
|
|
@@ -58035,12 +58274,12 @@ var completion_verify = createSwarmTool({
|
|
|
58035
58274
|
});
|
|
58036
58275
|
// src/tools/complexity-hotspots.ts
|
|
58037
58276
|
init_dist();
|
|
58038
|
-
import * as
|
|
58039
|
-
import * as
|
|
58277
|
+
import * as fs37 from "fs";
|
|
58278
|
+
import * as path49 from "path";
|
|
58040
58279
|
|
|
58041
58280
|
// src/quality/metrics.ts
|
|
58042
|
-
import * as
|
|
58043
|
-
import * as
|
|
58281
|
+
import * as fs36 from "fs";
|
|
58282
|
+
import * as path48 from "path";
|
|
58044
58283
|
var MAX_FILE_SIZE_BYTES2 = 256 * 1024;
|
|
58045
58284
|
var MIN_DUPLICATION_LINES = 10;
|
|
58046
58285
|
function estimateCyclomaticComplexity(content) {
|
|
@@ -58078,11 +58317,11 @@ function estimateCyclomaticComplexity(content) {
|
|
|
58078
58317
|
}
|
|
58079
58318
|
function getComplexityForFile(filePath) {
|
|
58080
58319
|
try {
|
|
58081
|
-
const stat2 =
|
|
58320
|
+
const stat2 = fs36.statSync(filePath);
|
|
58082
58321
|
if (stat2.size > MAX_FILE_SIZE_BYTES2) {
|
|
58083
58322
|
return null;
|
|
58084
58323
|
}
|
|
58085
|
-
const content =
|
|
58324
|
+
const content = fs36.readFileSync(filePath, "utf-8");
|
|
58086
58325
|
return estimateCyclomaticComplexity(content);
|
|
58087
58326
|
} catch {
|
|
58088
58327
|
return null;
|
|
@@ -58092,8 +58331,8 @@ async function computeComplexityDelta(files, workingDir) {
|
|
|
58092
58331
|
let totalComplexity = 0;
|
|
58093
58332
|
const analyzedFiles = [];
|
|
58094
58333
|
for (const file3 of files) {
|
|
58095
|
-
const fullPath =
|
|
58096
|
-
if (!
|
|
58334
|
+
const fullPath = path48.isAbsolute(file3) ? file3 : path48.join(workingDir, file3);
|
|
58335
|
+
if (!fs36.existsSync(fullPath)) {
|
|
58097
58336
|
continue;
|
|
58098
58337
|
}
|
|
58099
58338
|
const complexity = getComplexityForFile(fullPath);
|
|
@@ -58214,8 +58453,8 @@ function countGoExports(content) {
|
|
|
58214
58453
|
}
|
|
58215
58454
|
function getExportCountForFile(filePath) {
|
|
58216
58455
|
try {
|
|
58217
|
-
const content =
|
|
58218
|
-
const ext =
|
|
58456
|
+
const content = fs36.readFileSync(filePath, "utf-8");
|
|
58457
|
+
const ext = path48.extname(filePath).toLowerCase();
|
|
58219
58458
|
switch (ext) {
|
|
58220
58459
|
case ".ts":
|
|
58221
58460
|
case ".tsx":
|
|
@@ -58241,8 +58480,8 @@ async function computePublicApiDelta(files, workingDir) {
|
|
|
58241
58480
|
let totalExports = 0;
|
|
58242
58481
|
const analyzedFiles = [];
|
|
58243
58482
|
for (const file3 of files) {
|
|
58244
|
-
const fullPath =
|
|
58245
|
-
if (!
|
|
58483
|
+
const fullPath = path48.isAbsolute(file3) ? file3 : path48.join(workingDir, file3);
|
|
58484
|
+
if (!fs36.existsSync(fullPath)) {
|
|
58246
58485
|
continue;
|
|
58247
58486
|
}
|
|
58248
58487
|
const exports = getExportCountForFile(fullPath);
|
|
@@ -58275,16 +58514,16 @@ async function computeDuplicationRatio(files, workingDir) {
|
|
|
58275
58514
|
let duplicateLines = 0;
|
|
58276
58515
|
const analyzedFiles = [];
|
|
58277
58516
|
for (const file3 of files) {
|
|
58278
|
-
const fullPath =
|
|
58279
|
-
if (!
|
|
58517
|
+
const fullPath = path48.isAbsolute(file3) ? file3 : path48.join(workingDir, file3);
|
|
58518
|
+
if (!fs36.existsSync(fullPath)) {
|
|
58280
58519
|
continue;
|
|
58281
58520
|
}
|
|
58282
58521
|
try {
|
|
58283
|
-
const stat2 =
|
|
58522
|
+
const stat2 = fs36.statSync(fullPath);
|
|
58284
58523
|
if (stat2.size > MAX_FILE_SIZE_BYTES2) {
|
|
58285
58524
|
continue;
|
|
58286
58525
|
}
|
|
58287
|
-
const content =
|
|
58526
|
+
const content = fs36.readFileSync(fullPath, "utf-8");
|
|
58288
58527
|
const lines = content.split(`
|
|
58289
58528
|
`).filter((line) => line.trim().length > 0);
|
|
58290
58529
|
if (lines.length < MIN_DUPLICATION_LINES) {
|
|
@@ -58308,8 +58547,8 @@ function countCodeLines(content) {
|
|
|
58308
58547
|
return lines.length;
|
|
58309
58548
|
}
|
|
58310
58549
|
function isTestFile(filePath) {
|
|
58311
|
-
const basename7 =
|
|
58312
|
-
const _ext =
|
|
58550
|
+
const basename7 = path48.basename(filePath);
|
|
58551
|
+
const _ext = path48.extname(filePath).toLowerCase();
|
|
58313
58552
|
const testPatterns = [
|
|
58314
58553
|
".test.",
|
|
58315
58554
|
".spec.",
|
|
@@ -58390,8 +58629,8 @@ function matchGlobSegment(globSegments, pathSegments) {
|
|
|
58390
58629
|
}
|
|
58391
58630
|
return gIndex === globSegments.length && pIndex === pathSegments.length;
|
|
58392
58631
|
}
|
|
58393
|
-
function matchesGlobSegment(
|
|
58394
|
-
const normalizedPath =
|
|
58632
|
+
function matchesGlobSegment(path49, glob) {
|
|
58633
|
+
const normalizedPath = path49.replace(/\\/g, "/");
|
|
58395
58634
|
const normalizedGlob = glob.replace(/\\/g, "/");
|
|
58396
58635
|
if (normalizedPath.includes("//")) {
|
|
58397
58636
|
return false;
|
|
@@ -58422,8 +58661,8 @@ function simpleGlobToRegex2(glob) {
|
|
|
58422
58661
|
function hasGlobstar(glob) {
|
|
58423
58662
|
return glob.includes("**");
|
|
58424
58663
|
}
|
|
58425
|
-
function globMatches(
|
|
58426
|
-
const normalizedPath =
|
|
58664
|
+
function globMatches(path49, glob) {
|
|
58665
|
+
const normalizedPath = path49.replace(/\\/g, "/");
|
|
58427
58666
|
if (!glob || glob === "") {
|
|
58428
58667
|
if (normalizedPath.includes("//")) {
|
|
58429
58668
|
return false;
|
|
@@ -58459,31 +58698,31 @@ function shouldExcludeFile(filePath, excludeGlobs) {
|
|
|
58459
58698
|
async function computeTestToCodeRatio(workingDir, enforceGlobs, excludeGlobs) {
|
|
58460
58699
|
let testLines = 0;
|
|
58461
58700
|
let codeLines = 0;
|
|
58462
|
-
const srcDir =
|
|
58463
|
-
if (
|
|
58701
|
+
const srcDir = path48.join(workingDir, "src");
|
|
58702
|
+
if (fs36.existsSync(srcDir)) {
|
|
58464
58703
|
await scanDirectoryForLines(srcDir, enforceGlobs, excludeGlobs, false, (lines) => {
|
|
58465
58704
|
codeLines += lines;
|
|
58466
58705
|
});
|
|
58467
58706
|
}
|
|
58468
58707
|
const possibleSrcDirs = ["lib", "app", "source", "core"];
|
|
58469
58708
|
for (const dir of possibleSrcDirs) {
|
|
58470
|
-
const dirPath =
|
|
58471
|
-
if (
|
|
58709
|
+
const dirPath = path48.join(workingDir, dir);
|
|
58710
|
+
if (fs36.existsSync(dirPath)) {
|
|
58472
58711
|
await scanDirectoryForLines(dirPath, enforceGlobs, excludeGlobs, false, (lines) => {
|
|
58473
58712
|
codeLines += lines;
|
|
58474
58713
|
});
|
|
58475
58714
|
}
|
|
58476
58715
|
}
|
|
58477
|
-
const testsDir =
|
|
58478
|
-
if (
|
|
58716
|
+
const testsDir = path48.join(workingDir, "tests");
|
|
58717
|
+
if (fs36.existsSync(testsDir)) {
|
|
58479
58718
|
await scanDirectoryForLines(testsDir, ["**"], ["node_modules", "dist"], true, (lines) => {
|
|
58480
58719
|
testLines += lines;
|
|
58481
58720
|
});
|
|
58482
58721
|
}
|
|
58483
58722
|
const possibleTestDirs = ["test", "__tests__", "specs"];
|
|
58484
58723
|
for (const dir of possibleTestDirs) {
|
|
58485
|
-
const dirPath =
|
|
58486
|
-
if (
|
|
58724
|
+
const dirPath = path48.join(workingDir, dir);
|
|
58725
|
+
if (fs36.existsSync(dirPath) && dirPath !== testsDir) {
|
|
58487
58726
|
await scanDirectoryForLines(dirPath, ["**"], ["node_modules", "dist"], true, (lines) => {
|
|
58488
58727
|
testLines += lines;
|
|
58489
58728
|
});
|
|
@@ -58495,9 +58734,9 @@ async function computeTestToCodeRatio(workingDir, enforceGlobs, excludeGlobs) {
|
|
|
58495
58734
|
}
|
|
58496
58735
|
async function scanDirectoryForLines(dirPath, includeGlobs, excludeGlobs, isTestScan, callback) {
|
|
58497
58736
|
try {
|
|
58498
|
-
const entries =
|
|
58737
|
+
const entries = fs36.readdirSync(dirPath, { withFileTypes: true });
|
|
58499
58738
|
for (const entry of entries) {
|
|
58500
|
-
const fullPath =
|
|
58739
|
+
const fullPath = path48.join(dirPath, entry.name);
|
|
58501
58740
|
if (entry.isDirectory()) {
|
|
58502
58741
|
if (entry.name === "node_modules" || entry.name === "dist" || entry.name === "build" || entry.name === ".git") {
|
|
58503
58742
|
continue;
|
|
@@ -58505,7 +58744,7 @@ async function scanDirectoryForLines(dirPath, includeGlobs, excludeGlobs, isTest
|
|
|
58505
58744
|
await scanDirectoryForLines(fullPath, includeGlobs, excludeGlobs, isTestScan, callback);
|
|
58506
58745
|
} else if (entry.isFile()) {
|
|
58507
58746
|
const relativePath = fullPath.replace(`${dirPath}/`, "");
|
|
58508
|
-
const ext =
|
|
58747
|
+
const ext = path48.extname(entry.name).toLowerCase();
|
|
58509
58748
|
const validExts = [
|
|
58510
58749
|
".ts",
|
|
58511
58750
|
".tsx",
|
|
@@ -58541,7 +58780,7 @@ async function scanDirectoryForLines(dirPath, includeGlobs, excludeGlobs, isTest
|
|
|
58541
58780
|
continue;
|
|
58542
58781
|
}
|
|
58543
58782
|
try {
|
|
58544
|
-
const content =
|
|
58783
|
+
const content = fs36.readFileSync(fullPath, "utf-8");
|
|
58545
58784
|
const lines = countCodeLines(content);
|
|
58546
58785
|
callback(lines);
|
|
58547
58786
|
} catch {}
|
|
@@ -58742,11 +58981,11 @@ async function getGitChurn(days, directory) {
|
|
|
58742
58981
|
}
|
|
58743
58982
|
function getComplexityForFile2(filePath) {
|
|
58744
58983
|
try {
|
|
58745
|
-
const stat2 =
|
|
58984
|
+
const stat2 = fs37.statSync(filePath);
|
|
58746
58985
|
if (stat2.size > MAX_FILE_SIZE_BYTES3) {
|
|
58747
58986
|
return null;
|
|
58748
58987
|
}
|
|
58749
|
-
const content =
|
|
58988
|
+
const content = fs37.readFileSync(filePath, "utf-8");
|
|
58750
58989
|
return estimateCyclomaticComplexity(content);
|
|
58751
58990
|
} catch {
|
|
58752
58991
|
return null;
|
|
@@ -58757,7 +58996,7 @@ async function analyzeHotspots(days, topN, extensions, directory) {
|
|
|
58757
58996
|
const extSet = new Set(extensions.map((e) => e.startsWith(".") ? e : `.${e}`));
|
|
58758
58997
|
const filteredChurn = new Map;
|
|
58759
58998
|
for (const [file3, count] of churnMap) {
|
|
58760
|
-
const ext =
|
|
58999
|
+
const ext = path49.extname(file3).toLowerCase();
|
|
58761
59000
|
if (extSet.has(ext)) {
|
|
58762
59001
|
filteredChurn.set(file3, count);
|
|
58763
59002
|
}
|
|
@@ -58767,8 +59006,8 @@ async function analyzeHotspots(days, topN, extensions, directory) {
|
|
|
58767
59006
|
let analyzedFiles = 0;
|
|
58768
59007
|
for (const [file3, churnCount] of filteredChurn) {
|
|
58769
59008
|
let fullPath = file3;
|
|
58770
|
-
if (!
|
|
58771
|
-
fullPath =
|
|
59009
|
+
if (!fs37.existsSync(fullPath)) {
|
|
59010
|
+
fullPath = path49.join(cwd, file3);
|
|
58772
59011
|
}
|
|
58773
59012
|
const complexity = getComplexityForFile2(fullPath);
|
|
58774
59013
|
if (complexity !== null) {
|
|
@@ -58917,6 +59156,7 @@ var complexity_hotspots = createSwarmTool({
|
|
|
58917
59156
|
init_dist();
|
|
58918
59157
|
init_config();
|
|
58919
59158
|
init_schema();
|
|
59159
|
+
init_review_receipt();
|
|
58920
59160
|
init_create_tool();
|
|
58921
59161
|
var curator_analyze = createSwarmTool({
|
|
58922
59162
|
description: "Run curator phase analysis and optionally apply knowledge recommendations. " + "Call this after reviewing a phase to apply knowledge updates. " + "If recommendations is provided, applies them via applyCuratorKnowledgeUpdates.",
|
|
@@ -58952,7 +59192,40 @@ var curator_analyze = createSwarmTool({
|
|
|
58952
59192
|
const { config: config3 } = loadPluginConfigWithMeta(directory);
|
|
58953
59193
|
const curatorConfig = CuratorConfigSchema.parse(config3.curator ?? {});
|
|
58954
59194
|
const knowledgeConfig = KnowledgeConfigSchema.parse(config3.knowledge ?? {});
|
|
58955
|
-
const
|
|
59195
|
+
const llmDelegate = createCuratorLLMDelegate(directory);
|
|
59196
|
+
const curatorResult = await runCuratorPhase(directory, typedArgs.phase, [], curatorConfig, {}, llmDelegate);
|
|
59197
|
+
{
|
|
59198
|
+
const scopeContent = curatorResult.digest?.summary ?? `Phase ${typedArgs.phase} curator analysis`;
|
|
59199
|
+
const complianceWarnings = curatorResult.compliance.filter((c) => c.severity === "warning");
|
|
59200
|
+
const receipt = complianceWarnings.length > 0 ? buildRejectedReceipt({
|
|
59201
|
+
agent: "curator",
|
|
59202
|
+
scopeContent,
|
|
59203
|
+
scopeDescription: "phase-digest",
|
|
59204
|
+
blockingFindings: complianceWarnings.map((c) => ({
|
|
59205
|
+
location: `phase-${c.phase}`,
|
|
59206
|
+
summary: c.description,
|
|
59207
|
+
severity: c.type === "missing_reviewer" ? "high" : "medium"
|
|
59208
|
+
})),
|
|
59209
|
+
evidenceReferences: [],
|
|
59210
|
+
passConditions: [
|
|
59211
|
+
"resolve all compliance warnings before phase completion"
|
|
59212
|
+
]
|
|
59213
|
+
}) : buildApprovedReceipt({
|
|
59214
|
+
agent: "curator",
|
|
59215
|
+
scopeContent,
|
|
59216
|
+
scopeDescription: "phase-digest",
|
|
59217
|
+
checkedAspects: [
|
|
59218
|
+
"phase_compliance",
|
|
59219
|
+
"knowledge_recommendations",
|
|
59220
|
+
"phase_digest"
|
|
59221
|
+
],
|
|
59222
|
+
validatedClaims: [
|
|
59223
|
+
`phase: ${typedArgs.phase}`,
|
|
59224
|
+
`knowledge_recommendations: ${curatorResult.knowledge_recommendations.length}`
|
|
59225
|
+
]
|
|
59226
|
+
});
|
|
59227
|
+
persistReviewReceipt(directory, receipt).catch(() => {});
|
|
59228
|
+
}
|
|
58956
59229
|
let applied = 0;
|
|
58957
59230
|
let skipped = 0;
|
|
58958
59231
|
if (typedArgs.recommendations && typedArgs.recommendations.length > 0) {
|
|
@@ -58976,8 +59249,8 @@ var curator_analyze = createSwarmTool({
|
|
|
58976
59249
|
});
|
|
58977
59250
|
// src/tools/declare-scope.ts
|
|
58978
59251
|
init_tool();
|
|
58979
|
-
import * as
|
|
58980
|
-
import * as
|
|
59252
|
+
import * as fs38 from "fs";
|
|
59253
|
+
import * as path50 from "path";
|
|
58981
59254
|
init_create_tool();
|
|
58982
59255
|
function validateTaskIdFormat(taskId) {
|
|
58983
59256
|
const taskIdPattern = /^\d+\.\d+(\.\d+)*$/;
|
|
@@ -59056,8 +59329,8 @@ async function executeDeclareScope(args2, fallbackDir) {
|
|
|
59056
59329
|
};
|
|
59057
59330
|
}
|
|
59058
59331
|
}
|
|
59059
|
-
normalizedDir =
|
|
59060
|
-
const pathParts = normalizedDir.split(
|
|
59332
|
+
normalizedDir = path50.normalize(args2.working_directory);
|
|
59333
|
+
const pathParts = normalizedDir.split(path50.sep);
|
|
59061
59334
|
if (pathParts.includes("..")) {
|
|
59062
59335
|
return {
|
|
59063
59336
|
success: false,
|
|
@@ -59067,11 +59340,11 @@ async function executeDeclareScope(args2, fallbackDir) {
|
|
|
59067
59340
|
]
|
|
59068
59341
|
};
|
|
59069
59342
|
}
|
|
59070
|
-
const resolvedDir =
|
|
59343
|
+
const resolvedDir = path50.resolve(normalizedDir);
|
|
59071
59344
|
try {
|
|
59072
|
-
const realPath =
|
|
59073
|
-
const planPath2 =
|
|
59074
|
-
if (!
|
|
59345
|
+
const realPath = fs38.realpathSync(resolvedDir);
|
|
59346
|
+
const planPath2 = path50.join(realPath, ".swarm", "plan.json");
|
|
59347
|
+
if (!fs38.existsSync(planPath2)) {
|
|
59075
59348
|
return {
|
|
59076
59349
|
success: false,
|
|
59077
59350
|
message: `Invalid working_directory: plan not found in "${realPath}"`,
|
|
@@ -59094,8 +59367,8 @@ async function executeDeclareScope(args2, fallbackDir) {
|
|
|
59094
59367
|
console.warn("[declare-scope] fallbackDir is undefined, falling back to process.cwd()");
|
|
59095
59368
|
}
|
|
59096
59369
|
const directory = normalizedDir || fallbackDir;
|
|
59097
|
-
const planPath =
|
|
59098
|
-
if (!
|
|
59370
|
+
const planPath = path50.resolve(directory, ".swarm", "plan.json");
|
|
59371
|
+
if (!fs38.existsSync(planPath)) {
|
|
59099
59372
|
return {
|
|
59100
59373
|
success: false,
|
|
59101
59374
|
message: "No plan found",
|
|
@@ -59104,7 +59377,7 @@ async function executeDeclareScope(args2, fallbackDir) {
|
|
|
59104
59377
|
}
|
|
59105
59378
|
let planContent;
|
|
59106
59379
|
try {
|
|
59107
|
-
planContent = JSON.parse(
|
|
59380
|
+
planContent = JSON.parse(fs38.readFileSync(planPath, "utf-8"));
|
|
59108
59381
|
} catch {
|
|
59109
59382
|
return {
|
|
59110
59383
|
success: false,
|
|
@@ -59136,8 +59409,8 @@ async function executeDeclareScope(args2, fallbackDir) {
|
|
|
59136
59409
|
const normalizeErrors = [];
|
|
59137
59410
|
const dir = normalizedDir || fallbackDir || process.cwd();
|
|
59138
59411
|
const mergedFiles = rawMergedFiles.map((file3) => {
|
|
59139
|
-
if (
|
|
59140
|
-
const relativePath =
|
|
59412
|
+
if (path50.isAbsolute(file3)) {
|
|
59413
|
+
const relativePath = path50.relative(dir, file3).replace(/\\/g, "/");
|
|
59141
59414
|
if (relativePath.startsWith("..")) {
|
|
59142
59415
|
normalizeErrors.push(`Path '${file3}' resolves outside the project directory`);
|
|
59143
59416
|
return file3;
|
|
@@ -59463,20 +59736,20 @@ function validateBase(base) {
|
|
|
59463
59736
|
function validatePaths(paths) {
|
|
59464
59737
|
if (!paths)
|
|
59465
59738
|
return null;
|
|
59466
|
-
for (const
|
|
59467
|
-
if (!
|
|
59739
|
+
for (const path52 of paths) {
|
|
59740
|
+
if (!path52 || path52.length === 0) {
|
|
59468
59741
|
return "empty path not allowed";
|
|
59469
59742
|
}
|
|
59470
|
-
if (
|
|
59743
|
+
if (path52.length > MAX_PATH_LENGTH) {
|
|
59471
59744
|
return `path exceeds maximum length of ${MAX_PATH_LENGTH}`;
|
|
59472
59745
|
}
|
|
59473
|
-
if (SHELL_METACHARACTERS2.test(
|
|
59746
|
+
if (SHELL_METACHARACTERS2.test(path52)) {
|
|
59474
59747
|
return "path contains shell metacharacters";
|
|
59475
59748
|
}
|
|
59476
|
-
if (
|
|
59749
|
+
if (path52.startsWith("-")) {
|
|
59477
59750
|
return 'path cannot start with "-" (option-like arguments not allowed)';
|
|
59478
59751
|
}
|
|
59479
|
-
if (CONTROL_CHAR_PATTERN2.test(
|
|
59752
|
+
if (CONTROL_CHAR_PATTERN2.test(path52)) {
|
|
59480
59753
|
return "path contains control characters";
|
|
59481
59754
|
}
|
|
59482
59755
|
}
|
|
@@ -59557,8 +59830,8 @@ var diff = createSwarmTool({
|
|
|
59557
59830
|
if (parts2.length >= 3) {
|
|
59558
59831
|
const additions = parseInt(parts2[0], 10) || 0;
|
|
59559
59832
|
const deletions = parseInt(parts2[1], 10) || 0;
|
|
59560
|
-
const
|
|
59561
|
-
files.push({ path:
|
|
59833
|
+
const path52 = parts2[2];
|
|
59834
|
+
files.push({ path: path52, additions, deletions });
|
|
59562
59835
|
}
|
|
59563
59836
|
}
|
|
59564
59837
|
const contractChanges = [];
|
|
@@ -59840,8 +60113,8 @@ Use these as DOMAIN values when delegating to @sme.`;
|
|
|
59840
60113
|
// src/tools/evidence-check.ts
|
|
59841
60114
|
init_dist();
|
|
59842
60115
|
init_create_tool();
|
|
59843
|
-
import * as
|
|
59844
|
-
import * as
|
|
60116
|
+
import * as fs39 from "fs";
|
|
60117
|
+
import * as path52 from "path";
|
|
59845
60118
|
var MAX_FILE_SIZE_BYTES4 = 1024 * 1024;
|
|
59846
60119
|
var MAX_EVIDENCE_FILES = 1000;
|
|
59847
60120
|
var EVIDENCE_DIR2 = ".swarm/evidence";
|
|
@@ -59868,9 +60141,9 @@ function validateRequiredTypes(input) {
|
|
|
59868
60141
|
return null;
|
|
59869
60142
|
}
|
|
59870
60143
|
function isPathWithinSwarm2(filePath, cwd) {
|
|
59871
|
-
const normalizedCwd =
|
|
59872
|
-
const swarmPath =
|
|
59873
|
-
const normalizedPath =
|
|
60144
|
+
const normalizedCwd = path52.resolve(cwd);
|
|
60145
|
+
const swarmPath = path52.join(normalizedCwd, ".swarm");
|
|
60146
|
+
const normalizedPath = path52.resolve(filePath);
|
|
59874
60147
|
return normalizedPath.startsWith(swarmPath);
|
|
59875
60148
|
}
|
|
59876
60149
|
function parseCompletedTasks(planContent) {
|
|
@@ -59886,12 +60159,12 @@ function parseCompletedTasks(planContent) {
|
|
|
59886
60159
|
}
|
|
59887
60160
|
function readEvidenceFiles(evidenceDir, _cwd) {
|
|
59888
60161
|
const evidence = [];
|
|
59889
|
-
if (!
|
|
60162
|
+
if (!fs39.existsSync(evidenceDir) || !fs39.statSync(evidenceDir).isDirectory()) {
|
|
59890
60163
|
return evidence;
|
|
59891
60164
|
}
|
|
59892
60165
|
let files;
|
|
59893
60166
|
try {
|
|
59894
|
-
files =
|
|
60167
|
+
files = fs39.readdirSync(evidenceDir);
|
|
59895
60168
|
} catch {
|
|
59896
60169
|
return evidence;
|
|
59897
60170
|
}
|
|
@@ -59900,14 +60173,14 @@ function readEvidenceFiles(evidenceDir, _cwd) {
|
|
|
59900
60173
|
if (!VALID_EVIDENCE_FILENAME_REGEX.test(filename)) {
|
|
59901
60174
|
continue;
|
|
59902
60175
|
}
|
|
59903
|
-
const filePath =
|
|
60176
|
+
const filePath = path52.join(evidenceDir, filename);
|
|
59904
60177
|
try {
|
|
59905
|
-
const resolvedPath =
|
|
59906
|
-
const evidenceDirResolved =
|
|
60178
|
+
const resolvedPath = path52.resolve(filePath);
|
|
60179
|
+
const evidenceDirResolved = path52.resolve(evidenceDir);
|
|
59907
60180
|
if (!resolvedPath.startsWith(evidenceDirResolved)) {
|
|
59908
60181
|
continue;
|
|
59909
60182
|
}
|
|
59910
|
-
const stat2 =
|
|
60183
|
+
const stat2 = fs39.lstatSync(filePath);
|
|
59911
60184
|
if (!stat2.isFile()) {
|
|
59912
60185
|
continue;
|
|
59913
60186
|
}
|
|
@@ -59916,7 +60189,7 @@ function readEvidenceFiles(evidenceDir, _cwd) {
|
|
|
59916
60189
|
}
|
|
59917
60190
|
let fileStat;
|
|
59918
60191
|
try {
|
|
59919
|
-
fileStat =
|
|
60192
|
+
fileStat = fs39.statSync(filePath);
|
|
59920
60193
|
if (fileStat.size > MAX_FILE_SIZE_BYTES4) {
|
|
59921
60194
|
continue;
|
|
59922
60195
|
}
|
|
@@ -59925,7 +60198,7 @@ function readEvidenceFiles(evidenceDir, _cwd) {
|
|
|
59925
60198
|
}
|
|
59926
60199
|
let content;
|
|
59927
60200
|
try {
|
|
59928
|
-
content =
|
|
60201
|
+
content = fs39.readFileSync(filePath, "utf-8");
|
|
59929
60202
|
} catch {
|
|
59930
60203
|
continue;
|
|
59931
60204
|
}
|
|
@@ -60021,7 +60294,7 @@ var evidence_check = createSwarmTool({
|
|
|
60021
60294
|
return JSON.stringify(errorResult, null, 2);
|
|
60022
60295
|
}
|
|
60023
60296
|
const requiredTypes = requiredTypesValue.split(",").map((t) => t.trim()).filter((t) => t.length > 0).map(normalizeEvidenceType);
|
|
60024
|
-
const planPath =
|
|
60297
|
+
const planPath = path52.join(cwd, PLAN_FILE);
|
|
60025
60298
|
if (!isPathWithinSwarm2(planPath, cwd)) {
|
|
60026
60299
|
const errorResult = {
|
|
60027
60300
|
error: "plan file path validation failed",
|
|
@@ -60035,7 +60308,7 @@ var evidence_check = createSwarmTool({
|
|
|
60035
60308
|
}
|
|
60036
60309
|
let planContent;
|
|
60037
60310
|
try {
|
|
60038
|
-
planContent =
|
|
60311
|
+
planContent = fs39.readFileSync(planPath, "utf-8");
|
|
60039
60312
|
} catch {
|
|
60040
60313
|
const result2 = {
|
|
60041
60314
|
message: "No completed tasks found in plan.",
|
|
@@ -60053,7 +60326,7 @@ var evidence_check = createSwarmTool({
|
|
|
60053
60326
|
};
|
|
60054
60327
|
return JSON.stringify(result2, null, 2);
|
|
60055
60328
|
}
|
|
60056
|
-
const evidenceDir =
|
|
60329
|
+
const evidenceDir = path52.join(cwd, EVIDENCE_DIR2);
|
|
60057
60330
|
const evidence = readEvidenceFiles(evidenceDir, cwd);
|
|
60058
60331
|
const { tasksWithFullEvidence, gaps } = analyzeGaps(completedTasks, evidence, requiredTypes);
|
|
60059
60332
|
const completeness = completedTasks.length > 0 ? Math.round(tasksWithFullEvidence.length / completedTasks.length * 100) / 100 : 1;
|
|
@@ -60070,8 +60343,8 @@ var evidence_check = createSwarmTool({
|
|
|
60070
60343
|
// src/tools/file-extractor.ts
|
|
60071
60344
|
init_tool();
|
|
60072
60345
|
init_create_tool();
|
|
60073
|
-
import * as
|
|
60074
|
-
import * as
|
|
60346
|
+
import * as fs40 from "fs";
|
|
60347
|
+
import * as path53 from "path";
|
|
60075
60348
|
var EXT_MAP = {
|
|
60076
60349
|
python: ".py",
|
|
60077
60350
|
py: ".py",
|
|
@@ -60133,8 +60406,8 @@ var extract_code_blocks = createSwarmTool({
|
|
|
60133
60406
|
execute: async (args2, directory) => {
|
|
60134
60407
|
const { content, output_dir, prefix } = args2;
|
|
60135
60408
|
const targetDir = output_dir || directory;
|
|
60136
|
-
if (!
|
|
60137
|
-
|
|
60409
|
+
if (!fs40.existsSync(targetDir)) {
|
|
60410
|
+
fs40.mkdirSync(targetDir, { recursive: true });
|
|
60138
60411
|
}
|
|
60139
60412
|
if (!content) {
|
|
60140
60413
|
return "Error: content is required";
|
|
@@ -60152,16 +60425,16 @@ var extract_code_blocks = createSwarmTool({
|
|
|
60152
60425
|
if (prefix) {
|
|
60153
60426
|
filename = `${prefix}_${filename}`;
|
|
60154
60427
|
}
|
|
60155
|
-
let filepath =
|
|
60156
|
-
const base =
|
|
60157
|
-
const ext =
|
|
60428
|
+
let filepath = path53.join(targetDir, filename);
|
|
60429
|
+
const base = path53.basename(filepath, path53.extname(filepath));
|
|
60430
|
+
const ext = path53.extname(filepath);
|
|
60158
60431
|
let counter = 1;
|
|
60159
|
-
while (
|
|
60160
|
-
filepath =
|
|
60432
|
+
while (fs40.existsSync(filepath)) {
|
|
60433
|
+
filepath = path53.join(targetDir, `${base}_${counter}${ext}`);
|
|
60161
60434
|
counter++;
|
|
60162
60435
|
}
|
|
60163
60436
|
try {
|
|
60164
|
-
|
|
60437
|
+
fs40.writeFileSync(filepath, code.trim(), "utf-8");
|
|
60165
60438
|
savedFiles.push(filepath);
|
|
60166
60439
|
} catch (error93) {
|
|
60167
60440
|
errors5.push(`Failed to save ${filename}: ${error93 instanceof Error ? error93.message : String(error93)}`);
|
|
@@ -60277,8 +60550,8 @@ var gitingest = createSwarmTool({
|
|
|
60277
60550
|
// src/tools/imports.ts
|
|
60278
60551
|
init_dist();
|
|
60279
60552
|
init_create_tool();
|
|
60280
|
-
import * as
|
|
60281
|
-
import * as
|
|
60553
|
+
import * as fs41 from "fs";
|
|
60554
|
+
import * as path54 from "path";
|
|
60282
60555
|
var MAX_FILE_PATH_LENGTH2 = 500;
|
|
60283
60556
|
var MAX_SYMBOL_LENGTH = 256;
|
|
60284
60557
|
var MAX_FILE_SIZE_BYTES5 = 1024 * 1024;
|
|
@@ -60326,7 +60599,7 @@ function validateSymbolInput(symbol3) {
|
|
|
60326
60599
|
return null;
|
|
60327
60600
|
}
|
|
60328
60601
|
function isBinaryFile2(filePath, buffer) {
|
|
60329
|
-
const ext =
|
|
60602
|
+
const ext = path54.extname(filePath).toLowerCase();
|
|
60330
60603
|
if (ext === ".json" || ext === ".md" || ext === ".txt") {
|
|
60331
60604
|
return false;
|
|
60332
60605
|
}
|
|
@@ -60350,15 +60623,15 @@ function parseImports(content, targetFile, targetSymbol) {
|
|
|
60350
60623
|
const imports = [];
|
|
60351
60624
|
let _resolvedTarget;
|
|
60352
60625
|
try {
|
|
60353
|
-
_resolvedTarget =
|
|
60626
|
+
_resolvedTarget = path54.resolve(targetFile);
|
|
60354
60627
|
} catch {
|
|
60355
60628
|
_resolvedTarget = targetFile;
|
|
60356
60629
|
}
|
|
60357
|
-
const targetBasename =
|
|
60630
|
+
const targetBasename = path54.basename(targetFile, path54.extname(targetFile));
|
|
60358
60631
|
const targetWithExt = targetFile;
|
|
60359
60632
|
const targetWithoutExt = targetFile.replace(/\.(ts|tsx|js|jsx|mjs|cjs)$/i, "");
|
|
60360
|
-
const normalizedTargetWithExt =
|
|
60361
|
-
const normalizedTargetWithoutExt =
|
|
60633
|
+
const normalizedTargetWithExt = path54.normalize(targetWithExt).replace(/\\/g, "/");
|
|
60634
|
+
const normalizedTargetWithoutExt = path54.normalize(targetWithoutExt).replace(/\\/g, "/");
|
|
60362
60635
|
const importRegex = /import\s+(?:\{[\s\S]*?\}|(?:\*\s+as\s+\w+)|\w+)\s+from\s+['"`]([^'"`]+)['"`]|import\s+['"`]([^'"`]+)['"`]|require\s*\(\s*['"`]([^'"`]+)['"`]\s*\)/g;
|
|
60363
60636
|
for (let match = importRegex.exec(content);match !== null; match = importRegex.exec(content)) {
|
|
60364
60637
|
const modulePath = match[1] || match[2] || match[3];
|
|
@@ -60381,9 +60654,9 @@ function parseImports(content, targetFile, targetSymbol) {
|
|
|
60381
60654
|
}
|
|
60382
60655
|
const _normalizedModule = modulePath.replace(/^\.\//, "").replace(/^\.\.\\/, "../");
|
|
60383
60656
|
let isMatch = false;
|
|
60384
|
-
const _targetDir =
|
|
60385
|
-
const targetExt =
|
|
60386
|
-
const targetBasenameNoExt =
|
|
60657
|
+
const _targetDir = path54.dirname(targetFile);
|
|
60658
|
+
const targetExt = path54.extname(targetFile);
|
|
60659
|
+
const targetBasenameNoExt = path54.basename(targetFile, targetExt);
|
|
60387
60660
|
const moduleNormalized = modulePath.replace(/\\/g, "/").replace(/^\.\//, "");
|
|
60388
60661
|
const moduleName = modulePath.split(/[/\\]/).pop() || "";
|
|
60389
60662
|
const moduleNameNoExt = moduleName.replace(/\.(ts|tsx|js|jsx|mjs|cjs)$/i, "");
|
|
@@ -60440,7 +60713,7 @@ var SKIP_DIRECTORIES3 = new Set([
|
|
|
60440
60713
|
function findSourceFiles(dir, files = [], stats = { skippedDirs: [], skippedFiles: 0, fileErrors: [] }) {
|
|
60441
60714
|
let entries;
|
|
60442
60715
|
try {
|
|
60443
|
-
entries =
|
|
60716
|
+
entries = fs41.readdirSync(dir);
|
|
60444
60717
|
} catch (e) {
|
|
60445
60718
|
stats.fileErrors.push({
|
|
60446
60719
|
path: dir,
|
|
@@ -60451,13 +60724,13 @@ function findSourceFiles(dir, files = [], stats = { skippedDirs: [], skippedFile
|
|
|
60451
60724
|
entries.sort((a, b) => a.toLowerCase().localeCompare(b.toLowerCase()));
|
|
60452
60725
|
for (const entry of entries) {
|
|
60453
60726
|
if (SKIP_DIRECTORIES3.has(entry)) {
|
|
60454
|
-
stats.skippedDirs.push(
|
|
60727
|
+
stats.skippedDirs.push(path54.join(dir, entry));
|
|
60455
60728
|
continue;
|
|
60456
60729
|
}
|
|
60457
|
-
const fullPath =
|
|
60730
|
+
const fullPath = path54.join(dir, entry);
|
|
60458
60731
|
let stat2;
|
|
60459
60732
|
try {
|
|
60460
|
-
stat2 =
|
|
60733
|
+
stat2 = fs41.statSync(fullPath);
|
|
60461
60734
|
} catch (e) {
|
|
60462
60735
|
stats.fileErrors.push({
|
|
60463
60736
|
path: fullPath,
|
|
@@ -60468,7 +60741,7 @@ function findSourceFiles(dir, files = [], stats = { skippedDirs: [], skippedFile
|
|
|
60468
60741
|
if (stat2.isDirectory()) {
|
|
60469
60742
|
findSourceFiles(fullPath, files, stats);
|
|
60470
60743
|
} else if (stat2.isFile()) {
|
|
60471
|
-
const ext =
|
|
60744
|
+
const ext = path54.extname(fullPath).toLowerCase();
|
|
60472
60745
|
if (SUPPORTED_EXTENSIONS.includes(ext)) {
|
|
60473
60746
|
files.push(fullPath);
|
|
60474
60747
|
}
|
|
@@ -60525,8 +60798,8 @@ var imports = createSwarmTool({
|
|
|
60525
60798
|
return JSON.stringify(errorResult, null, 2);
|
|
60526
60799
|
}
|
|
60527
60800
|
try {
|
|
60528
|
-
const targetFile =
|
|
60529
|
-
if (!
|
|
60801
|
+
const targetFile = path54.resolve(file3);
|
|
60802
|
+
if (!fs41.existsSync(targetFile)) {
|
|
60530
60803
|
const errorResult = {
|
|
60531
60804
|
error: `target file not found: ${file3}`,
|
|
60532
60805
|
target: file3,
|
|
@@ -60536,7 +60809,7 @@ var imports = createSwarmTool({
|
|
|
60536
60809
|
};
|
|
60537
60810
|
return JSON.stringify(errorResult, null, 2);
|
|
60538
60811
|
}
|
|
60539
|
-
const targetStat =
|
|
60812
|
+
const targetStat = fs41.statSync(targetFile);
|
|
60540
60813
|
if (!targetStat.isFile()) {
|
|
60541
60814
|
const errorResult = {
|
|
60542
60815
|
error: "target must be a file, not a directory",
|
|
@@ -60547,7 +60820,7 @@ var imports = createSwarmTool({
|
|
|
60547
60820
|
};
|
|
60548
60821
|
return JSON.stringify(errorResult, null, 2);
|
|
60549
60822
|
}
|
|
60550
|
-
const baseDir =
|
|
60823
|
+
const baseDir = path54.dirname(targetFile);
|
|
60551
60824
|
const scanStats = {
|
|
60552
60825
|
skippedDirs: [],
|
|
60553
60826
|
skippedFiles: 0,
|
|
@@ -60562,12 +60835,12 @@ var imports = createSwarmTool({
|
|
|
60562
60835
|
if (consumers.length >= MAX_CONSUMERS)
|
|
60563
60836
|
break;
|
|
60564
60837
|
try {
|
|
60565
|
-
const stat2 =
|
|
60838
|
+
const stat2 = fs41.statSync(filePath);
|
|
60566
60839
|
if (stat2.size > MAX_FILE_SIZE_BYTES5) {
|
|
60567
60840
|
skippedFileCount++;
|
|
60568
60841
|
continue;
|
|
60569
60842
|
}
|
|
60570
|
-
const buffer =
|
|
60843
|
+
const buffer = fs41.readFileSync(filePath);
|
|
60571
60844
|
if (isBinaryFile2(filePath, buffer)) {
|
|
60572
60845
|
skippedFileCount++;
|
|
60573
60846
|
continue;
|
|
@@ -60634,7 +60907,7 @@ var imports = createSwarmTool({
|
|
|
60634
60907
|
init_dist();
|
|
60635
60908
|
init_config();
|
|
60636
60909
|
init_knowledge_store();
|
|
60637
|
-
import { randomUUID as
|
|
60910
|
+
import { randomUUID as randomUUID5 } from "crypto";
|
|
60638
60911
|
init_manager2();
|
|
60639
60912
|
init_create_tool();
|
|
60640
60913
|
var VALID_CATEGORIES2 = [
|
|
@@ -60709,7 +60982,7 @@ var knowledgeAdd = createSwarmTool({
|
|
|
60709
60982
|
project_name = plan?.title ?? "";
|
|
60710
60983
|
} catch {}
|
|
60711
60984
|
const entry = {
|
|
60712
|
-
id:
|
|
60985
|
+
id: randomUUID5(),
|
|
60713
60986
|
tier: "swarm",
|
|
60714
60987
|
lesson,
|
|
60715
60988
|
category,
|
|
@@ -60767,7 +61040,7 @@ init_dist();
|
|
|
60767
61040
|
init_config();
|
|
60768
61041
|
init_knowledge_store();
|
|
60769
61042
|
init_create_tool();
|
|
60770
|
-
import { existsSync as
|
|
61043
|
+
import { existsSync as existsSync33 } from "fs";
|
|
60771
61044
|
var DEFAULT_LIMIT = 10;
|
|
60772
61045
|
var MAX_LESSON_LENGTH = 200;
|
|
60773
61046
|
var VALID_CATEGORIES3 = [
|
|
@@ -60836,14 +61109,14 @@ function validateLimit(limit) {
|
|
|
60836
61109
|
}
|
|
60837
61110
|
async function readSwarmKnowledge(directory) {
|
|
60838
61111
|
const swarmPath = resolveSwarmKnowledgePath(directory);
|
|
60839
|
-
if (!
|
|
61112
|
+
if (!existsSync33(swarmPath)) {
|
|
60840
61113
|
return [];
|
|
60841
61114
|
}
|
|
60842
61115
|
return readKnowledge(swarmPath);
|
|
60843
61116
|
}
|
|
60844
61117
|
async function readHiveKnowledge() {
|
|
60845
61118
|
const hivePath = resolveHiveKnowledgePath();
|
|
60846
|
-
if (!
|
|
61119
|
+
if (!existsSync33(hivePath)) {
|
|
60847
61120
|
return [];
|
|
60848
61121
|
}
|
|
60849
61122
|
return readKnowledge(hivePath);
|
|
@@ -61156,8 +61429,9 @@ init_dist();
|
|
|
61156
61429
|
init_config();
|
|
61157
61430
|
init_schema();
|
|
61158
61431
|
init_manager();
|
|
61159
|
-
import * as
|
|
61160
|
-
import * as
|
|
61432
|
+
import * as fs42 from "fs";
|
|
61433
|
+
import * as path55 from "path";
|
|
61434
|
+
init_review_receipt();
|
|
61161
61435
|
init_utils2();
|
|
61162
61436
|
init_telemetry();
|
|
61163
61437
|
init_create_tool();
|
|
@@ -61378,11 +61652,11 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
|
|
|
61378
61652
|
safeWarn(`[phase_complete] Completion verify error (non-blocking):`, completionError);
|
|
61379
61653
|
}
|
|
61380
61654
|
try {
|
|
61381
|
-
const driftEvidencePath =
|
|
61655
|
+
const driftEvidencePath = path55.join(dir, ".swarm", "evidence", String(phase), "drift-verifier.json");
|
|
61382
61656
|
let driftVerdictFound = false;
|
|
61383
61657
|
let driftVerdictApproved = false;
|
|
61384
61658
|
try {
|
|
61385
|
-
const driftEvidenceContent =
|
|
61659
|
+
const driftEvidenceContent = fs42.readFileSync(driftEvidencePath, "utf-8");
|
|
61386
61660
|
const driftEvidence = JSON.parse(driftEvidenceContent);
|
|
61387
61661
|
const entries = driftEvidence.entries ?? [];
|
|
61388
61662
|
for (const entry of entries) {
|
|
@@ -61412,14 +61686,14 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
|
|
|
61412
61686
|
driftVerdictFound = false;
|
|
61413
61687
|
}
|
|
61414
61688
|
if (!driftVerdictFound) {
|
|
61415
|
-
const specPath =
|
|
61416
|
-
const specExists =
|
|
61689
|
+
const specPath = path55.join(dir, ".swarm", "spec.md");
|
|
61690
|
+
const specExists = fs42.existsSync(specPath);
|
|
61417
61691
|
if (!specExists) {
|
|
61418
61692
|
let incompleteTaskCount = 0;
|
|
61419
61693
|
let planPhaseFound = false;
|
|
61420
61694
|
try {
|
|
61421
61695
|
const planPath = validateSwarmPath(dir, "plan.json");
|
|
61422
|
-
const planRaw =
|
|
61696
|
+
const planRaw = fs42.readFileSync(planPath, "utf-8");
|
|
61423
61697
|
const plan = JSON.parse(planRaw);
|
|
61424
61698
|
const targetPhase = plan.phases.find((p) => p.id === phase);
|
|
61425
61699
|
if (targetPhase) {
|
|
@@ -61461,32 +61735,10 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
|
|
|
61461
61735
|
safeWarn(`[phase_complete] Drift verifier error (non-blocking):`, driftError);
|
|
61462
61736
|
}
|
|
61463
61737
|
}
|
|
61464
|
-
const knowledgeConfig = {
|
|
61465
|
-
enabled: true,
|
|
61466
|
-
swarm_max_entries: 100,
|
|
61467
|
-
hive_max_entries: 200,
|
|
61468
|
-
auto_promote_days: 90,
|
|
61469
|
-
max_inject_count: 5,
|
|
61470
|
-
dedup_threshold: 0.6,
|
|
61471
|
-
scope_filter: ["global"],
|
|
61472
|
-
hive_enabled: true,
|
|
61473
|
-
rejected_max_entries: 20,
|
|
61474
|
-
validation_enabled: true,
|
|
61475
|
-
evergreen_confidence: 0.9,
|
|
61476
|
-
evergreen_utility: 0.8,
|
|
61477
|
-
low_utility_threshold: 0.3,
|
|
61478
|
-
min_retrievals_for_utility: 3,
|
|
61479
|
-
schema_version: 1,
|
|
61480
|
-
same_project_weight: 1,
|
|
61481
|
-
cross_project_weight: 0.5,
|
|
61482
|
-
min_encounter_score: 0.1,
|
|
61483
|
-
initial_encounter_score: 1,
|
|
61484
|
-
encounter_increment: 0.1,
|
|
61485
|
-
max_encounter_score: 10
|
|
61486
|
-
};
|
|
61738
|
+
const knowledgeConfig = KnowledgeConfigSchema.parse(config3.knowledge ?? {});
|
|
61487
61739
|
if (retroFound && retroEntry?.lessons_learned && retroEntry.lessons_learned.length > 0) {
|
|
61488
61740
|
try {
|
|
61489
|
-
const projectName =
|
|
61741
|
+
const projectName = path55.basename(dir);
|
|
61490
61742
|
const curationResult = await curateAndStoreSwarm(retroEntry.lessons_learned, projectName, { phase_number: phase }, dir, knowledgeConfig);
|
|
61491
61743
|
if (curationResult) {
|
|
61492
61744
|
const sessionState = swarmState.agentSessions.get(sessionID);
|
|
@@ -61495,6 +61747,7 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
|
|
|
61495
61747
|
sessionState.pendingAdvisoryMessages.push(`[CURATOR] Knowledge curation: ${curationResult.stored} stored, ${curationResult.skipped} skipped, ${curationResult.rejected} rejected.`);
|
|
61496
61748
|
}
|
|
61497
61749
|
}
|
|
61750
|
+
await updateRetrievalOutcome(dir, `Phase ${phase}`, true);
|
|
61498
61751
|
} catch (error93) {
|
|
61499
61752
|
safeWarn("[phase_complete] Failed to curate lessons from retrospective:", error93);
|
|
61500
61753
|
}
|
|
@@ -61503,7 +61756,41 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
|
|
|
61503
61756
|
try {
|
|
61504
61757
|
const curatorConfig = CuratorConfigSchema.parse(config3.curator ?? {});
|
|
61505
61758
|
if (curatorConfig.enabled && curatorConfig.phase_enabled) {
|
|
61506
|
-
const
|
|
61759
|
+
const llmDelegate = createCuratorLLMDelegate(dir);
|
|
61760
|
+
const curatorResult = await runCuratorPhase(dir, phase, agentsDispatched, curatorConfig, {}, llmDelegate);
|
|
61761
|
+
{
|
|
61762
|
+
const scopeContent = curatorResult.digest?.summary ?? `Phase ${phase} curator analysis`;
|
|
61763
|
+
const complianceWarnings2 = curatorResult.compliance.filter((c) => c.severity === "warning");
|
|
61764
|
+
const receipt = complianceWarnings2.length > 0 ? buildRejectedReceipt({
|
|
61765
|
+
agent: "curator",
|
|
61766
|
+
scopeContent,
|
|
61767
|
+
scopeDescription: "phase-digest",
|
|
61768
|
+
blockingFindings: complianceWarnings2.map((c) => ({
|
|
61769
|
+
location: `phase-${c.phase}`,
|
|
61770
|
+
summary: c.description,
|
|
61771
|
+
severity: c.type === "missing_reviewer" ? "high" : "medium"
|
|
61772
|
+
})),
|
|
61773
|
+
evidenceReferences: [],
|
|
61774
|
+
passConditions: [
|
|
61775
|
+
"resolve all compliance warnings before phase completion"
|
|
61776
|
+
]
|
|
61777
|
+
}) : buildApprovedReceipt({
|
|
61778
|
+
agent: "curator",
|
|
61779
|
+
scopeContent,
|
|
61780
|
+
scopeDescription: "phase-digest",
|
|
61781
|
+
checkedAspects: [
|
|
61782
|
+
"phase_compliance",
|
|
61783
|
+
"knowledge_recommendations",
|
|
61784
|
+
"phase_digest"
|
|
61785
|
+
],
|
|
61786
|
+
validatedClaims: [
|
|
61787
|
+
`phase: ${phase}`,
|
|
61788
|
+
`agents_dispatched: ${agentsDispatched.length}`,
|
|
61789
|
+
`knowledge_recommendations: ${curatorResult.knowledge_recommendations.length}`
|
|
61790
|
+
]
|
|
61791
|
+
});
|
|
61792
|
+
persistReviewReceipt(dir, receipt).catch(() => {});
|
|
61793
|
+
}
|
|
61507
61794
|
const knowledgeResult = await applyCuratorKnowledgeUpdates(dir, curatorResult.knowledge_recommendations, knowledgeConfig);
|
|
61508
61795
|
const callerSessionState = swarmState.agentSessions.get(sessionID);
|
|
61509
61796
|
if (callerSessionState) {
|
|
@@ -61531,7 +61818,7 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
|
|
|
61531
61818
|
let phaseRequiredAgents;
|
|
61532
61819
|
try {
|
|
61533
61820
|
const planPath = validateSwarmPath(dir, "plan.json");
|
|
61534
|
-
const planRaw =
|
|
61821
|
+
const planRaw = fs42.readFileSync(planPath, "utf-8");
|
|
61535
61822
|
const plan = JSON.parse(planRaw);
|
|
61536
61823
|
const phaseObj = plan.phases.find((p) => p.id === phase);
|
|
61537
61824
|
phaseRequiredAgents = phaseObj?.required_agents;
|
|
@@ -61546,7 +61833,7 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
|
|
|
61546
61833
|
if (agentsMissing.length > 0) {
|
|
61547
61834
|
try {
|
|
61548
61835
|
const planPath = validateSwarmPath(dir, "plan.json");
|
|
61549
|
-
const planRaw =
|
|
61836
|
+
const planRaw = fs42.readFileSync(planPath, "utf-8");
|
|
61550
61837
|
const plan = JSON.parse(planRaw);
|
|
61551
61838
|
const targetPhase = plan.phases.find((p) => p.id === phase);
|
|
61552
61839
|
if (targetPhase && targetPhase.tasks.length > 0 && targetPhase.tasks.every((t) => t.status === "completed")) {
|
|
@@ -61577,7 +61864,7 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
|
|
|
61577
61864
|
if (phaseCompleteConfig.regression_sweep?.enforce) {
|
|
61578
61865
|
try {
|
|
61579
61866
|
const planPath = validateSwarmPath(dir, "plan.json");
|
|
61580
|
-
const planRaw =
|
|
61867
|
+
const planRaw = fs42.readFileSync(planPath, "utf-8");
|
|
61581
61868
|
const plan = JSON.parse(planRaw);
|
|
61582
61869
|
const targetPhase = plan.phases.find((p) => p.id === phase);
|
|
61583
61870
|
if (targetPhase) {
|
|
@@ -61615,7 +61902,7 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
|
|
|
61615
61902
|
};
|
|
61616
61903
|
try {
|
|
61617
61904
|
const eventsPath = validateSwarmPath(dir, "events.jsonl");
|
|
61618
|
-
|
|
61905
|
+
fs42.appendFileSync(eventsPath, `${JSON.stringify(event)}
|
|
61619
61906
|
`, "utf-8");
|
|
61620
61907
|
} catch (writeError) {
|
|
61621
61908
|
warnings.push(`Warning: failed to write phase complete event: ${writeError instanceof Error ? writeError.message : String(writeError)}`);
|
|
@@ -61639,12 +61926,12 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
|
|
|
61639
61926
|
}
|
|
61640
61927
|
try {
|
|
61641
61928
|
const planPath = validateSwarmPath(dir, "plan.json");
|
|
61642
|
-
const planJson =
|
|
61929
|
+
const planJson = fs42.readFileSync(planPath, "utf-8");
|
|
61643
61930
|
const plan = JSON.parse(planJson);
|
|
61644
61931
|
const phaseObj = plan.phases.find((p) => p.id === phase);
|
|
61645
61932
|
if (phaseObj) {
|
|
61646
61933
|
phaseObj.status = "completed";
|
|
61647
|
-
|
|
61934
|
+
fs42.writeFileSync(planPath, `${JSON.stringify(plan, null, 2)}
|
|
61648
61935
|
`, "utf-8");
|
|
61649
61936
|
}
|
|
61650
61937
|
} catch (error93) {
|
|
@@ -61711,8 +61998,8 @@ init_dist();
|
|
|
61711
61998
|
init_discovery();
|
|
61712
61999
|
init_utils();
|
|
61713
62000
|
init_create_tool();
|
|
61714
|
-
import * as
|
|
61715
|
-
import * as
|
|
62001
|
+
import * as fs43 from "fs";
|
|
62002
|
+
import * as path56 from "path";
|
|
61716
62003
|
var MAX_OUTPUT_BYTES5 = 52428800;
|
|
61717
62004
|
var AUDIT_TIMEOUT_MS = 120000;
|
|
61718
62005
|
function isValidEcosystem(value) {
|
|
@@ -61730,28 +62017,28 @@ function validateArgs3(args2) {
|
|
|
61730
62017
|
function detectEcosystems(directory) {
|
|
61731
62018
|
const ecosystems = [];
|
|
61732
62019
|
const cwd = directory;
|
|
61733
|
-
if (
|
|
62020
|
+
if (fs43.existsSync(path56.join(cwd, "package.json"))) {
|
|
61734
62021
|
ecosystems.push("npm");
|
|
61735
62022
|
}
|
|
61736
|
-
if (
|
|
62023
|
+
if (fs43.existsSync(path56.join(cwd, "pyproject.toml")) || fs43.existsSync(path56.join(cwd, "requirements.txt"))) {
|
|
61737
62024
|
ecosystems.push("pip");
|
|
61738
62025
|
}
|
|
61739
|
-
if (
|
|
62026
|
+
if (fs43.existsSync(path56.join(cwd, "Cargo.toml"))) {
|
|
61740
62027
|
ecosystems.push("cargo");
|
|
61741
62028
|
}
|
|
61742
|
-
if (
|
|
62029
|
+
if (fs43.existsSync(path56.join(cwd, "go.mod"))) {
|
|
61743
62030
|
ecosystems.push("go");
|
|
61744
62031
|
}
|
|
61745
62032
|
try {
|
|
61746
|
-
const files =
|
|
62033
|
+
const files = fs43.readdirSync(cwd);
|
|
61747
62034
|
if (files.some((f) => f.endsWith(".csproj") || f.endsWith(".sln"))) {
|
|
61748
62035
|
ecosystems.push("dotnet");
|
|
61749
62036
|
}
|
|
61750
62037
|
} catch {}
|
|
61751
|
-
if (
|
|
62038
|
+
if (fs43.existsSync(path56.join(cwd, "Gemfile")) || fs43.existsSync(path56.join(cwd, "Gemfile.lock"))) {
|
|
61752
62039
|
ecosystems.push("ruby");
|
|
61753
62040
|
}
|
|
61754
|
-
if (
|
|
62041
|
+
if (fs43.existsSync(path56.join(cwd, "pubspec.yaml"))) {
|
|
61755
62042
|
ecosystems.push("dart");
|
|
61756
62043
|
}
|
|
61757
62044
|
return ecosystems;
|
|
@@ -62772,8 +63059,8 @@ var SUPPORTED_PARSER_EXTENSIONS = new Set([
|
|
|
62772
63059
|
]);
|
|
62773
63060
|
// src/tools/pre-check-batch.ts
|
|
62774
63061
|
init_dist();
|
|
62775
|
-
import * as
|
|
62776
|
-
import * as
|
|
63062
|
+
import * as fs45 from "fs";
|
|
63063
|
+
import * as path58 from "path";
|
|
62777
63064
|
|
|
62778
63065
|
// node_modules/yocto-queue/index.js
|
|
62779
63066
|
class Node2 {
|
|
@@ -62918,8 +63205,8 @@ function pLimit(concurrency) {
|
|
|
62918
63205
|
},
|
|
62919
63206
|
map: {
|
|
62920
63207
|
async value(iterable, function_) {
|
|
62921
|
-
const
|
|
62922
|
-
return Promise.all(
|
|
63208
|
+
const promises6 = Array.from(iterable, (value, index) => this(function_, value, index));
|
|
63209
|
+
return Promise.all(promises6);
|
|
62923
63210
|
}
|
|
62924
63211
|
}
|
|
62925
63212
|
});
|
|
@@ -63047,8 +63334,8 @@ async function qualityBudget(input, directory) {
|
|
|
63047
63334
|
init_dist();
|
|
63048
63335
|
init_manager();
|
|
63049
63336
|
init_detector();
|
|
63050
|
-
import * as
|
|
63051
|
-
import * as
|
|
63337
|
+
import * as fs44 from "fs";
|
|
63338
|
+
import * as path57 from "path";
|
|
63052
63339
|
import { extname as extname10 } from "path";
|
|
63053
63340
|
|
|
63054
63341
|
// src/sast/rules/c.ts
|
|
@@ -63918,17 +64205,17 @@ var SEVERITY_ORDER = {
|
|
|
63918
64205
|
};
|
|
63919
64206
|
function shouldSkipFile(filePath) {
|
|
63920
64207
|
try {
|
|
63921
|
-
const stats =
|
|
64208
|
+
const stats = fs44.statSync(filePath);
|
|
63922
64209
|
if (stats.size > MAX_FILE_SIZE_BYTES6) {
|
|
63923
64210
|
return { skip: true, reason: "file too large" };
|
|
63924
64211
|
}
|
|
63925
64212
|
if (stats.size === 0) {
|
|
63926
64213
|
return { skip: true, reason: "empty file" };
|
|
63927
64214
|
}
|
|
63928
|
-
const fd =
|
|
64215
|
+
const fd = fs44.openSync(filePath, "r");
|
|
63929
64216
|
const buffer = Buffer.alloc(8192);
|
|
63930
|
-
const bytesRead =
|
|
63931
|
-
|
|
64217
|
+
const bytesRead = fs44.readSync(fd, buffer, 0, 8192, 0);
|
|
64218
|
+
fs44.closeSync(fd);
|
|
63932
64219
|
if (bytesRead > 0) {
|
|
63933
64220
|
let nullCount = 0;
|
|
63934
64221
|
for (let i2 = 0;i2 < bytesRead; i2++) {
|
|
@@ -63967,7 +64254,7 @@ function countBySeverity(findings) {
|
|
|
63967
64254
|
}
|
|
63968
64255
|
function scanFileWithTierA(filePath, language) {
|
|
63969
64256
|
try {
|
|
63970
|
-
const content =
|
|
64257
|
+
const content = fs44.readFileSync(filePath, "utf-8");
|
|
63971
64258
|
const findings = executeRulesSync(filePath, content, language);
|
|
63972
64259
|
return findings.map((f) => ({
|
|
63973
64260
|
rule_id: f.rule_id,
|
|
@@ -64014,8 +64301,8 @@ async function sastScan(input, directory, config3) {
|
|
|
64014
64301
|
_filesSkipped++;
|
|
64015
64302
|
continue;
|
|
64016
64303
|
}
|
|
64017
|
-
const resolvedPath =
|
|
64018
|
-
if (!
|
|
64304
|
+
const resolvedPath = path57.isAbsolute(filePath) ? filePath : path57.resolve(directory, filePath);
|
|
64305
|
+
if (!fs44.existsSync(resolvedPath)) {
|
|
64019
64306
|
_filesSkipped++;
|
|
64020
64307
|
continue;
|
|
64021
64308
|
}
|
|
@@ -64213,18 +64500,18 @@ function validatePath(inputPath, baseDir, workspaceDir) {
|
|
|
64213
64500
|
let resolved;
|
|
64214
64501
|
const isWinAbs = isWindowsAbsolutePath(inputPath);
|
|
64215
64502
|
if (isWinAbs) {
|
|
64216
|
-
resolved =
|
|
64217
|
-
} else if (
|
|
64218
|
-
resolved =
|
|
64503
|
+
resolved = path58.win32.resolve(inputPath);
|
|
64504
|
+
} else if (path58.isAbsolute(inputPath)) {
|
|
64505
|
+
resolved = path58.resolve(inputPath);
|
|
64219
64506
|
} else {
|
|
64220
|
-
resolved =
|
|
64507
|
+
resolved = path58.resolve(baseDir, inputPath);
|
|
64221
64508
|
}
|
|
64222
|
-
const workspaceResolved =
|
|
64509
|
+
const workspaceResolved = path58.resolve(workspaceDir);
|
|
64223
64510
|
let relative8;
|
|
64224
64511
|
if (isWinAbs) {
|
|
64225
|
-
relative8 =
|
|
64512
|
+
relative8 = path58.win32.relative(workspaceResolved, resolved);
|
|
64226
64513
|
} else {
|
|
64227
|
-
relative8 =
|
|
64514
|
+
relative8 = path58.relative(workspaceResolved, resolved);
|
|
64228
64515
|
}
|
|
64229
64516
|
if (relative8.startsWith("..")) {
|
|
64230
64517
|
return "path traversal detected";
|
|
@@ -64285,13 +64572,13 @@ async function runLintWrapped(files, directory, _config) {
|
|
|
64285
64572
|
}
|
|
64286
64573
|
async function runLintOnFiles(linter, files, workspaceDir) {
|
|
64287
64574
|
const isWindows = process.platform === "win32";
|
|
64288
|
-
const binDir =
|
|
64575
|
+
const binDir = path58.join(workspaceDir, "node_modules", ".bin");
|
|
64289
64576
|
const validatedFiles = [];
|
|
64290
64577
|
for (const file3 of files) {
|
|
64291
64578
|
if (typeof file3 !== "string") {
|
|
64292
64579
|
continue;
|
|
64293
64580
|
}
|
|
64294
|
-
const resolvedPath =
|
|
64581
|
+
const resolvedPath = path58.resolve(file3);
|
|
64295
64582
|
const validationError = validatePath(resolvedPath, workspaceDir, workspaceDir);
|
|
64296
64583
|
if (validationError) {
|
|
64297
64584
|
continue;
|
|
@@ -64309,10 +64596,10 @@ async function runLintOnFiles(linter, files, workspaceDir) {
|
|
|
64309
64596
|
}
|
|
64310
64597
|
let command;
|
|
64311
64598
|
if (linter === "biome") {
|
|
64312
|
-
const biomeBin = isWindows ?
|
|
64599
|
+
const biomeBin = isWindows ? path58.join(binDir, "biome.EXE") : path58.join(binDir, "biome");
|
|
64313
64600
|
command = [biomeBin, "check", ...validatedFiles];
|
|
64314
64601
|
} else {
|
|
64315
|
-
const eslintBin = isWindows ?
|
|
64602
|
+
const eslintBin = isWindows ? path58.join(binDir, "eslint.cmd") : path58.join(binDir, "eslint");
|
|
64316
64603
|
command = [eslintBin, ...validatedFiles];
|
|
64317
64604
|
}
|
|
64318
64605
|
try {
|
|
@@ -64449,7 +64736,7 @@ async function runSecretscanWithFiles(files, directory) {
|
|
|
64449
64736
|
skippedFiles++;
|
|
64450
64737
|
continue;
|
|
64451
64738
|
}
|
|
64452
|
-
const resolvedPath =
|
|
64739
|
+
const resolvedPath = path58.resolve(file3);
|
|
64453
64740
|
const validationError = validatePath(resolvedPath, directory, directory);
|
|
64454
64741
|
if (validationError) {
|
|
64455
64742
|
skippedFiles++;
|
|
@@ -64467,14 +64754,14 @@ async function runSecretscanWithFiles(files, directory) {
|
|
|
64467
64754
|
};
|
|
64468
64755
|
}
|
|
64469
64756
|
for (const file3 of validatedFiles) {
|
|
64470
|
-
const ext =
|
|
64757
|
+
const ext = path58.extname(file3).toLowerCase();
|
|
64471
64758
|
if (DEFAULT_EXCLUDE_EXTENSIONS2.has(ext)) {
|
|
64472
64759
|
skippedFiles++;
|
|
64473
64760
|
continue;
|
|
64474
64761
|
}
|
|
64475
64762
|
let stat2;
|
|
64476
64763
|
try {
|
|
64477
|
-
stat2 =
|
|
64764
|
+
stat2 = fs45.statSync(file3);
|
|
64478
64765
|
} catch {
|
|
64479
64766
|
skippedFiles++;
|
|
64480
64767
|
continue;
|
|
@@ -64485,7 +64772,7 @@ async function runSecretscanWithFiles(files, directory) {
|
|
|
64485
64772
|
}
|
|
64486
64773
|
let content;
|
|
64487
64774
|
try {
|
|
64488
|
-
const buffer =
|
|
64775
|
+
const buffer = fs45.readFileSync(file3);
|
|
64489
64776
|
if (buffer.includes(0)) {
|
|
64490
64777
|
skippedFiles++;
|
|
64491
64778
|
continue;
|
|
@@ -64673,7 +64960,7 @@ function classifySastFindings(findings, changedLineRanges, directory) {
|
|
|
64673
64960
|
const preexistingFindings = [];
|
|
64674
64961
|
for (const finding of findings) {
|
|
64675
64962
|
const filePath = finding.location.file;
|
|
64676
|
-
const normalised =
|
|
64963
|
+
const normalised = path58.relative(directory, filePath).replace(/\\/g, "/");
|
|
64677
64964
|
const changedLines = changedLineRanges.get(normalised);
|
|
64678
64965
|
if (changedLines && changedLines.has(finding.location.line)) {
|
|
64679
64966
|
newFindings.push(finding);
|
|
@@ -64724,7 +65011,7 @@ async function runPreCheckBatch(input, workspaceDir, contextDir) {
|
|
|
64724
65011
|
warn(`pre_check_batch: Invalid file path: ${file3}`);
|
|
64725
65012
|
continue;
|
|
64726
65013
|
}
|
|
64727
|
-
changedFiles.push(
|
|
65014
|
+
changedFiles.push(path58.resolve(directory, file3));
|
|
64728
65015
|
}
|
|
64729
65016
|
if (changedFiles.length === 0) {
|
|
64730
65017
|
warn("pre_check_batch: No valid files after validation, skipping all tools (fail-closed)");
|
|
@@ -64912,7 +65199,7 @@ var pre_check_batch = createSwarmTool({
|
|
|
64912
65199
|
};
|
|
64913
65200
|
return JSON.stringify(errorResult, null, 2);
|
|
64914
65201
|
}
|
|
64915
|
-
const resolvedDirectory =
|
|
65202
|
+
const resolvedDirectory = path58.resolve(typedArgs.directory);
|
|
64916
65203
|
const workspaceAnchor = resolvedDirectory;
|
|
64917
65204
|
const dirError = validateDirectory2(resolvedDirectory, workspaceAnchor);
|
|
64918
65205
|
if (dirError) {
|
|
@@ -65018,38 +65305,38 @@ ${paginatedContent}`;
|
|
|
65018
65305
|
});
|
|
65019
65306
|
// src/tools/save-plan.ts
|
|
65020
65307
|
init_tool();
|
|
65021
|
-
import * as
|
|
65022
|
-
import * as
|
|
65308
|
+
import * as fs47 from "fs";
|
|
65309
|
+
import * as path60 from "path";
|
|
65023
65310
|
|
|
65024
65311
|
// src/parallel/file-locks.ts
|
|
65025
|
-
import * as
|
|
65026
|
-
import * as
|
|
65312
|
+
import * as fs46 from "fs";
|
|
65313
|
+
import * as path59 from "path";
|
|
65027
65314
|
var LOCKS_DIR = ".swarm/locks";
|
|
65028
65315
|
var LOCK_TIMEOUT_MS = 5 * 60 * 1000;
|
|
65029
65316
|
function getLockFilePath(directory, filePath) {
|
|
65030
|
-
const normalized =
|
|
65031
|
-
if (!normalized.startsWith(
|
|
65317
|
+
const normalized = path59.resolve(directory, filePath);
|
|
65318
|
+
if (!normalized.startsWith(path59.resolve(directory))) {
|
|
65032
65319
|
throw new Error("Invalid file path: path traversal not allowed");
|
|
65033
65320
|
}
|
|
65034
65321
|
const hash3 = Buffer.from(normalized).toString("base64").replace(/[/+=]/g, "_");
|
|
65035
|
-
return
|
|
65322
|
+
return path59.join(directory, LOCKS_DIR, `${hash3}.lock`);
|
|
65036
65323
|
}
|
|
65037
65324
|
function tryAcquireLock(directory, filePath, agent, taskId) {
|
|
65038
65325
|
const lockPath = getLockFilePath(directory, filePath);
|
|
65039
|
-
const locksDir =
|
|
65040
|
-
if (!
|
|
65041
|
-
|
|
65326
|
+
const locksDir = path59.dirname(lockPath);
|
|
65327
|
+
if (!fs46.existsSync(locksDir)) {
|
|
65328
|
+
fs46.mkdirSync(locksDir, { recursive: true });
|
|
65042
65329
|
}
|
|
65043
|
-
if (
|
|
65330
|
+
if (fs46.existsSync(lockPath)) {
|
|
65044
65331
|
try {
|
|
65045
|
-
const existingLock = JSON.parse(
|
|
65332
|
+
const existingLock = JSON.parse(fs46.readFileSync(lockPath, "utf-8"));
|
|
65046
65333
|
if (Date.now() > existingLock.expiresAt) {
|
|
65047
|
-
|
|
65334
|
+
fs46.unlinkSync(lockPath);
|
|
65048
65335
|
} else {
|
|
65049
65336
|
return { acquired: false, existing: existingLock };
|
|
65050
65337
|
}
|
|
65051
65338
|
} catch {
|
|
65052
|
-
|
|
65339
|
+
fs46.unlinkSync(lockPath);
|
|
65053
65340
|
}
|
|
65054
65341
|
}
|
|
65055
65342
|
const lock = {
|
|
@@ -65060,24 +65347,24 @@ function tryAcquireLock(directory, filePath, agent, taskId) {
|
|
|
65060
65347
|
expiresAt: Date.now() + LOCK_TIMEOUT_MS
|
|
65061
65348
|
};
|
|
65062
65349
|
const tempPath = `${lockPath}.tmp`;
|
|
65063
|
-
|
|
65064
|
-
|
|
65350
|
+
fs46.writeFileSync(tempPath, JSON.stringify(lock, null, 2), "utf-8");
|
|
65351
|
+
fs46.renameSync(tempPath, lockPath);
|
|
65065
65352
|
return { acquired: true, lock };
|
|
65066
65353
|
}
|
|
65067
65354
|
function releaseLock(directory, filePath, taskId) {
|
|
65068
65355
|
const lockPath = getLockFilePath(directory, filePath);
|
|
65069
|
-
if (!
|
|
65356
|
+
if (!fs46.existsSync(lockPath)) {
|
|
65070
65357
|
return true;
|
|
65071
65358
|
}
|
|
65072
65359
|
try {
|
|
65073
|
-
const lock = JSON.parse(
|
|
65360
|
+
const lock = JSON.parse(fs46.readFileSync(lockPath, "utf-8"));
|
|
65074
65361
|
if (lock.taskId === taskId) {
|
|
65075
|
-
|
|
65362
|
+
fs46.unlinkSync(lockPath);
|
|
65076
65363
|
return true;
|
|
65077
65364
|
}
|
|
65078
65365
|
return false;
|
|
65079
65366
|
} catch {
|
|
65080
|
-
|
|
65367
|
+
fs46.unlinkSync(lockPath);
|
|
65081
65368
|
return true;
|
|
65082
65369
|
}
|
|
65083
65370
|
}
|
|
@@ -65202,14 +65489,14 @@ async function executeSavePlan(args2, fallbackDir) {
|
|
|
65202
65489
|
try {
|
|
65203
65490
|
await savePlan(dir, plan);
|
|
65204
65491
|
try {
|
|
65205
|
-
const markerPath =
|
|
65492
|
+
const markerPath = path60.join(dir, ".swarm", ".plan-write-marker");
|
|
65206
65493
|
const marker = JSON.stringify({
|
|
65207
65494
|
source: "save_plan",
|
|
65208
65495
|
timestamp: new Date().toISOString(),
|
|
65209
65496
|
phases_count: plan.phases.length,
|
|
65210
65497
|
tasks_count: tasksCount
|
|
65211
65498
|
});
|
|
65212
|
-
await
|
|
65499
|
+
await fs47.promises.writeFile(markerPath, marker, "utf8");
|
|
65213
65500
|
} catch {}
|
|
65214
65501
|
const warnings = [];
|
|
65215
65502
|
let criticReviewFound = false;
|
|
@@ -65225,7 +65512,7 @@ async function executeSavePlan(args2, fallbackDir) {
|
|
|
65225
65512
|
return {
|
|
65226
65513
|
success: true,
|
|
65227
65514
|
message: "Plan saved successfully",
|
|
65228
|
-
plan_path:
|
|
65515
|
+
plan_path: path60.join(dir, ".swarm", "plan.json"),
|
|
65229
65516
|
phases_count: plan.phases.length,
|
|
65230
65517
|
tasks_count: tasksCount,
|
|
65231
65518
|
...warnings.length > 0 ? { warnings } : {}
|
|
@@ -65267,8 +65554,8 @@ var save_plan = createSwarmTool({
|
|
|
65267
65554
|
// src/tools/sbom-generate.ts
|
|
65268
65555
|
init_dist();
|
|
65269
65556
|
init_manager();
|
|
65270
|
-
import * as
|
|
65271
|
-
import * as
|
|
65557
|
+
import * as fs48 from "fs";
|
|
65558
|
+
import * as path61 from "path";
|
|
65272
65559
|
|
|
65273
65560
|
// src/sbom/detectors/index.ts
|
|
65274
65561
|
init_utils();
|
|
@@ -66116,9 +66403,9 @@ function findManifestFiles(rootDir) {
|
|
|
66116
66403
|
const patterns = [...new Set(allDetectors.flatMap((d) => d.patterns))];
|
|
66117
66404
|
function searchDir(dir) {
|
|
66118
66405
|
try {
|
|
66119
|
-
const entries =
|
|
66406
|
+
const entries = fs48.readdirSync(dir, { withFileTypes: true });
|
|
66120
66407
|
for (const entry of entries) {
|
|
66121
|
-
const fullPath =
|
|
66408
|
+
const fullPath = path61.join(dir, entry.name);
|
|
66122
66409
|
if (entry.name.startsWith(".") || entry.name === "node_modules" || entry.name === "dist" || entry.name === "build" || entry.name === "target") {
|
|
66123
66410
|
continue;
|
|
66124
66411
|
}
|
|
@@ -66127,7 +66414,7 @@ function findManifestFiles(rootDir) {
|
|
|
66127
66414
|
} else if (entry.isFile()) {
|
|
66128
66415
|
for (const pattern of patterns) {
|
|
66129
66416
|
if (simpleGlobToRegex(pattern).test(entry.name)) {
|
|
66130
|
-
manifestFiles.push(
|
|
66417
|
+
manifestFiles.push(path61.relative(rootDir, fullPath));
|
|
66131
66418
|
break;
|
|
66132
66419
|
}
|
|
66133
66420
|
}
|
|
@@ -66143,13 +66430,13 @@ function findManifestFilesInDirs(directories, workingDir) {
|
|
|
66143
66430
|
const patterns = [...new Set(allDetectors.flatMap((d) => d.patterns))];
|
|
66144
66431
|
for (const dir of directories) {
|
|
66145
66432
|
try {
|
|
66146
|
-
const entries =
|
|
66433
|
+
const entries = fs48.readdirSync(dir, { withFileTypes: true });
|
|
66147
66434
|
for (const entry of entries) {
|
|
66148
|
-
const fullPath =
|
|
66435
|
+
const fullPath = path61.join(dir, entry.name);
|
|
66149
66436
|
if (entry.isFile()) {
|
|
66150
66437
|
for (const pattern of patterns) {
|
|
66151
66438
|
if (simpleGlobToRegex(pattern).test(entry.name)) {
|
|
66152
|
-
found.push(
|
|
66439
|
+
found.push(path61.relative(workingDir, fullPath));
|
|
66153
66440
|
break;
|
|
66154
66441
|
}
|
|
66155
66442
|
}
|
|
@@ -66162,11 +66449,11 @@ function findManifestFilesInDirs(directories, workingDir) {
|
|
|
66162
66449
|
function getDirectoriesFromChangedFiles(changedFiles, workingDir) {
|
|
66163
66450
|
const dirs = new Set;
|
|
66164
66451
|
for (const file3 of changedFiles) {
|
|
66165
|
-
let currentDir =
|
|
66452
|
+
let currentDir = path61.dirname(file3);
|
|
66166
66453
|
while (true) {
|
|
66167
|
-
if (currentDir && currentDir !== "." && currentDir !==
|
|
66168
|
-
dirs.add(
|
|
66169
|
-
const parent =
|
|
66454
|
+
if (currentDir && currentDir !== "." && currentDir !== path61.sep) {
|
|
66455
|
+
dirs.add(path61.join(workingDir, currentDir));
|
|
66456
|
+
const parent = path61.dirname(currentDir);
|
|
66170
66457
|
if (parent === currentDir)
|
|
66171
66458
|
break;
|
|
66172
66459
|
currentDir = parent;
|
|
@@ -66180,7 +66467,7 @@ function getDirectoriesFromChangedFiles(changedFiles, workingDir) {
|
|
|
66180
66467
|
}
|
|
66181
66468
|
function ensureOutputDir(outputDir) {
|
|
66182
66469
|
try {
|
|
66183
|
-
|
|
66470
|
+
fs48.mkdirSync(outputDir, { recursive: true });
|
|
66184
66471
|
} catch (error93) {
|
|
66185
66472
|
if (!error93 || error93.code !== "EEXIST") {
|
|
66186
66473
|
throw error93;
|
|
@@ -66250,7 +66537,7 @@ var sbom_generate = createSwarmTool({
|
|
|
66250
66537
|
const changedFiles = obj.changed_files;
|
|
66251
66538
|
const relativeOutputDir = obj.output_dir || DEFAULT_OUTPUT_DIR;
|
|
66252
66539
|
const workingDir = directory;
|
|
66253
|
-
const outputDir =
|
|
66540
|
+
const outputDir = path61.isAbsolute(relativeOutputDir) ? relativeOutputDir : path61.join(workingDir, relativeOutputDir);
|
|
66254
66541
|
let manifestFiles = [];
|
|
66255
66542
|
if (scope === "all") {
|
|
66256
66543
|
manifestFiles = findManifestFiles(workingDir);
|
|
@@ -66273,11 +66560,11 @@ var sbom_generate = createSwarmTool({
|
|
|
66273
66560
|
const processedFiles = [];
|
|
66274
66561
|
for (const manifestFile of manifestFiles) {
|
|
66275
66562
|
try {
|
|
66276
|
-
const fullPath =
|
|
66277
|
-
if (!
|
|
66563
|
+
const fullPath = path61.isAbsolute(manifestFile) ? manifestFile : path61.join(workingDir, manifestFile);
|
|
66564
|
+
if (!fs48.existsSync(fullPath)) {
|
|
66278
66565
|
continue;
|
|
66279
66566
|
}
|
|
66280
|
-
const content =
|
|
66567
|
+
const content = fs48.readFileSync(fullPath, "utf-8");
|
|
66281
66568
|
const components = detectComponents(manifestFile, content);
|
|
66282
66569
|
processedFiles.push(manifestFile);
|
|
66283
66570
|
if (components.length > 0) {
|
|
@@ -66290,8 +66577,8 @@ var sbom_generate = createSwarmTool({
|
|
|
66290
66577
|
const bom = generateCycloneDX(allComponents);
|
|
66291
66578
|
const bomJson = serializeCycloneDX(bom);
|
|
66292
66579
|
const filename = generateSbomFilename();
|
|
66293
|
-
const outputPath =
|
|
66294
|
-
|
|
66580
|
+
const outputPath = path61.join(outputDir, filename);
|
|
66581
|
+
fs48.writeFileSync(outputPath, bomJson, "utf-8");
|
|
66295
66582
|
const verdict = processedFiles.length > 0 ? "pass" : "pass";
|
|
66296
66583
|
try {
|
|
66297
66584
|
const timestamp = new Date().toISOString();
|
|
@@ -66333,8 +66620,8 @@ var sbom_generate = createSwarmTool({
|
|
|
66333
66620
|
// src/tools/schema-drift.ts
|
|
66334
66621
|
init_dist();
|
|
66335
66622
|
init_create_tool();
|
|
66336
|
-
import * as
|
|
66337
|
-
import * as
|
|
66623
|
+
import * as fs49 from "fs";
|
|
66624
|
+
import * as path62 from "path";
|
|
66338
66625
|
var SPEC_CANDIDATES = [
|
|
66339
66626
|
"openapi.json",
|
|
66340
66627
|
"openapi.yaml",
|
|
@@ -66366,28 +66653,28 @@ function normalizePath2(p) {
|
|
|
66366
66653
|
}
|
|
66367
66654
|
function discoverSpecFile(cwd, specFileArg) {
|
|
66368
66655
|
if (specFileArg) {
|
|
66369
|
-
const resolvedPath =
|
|
66370
|
-
const normalizedCwd = cwd.endsWith(
|
|
66656
|
+
const resolvedPath = path62.resolve(cwd, specFileArg);
|
|
66657
|
+
const normalizedCwd = cwd.endsWith(path62.sep) ? cwd : cwd + path62.sep;
|
|
66371
66658
|
if (!resolvedPath.startsWith(normalizedCwd) && resolvedPath !== cwd) {
|
|
66372
66659
|
throw new Error("Invalid spec_file: path traversal detected");
|
|
66373
66660
|
}
|
|
66374
|
-
const ext =
|
|
66661
|
+
const ext = path62.extname(resolvedPath).toLowerCase();
|
|
66375
66662
|
if (!ALLOWED_EXTENSIONS.includes(ext)) {
|
|
66376
66663
|
throw new Error(`Invalid spec_file: must end in .json, .yaml, or .yml, got ${ext}`);
|
|
66377
66664
|
}
|
|
66378
|
-
const stats =
|
|
66665
|
+
const stats = fs49.statSync(resolvedPath);
|
|
66379
66666
|
if (stats.size > MAX_SPEC_SIZE) {
|
|
66380
66667
|
throw new Error(`Invalid spec_file: file exceeds ${MAX_SPEC_SIZE / 1024 / 1024}MB limit`);
|
|
66381
66668
|
}
|
|
66382
|
-
if (!
|
|
66669
|
+
if (!fs49.existsSync(resolvedPath)) {
|
|
66383
66670
|
throw new Error(`Spec file not found: ${resolvedPath}`);
|
|
66384
66671
|
}
|
|
66385
66672
|
return resolvedPath;
|
|
66386
66673
|
}
|
|
66387
66674
|
for (const candidate of SPEC_CANDIDATES) {
|
|
66388
|
-
const candidatePath =
|
|
66389
|
-
if (
|
|
66390
|
-
const stats =
|
|
66675
|
+
const candidatePath = path62.resolve(cwd, candidate);
|
|
66676
|
+
if (fs49.existsSync(candidatePath)) {
|
|
66677
|
+
const stats = fs49.statSync(candidatePath);
|
|
66391
66678
|
if (stats.size <= MAX_SPEC_SIZE) {
|
|
66392
66679
|
return candidatePath;
|
|
66393
66680
|
}
|
|
@@ -66396,8 +66683,8 @@ function discoverSpecFile(cwd, specFileArg) {
|
|
|
66396
66683
|
return null;
|
|
66397
66684
|
}
|
|
66398
66685
|
function parseSpec(specFile) {
|
|
66399
|
-
const content =
|
|
66400
|
-
const ext =
|
|
66686
|
+
const content = fs49.readFileSync(specFile, "utf-8");
|
|
66687
|
+
const ext = path62.extname(specFile).toLowerCase();
|
|
66401
66688
|
if (ext === ".json") {
|
|
66402
66689
|
return parseJsonSpec(content);
|
|
66403
66690
|
}
|
|
@@ -66468,12 +66755,12 @@ function extractRoutes(cwd) {
|
|
|
66468
66755
|
function walkDir(dir) {
|
|
66469
66756
|
let entries;
|
|
66470
66757
|
try {
|
|
66471
|
-
entries =
|
|
66758
|
+
entries = fs49.readdirSync(dir, { withFileTypes: true });
|
|
66472
66759
|
} catch {
|
|
66473
66760
|
return;
|
|
66474
66761
|
}
|
|
66475
66762
|
for (const entry of entries) {
|
|
66476
|
-
const fullPath =
|
|
66763
|
+
const fullPath = path62.join(dir, entry.name);
|
|
66477
66764
|
if (entry.isSymbolicLink()) {
|
|
66478
66765
|
continue;
|
|
66479
66766
|
}
|
|
@@ -66483,7 +66770,7 @@ function extractRoutes(cwd) {
|
|
|
66483
66770
|
}
|
|
66484
66771
|
walkDir(fullPath);
|
|
66485
66772
|
} else if (entry.isFile()) {
|
|
66486
|
-
const ext =
|
|
66773
|
+
const ext = path62.extname(entry.name).toLowerCase();
|
|
66487
66774
|
const baseName = entry.name.toLowerCase();
|
|
66488
66775
|
if (![".ts", ".js", ".mjs"].includes(ext)) {
|
|
66489
66776
|
continue;
|
|
@@ -66501,7 +66788,7 @@ function extractRoutes(cwd) {
|
|
|
66501
66788
|
}
|
|
66502
66789
|
function extractRoutesFromFile(filePath) {
|
|
66503
66790
|
const routes = [];
|
|
66504
|
-
const content =
|
|
66791
|
+
const content = fs49.readFileSync(filePath, "utf-8");
|
|
66505
66792
|
const lines = content.split(/\r?\n/);
|
|
66506
66793
|
const expressRegex = /(?:app|router|server|express)\.(get|post|put|patch|delete|options|head)\s*\(\s*['"`]([^'"`]+)['"`]/g;
|
|
66507
66794
|
const flaskRegex = /@(?:app|blueprint|bp)\.route\s*\(\s*['"]([^'"]+)['"]/g;
|
|
@@ -66652,8 +66939,8 @@ init_secretscan();
|
|
|
66652
66939
|
// src/tools/symbols.ts
|
|
66653
66940
|
init_tool();
|
|
66654
66941
|
init_create_tool();
|
|
66655
|
-
import * as
|
|
66656
|
-
import * as
|
|
66942
|
+
import * as fs50 from "fs";
|
|
66943
|
+
import * as path63 from "path";
|
|
66657
66944
|
var MAX_FILE_SIZE_BYTES7 = 1024 * 1024;
|
|
66658
66945
|
var WINDOWS_RESERVED_NAMES = /^(con|prn|aux|nul|com[1-9]|lpt[1-9])(\.|:|$)/i;
|
|
66659
66946
|
function containsWindowsAttacks(str) {
|
|
@@ -66670,11 +66957,11 @@ function containsWindowsAttacks(str) {
|
|
|
66670
66957
|
}
|
|
66671
66958
|
function isPathInWorkspace(filePath, workspace) {
|
|
66672
66959
|
try {
|
|
66673
|
-
const resolvedPath =
|
|
66674
|
-
const realWorkspace =
|
|
66675
|
-
const realResolvedPath =
|
|
66676
|
-
const relativePath =
|
|
66677
|
-
if (relativePath.startsWith("..") ||
|
|
66960
|
+
const resolvedPath = path63.resolve(workspace, filePath);
|
|
66961
|
+
const realWorkspace = fs50.realpathSync(workspace);
|
|
66962
|
+
const realResolvedPath = fs50.realpathSync(resolvedPath);
|
|
66963
|
+
const relativePath = path63.relative(realWorkspace, realResolvedPath);
|
|
66964
|
+
if (relativePath.startsWith("..") || path63.isAbsolute(relativePath)) {
|
|
66678
66965
|
return false;
|
|
66679
66966
|
}
|
|
66680
66967
|
return true;
|
|
@@ -66686,17 +66973,17 @@ function validatePathForRead(filePath, workspace) {
|
|
|
66686
66973
|
return isPathInWorkspace(filePath, workspace);
|
|
66687
66974
|
}
|
|
66688
66975
|
function extractTSSymbols(filePath, cwd) {
|
|
66689
|
-
const fullPath =
|
|
66976
|
+
const fullPath = path63.join(cwd, filePath);
|
|
66690
66977
|
if (!validatePathForRead(fullPath, cwd)) {
|
|
66691
66978
|
return [];
|
|
66692
66979
|
}
|
|
66693
66980
|
let content;
|
|
66694
66981
|
try {
|
|
66695
|
-
const stats =
|
|
66982
|
+
const stats = fs50.statSync(fullPath);
|
|
66696
66983
|
if (stats.size > MAX_FILE_SIZE_BYTES7) {
|
|
66697
66984
|
throw new Error(`File too large: ${stats.size} bytes (max: ${MAX_FILE_SIZE_BYTES7})`);
|
|
66698
66985
|
}
|
|
66699
|
-
content =
|
|
66986
|
+
content = fs50.readFileSync(fullPath, "utf-8");
|
|
66700
66987
|
} catch {
|
|
66701
66988
|
return [];
|
|
66702
66989
|
}
|
|
@@ -66838,17 +67125,17 @@ function extractTSSymbols(filePath, cwd) {
|
|
|
66838
67125
|
});
|
|
66839
67126
|
}
|
|
66840
67127
|
function extractPythonSymbols(filePath, cwd) {
|
|
66841
|
-
const fullPath =
|
|
67128
|
+
const fullPath = path63.join(cwd, filePath);
|
|
66842
67129
|
if (!validatePathForRead(fullPath, cwd)) {
|
|
66843
67130
|
return [];
|
|
66844
67131
|
}
|
|
66845
67132
|
let content;
|
|
66846
67133
|
try {
|
|
66847
|
-
const stats =
|
|
67134
|
+
const stats = fs50.statSync(fullPath);
|
|
66848
67135
|
if (stats.size > MAX_FILE_SIZE_BYTES7) {
|
|
66849
67136
|
throw new Error(`File too large: ${stats.size} bytes (max: ${MAX_FILE_SIZE_BYTES7})`);
|
|
66850
67137
|
}
|
|
66851
|
-
content =
|
|
67138
|
+
content = fs50.readFileSync(fullPath, "utf-8");
|
|
66852
67139
|
} catch {
|
|
66853
67140
|
return [];
|
|
66854
67141
|
}
|
|
@@ -66921,7 +67208,7 @@ var symbols = createSwarmTool({
|
|
|
66921
67208
|
}, null, 2);
|
|
66922
67209
|
}
|
|
66923
67210
|
const cwd = directory;
|
|
66924
|
-
const ext =
|
|
67211
|
+
const ext = path63.extname(file3);
|
|
66925
67212
|
if (containsControlChars(file3)) {
|
|
66926
67213
|
return JSON.stringify({
|
|
66927
67214
|
file: file3,
|
|
@@ -66992,8 +67279,8 @@ init_test_runner();
|
|
|
66992
67279
|
init_dist();
|
|
66993
67280
|
init_utils();
|
|
66994
67281
|
init_create_tool();
|
|
66995
|
-
import * as
|
|
66996
|
-
import * as
|
|
67282
|
+
import * as fs51 from "fs";
|
|
67283
|
+
import * as path64 from "path";
|
|
66997
67284
|
var MAX_TEXT_LENGTH = 200;
|
|
66998
67285
|
var MAX_FILE_SIZE_BYTES8 = 1024 * 1024;
|
|
66999
67286
|
var SUPPORTED_EXTENSIONS2 = new Set([
|
|
@@ -67058,9 +67345,9 @@ function validatePathsInput(paths, cwd) {
|
|
|
67058
67345
|
return { error: "paths contains path traversal", resolvedPath: null };
|
|
67059
67346
|
}
|
|
67060
67347
|
try {
|
|
67061
|
-
const resolvedPath =
|
|
67062
|
-
const normalizedCwd =
|
|
67063
|
-
const normalizedResolved =
|
|
67348
|
+
const resolvedPath = path64.resolve(paths);
|
|
67349
|
+
const normalizedCwd = path64.resolve(cwd);
|
|
67350
|
+
const normalizedResolved = path64.resolve(resolvedPath);
|
|
67064
67351
|
if (!normalizedResolved.startsWith(normalizedCwd)) {
|
|
67065
67352
|
return {
|
|
67066
67353
|
error: "paths must be within the current working directory",
|
|
@@ -67076,13 +67363,13 @@ function validatePathsInput(paths, cwd) {
|
|
|
67076
67363
|
}
|
|
67077
67364
|
}
|
|
67078
67365
|
function isSupportedExtension(filePath) {
|
|
67079
|
-
const ext =
|
|
67366
|
+
const ext = path64.extname(filePath).toLowerCase();
|
|
67080
67367
|
return SUPPORTED_EXTENSIONS2.has(ext);
|
|
67081
67368
|
}
|
|
67082
67369
|
function findSourceFiles2(dir, files = []) {
|
|
67083
67370
|
let entries;
|
|
67084
67371
|
try {
|
|
67085
|
-
entries =
|
|
67372
|
+
entries = fs51.readdirSync(dir);
|
|
67086
67373
|
} catch {
|
|
67087
67374
|
return files;
|
|
67088
67375
|
}
|
|
@@ -67091,10 +67378,10 @@ function findSourceFiles2(dir, files = []) {
|
|
|
67091
67378
|
if (SKIP_DIRECTORIES4.has(entry)) {
|
|
67092
67379
|
continue;
|
|
67093
67380
|
}
|
|
67094
|
-
const fullPath =
|
|
67381
|
+
const fullPath = path64.join(dir, entry);
|
|
67095
67382
|
let stat2;
|
|
67096
67383
|
try {
|
|
67097
|
-
stat2 =
|
|
67384
|
+
stat2 = fs51.statSync(fullPath);
|
|
67098
67385
|
} catch {
|
|
67099
67386
|
continue;
|
|
67100
67387
|
}
|
|
@@ -67187,7 +67474,7 @@ var todo_extract = createSwarmTool({
|
|
|
67187
67474
|
return JSON.stringify(errorResult, null, 2);
|
|
67188
67475
|
}
|
|
67189
67476
|
const scanPath = resolvedPath;
|
|
67190
|
-
if (!
|
|
67477
|
+
if (!fs51.existsSync(scanPath)) {
|
|
67191
67478
|
const errorResult = {
|
|
67192
67479
|
error: `path not found: ${pathsInput}`,
|
|
67193
67480
|
total: 0,
|
|
@@ -67197,13 +67484,13 @@ var todo_extract = createSwarmTool({
|
|
|
67197
67484
|
return JSON.stringify(errorResult, null, 2);
|
|
67198
67485
|
}
|
|
67199
67486
|
const filesToScan = [];
|
|
67200
|
-
const stat2 =
|
|
67487
|
+
const stat2 = fs51.statSync(scanPath);
|
|
67201
67488
|
if (stat2.isFile()) {
|
|
67202
67489
|
if (isSupportedExtension(scanPath)) {
|
|
67203
67490
|
filesToScan.push(scanPath);
|
|
67204
67491
|
} else {
|
|
67205
67492
|
const errorResult = {
|
|
67206
|
-
error: `unsupported file extension: ${
|
|
67493
|
+
error: `unsupported file extension: ${path64.extname(scanPath)}`,
|
|
67207
67494
|
total: 0,
|
|
67208
67495
|
byPriority: { high: 0, medium: 0, low: 0 },
|
|
67209
67496
|
entries: []
|
|
@@ -67216,11 +67503,11 @@ var todo_extract = createSwarmTool({
|
|
|
67216
67503
|
const allEntries = [];
|
|
67217
67504
|
for (const filePath of filesToScan) {
|
|
67218
67505
|
try {
|
|
67219
|
-
const fileStat =
|
|
67506
|
+
const fileStat = fs51.statSync(filePath);
|
|
67220
67507
|
if (fileStat.size > MAX_FILE_SIZE_BYTES8) {
|
|
67221
67508
|
continue;
|
|
67222
67509
|
}
|
|
67223
|
-
const content =
|
|
67510
|
+
const content = fs51.readFileSync(filePath, "utf-8");
|
|
67224
67511
|
const entries = parseTodoComments(content, filePath, tagsSet);
|
|
67225
67512
|
allEntries.push(...entries);
|
|
67226
67513
|
} catch {}
|
|
@@ -67249,18 +67536,18 @@ var todo_extract = createSwarmTool({
|
|
|
67249
67536
|
init_tool();
|
|
67250
67537
|
init_schema();
|
|
67251
67538
|
init_gate_evidence();
|
|
67252
|
-
import * as
|
|
67253
|
-
import * as
|
|
67539
|
+
import * as fs53 from "fs";
|
|
67540
|
+
import * as path66 from "path";
|
|
67254
67541
|
|
|
67255
67542
|
// src/hooks/diff-scope.ts
|
|
67256
|
-
import * as
|
|
67257
|
-
import * as
|
|
67543
|
+
import * as fs52 from "fs";
|
|
67544
|
+
import * as path65 from "path";
|
|
67258
67545
|
function getDeclaredScope(taskId, directory) {
|
|
67259
67546
|
try {
|
|
67260
|
-
const planPath =
|
|
67261
|
-
if (!
|
|
67547
|
+
const planPath = path65.join(directory, ".swarm", "plan.json");
|
|
67548
|
+
if (!fs52.existsSync(planPath))
|
|
67262
67549
|
return null;
|
|
67263
|
-
const raw =
|
|
67550
|
+
const raw = fs52.readFileSync(planPath, "utf-8");
|
|
67264
67551
|
const plan = JSON.parse(raw);
|
|
67265
67552
|
for (const phase of plan.phases ?? []) {
|
|
67266
67553
|
for (const task of phase.tasks ?? []) {
|
|
@@ -67373,7 +67660,7 @@ var TIER_3_PATTERNS = [
|
|
|
67373
67660
|
];
|
|
67374
67661
|
function matchesTier3Pattern(files) {
|
|
67375
67662
|
for (const file3 of files) {
|
|
67376
|
-
const fileName =
|
|
67663
|
+
const fileName = path66.basename(file3);
|
|
67377
67664
|
for (const pattern of TIER_3_PATTERNS) {
|
|
67378
67665
|
if (pattern.test(fileName)) {
|
|
67379
67666
|
return true;
|
|
@@ -67387,8 +67674,8 @@ function checkReviewerGate(taskId, workingDirectory) {
|
|
|
67387
67674
|
if (hasActiveTurboMode()) {
|
|
67388
67675
|
const resolvedDir2 = workingDirectory;
|
|
67389
67676
|
try {
|
|
67390
|
-
const planPath =
|
|
67391
|
-
const planRaw =
|
|
67677
|
+
const planPath = path66.join(resolvedDir2, ".swarm", "plan.json");
|
|
67678
|
+
const planRaw = fs53.readFileSync(planPath, "utf-8");
|
|
67392
67679
|
const plan = JSON.parse(planRaw);
|
|
67393
67680
|
for (const planPhase of plan.phases ?? []) {
|
|
67394
67681
|
for (const task of planPhase.tasks ?? []) {
|
|
@@ -67454,8 +67741,8 @@ function checkReviewerGate(taskId, workingDirectory) {
|
|
|
67454
67741
|
}
|
|
67455
67742
|
try {
|
|
67456
67743
|
const resolvedDir2 = workingDirectory;
|
|
67457
|
-
const planPath =
|
|
67458
|
-
const planRaw =
|
|
67744
|
+
const planPath = path66.join(resolvedDir2, ".swarm", "plan.json");
|
|
67745
|
+
const planRaw = fs53.readFileSync(planPath, "utf-8");
|
|
67459
67746
|
const plan = JSON.parse(planRaw);
|
|
67460
67747
|
for (const planPhase of plan.phases ?? []) {
|
|
67461
67748
|
for (const task of planPhase.tasks ?? []) {
|
|
@@ -67637,8 +67924,8 @@ async function executeUpdateTaskStatus(args2, fallbackDir) {
|
|
|
67637
67924
|
};
|
|
67638
67925
|
}
|
|
67639
67926
|
}
|
|
67640
|
-
normalizedDir =
|
|
67641
|
-
const pathParts = normalizedDir.split(
|
|
67927
|
+
normalizedDir = path66.normalize(args2.working_directory);
|
|
67928
|
+
const pathParts = normalizedDir.split(path66.sep);
|
|
67642
67929
|
if (pathParts.includes("..")) {
|
|
67643
67930
|
return {
|
|
67644
67931
|
success: false,
|
|
@@ -67648,11 +67935,11 @@ async function executeUpdateTaskStatus(args2, fallbackDir) {
|
|
|
67648
67935
|
]
|
|
67649
67936
|
};
|
|
67650
67937
|
}
|
|
67651
|
-
const resolvedDir =
|
|
67938
|
+
const resolvedDir = path66.resolve(normalizedDir);
|
|
67652
67939
|
try {
|
|
67653
|
-
const realPath =
|
|
67654
|
-
const planPath =
|
|
67655
|
-
if (!
|
|
67940
|
+
const realPath = fs53.realpathSync(resolvedDir);
|
|
67941
|
+
const planPath = path66.join(realPath, ".swarm", "plan.json");
|
|
67942
|
+
if (!fs53.existsSync(planPath)) {
|
|
67656
67943
|
return {
|
|
67657
67944
|
success: false,
|
|
67658
67945
|
message: `Invalid working_directory: plan not found in "${realPath}"`,
|
|
@@ -67685,8 +67972,8 @@ async function executeUpdateTaskStatus(args2, fallbackDir) {
|
|
|
67685
67972
|
recoverTaskStateFromDelegations(args2.task_id);
|
|
67686
67973
|
let phaseRequiresReviewer = true;
|
|
67687
67974
|
try {
|
|
67688
|
-
const planPath =
|
|
67689
|
-
const planRaw =
|
|
67975
|
+
const planPath = path66.join(directory, ".swarm", "plan.json");
|
|
67976
|
+
const planRaw = fs53.readFileSync(planPath, "utf-8");
|
|
67690
67977
|
const plan = JSON.parse(planRaw);
|
|
67691
67978
|
const taskPhase = plan.phases.find((p) => p.tasks.some((t) => t.id === args2.task_id));
|
|
67692
67979
|
if (taskPhase?.required_agents && !taskPhase.required_agents.includes("reviewer")) {
|
|
@@ -67749,8 +68036,8 @@ var update_task_status = createSwarmTool({
|
|
|
67749
68036
|
init_tool();
|
|
67750
68037
|
init_utils2();
|
|
67751
68038
|
init_create_tool();
|
|
67752
|
-
import
|
|
67753
|
-
import
|
|
68039
|
+
import fs54 from "fs";
|
|
68040
|
+
import path67 from "path";
|
|
67754
68041
|
function normalizeVerdict(verdict) {
|
|
67755
68042
|
switch (verdict) {
|
|
67756
68043
|
case "APPROVED":
|
|
@@ -67797,7 +68084,7 @@ async function executeWriteDriftEvidence(args2, directory) {
|
|
|
67797
68084
|
entries: [evidenceEntry]
|
|
67798
68085
|
};
|
|
67799
68086
|
const filename = "drift-verifier.json";
|
|
67800
|
-
const relativePath =
|
|
68087
|
+
const relativePath = path67.join("evidence", String(phase), filename);
|
|
67801
68088
|
let validatedPath;
|
|
67802
68089
|
try {
|
|
67803
68090
|
validatedPath = validateSwarmPath(directory, relativePath);
|
|
@@ -67808,12 +68095,12 @@ async function executeWriteDriftEvidence(args2, directory) {
|
|
|
67808
68095
|
message: error93 instanceof Error ? error93.message : "Failed to validate path"
|
|
67809
68096
|
}, null, 2);
|
|
67810
68097
|
}
|
|
67811
|
-
const evidenceDir =
|
|
68098
|
+
const evidenceDir = path67.dirname(validatedPath);
|
|
67812
68099
|
try {
|
|
67813
|
-
await
|
|
67814
|
-
const tempPath =
|
|
67815
|
-
await
|
|
67816
|
-
await
|
|
68100
|
+
await fs54.promises.mkdir(evidenceDir, { recursive: true });
|
|
68101
|
+
const tempPath = path67.join(evidenceDir, `.${filename}.tmp`);
|
|
68102
|
+
await fs54.promises.writeFile(tempPath, JSON.stringify(evidenceContent, null, 2), "utf-8");
|
|
68103
|
+
await fs54.promises.rename(tempPath, validatedPath);
|
|
67817
68104
|
return JSON.stringify({
|
|
67818
68105
|
success: true,
|
|
67819
68106
|
phase,
|
|
@@ -67891,6 +68178,7 @@ ${footerLines.join(`
|
|
|
67891
68178
|
var _heartbeatTimers = new Map;
|
|
67892
68179
|
var OpenCodeSwarm = async (ctx) => {
|
|
67893
68180
|
const { config: config3, loadedFromFile } = loadPluginConfigWithMeta(ctx.directory);
|
|
68181
|
+
swarmState.opencodeClient = ctx.client;
|
|
67894
68182
|
await loadSnapshot(ctx.directory);
|
|
67895
68183
|
initTelemetry(ctx.directory);
|
|
67896
68184
|
const agents = getAgentConfigs(config3);
|
|
@@ -68001,7 +68289,7 @@ var OpenCodeSwarm = async (ctx) => {
|
|
|
68001
68289
|
const { PreflightTriggerManager: PTM } = await Promise.resolve().then(() => (init_trigger(), exports_trigger));
|
|
68002
68290
|
preflightTriggerManager = new PTM(automationConfig);
|
|
68003
68291
|
const { AutomationStatusArtifact: ASA } = await Promise.resolve().then(() => (init_status_artifact(), exports_status_artifact));
|
|
68004
|
-
const swarmDir =
|
|
68292
|
+
const swarmDir = path68.resolve(ctx.directory, ".swarm");
|
|
68005
68293
|
statusArtifact = new ASA(swarmDir);
|
|
68006
68294
|
statusArtifact.updateConfig(automationConfig.mode, automationConfig.capabilities);
|
|
68007
68295
|
if (automationConfig.capabilities?.evidence_auto_summaries === true) {
|
|
@@ -68333,7 +68621,7 @@ var OpenCodeSwarm = async (ctx) => {
|
|
|
68333
68621
|
} catch {}
|
|
68334
68622
|
return Promise.resolve();
|
|
68335
68623
|
},
|
|
68336
|
-
automationConfig.capabilities?.phase_preflight === true && preflightTriggerManager ? createPhaseMonitorHook(ctx.directory, preflightTriggerManager) : knowledgeConfig.enabled ? createPhaseMonitorHook(ctx.directory) : undefined
|
|
68624
|
+
automationConfig.capabilities?.phase_preflight === true && preflightTriggerManager ? createPhaseMonitorHook(ctx.directory, preflightTriggerManager, undefined, createCuratorLLMDelegate(ctx.directory)) : knowledgeConfig.enabled ? createPhaseMonitorHook(ctx.directory, undefined, undefined, createCuratorLLMDelegate(ctx.directory)) : undefined
|
|
68337
68625
|
].filter(Boolean)),
|
|
68338
68626
|
"experimental.session.compacting": compactionHook["experimental.session.compacting"],
|
|
68339
68627
|
"command.execute.before": safeHook(commandHandler),
|