opencode-swarm 6.41.4 → 6.42.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli/index.js +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 +725 -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,42 @@ 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
|
+
system: systemPrompt,
|
|
52390
|
+
tools: { write: false, edit: false, patch: false },
|
|
52391
|
+
parts: [{ type: "text", text: userInput }]
|
|
52392
|
+
}
|
|
52393
|
+
});
|
|
52394
|
+
if (!promptResult.data) {
|
|
52395
|
+
throw new Error(`Curator LLM prompt failed: ${JSON.stringify(promptResult.error)}`);
|
|
52396
|
+
}
|
|
52397
|
+
const textParts = promptResult.data.parts.filter((p) => p.type === "text");
|
|
52398
|
+
return textParts.map((p) => p.text).join(`
|
|
52399
|
+
`);
|
|
52400
|
+
} finally {
|
|
52401
|
+
if (ephemeralSessionId) {
|
|
52402
|
+
client.session.delete({ path: { id: ephemeralSessionId } }).catch(() => {});
|
|
52403
|
+
}
|
|
52404
|
+
}
|
|
52405
|
+
};
|
|
52406
|
+
}
|
|
52179
52407
|
// src/hooks/delegation-gate.ts
|
|
52180
52408
|
init_schema();
|
|
52181
52409
|
import * as fs23 from "fs";
|
|
@@ -54198,11 +54426,12 @@ function consolidateSystemMessages(messages) {
|
|
|
54198
54426
|
// src/hooks/phase-monitor.ts
|
|
54199
54427
|
init_schema();
|
|
54200
54428
|
init_manager2();
|
|
54201
|
-
import * as
|
|
54429
|
+
import * as path37 from "path";
|
|
54202
54430
|
init_utils2();
|
|
54203
|
-
function createPhaseMonitorHook(directory, preflightManager, curatorRunner
|
|
54431
|
+
function createPhaseMonitorHook(directory, preflightManager, curatorRunner, llmDelegate) {
|
|
54204
54432
|
let lastKnownPhase = null;
|
|
54205
54433
|
const handler = async (_input, _output) => {
|
|
54434
|
+
const runner = curatorRunner ?? runCuratorInit;
|
|
54206
54435
|
const plan = await loadPlan(directory);
|
|
54207
54436
|
if (!plan)
|
|
54208
54437
|
return;
|
|
@@ -54214,12 +54443,29 @@ function createPhaseMonitorHook(directory, preflightManager, curatorRunner = run
|
|
|
54214
54443
|
const { config: config3 } = loadPluginConfigWithMeta2(directory);
|
|
54215
54444
|
const curatorConfig = CuratorConfigSchema.parse(config3.curator ?? {});
|
|
54216
54445
|
if (curatorConfig.enabled && curatorConfig.init_enabled) {
|
|
54217
|
-
const initResult = await
|
|
54446
|
+
const initResult = await runner(directory, curatorConfig, llmDelegate);
|
|
54218
54447
|
if (initResult.briefing) {
|
|
54219
|
-
const briefingPath =
|
|
54448
|
+
const briefingPath = path37.join(directory, ".swarm", "curator-briefing.md");
|
|
54220
54449
|
const { mkdir: mkdir5, writeFile: writeFile5 } = await import("fs/promises");
|
|
54221
|
-
await mkdir5(
|
|
54450
|
+
await mkdir5(path37.dirname(briefingPath), { recursive: true });
|
|
54222
54451
|
await writeFile5(briefingPath, initResult.briefing, "utf-8");
|
|
54452
|
+
const { buildApprovedReceipt: buildApprovedReceipt2, persistReviewReceipt: persistReviewReceipt2 } = await Promise.resolve().then(() => (init_review_receipt(), exports_review_receipt));
|
|
54453
|
+
const initReceipt = buildApprovedReceipt2({
|
|
54454
|
+
agent: "curator",
|
|
54455
|
+
scopeContent: initResult.briefing,
|
|
54456
|
+
scopeDescription: "curator-init-briefing",
|
|
54457
|
+
checkedAspects: [
|
|
54458
|
+
"knowledge_entries",
|
|
54459
|
+
"prior_phase_summaries",
|
|
54460
|
+
"contradiction_detection"
|
|
54461
|
+
],
|
|
54462
|
+
validatedClaims: [
|
|
54463
|
+
`knowledge_entries_reviewed: ${initResult.knowledge_entries_reviewed}`,
|
|
54464
|
+
`prior_phases_covered: ${initResult.prior_phases_covered}`,
|
|
54465
|
+
`contradictions: ${initResult.contradictions.length}`
|
|
54466
|
+
]
|
|
54467
|
+
});
|
|
54468
|
+
persistReviewReceipt2(directory, initReceipt).catch(() => {});
|
|
54223
54469
|
}
|
|
54224
54470
|
}
|
|
54225
54471
|
} catch {}
|
|
@@ -54324,21 +54570,25 @@ ${originalText}`;
|
|
|
54324
54570
|
})
|
|
54325
54571
|
};
|
|
54326
54572
|
}
|
|
54573
|
+
|
|
54574
|
+
// src/hooks/index.ts
|
|
54575
|
+
init_review_receipt();
|
|
54576
|
+
|
|
54327
54577
|
// src/hooks/system-enhancer.ts
|
|
54328
54578
|
init_constants();
|
|
54329
54579
|
init_schema();
|
|
54330
54580
|
init_manager();
|
|
54331
54581
|
init_detector();
|
|
54332
54582
|
init_manager2();
|
|
54333
|
-
import * as
|
|
54334
|
-
import * as
|
|
54583
|
+
import * as fs29 from "fs";
|
|
54584
|
+
import * as path41 from "path";
|
|
54335
54585
|
|
|
54336
54586
|
// src/services/decision-drift-analyzer.ts
|
|
54337
54587
|
init_utils2();
|
|
54338
54588
|
init_manager2();
|
|
54339
54589
|
init_utils();
|
|
54340
|
-
import * as
|
|
54341
|
-
import * as
|
|
54590
|
+
import * as fs26 from "fs";
|
|
54591
|
+
import * as path38 from "path";
|
|
54342
54592
|
var DEFAULT_DRIFT_CONFIG = {
|
|
54343
54593
|
staleThresholdPhases: 1,
|
|
54344
54594
|
detectContradictions: true,
|
|
@@ -54492,11 +54742,11 @@ async function analyzeDecisionDrift(directory, config3 = {}) {
|
|
|
54492
54742
|
currentPhase = legacyPhase;
|
|
54493
54743
|
}
|
|
54494
54744
|
}
|
|
54495
|
-
const contextPath =
|
|
54745
|
+
const contextPath = path38.join(directory, ".swarm", "context.md");
|
|
54496
54746
|
let contextContent = "";
|
|
54497
54747
|
try {
|
|
54498
|
-
if (
|
|
54499
|
-
contextContent =
|
|
54748
|
+
if (fs26.existsSync(contextPath)) {
|
|
54749
|
+
contextContent = fs26.readFileSync(contextPath, "utf-8");
|
|
54500
54750
|
}
|
|
54501
54751
|
} catch (error93) {
|
|
54502
54752
|
log("[DecisionDriftAnalyzer] context file read failed", {
|
|
@@ -54621,8 +54871,8 @@ init_utils();
|
|
|
54621
54871
|
// src/hooks/adversarial-detector.ts
|
|
54622
54872
|
init_constants();
|
|
54623
54873
|
init_schema();
|
|
54624
|
-
import * as
|
|
54625
|
-
import * as
|
|
54874
|
+
import * as fs27 from "fs/promises";
|
|
54875
|
+
import * as path39 from "path";
|
|
54626
54876
|
function safeGet(obj, key) {
|
|
54627
54877
|
if (!obj || !Object.hasOwn(obj, key))
|
|
54628
54878
|
return;
|
|
@@ -54836,10 +55086,10 @@ async function handleDebuggingSpiral(match, taskId, directory) {
|
|
|
54836
55086
|
let eventLogged = false;
|
|
54837
55087
|
let checkpointCreated = false;
|
|
54838
55088
|
try {
|
|
54839
|
-
const swarmDir =
|
|
54840
|
-
await
|
|
54841
|
-
const eventsPath =
|
|
54842
|
-
await
|
|
55089
|
+
const swarmDir = path39.join(directory, ".swarm");
|
|
55090
|
+
await fs27.mkdir(swarmDir, { recursive: true });
|
|
55091
|
+
const eventsPath = path39.join(swarmDir, "events.jsonl");
|
|
55092
|
+
await fs27.appendFile(eventsPath, `${formatDebuggingSpiralEvent(match, taskId)}
|
|
54843
55093
|
`);
|
|
54844
55094
|
eventLogged = true;
|
|
54845
55095
|
} catch {}
|
|
@@ -55220,7 +55470,7 @@ function createSystemEnhancerHook(config3, directory) {
|
|
|
55220
55470
|
} catch {}
|
|
55221
55471
|
try {
|
|
55222
55472
|
const darkMatterPath = validateSwarmPath(directory, "dark-matter.md");
|
|
55223
|
-
if (!
|
|
55473
|
+
if (!fs29.existsSync(darkMatterPath)) {
|
|
55224
55474
|
const {
|
|
55225
55475
|
detectDarkMatter: detectDarkMatter2,
|
|
55226
55476
|
formatDarkMatterOutput: formatDarkMatterOutput2,
|
|
@@ -55232,10 +55482,10 @@ function createSystemEnhancerHook(config3, directory) {
|
|
|
55232
55482
|
});
|
|
55233
55483
|
if (darkMatter && darkMatter.length > 0) {
|
|
55234
55484
|
const darkMatterReport = formatDarkMatterOutput2(darkMatter);
|
|
55235
|
-
await
|
|
55485
|
+
await fs29.promises.writeFile(darkMatterPath, darkMatterReport, "utf-8");
|
|
55236
55486
|
warn(`[system-enhancer] Dark matter scan complete: ${darkMatter.length} co-change patterns found`);
|
|
55237
55487
|
try {
|
|
55238
|
-
const projectName =
|
|
55488
|
+
const projectName = path41.basename(path41.resolve(directory));
|
|
55239
55489
|
const knowledgeEntries = darkMatterToKnowledgeEntries2(darkMatter, projectName);
|
|
55240
55490
|
const knowledgePath = resolveSwarmKnowledgePath(directory);
|
|
55241
55491
|
const existingEntries = await readKnowledge(knowledgePath);
|
|
@@ -55299,11 +55549,11 @@ function createSystemEnhancerHook(config3, directory) {
|
|
|
55299
55549
|
if (handoffContent) {
|
|
55300
55550
|
const handoffPath = validateSwarmPath(directory, "handoff.md");
|
|
55301
55551
|
const consumedPath = validateSwarmPath(directory, "handoff-consumed.md");
|
|
55302
|
-
if (
|
|
55552
|
+
if (fs29.existsSync(consumedPath)) {
|
|
55303
55553
|
warn("Duplicate handoff detected: handoff-consumed.md already exists");
|
|
55304
|
-
|
|
55554
|
+
fs29.unlinkSync(consumedPath);
|
|
55305
55555
|
}
|
|
55306
|
-
|
|
55556
|
+
fs29.renameSync(handoffPath, consumedPath);
|
|
55307
55557
|
const handoffBlock = `## HANDOFF \u2014 Resuming from model switch
|
|
55308
55558
|
The previous model's session ended. Here is your starting context:
|
|
55309
55559
|
|
|
@@ -55584,11 +55834,11 @@ ${budgetWarning}`);
|
|
|
55584
55834
|
if (handoffContent) {
|
|
55585
55835
|
const handoffPath = validateSwarmPath(directory, "handoff.md");
|
|
55586
55836
|
const consumedPath = validateSwarmPath(directory, "handoff-consumed.md");
|
|
55587
|
-
if (
|
|
55837
|
+
if (fs29.existsSync(consumedPath)) {
|
|
55588
55838
|
warn("Duplicate handoff detected: handoff-consumed.md already exists");
|
|
55589
|
-
|
|
55839
|
+
fs29.unlinkSync(consumedPath);
|
|
55590
55840
|
}
|
|
55591
|
-
|
|
55841
|
+
fs29.renameSync(handoffPath, consumedPath);
|
|
55592
55842
|
const handoffBlock = `## HANDOFF \u2014 Resuming from model switch
|
|
55593
55843
|
The previous model's session ended. Here is your starting context:
|
|
55594
55844
|
|
|
@@ -56358,8 +56608,8 @@ function isReadTool(toolName) {
|
|
|
56358
56608
|
}
|
|
56359
56609
|
|
|
56360
56610
|
// src/hooks/incremental-verify.ts
|
|
56361
|
-
import * as
|
|
56362
|
-
import * as
|
|
56611
|
+
import * as fs30 from "fs";
|
|
56612
|
+
import * as path42 from "path";
|
|
56363
56613
|
|
|
56364
56614
|
// src/hooks/spawn-helper.ts
|
|
56365
56615
|
import { spawn } from "child_process";
|
|
@@ -56434,21 +56684,21 @@ function spawnAsync(command, cwd, timeoutMs) {
|
|
|
56434
56684
|
// src/hooks/incremental-verify.ts
|
|
56435
56685
|
var emittedSkipAdvisories = new Set;
|
|
56436
56686
|
function detectPackageManager(projectDir) {
|
|
56437
|
-
if (
|
|
56687
|
+
if (fs30.existsSync(path42.join(projectDir, "bun.lockb")))
|
|
56438
56688
|
return "bun";
|
|
56439
|
-
if (
|
|
56689
|
+
if (fs30.existsSync(path42.join(projectDir, "pnpm-lock.yaml")))
|
|
56440
56690
|
return "pnpm";
|
|
56441
|
-
if (
|
|
56691
|
+
if (fs30.existsSync(path42.join(projectDir, "yarn.lock")))
|
|
56442
56692
|
return "yarn";
|
|
56443
|
-
if (
|
|
56693
|
+
if (fs30.existsSync(path42.join(projectDir, "package-lock.json")))
|
|
56444
56694
|
return "npm";
|
|
56445
56695
|
return "bun";
|
|
56446
56696
|
}
|
|
56447
56697
|
function detectTypecheckCommand(projectDir) {
|
|
56448
|
-
const pkgPath =
|
|
56449
|
-
if (
|
|
56698
|
+
const pkgPath = path42.join(projectDir, "package.json");
|
|
56699
|
+
if (fs30.existsSync(pkgPath)) {
|
|
56450
56700
|
try {
|
|
56451
|
-
const pkg = JSON.parse(
|
|
56701
|
+
const pkg = JSON.parse(fs30.readFileSync(pkgPath, "utf8"));
|
|
56452
56702
|
const scripts = pkg.scripts;
|
|
56453
56703
|
if (scripts?.typecheck) {
|
|
56454
56704
|
const pm = detectPackageManager(projectDir);
|
|
@@ -56462,8 +56712,8 @@ function detectTypecheckCommand(projectDir) {
|
|
|
56462
56712
|
...pkg.dependencies,
|
|
56463
56713
|
...pkg.devDependencies
|
|
56464
56714
|
};
|
|
56465
|
-
if (!deps?.typescript && !
|
|
56466
|
-
const hasTSMarkers = deps?.typescript ||
|
|
56715
|
+
if (!deps?.typescript && !fs30.existsSync(path42.join(projectDir, "tsconfig.json"))) {}
|
|
56716
|
+
const hasTSMarkers = deps?.typescript || fs30.existsSync(path42.join(projectDir, "tsconfig.json"));
|
|
56467
56717
|
if (hasTSMarkers) {
|
|
56468
56718
|
return { command: ["npx", "tsc", "--noEmit"], language: "typescript" };
|
|
56469
56719
|
}
|
|
@@ -56471,17 +56721,17 @@ function detectTypecheckCommand(projectDir) {
|
|
|
56471
56721
|
return null;
|
|
56472
56722
|
}
|
|
56473
56723
|
}
|
|
56474
|
-
if (
|
|
56724
|
+
if (fs30.existsSync(path42.join(projectDir, "go.mod"))) {
|
|
56475
56725
|
return { command: ["go", "vet", "./..."], language: "go" };
|
|
56476
56726
|
}
|
|
56477
|
-
if (
|
|
56727
|
+
if (fs30.existsSync(path42.join(projectDir, "Cargo.toml"))) {
|
|
56478
56728
|
return { command: ["cargo", "check"], language: "rust" };
|
|
56479
56729
|
}
|
|
56480
|
-
if (
|
|
56730
|
+
if (fs30.existsSync(path42.join(projectDir, "pyproject.toml")) || fs30.existsSync(path42.join(projectDir, "requirements.txt")) || fs30.existsSync(path42.join(projectDir, "setup.py"))) {
|
|
56481
56731
|
return { command: null, language: "python" };
|
|
56482
56732
|
}
|
|
56483
56733
|
try {
|
|
56484
|
-
const entries =
|
|
56734
|
+
const entries = fs30.readdirSync(projectDir);
|
|
56485
56735
|
if (entries.some((f) => f.endsWith(".csproj") || f.endsWith(".sln"))) {
|
|
56486
56736
|
return {
|
|
56487
56737
|
command: ["dotnet", "build", "--no-restore"],
|
|
@@ -56661,19 +56911,7 @@ function sanitizeLessonForContext(text) {
|
|
|
56661
56911
|
}
|
|
56662
56912
|
function isOrchestratorAgent(agentName) {
|
|
56663
56913
|
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());
|
|
56914
|
+
return stripped.toLowerCase() === "architect";
|
|
56677
56915
|
}
|
|
56678
56916
|
function injectKnowledgeMessage(output, text) {
|
|
56679
56917
|
if (!output.messages)
|
|
@@ -56790,7 +57028,7 @@ ${injectionText}`;
|
|
|
56790
57028
|
// src/hooks/scope-guard.ts
|
|
56791
57029
|
init_constants();
|
|
56792
57030
|
init_schema();
|
|
56793
|
-
import * as
|
|
57031
|
+
import * as path44 from "path";
|
|
56794
57032
|
var WRITE_TOOLS = new Set([
|
|
56795
57033
|
"write",
|
|
56796
57034
|
"edit",
|
|
@@ -56852,13 +57090,13 @@ function createScopeGuardHook(config3, directory, injectAdvisory) {
|
|
|
56852
57090
|
}
|
|
56853
57091
|
function isFileInScope(filePath, scopeEntries, directory) {
|
|
56854
57092
|
const dir = directory ?? process.cwd();
|
|
56855
|
-
const resolvedFile =
|
|
57093
|
+
const resolvedFile = path44.resolve(dir, filePath);
|
|
56856
57094
|
return scopeEntries.some((scope) => {
|
|
56857
|
-
const resolvedScope =
|
|
57095
|
+
const resolvedScope = path44.resolve(dir, scope);
|
|
56858
57096
|
if (resolvedFile === resolvedScope)
|
|
56859
57097
|
return true;
|
|
56860
|
-
const rel =
|
|
56861
|
-
return rel.length > 0 && !rel.startsWith("..") && !
|
|
57098
|
+
const rel = path44.relative(resolvedScope, resolvedFile);
|
|
57099
|
+
return rel.length > 0 && !rel.startsWith("..") && !path44.isAbsolute(rel);
|
|
56862
57100
|
});
|
|
56863
57101
|
}
|
|
56864
57102
|
|
|
@@ -56907,8 +57145,8 @@ function createSelfReviewHook(config3, injectAdvisory) {
|
|
|
56907
57145
|
}
|
|
56908
57146
|
|
|
56909
57147
|
// src/hooks/slop-detector.ts
|
|
56910
|
-
import * as
|
|
56911
|
-
import * as
|
|
57148
|
+
import * as fs32 from "fs";
|
|
57149
|
+
import * as path45 from "path";
|
|
56912
57150
|
var WRITE_EDIT_TOOLS = new Set([
|
|
56913
57151
|
"write",
|
|
56914
57152
|
"edit",
|
|
@@ -56953,12 +57191,12 @@ function checkBoilerplateExplosion(content, taskDescription, threshold) {
|
|
|
56953
57191
|
function walkFiles(dir, exts, deadline) {
|
|
56954
57192
|
const results = [];
|
|
56955
57193
|
try {
|
|
56956
|
-
for (const entry of
|
|
57194
|
+
for (const entry of fs32.readdirSync(dir, { withFileTypes: true })) {
|
|
56957
57195
|
if (deadline !== undefined && Date.now() > deadline)
|
|
56958
57196
|
break;
|
|
56959
57197
|
if (entry.isSymbolicLink())
|
|
56960
57198
|
continue;
|
|
56961
|
-
const full =
|
|
57199
|
+
const full = path45.join(dir, entry.name);
|
|
56962
57200
|
if (entry.isDirectory()) {
|
|
56963
57201
|
if (entry.name === "node_modules" || entry.name === ".git")
|
|
56964
57202
|
continue;
|
|
@@ -56973,7 +57211,7 @@ function walkFiles(dir, exts, deadline) {
|
|
|
56973
57211
|
return results;
|
|
56974
57212
|
}
|
|
56975
57213
|
function checkDeadExports(content, projectDir, startTime) {
|
|
56976
|
-
const hasPackageJson =
|
|
57214
|
+
const hasPackageJson = fs32.existsSync(path45.join(projectDir, "package.json"));
|
|
56977
57215
|
if (!hasPackageJson)
|
|
56978
57216
|
return null;
|
|
56979
57217
|
const exportMatches = content.matchAll(/^\+(?:export)\s+(?:function|class|const|type|interface)\s+(\w{3,})/gm);
|
|
@@ -56996,7 +57234,7 @@ function checkDeadExports(content, projectDir, startTime) {
|
|
|
56996
57234
|
if (found || Date.now() - startTime > 480)
|
|
56997
57235
|
break;
|
|
56998
57236
|
try {
|
|
56999
|
-
const text =
|
|
57237
|
+
const text = fs32.readFileSync(file3, "utf-8");
|
|
57000
57238
|
if (importPattern.test(text))
|
|
57001
57239
|
found = true;
|
|
57002
57240
|
importPattern.lastIndex = 0;
|
|
@@ -57129,7 +57367,7 @@ Review before proceeding.`;
|
|
|
57129
57367
|
|
|
57130
57368
|
// src/hooks/steering-consumed.ts
|
|
57131
57369
|
init_utils2();
|
|
57132
|
-
import * as
|
|
57370
|
+
import * as fs33 from "fs";
|
|
57133
57371
|
function recordSteeringConsumed(directory, directiveId) {
|
|
57134
57372
|
try {
|
|
57135
57373
|
const eventsPath = validateSwarmPath(directory, "events.jsonl");
|
|
@@ -57138,7 +57376,7 @@ function recordSteeringConsumed(directory, directiveId) {
|
|
|
57138
57376
|
directiveId,
|
|
57139
57377
|
timestamp: new Date().toISOString()
|
|
57140
57378
|
};
|
|
57141
|
-
|
|
57379
|
+
fs33.appendFileSync(eventsPath, `${JSON.stringify(event)}
|
|
57142
57380
|
`, "utf-8");
|
|
57143
57381
|
} catch {}
|
|
57144
57382
|
}
|
|
@@ -57183,7 +57421,7 @@ init_config_doctor();
|
|
|
57183
57421
|
|
|
57184
57422
|
// src/session/snapshot-reader.ts
|
|
57185
57423
|
init_utils2();
|
|
57186
|
-
import { renameSync as
|
|
57424
|
+
import { renameSync as renameSync12 } from "fs";
|
|
57187
57425
|
var TRANSIENT_SESSION_FIELDS = [
|
|
57188
57426
|
{ name: "revisionLimitHit", resetValue: false },
|
|
57189
57427
|
{ name: "coderRevisions", resetValue: 0 },
|
|
@@ -57294,7 +57532,7 @@ async function readSnapshot(directory) {
|
|
|
57294
57532
|
if (parsed.version !== 1 && parsed.version !== 2) {
|
|
57295
57533
|
try {
|
|
57296
57534
|
const quarantinePath = validateSwarmPath(directory, "session/state.json.quarantine");
|
|
57297
|
-
|
|
57535
|
+
renameSync12(resolvedPath, quarantinePath);
|
|
57298
57536
|
} catch {}
|
|
57299
57537
|
return null;
|
|
57300
57538
|
}
|
|
@@ -57551,8 +57789,8 @@ init_dist();
|
|
|
57551
57789
|
init_manager();
|
|
57552
57790
|
init_create_tool();
|
|
57553
57791
|
init_resolve_working_directory();
|
|
57554
|
-
import * as
|
|
57555
|
-
import * as
|
|
57792
|
+
import * as fs34 from "fs";
|
|
57793
|
+
import * as path46 from "path";
|
|
57556
57794
|
var EVIDENCE_DIR = ".swarm/evidence";
|
|
57557
57795
|
var TASK_ID_PATTERN2 = /^\d+\.\d+(\.\d+)*$/;
|
|
57558
57796
|
function isValidTaskId3(taskId) {
|
|
@@ -57569,18 +57807,18 @@ function isValidTaskId3(taskId) {
|
|
|
57569
57807
|
return TASK_ID_PATTERN2.test(taskId);
|
|
57570
57808
|
}
|
|
57571
57809
|
function isPathWithinSwarm(filePath, workspaceRoot) {
|
|
57572
|
-
const normalizedWorkspace =
|
|
57573
|
-
const swarmPath =
|
|
57574
|
-
const normalizedPath =
|
|
57810
|
+
const normalizedWorkspace = path46.resolve(workspaceRoot);
|
|
57811
|
+
const swarmPath = path46.join(normalizedWorkspace, ".swarm", "evidence");
|
|
57812
|
+
const normalizedPath = path46.resolve(filePath);
|
|
57575
57813
|
return normalizedPath.startsWith(swarmPath);
|
|
57576
57814
|
}
|
|
57577
57815
|
function readEvidenceFile(evidencePath) {
|
|
57578
|
-
if (!
|
|
57816
|
+
if (!fs34.existsSync(evidencePath)) {
|
|
57579
57817
|
return null;
|
|
57580
57818
|
}
|
|
57581
57819
|
let content;
|
|
57582
57820
|
try {
|
|
57583
|
-
content =
|
|
57821
|
+
content = fs34.readFileSync(evidencePath, "utf-8");
|
|
57584
57822
|
} catch {
|
|
57585
57823
|
return null;
|
|
57586
57824
|
}
|
|
@@ -57652,7 +57890,7 @@ var check_gate_status = createSwarmTool({
|
|
|
57652
57890
|
};
|
|
57653
57891
|
return JSON.stringify(errorResult, null, 2);
|
|
57654
57892
|
}
|
|
57655
|
-
const evidencePath =
|
|
57893
|
+
const evidencePath = path46.join(directory, EVIDENCE_DIR, `${taskIdInput}.json`);
|
|
57656
57894
|
if (!isPathWithinSwarm(evidencePath, directory)) {
|
|
57657
57895
|
const errorResult = {
|
|
57658
57896
|
taskId: taskIdInput,
|
|
@@ -57745,8 +57983,8 @@ init_co_change_analyzer();
|
|
|
57745
57983
|
// src/tools/completion-verify.ts
|
|
57746
57984
|
init_dist();
|
|
57747
57985
|
init_utils2();
|
|
57748
|
-
import * as
|
|
57749
|
-
import * as
|
|
57986
|
+
import * as fs35 from "fs";
|
|
57987
|
+
import * as path47 from "path";
|
|
57750
57988
|
init_create_tool();
|
|
57751
57989
|
init_resolve_working_directory();
|
|
57752
57990
|
function extractMatches(regex, text) {
|
|
@@ -57842,7 +58080,7 @@ async function executeCompletionVerify(args2, directory) {
|
|
|
57842
58080
|
let plan;
|
|
57843
58081
|
try {
|
|
57844
58082
|
const planPath = validateSwarmPath(directory, "plan.json");
|
|
57845
|
-
const planRaw =
|
|
58083
|
+
const planRaw = fs35.readFileSync(planPath, "utf-8");
|
|
57846
58084
|
plan = JSON.parse(planRaw);
|
|
57847
58085
|
} catch {
|
|
57848
58086
|
const result2 = {
|
|
@@ -57900,10 +58138,10 @@ async function executeCompletionVerify(args2, directory) {
|
|
|
57900
58138
|
let hasFileReadFailure = false;
|
|
57901
58139
|
for (const filePath of fileTargets) {
|
|
57902
58140
|
const normalizedPath = filePath.replace(/\\/g, "/");
|
|
57903
|
-
const resolvedPath =
|
|
57904
|
-
const projectRoot =
|
|
57905
|
-
const relative6 =
|
|
57906
|
-
const withinProject = relative6 === "" || !relative6.startsWith("..") && !
|
|
58141
|
+
const resolvedPath = path47.resolve(directory, normalizedPath);
|
|
58142
|
+
const projectRoot = path47.resolve(directory);
|
|
58143
|
+
const relative6 = path47.relative(projectRoot, resolvedPath);
|
|
58144
|
+
const withinProject = relative6 === "" || !relative6.startsWith("..") && !path47.isAbsolute(relative6);
|
|
57907
58145
|
if (!withinProject) {
|
|
57908
58146
|
blockedTasks.push({
|
|
57909
58147
|
task_id: task.id,
|
|
@@ -57916,7 +58154,7 @@ async function executeCompletionVerify(args2, directory) {
|
|
|
57916
58154
|
}
|
|
57917
58155
|
let fileContent;
|
|
57918
58156
|
try {
|
|
57919
|
-
fileContent =
|
|
58157
|
+
fileContent = fs35.readFileSync(resolvedPath, "utf-8");
|
|
57920
58158
|
} catch {
|
|
57921
58159
|
blockedTasks.push({
|
|
57922
58160
|
task_id: task.id,
|
|
@@ -57958,9 +58196,9 @@ async function executeCompletionVerify(args2, directory) {
|
|
|
57958
58196
|
blockedTasks
|
|
57959
58197
|
};
|
|
57960
58198
|
try {
|
|
57961
|
-
const evidenceDir =
|
|
57962
|
-
const evidencePath =
|
|
57963
|
-
|
|
58199
|
+
const evidenceDir = path47.join(directory, ".swarm", "evidence", `${phase}`);
|
|
58200
|
+
const evidencePath = path47.join(evidenceDir, "completion-verify.json");
|
|
58201
|
+
fs35.mkdirSync(evidenceDir, { recursive: true });
|
|
57964
58202
|
const evidenceBundle = {
|
|
57965
58203
|
schema_version: "1.0.0",
|
|
57966
58204
|
task_id: "completion-verify",
|
|
@@ -57981,7 +58219,7 @@ async function executeCompletionVerify(args2, directory) {
|
|
|
57981
58219
|
}
|
|
57982
58220
|
]
|
|
57983
58221
|
};
|
|
57984
|
-
|
|
58222
|
+
fs35.writeFileSync(evidencePath, JSON.stringify(evidenceBundle, null, 2), "utf-8");
|
|
57985
58223
|
} catch {}
|
|
57986
58224
|
return JSON.stringify(result, null, 2);
|
|
57987
58225
|
}
|
|
@@ -58035,12 +58273,12 @@ var completion_verify = createSwarmTool({
|
|
|
58035
58273
|
});
|
|
58036
58274
|
// src/tools/complexity-hotspots.ts
|
|
58037
58275
|
init_dist();
|
|
58038
|
-
import * as
|
|
58039
|
-
import * as
|
|
58276
|
+
import * as fs37 from "fs";
|
|
58277
|
+
import * as path49 from "path";
|
|
58040
58278
|
|
|
58041
58279
|
// src/quality/metrics.ts
|
|
58042
|
-
import * as
|
|
58043
|
-
import * as
|
|
58280
|
+
import * as fs36 from "fs";
|
|
58281
|
+
import * as path48 from "path";
|
|
58044
58282
|
var MAX_FILE_SIZE_BYTES2 = 256 * 1024;
|
|
58045
58283
|
var MIN_DUPLICATION_LINES = 10;
|
|
58046
58284
|
function estimateCyclomaticComplexity(content) {
|
|
@@ -58078,11 +58316,11 @@ function estimateCyclomaticComplexity(content) {
|
|
|
58078
58316
|
}
|
|
58079
58317
|
function getComplexityForFile(filePath) {
|
|
58080
58318
|
try {
|
|
58081
|
-
const stat2 =
|
|
58319
|
+
const stat2 = fs36.statSync(filePath);
|
|
58082
58320
|
if (stat2.size > MAX_FILE_SIZE_BYTES2) {
|
|
58083
58321
|
return null;
|
|
58084
58322
|
}
|
|
58085
|
-
const content =
|
|
58323
|
+
const content = fs36.readFileSync(filePath, "utf-8");
|
|
58086
58324
|
return estimateCyclomaticComplexity(content);
|
|
58087
58325
|
} catch {
|
|
58088
58326
|
return null;
|
|
@@ -58092,8 +58330,8 @@ async function computeComplexityDelta(files, workingDir) {
|
|
|
58092
58330
|
let totalComplexity = 0;
|
|
58093
58331
|
const analyzedFiles = [];
|
|
58094
58332
|
for (const file3 of files) {
|
|
58095
|
-
const fullPath =
|
|
58096
|
-
if (!
|
|
58333
|
+
const fullPath = path48.isAbsolute(file3) ? file3 : path48.join(workingDir, file3);
|
|
58334
|
+
if (!fs36.existsSync(fullPath)) {
|
|
58097
58335
|
continue;
|
|
58098
58336
|
}
|
|
58099
58337
|
const complexity = getComplexityForFile(fullPath);
|
|
@@ -58214,8 +58452,8 @@ function countGoExports(content) {
|
|
|
58214
58452
|
}
|
|
58215
58453
|
function getExportCountForFile(filePath) {
|
|
58216
58454
|
try {
|
|
58217
|
-
const content =
|
|
58218
|
-
const ext =
|
|
58455
|
+
const content = fs36.readFileSync(filePath, "utf-8");
|
|
58456
|
+
const ext = path48.extname(filePath).toLowerCase();
|
|
58219
58457
|
switch (ext) {
|
|
58220
58458
|
case ".ts":
|
|
58221
58459
|
case ".tsx":
|
|
@@ -58241,8 +58479,8 @@ async function computePublicApiDelta(files, workingDir) {
|
|
|
58241
58479
|
let totalExports = 0;
|
|
58242
58480
|
const analyzedFiles = [];
|
|
58243
58481
|
for (const file3 of files) {
|
|
58244
|
-
const fullPath =
|
|
58245
|
-
if (!
|
|
58482
|
+
const fullPath = path48.isAbsolute(file3) ? file3 : path48.join(workingDir, file3);
|
|
58483
|
+
if (!fs36.existsSync(fullPath)) {
|
|
58246
58484
|
continue;
|
|
58247
58485
|
}
|
|
58248
58486
|
const exports = getExportCountForFile(fullPath);
|
|
@@ -58275,16 +58513,16 @@ async function computeDuplicationRatio(files, workingDir) {
|
|
|
58275
58513
|
let duplicateLines = 0;
|
|
58276
58514
|
const analyzedFiles = [];
|
|
58277
58515
|
for (const file3 of files) {
|
|
58278
|
-
const fullPath =
|
|
58279
|
-
if (!
|
|
58516
|
+
const fullPath = path48.isAbsolute(file3) ? file3 : path48.join(workingDir, file3);
|
|
58517
|
+
if (!fs36.existsSync(fullPath)) {
|
|
58280
58518
|
continue;
|
|
58281
58519
|
}
|
|
58282
58520
|
try {
|
|
58283
|
-
const stat2 =
|
|
58521
|
+
const stat2 = fs36.statSync(fullPath);
|
|
58284
58522
|
if (stat2.size > MAX_FILE_SIZE_BYTES2) {
|
|
58285
58523
|
continue;
|
|
58286
58524
|
}
|
|
58287
|
-
const content =
|
|
58525
|
+
const content = fs36.readFileSync(fullPath, "utf-8");
|
|
58288
58526
|
const lines = content.split(`
|
|
58289
58527
|
`).filter((line) => line.trim().length > 0);
|
|
58290
58528
|
if (lines.length < MIN_DUPLICATION_LINES) {
|
|
@@ -58308,8 +58546,8 @@ function countCodeLines(content) {
|
|
|
58308
58546
|
return lines.length;
|
|
58309
58547
|
}
|
|
58310
58548
|
function isTestFile(filePath) {
|
|
58311
|
-
const basename7 =
|
|
58312
|
-
const _ext =
|
|
58549
|
+
const basename7 = path48.basename(filePath);
|
|
58550
|
+
const _ext = path48.extname(filePath).toLowerCase();
|
|
58313
58551
|
const testPatterns = [
|
|
58314
58552
|
".test.",
|
|
58315
58553
|
".spec.",
|
|
@@ -58390,8 +58628,8 @@ function matchGlobSegment(globSegments, pathSegments) {
|
|
|
58390
58628
|
}
|
|
58391
58629
|
return gIndex === globSegments.length && pIndex === pathSegments.length;
|
|
58392
58630
|
}
|
|
58393
|
-
function matchesGlobSegment(
|
|
58394
|
-
const normalizedPath =
|
|
58631
|
+
function matchesGlobSegment(path49, glob) {
|
|
58632
|
+
const normalizedPath = path49.replace(/\\/g, "/");
|
|
58395
58633
|
const normalizedGlob = glob.replace(/\\/g, "/");
|
|
58396
58634
|
if (normalizedPath.includes("//")) {
|
|
58397
58635
|
return false;
|
|
@@ -58422,8 +58660,8 @@ function simpleGlobToRegex2(glob) {
|
|
|
58422
58660
|
function hasGlobstar(glob) {
|
|
58423
58661
|
return glob.includes("**");
|
|
58424
58662
|
}
|
|
58425
|
-
function globMatches(
|
|
58426
|
-
const normalizedPath =
|
|
58663
|
+
function globMatches(path49, glob) {
|
|
58664
|
+
const normalizedPath = path49.replace(/\\/g, "/");
|
|
58427
58665
|
if (!glob || glob === "") {
|
|
58428
58666
|
if (normalizedPath.includes("//")) {
|
|
58429
58667
|
return false;
|
|
@@ -58459,31 +58697,31 @@ function shouldExcludeFile(filePath, excludeGlobs) {
|
|
|
58459
58697
|
async function computeTestToCodeRatio(workingDir, enforceGlobs, excludeGlobs) {
|
|
58460
58698
|
let testLines = 0;
|
|
58461
58699
|
let codeLines = 0;
|
|
58462
|
-
const srcDir =
|
|
58463
|
-
if (
|
|
58700
|
+
const srcDir = path48.join(workingDir, "src");
|
|
58701
|
+
if (fs36.existsSync(srcDir)) {
|
|
58464
58702
|
await scanDirectoryForLines(srcDir, enforceGlobs, excludeGlobs, false, (lines) => {
|
|
58465
58703
|
codeLines += lines;
|
|
58466
58704
|
});
|
|
58467
58705
|
}
|
|
58468
58706
|
const possibleSrcDirs = ["lib", "app", "source", "core"];
|
|
58469
58707
|
for (const dir of possibleSrcDirs) {
|
|
58470
|
-
const dirPath =
|
|
58471
|
-
if (
|
|
58708
|
+
const dirPath = path48.join(workingDir, dir);
|
|
58709
|
+
if (fs36.existsSync(dirPath)) {
|
|
58472
58710
|
await scanDirectoryForLines(dirPath, enforceGlobs, excludeGlobs, false, (lines) => {
|
|
58473
58711
|
codeLines += lines;
|
|
58474
58712
|
});
|
|
58475
58713
|
}
|
|
58476
58714
|
}
|
|
58477
|
-
const testsDir =
|
|
58478
|
-
if (
|
|
58715
|
+
const testsDir = path48.join(workingDir, "tests");
|
|
58716
|
+
if (fs36.existsSync(testsDir)) {
|
|
58479
58717
|
await scanDirectoryForLines(testsDir, ["**"], ["node_modules", "dist"], true, (lines) => {
|
|
58480
58718
|
testLines += lines;
|
|
58481
58719
|
});
|
|
58482
58720
|
}
|
|
58483
58721
|
const possibleTestDirs = ["test", "__tests__", "specs"];
|
|
58484
58722
|
for (const dir of possibleTestDirs) {
|
|
58485
|
-
const dirPath =
|
|
58486
|
-
if (
|
|
58723
|
+
const dirPath = path48.join(workingDir, dir);
|
|
58724
|
+
if (fs36.existsSync(dirPath) && dirPath !== testsDir) {
|
|
58487
58725
|
await scanDirectoryForLines(dirPath, ["**"], ["node_modules", "dist"], true, (lines) => {
|
|
58488
58726
|
testLines += lines;
|
|
58489
58727
|
});
|
|
@@ -58495,9 +58733,9 @@ async function computeTestToCodeRatio(workingDir, enforceGlobs, excludeGlobs) {
|
|
|
58495
58733
|
}
|
|
58496
58734
|
async function scanDirectoryForLines(dirPath, includeGlobs, excludeGlobs, isTestScan, callback) {
|
|
58497
58735
|
try {
|
|
58498
|
-
const entries =
|
|
58736
|
+
const entries = fs36.readdirSync(dirPath, { withFileTypes: true });
|
|
58499
58737
|
for (const entry of entries) {
|
|
58500
|
-
const fullPath =
|
|
58738
|
+
const fullPath = path48.join(dirPath, entry.name);
|
|
58501
58739
|
if (entry.isDirectory()) {
|
|
58502
58740
|
if (entry.name === "node_modules" || entry.name === "dist" || entry.name === "build" || entry.name === ".git") {
|
|
58503
58741
|
continue;
|
|
@@ -58505,7 +58743,7 @@ async function scanDirectoryForLines(dirPath, includeGlobs, excludeGlobs, isTest
|
|
|
58505
58743
|
await scanDirectoryForLines(fullPath, includeGlobs, excludeGlobs, isTestScan, callback);
|
|
58506
58744
|
} else if (entry.isFile()) {
|
|
58507
58745
|
const relativePath = fullPath.replace(`${dirPath}/`, "");
|
|
58508
|
-
const ext =
|
|
58746
|
+
const ext = path48.extname(entry.name).toLowerCase();
|
|
58509
58747
|
const validExts = [
|
|
58510
58748
|
".ts",
|
|
58511
58749
|
".tsx",
|
|
@@ -58541,7 +58779,7 @@ async function scanDirectoryForLines(dirPath, includeGlobs, excludeGlobs, isTest
|
|
|
58541
58779
|
continue;
|
|
58542
58780
|
}
|
|
58543
58781
|
try {
|
|
58544
|
-
const content =
|
|
58782
|
+
const content = fs36.readFileSync(fullPath, "utf-8");
|
|
58545
58783
|
const lines = countCodeLines(content);
|
|
58546
58784
|
callback(lines);
|
|
58547
58785
|
} catch {}
|
|
@@ -58742,11 +58980,11 @@ async function getGitChurn(days, directory) {
|
|
|
58742
58980
|
}
|
|
58743
58981
|
function getComplexityForFile2(filePath) {
|
|
58744
58982
|
try {
|
|
58745
|
-
const stat2 =
|
|
58983
|
+
const stat2 = fs37.statSync(filePath);
|
|
58746
58984
|
if (stat2.size > MAX_FILE_SIZE_BYTES3) {
|
|
58747
58985
|
return null;
|
|
58748
58986
|
}
|
|
58749
|
-
const content =
|
|
58987
|
+
const content = fs37.readFileSync(filePath, "utf-8");
|
|
58750
58988
|
return estimateCyclomaticComplexity(content);
|
|
58751
58989
|
} catch {
|
|
58752
58990
|
return null;
|
|
@@ -58757,7 +58995,7 @@ async function analyzeHotspots(days, topN, extensions, directory) {
|
|
|
58757
58995
|
const extSet = new Set(extensions.map((e) => e.startsWith(".") ? e : `.${e}`));
|
|
58758
58996
|
const filteredChurn = new Map;
|
|
58759
58997
|
for (const [file3, count] of churnMap) {
|
|
58760
|
-
const ext =
|
|
58998
|
+
const ext = path49.extname(file3).toLowerCase();
|
|
58761
58999
|
if (extSet.has(ext)) {
|
|
58762
59000
|
filteredChurn.set(file3, count);
|
|
58763
59001
|
}
|
|
@@ -58767,8 +59005,8 @@ async function analyzeHotspots(days, topN, extensions, directory) {
|
|
|
58767
59005
|
let analyzedFiles = 0;
|
|
58768
59006
|
for (const [file3, churnCount] of filteredChurn) {
|
|
58769
59007
|
let fullPath = file3;
|
|
58770
|
-
if (!
|
|
58771
|
-
fullPath =
|
|
59008
|
+
if (!fs37.existsSync(fullPath)) {
|
|
59009
|
+
fullPath = path49.join(cwd, file3);
|
|
58772
59010
|
}
|
|
58773
59011
|
const complexity = getComplexityForFile2(fullPath);
|
|
58774
59012
|
if (complexity !== null) {
|
|
@@ -58917,6 +59155,7 @@ var complexity_hotspots = createSwarmTool({
|
|
|
58917
59155
|
init_dist();
|
|
58918
59156
|
init_config();
|
|
58919
59157
|
init_schema();
|
|
59158
|
+
init_review_receipt();
|
|
58920
59159
|
init_create_tool();
|
|
58921
59160
|
var curator_analyze = createSwarmTool({
|
|
58922
59161
|
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 +59191,40 @@ var curator_analyze = createSwarmTool({
|
|
|
58952
59191
|
const { config: config3 } = loadPluginConfigWithMeta(directory);
|
|
58953
59192
|
const curatorConfig = CuratorConfigSchema.parse(config3.curator ?? {});
|
|
58954
59193
|
const knowledgeConfig = KnowledgeConfigSchema.parse(config3.knowledge ?? {});
|
|
58955
|
-
const
|
|
59194
|
+
const llmDelegate = createCuratorLLMDelegate(directory);
|
|
59195
|
+
const curatorResult = await runCuratorPhase(directory, typedArgs.phase, [], curatorConfig, {}, llmDelegate);
|
|
59196
|
+
{
|
|
59197
|
+
const scopeContent = curatorResult.digest?.summary ?? `Phase ${typedArgs.phase} curator analysis`;
|
|
59198
|
+
const complianceWarnings = curatorResult.compliance.filter((c) => c.severity === "warning");
|
|
59199
|
+
const receipt = complianceWarnings.length > 0 ? buildRejectedReceipt({
|
|
59200
|
+
agent: "curator",
|
|
59201
|
+
scopeContent,
|
|
59202
|
+
scopeDescription: "phase-digest",
|
|
59203
|
+
blockingFindings: complianceWarnings.map((c) => ({
|
|
59204
|
+
location: `phase-${c.phase}`,
|
|
59205
|
+
summary: c.description,
|
|
59206
|
+
severity: c.type === "missing_reviewer" ? "high" : "medium"
|
|
59207
|
+
})),
|
|
59208
|
+
evidenceReferences: [],
|
|
59209
|
+
passConditions: [
|
|
59210
|
+
"resolve all compliance warnings before phase completion"
|
|
59211
|
+
]
|
|
59212
|
+
}) : buildApprovedReceipt({
|
|
59213
|
+
agent: "curator",
|
|
59214
|
+
scopeContent,
|
|
59215
|
+
scopeDescription: "phase-digest",
|
|
59216
|
+
checkedAspects: [
|
|
59217
|
+
"phase_compliance",
|
|
59218
|
+
"knowledge_recommendations",
|
|
59219
|
+
"phase_digest"
|
|
59220
|
+
],
|
|
59221
|
+
validatedClaims: [
|
|
59222
|
+
`phase: ${typedArgs.phase}`,
|
|
59223
|
+
`knowledge_recommendations: ${curatorResult.knowledge_recommendations.length}`
|
|
59224
|
+
]
|
|
59225
|
+
});
|
|
59226
|
+
persistReviewReceipt(directory, receipt).catch(() => {});
|
|
59227
|
+
}
|
|
58956
59228
|
let applied = 0;
|
|
58957
59229
|
let skipped = 0;
|
|
58958
59230
|
if (typedArgs.recommendations && typedArgs.recommendations.length > 0) {
|
|
@@ -58976,8 +59248,8 @@ var curator_analyze = createSwarmTool({
|
|
|
58976
59248
|
});
|
|
58977
59249
|
// src/tools/declare-scope.ts
|
|
58978
59250
|
init_tool();
|
|
58979
|
-
import * as
|
|
58980
|
-
import * as
|
|
59251
|
+
import * as fs38 from "fs";
|
|
59252
|
+
import * as path50 from "path";
|
|
58981
59253
|
init_create_tool();
|
|
58982
59254
|
function validateTaskIdFormat(taskId) {
|
|
58983
59255
|
const taskIdPattern = /^\d+\.\d+(\.\d+)*$/;
|
|
@@ -59056,8 +59328,8 @@ async function executeDeclareScope(args2, fallbackDir) {
|
|
|
59056
59328
|
};
|
|
59057
59329
|
}
|
|
59058
59330
|
}
|
|
59059
|
-
normalizedDir =
|
|
59060
|
-
const pathParts = normalizedDir.split(
|
|
59331
|
+
normalizedDir = path50.normalize(args2.working_directory);
|
|
59332
|
+
const pathParts = normalizedDir.split(path50.sep);
|
|
59061
59333
|
if (pathParts.includes("..")) {
|
|
59062
59334
|
return {
|
|
59063
59335
|
success: false,
|
|
@@ -59067,11 +59339,11 @@ async function executeDeclareScope(args2, fallbackDir) {
|
|
|
59067
59339
|
]
|
|
59068
59340
|
};
|
|
59069
59341
|
}
|
|
59070
|
-
const resolvedDir =
|
|
59342
|
+
const resolvedDir = path50.resolve(normalizedDir);
|
|
59071
59343
|
try {
|
|
59072
|
-
const realPath =
|
|
59073
|
-
const planPath2 =
|
|
59074
|
-
if (!
|
|
59344
|
+
const realPath = fs38.realpathSync(resolvedDir);
|
|
59345
|
+
const planPath2 = path50.join(realPath, ".swarm", "plan.json");
|
|
59346
|
+
if (!fs38.existsSync(planPath2)) {
|
|
59075
59347
|
return {
|
|
59076
59348
|
success: false,
|
|
59077
59349
|
message: `Invalid working_directory: plan not found in "${realPath}"`,
|
|
@@ -59094,8 +59366,8 @@ async function executeDeclareScope(args2, fallbackDir) {
|
|
|
59094
59366
|
console.warn("[declare-scope] fallbackDir is undefined, falling back to process.cwd()");
|
|
59095
59367
|
}
|
|
59096
59368
|
const directory = normalizedDir || fallbackDir;
|
|
59097
|
-
const planPath =
|
|
59098
|
-
if (!
|
|
59369
|
+
const planPath = path50.resolve(directory, ".swarm", "plan.json");
|
|
59370
|
+
if (!fs38.existsSync(planPath)) {
|
|
59099
59371
|
return {
|
|
59100
59372
|
success: false,
|
|
59101
59373
|
message: "No plan found",
|
|
@@ -59104,7 +59376,7 @@ async function executeDeclareScope(args2, fallbackDir) {
|
|
|
59104
59376
|
}
|
|
59105
59377
|
let planContent;
|
|
59106
59378
|
try {
|
|
59107
|
-
planContent = JSON.parse(
|
|
59379
|
+
planContent = JSON.parse(fs38.readFileSync(planPath, "utf-8"));
|
|
59108
59380
|
} catch {
|
|
59109
59381
|
return {
|
|
59110
59382
|
success: false,
|
|
@@ -59136,8 +59408,8 @@ async function executeDeclareScope(args2, fallbackDir) {
|
|
|
59136
59408
|
const normalizeErrors = [];
|
|
59137
59409
|
const dir = normalizedDir || fallbackDir || process.cwd();
|
|
59138
59410
|
const mergedFiles = rawMergedFiles.map((file3) => {
|
|
59139
|
-
if (
|
|
59140
|
-
const relativePath =
|
|
59411
|
+
if (path50.isAbsolute(file3)) {
|
|
59412
|
+
const relativePath = path50.relative(dir, file3).replace(/\\/g, "/");
|
|
59141
59413
|
if (relativePath.startsWith("..")) {
|
|
59142
59414
|
normalizeErrors.push(`Path '${file3}' resolves outside the project directory`);
|
|
59143
59415
|
return file3;
|
|
@@ -59463,20 +59735,20 @@ function validateBase(base) {
|
|
|
59463
59735
|
function validatePaths(paths) {
|
|
59464
59736
|
if (!paths)
|
|
59465
59737
|
return null;
|
|
59466
|
-
for (const
|
|
59467
|
-
if (!
|
|
59738
|
+
for (const path52 of paths) {
|
|
59739
|
+
if (!path52 || path52.length === 0) {
|
|
59468
59740
|
return "empty path not allowed";
|
|
59469
59741
|
}
|
|
59470
|
-
if (
|
|
59742
|
+
if (path52.length > MAX_PATH_LENGTH) {
|
|
59471
59743
|
return `path exceeds maximum length of ${MAX_PATH_LENGTH}`;
|
|
59472
59744
|
}
|
|
59473
|
-
if (SHELL_METACHARACTERS2.test(
|
|
59745
|
+
if (SHELL_METACHARACTERS2.test(path52)) {
|
|
59474
59746
|
return "path contains shell metacharacters";
|
|
59475
59747
|
}
|
|
59476
|
-
if (
|
|
59748
|
+
if (path52.startsWith("-")) {
|
|
59477
59749
|
return 'path cannot start with "-" (option-like arguments not allowed)';
|
|
59478
59750
|
}
|
|
59479
|
-
if (CONTROL_CHAR_PATTERN2.test(
|
|
59751
|
+
if (CONTROL_CHAR_PATTERN2.test(path52)) {
|
|
59480
59752
|
return "path contains control characters";
|
|
59481
59753
|
}
|
|
59482
59754
|
}
|
|
@@ -59557,8 +59829,8 @@ var diff = createSwarmTool({
|
|
|
59557
59829
|
if (parts2.length >= 3) {
|
|
59558
59830
|
const additions = parseInt(parts2[0], 10) || 0;
|
|
59559
59831
|
const deletions = parseInt(parts2[1], 10) || 0;
|
|
59560
|
-
const
|
|
59561
|
-
files.push({ path:
|
|
59832
|
+
const path52 = parts2[2];
|
|
59833
|
+
files.push({ path: path52, additions, deletions });
|
|
59562
59834
|
}
|
|
59563
59835
|
}
|
|
59564
59836
|
const contractChanges = [];
|
|
@@ -59840,8 +60112,8 @@ Use these as DOMAIN values when delegating to @sme.`;
|
|
|
59840
60112
|
// src/tools/evidence-check.ts
|
|
59841
60113
|
init_dist();
|
|
59842
60114
|
init_create_tool();
|
|
59843
|
-
import * as
|
|
59844
|
-
import * as
|
|
60115
|
+
import * as fs39 from "fs";
|
|
60116
|
+
import * as path52 from "path";
|
|
59845
60117
|
var MAX_FILE_SIZE_BYTES4 = 1024 * 1024;
|
|
59846
60118
|
var MAX_EVIDENCE_FILES = 1000;
|
|
59847
60119
|
var EVIDENCE_DIR2 = ".swarm/evidence";
|
|
@@ -59868,9 +60140,9 @@ function validateRequiredTypes(input) {
|
|
|
59868
60140
|
return null;
|
|
59869
60141
|
}
|
|
59870
60142
|
function isPathWithinSwarm2(filePath, cwd) {
|
|
59871
|
-
const normalizedCwd =
|
|
59872
|
-
const swarmPath =
|
|
59873
|
-
const normalizedPath =
|
|
60143
|
+
const normalizedCwd = path52.resolve(cwd);
|
|
60144
|
+
const swarmPath = path52.join(normalizedCwd, ".swarm");
|
|
60145
|
+
const normalizedPath = path52.resolve(filePath);
|
|
59874
60146
|
return normalizedPath.startsWith(swarmPath);
|
|
59875
60147
|
}
|
|
59876
60148
|
function parseCompletedTasks(planContent) {
|
|
@@ -59886,12 +60158,12 @@ function parseCompletedTasks(planContent) {
|
|
|
59886
60158
|
}
|
|
59887
60159
|
function readEvidenceFiles(evidenceDir, _cwd) {
|
|
59888
60160
|
const evidence = [];
|
|
59889
|
-
if (!
|
|
60161
|
+
if (!fs39.existsSync(evidenceDir) || !fs39.statSync(evidenceDir).isDirectory()) {
|
|
59890
60162
|
return evidence;
|
|
59891
60163
|
}
|
|
59892
60164
|
let files;
|
|
59893
60165
|
try {
|
|
59894
|
-
files =
|
|
60166
|
+
files = fs39.readdirSync(evidenceDir);
|
|
59895
60167
|
} catch {
|
|
59896
60168
|
return evidence;
|
|
59897
60169
|
}
|
|
@@ -59900,14 +60172,14 @@ function readEvidenceFiles(evidenceDir, _cwd) {
|
|
|
59900
60172
|
if (!VALID_EVIDENCE_FILENAME_REGEX.test(filename)) {
|
|
59901
60173
|
continue;
|
|
59902
60174
|
}
|
|
59903
|
-
const filePath =
|
|
60175
|
+
const filePath = path52.join(evidenceDir, filename);
|
|
59904
60176
|
try {
|
|
59905
|
-
const resolvedPath =
|
|
59906
|
-
const evidenceDirResolved =
|
|
60177
|
+
const resolvedPath = path52.resolve(filePath);
|
|
60178
|
+
const evidenceDirResolved = path52.resolve(evidenceDir);
|
|
59907
60179
|
if (!resolvedPath.startsWith(evidenceDirResolved)) {
|
|
59908
60180
|
continue;
|
|
59909
60181
|
}
|
|
59910
|
-
const stat2 =
|
|
60182
|
+
const stat2 = fs39.lstatSync(filePath);
|
|
59911
60183
|
if (!stat2.isFile()) {
|
|
59912
60184
|
continue;
|
|
59913
60185
|
}
|
|
@@ -59916,7 +60188,7 @@ function readEvidenceFiles(evidenceDir, _cwd) {
|
|
|
59916
60188
|
}
|
|
59917
60189
|
let fileStat;
|
|
59918
60190
|
try {
|
|
59919
|
-
fileStat =
|
|
60191
|
+
fileStat = fs39.statSync(filePath);
|
|
59920
60192
|
if (fileStat.size > MAX_FILE_SIZE_BYTES4) {
|
|
59921
60193
|
continue;
|
|
59922
60194
|
}
|
|
@@ -59925,7 +60197,7 @@ function readEvidenceFiles(evidenceDir, _cwd) {
|
|
|
59925
60197
|
}
|
|
59926
60198
|
let content;
|
|
59927
60199
|
try {
|
|
59928
|
-
content =
|
|
60200
|
+
content = fs39.readFileSync(filePath, "utf-8");
|
|
59929
60201
|
} catch {
|
|
59930
60202
|
continue;
|
|
59931
60203
|
}
|
|
@@ -60021,7 +60293,7 @@ var evidence_check = createSwarmTool({
|
|
|
60021
60293
|
return JSON.stringify(errorResult, null, 2);
|
|
60022
60294
|
}
|
|
60023
60295
|
const requiredTypes = requiredTypesValue.split(",").map((t) => t.trim()).filter((t) => t.length > 0).map(normalizeEvidenceType);
|
|
60024
|
-
const planPath =
|
|
60296
|
+
const planPath = path52.join(cwd, PLAN_FILE);
|
|
60025
60297
|
if (!isPathWithinSwarm2(planPath, cwd)) {
|
|
60026
60298
|
const errorResult = {
|
|
60027
60299
|
error: "plan file path validation failed",
|
|
@@ -60035,7 +60307,7 @@ var evidence_check = createSwarmTool({
|
|
|
60035
60307
|
}
|
|
60036
60308
|
let planContent;
|
|
60037
60309
|
try {
|
|
60038
|
-
planContent =
|
|
60310
|
+
planContent = fs39.readFileSync(planPath, "utf-8");
|
|
60039
60311
|
} catch {
|
|
60040
60312
|
const result2 = {
|
|
60041
60313
|
message: "No completed tasks found in plan.",
|
|
@@ -60053,7 +60325,7 @@ var evidence_check = createSwarmTool({
|
|
|
60053
60325
|
};
|
|
60054
60326
|
return JSON.stringify(result2, null, 2);
|
|
60055
60327
|
}
|
|
60056
|
-
const evidenceDir =
|
|
60328
|
+
const evidenceDir = path52.join(cwd, EVIDENCE_DIR2);
|
|
60057
60329
|
const evidence = readEvidenceFiles(evidenceDir, cwd);
|
|
60058
60330
|
const { tasksWithFullEvidence, gaps } = analyzeGaps(completedTasks, evidence, requiredTypes);
|
|
60059
60331
|
const completeness = completedTasks.length > 0 ? Math.round(tasksWithFullEvidence.length / completedTasks.length * 100) / 100 : 1;
|
|
@@ -60070,8 +60342,8 @@ var evidence_check = createSwarmTool({
|
|
|
60070
60342
|
// src/tools/file-extractor.ts
|
|
60071
60343
|
init_tool();
|
|
60072
60344
|
init_create_tool();
|
|
60073
|
-
import * as
|
|
60074
|
-
import * as
|
|
60345
|
+
import * as fs40 from "fs";
|
|
60346
|
+
import * as path53 from "path";
|
|
60075
60347
|
var EXT_MAP = {
|
|
60076
60348
|
python: ".py",
|
|
60077
60349
|
py: ".py",
|
|
@@ -60133,8 +60405,8 @@ var extract_code_blocks = createSwarmTool({
|
|
|
60133
60405
|
execute: async (args2, directory) => {
|
|
60134
60406
|
const { content, output_dir, prefix } = args2;
|
|
60135
60407
|
const targetDir = output_dir || directory;
|
|
60136
|
-
if (!
|
|
60137
|
-
|
|
60408
|
+
if (!fs40.existsSync(targetDir)) {
|
|
60409
|
+
fs40.mkdirSync(targetDir, { recursive: true });
|
|
60138
60410
|
}
|
|
60139
60411
|
if (!content) {
|
|
60140
60412
|
return "Error: content is required";
|
|
@@ -60152,16 +60424,16 @@ var extract_code_blocks = createSwarmTool({
|
|
|
60152
60424
|
if (prefix) {
|
|
60153
60425
|
filename = `${prefix}_${filename}`;
|
|
60154
60426
|
}
|
|
60155
|
-
let filepath =
|
|
60156
|
-
const base =
|
|
60157
|
-
const ext =
|
|
60427
|
+
let filepath = path53.join(targetDir, filename);
|
|
60428
|
+
const base = path53.basename(filepath, path53.extname(filepath));
|
|
60429
|
+
const ext = path53.extname(filepath);
|
|
60158
60430
|
let counter = 1;
|
|
60159
|
-
while (
|
|
60160
|
-
filepath =
|
|
60431
|
+
while (fs40.existsSync(filepath)) {
|
|
60432
|
+
filepath = path53.join(targetDir, `${base}_${counter}${ext}`);
|
|
60161
60433
|
counter++;
|
|
60162
60434
|
}
|
|
60163
60435
|
try {
|
|
60164
|
-
|
|
60436
|
+
fs40.writeFileSync(filepath, code.trim(), "utf-8");
|
|
60165
60437
|
savedFiles.push(filepath);
|
|
60166
60438
|
} catch (error93) {
|
|
60167
60439
|
errors5.push(`Failed to save ${filename}: ${error93 instanceof Error ? error93.message : String(error93)}`);
|
|
@@ -60277,8 +60549,8 @@ var gitingest = createSwarmTool({
|
|
|
60277
60549
|
// src/tools/imports.ts
|
|
60278
60550
|
init_dist();
|
|
60279
60551
|
init_create_tool();
|
|
60280
|
-
import * as
|
|
60281
|
-
import * as
|
|
60552
|
+
import * as fs41 from "fs";
|
|
60553
|
+
import * as path54 from "path";
|
|
60282
60554
|
var MAX_FILE_PATH_LENGTH2 = 500;
|
|
60283
60555
|
var MAX_SYMBOL_LENGTH = 256;
|
|
60284
60556
|
var MAX_FILE_SIZE_BYTES5 = 1024 * 1024;
|
|
@@ -60326,7 +60598,7 @@ function validateSymbolInput(symbol3) {
|
|
|
60326
60598
|
return null;
|
|
60327
60599
|
}
|
|
60328
60600
|
function isBinaryFile2(filePath, buffer) {
|
|
60329
|
-
const ext =
|
|
60601
|
+
const ext = path54.extname(filePath).toLowerCase();
|
|
60330
60602
|
if (ext === ".json" || ext === ".md" || ext === ".txt") {
|
|
60331
60603
|
return false;
|
|
60332
60604
|
}
|
|
@@ -60350,15 +60622,15 @@ function parseImports(content, targetFile, targetSymbol) {
|
|
|
60350
60622
|
const imports = [];
|
|
60351
60623
|
let _resolvedTarget;
|
|
60352
60624
|
try {
|
|
60353
|
-
_resolvedTarget =
|
|
60625
|
+
_resolvedTarget = path54.resolve(targetFile);
|
|
60354
60626
|
} catch {
|
|
60355
60627
|
_resolvedTarget = targetFile;
|
|
60356
60628
|
}
|
|
60357
|
-
const targetBasename =
|
|
60629
|
+
const targetBasename = path54.basename(targetFile, path54.extname(targetFile));
|
|
60358
60630
|
const targetWithExt = targetFile;
|
|
60359
60631
|
const targetWithoutExt = targetFile.replace(/\.(ts|tsx|js|jsx|mjs|cjs)$/i, "");
|
|
60360
|
-
const normalizedTargetWithExt =
|
|
60361
|
-
const normalizedTargetWithoutExt =
|
|
60632
|
+
const normalizedTargetWithExt = path54.normalize(targetWithExt).replace(/\\/g, "/");
|
|
60633
|
+
const normalizedTargetWithoutExt = path54.normalize(targetWithoutExt).replace(/\\/g, "/");
|
|
60362
60634
|
const importRegex = /import\s+(?:\{[\s\S]*?\}|(?:\*\s+as\s+\w+)|\w+)\s+from\s+['"`]([^'"`]+)['"`]|import\s+['"`]([^'"`]+)['"`]|require\s*\(\s*['"`]([^'"`]+)['"`]\s*\)/g;
|
|
60363
60635
|
for (let match = importRegex.exec(content);match !== null; match = importRegex.exec(content)) {
|
|
60364
60636
|
const modulePath = match[1] || match[2] || match[3];
|
|
@@ -60381,9 +60653,9 @@ function parseImports(content, targetFile, targetSymbol) {
|
|
|
60381
60653
|
}
|
|
60382
60654
|
const _normalizedModule = modulePath.replace(/^\.\//, "").replace(/^\.\.\\/, "../");
|
|
60383
60655
|
let isMatch = false;
|
|
60384
|
-
const _targetDir =
|
|
60385
|
-
const targetExt =
|
|
60386
|
-
const targetBasenameNoExt =
|
|
60656
|
+
const _targetDir = path54.dirname(targetFile);
|
|
60657
|
+
const targetExt = path54.extname(targetFile);
|
|
60658
|
+
const targetBasenameNoExt = path54.basename(targetFile, targetExt);
|
|
60387
60659
|
const moduleNormalized = modulePath.replace(/\\/g, "/").replace(/^\.\//, "");
|
|
60388
60660
|
const moduleName = modulePath.split(/[/\\]/).pop() || "";
|
|
60389
60661
|
const moduleNameNoExt = moduleName.replace(/\.(ts|tsx|js|jsx|mjs|cjs)$/i, "");
|
|
@@ -60440,7 +60712,7 @@ var SKIP_DIRECTORIES3 = new Set([
|
|
|
60440
60712
|
function findSourceFiles(dir, files = [], stats = { skippedDirs: [], skippedFiles: 0, fileErrors: [] }) {
|
|
60441
60713
|
let entries;
|
|
60442
60714
|
try {
|
|
60443
|
-
entries =
|
|
60715
|
+
entries = fs41.readdirSync(dir);
|
|
60444
60716
|
} catch (e) {
|
|
60445
60717
|
stats.fileErrors.push({
|
|
60446
60718
|
path: dir,
|
|
@@ -60451,13 +60723,13 @@ function findSourceFiles(dir, files = [], stats = { skippedDirs: [], skippedFile
|
|
|
60451
60723
|
entries.sort((a, b) => a.toLowerCase().localeCompare(b.toLowerCase()));
|
|
60452
60724
|
for (const entry of entries) {
|
|
60453
60725
|
if (SKIP_DIRECTORIES3.has(entry)) {
|
|
60454
|
-
stats.skippedDirs.push(
|
|
60726
|
+
stats.skippedDirs.push(path54.join(dir, entry));
|
|
60455
60727
|
continue;
|
|
60456
60728
|
}
|
|
60457
|
-
const fullPath =
|
|
60729
|
+
const fullPath = path54.join(dir, entry);
|
|
60458
60730
|
let stat2;
|
|
60459
60731
|
try {
|
|
60460
|
-
stat2 =
|
|
60732
|
+
stat2 = fs41.statSync(fullPath);
|
|
60461
60733
|
} catch (e) {
|
|
60462
60734
|
stats.fileErrors.push({
|
|
60463
60735
|
path: fullPath,
|
|
@@ -60468,7 +60740,7 @@ function findSourceFiles(dir, files = [], stats = { skippedDirs: [], skippedFile
|
|
|
60468
60740
|
if (stat2.isDirectory()) {
|
|
60469
60741
|
findSourceFiles(fullPath, files, stats);
|
|
60470
60742
|
} else if (stat2.isFile()) {
|
|
60471
|
-
const ext =
|
|
60743
|
+
const ext = path54.extname(fullPath).toLowerCase();
|
|
60472
60744
|
if (SUPPORTED_EXTENSIONS.includes(ext)) {
|
|
60473
60745
|
files.push(fullPath);
|
|
60474
60746
|
}
|
|
@@ -60525,8 +60797,8 @@ var imports = createSwarmTool({
|
|
|
60525
60797
|
return JSON.stringify(errorResult, null, 2);
|
|
60526
60798
|
}
|
|
60527
60799
|
try {
|
|
60528
|
-
const targetFile =
|
|
60529
|
-
if (!
|
|
60800
|
+
const targetFile = path54.resolve(file3);
|
|
60801
|
+
if (!fs41.existsSync(targetFile)) {
|
|
60530
60802
|
const errorResult = {
|
|
60531
60803
|
error: `target file not found: ${file3}`,
|
|
60532
60804
|
target: file3,
|
|
@@ -60536,7 +60808,7 @@ var imports = createSwarmTool({
|
|
|
60536
60808
|
};
|
|
60537
60809
|
return JSON.stringify(errorResult, null, 2);
|
|
60538
60810
|
}
|
|
60539
|
-
const targetStat =
|
|
60811
|
+
const targetStat = fs41.statSync(targetFile);
|
|
60540
60812
|
if (!targetStat.isFile()) {
|
|
60541
60813
|
const errorResult = {
|
|
60542
60814
|
error: "target must be a file, not a directory",
|
|
@@ -60547,7 +60819,7 @@ var imports = createSwarmTool({
|
|
|
60547
60819
|
};
|
|
60548
60820
|
return JSON.stringify(errorResult, null, 2);
|
|
60549
60821
|
}
|
|
60550
|
-
const baseDir =
|
|
60822
|
+
const baseDir = path54.dirname(targetFile);
|
|
60551
60823
|
const scanStats = {
|
|
60552
60824
|
skippedDirs: [],
|
|
60553
60825
|
skippedFiles: 0,
|
|
@@ -60562,12 +60834,12 @@ var imports = createSwarmTool({
|
|
|
60562
60834
|
if (consumers.length >= MAX_CONSUMERS)
|
|
60563
60835
|
break;
|
|
60564
60836
|
try {
|
|
60565
|
-
const stat2 =
|
|
60837
|
+
const stat2 = fs41.statSync(filePath);
|
|
60566
60838
|
if (stat2.size > MAX_FILE_SIZE_BYTES5) {
|
|
60567
60839
|
skippedFileCount++;
|
|
60568
60840
|
continue;
|
|
60569
60841
|
}
|
|
60570
|
-
const buffer =
|
|
60842
|
+
const buffer = fs41.readFileSync(filePath);
|
|
60571
60843
|
if (isBinaryFile2(filePath, buffer)) {
|
|
60572
60844
|
skippedFileCount++;
|
|
60573
60845
|
continue;
|
|
@@ -60634,7 +60906,7 @@ var imports = createSwarmTool({
|
|
|
60634
60906
|
init_dist();
|
|
60635
60907
|
init_config();
|
|
60636
60908
|
init_knowledge_store();
|
|
60637
|
-
import { randomUUID as
|
|
60909
|
+
import { randomUUID as randomUUID5 } from "crypto";
|
|
60638
60910
|
init_manager2();
|
|
60639
60911
|
init_create_tool();
|
|
60640
60912
|
var VALID_CATEGORIES2 = [
|
|
@@ -60709,7 +60981,7 @@ var knowledgeAdd = createSwarmTool({
|
|
|
60709
60981
|
project_name = plan?.title ?? "";
|
|
60710
60982
|
} catch {}
|
|
60711
60983
|
const entry = {
|
|
60712
|
-
id:
|
|
60984
|
+
id: randomUUID5(),
|
|
60713
60985
|
tier: "swarm",
|
|
60714
60986
|
lesson,
|
|
60715
60987
|
category,
|
|
@@ -60767,7 +61039,7 @@ init_dist();
|
|
|
60767
61039
|
init_config();
|
|
60768
61040
|
init_knowledge_store();
|
|
60769
61041
|
init_create_tool();
|
|
60770
|
-
import { existsSync as
|
|
61042
|
+
import { existsSync as existsSync33 } from "fs";
|
|
60771
61043
|
var DEFAULT_LIMIT = 10;
|
|
60772
61044
|
var MAX_LESSON_LENGTH = 200;
|
|
60773
61045
|
var VALID_CATEGORIES3 = [
|
|
@@ -60836,14 +61108,14 @@ function validateLimit(limit) {
|
|
|
60836
61108
|
}
|
|
60837
61109
|
async function readSwarmKnowledge(directory) {
|
|
60838
61110
|
const swarmPath = resolveSwarmKnowledgePath(directory);
|
|
60839
|
-
if (!
|
|
61111
|
+
if (!existsSync33(swarmPath)) {
|
|
60840
61112
|
return [];
|
|
60841
61113
|
}
|
|
60842
61114
|
return readKnowledge(swarmPath);
|
|
60843
61115
|
}
|
|
60844
61116
|
async function readHiveKnowledge() {
|
|
60845
61117
|
const hivePath = resolveHiveKnowledgePath();
|
|
60846
|
-
if (!
|
|
61118
|
+
if (!existsSync33(hivePath)) {
|
|
60847
61119
|
return [];
|
|
60848
61120
|
}
|
|
60849
61121
|
return readKnowledge(hivePath);
|
|
@@ -61156,8 +61428,9 @@ init_dist();
|
|
|
61156
61428
|
init_config();
|
|
61157
61429
|
init_schema();
|
|
61158
61430
|
init_manager();
|
|
61159
|
-
import * as
|
|
61160
|
-
import * as
|
|
61431
|
+
import * as fs42 from "fs";
|
|
61432
|
+
import * as path55 from "path";
|
|
61433
|
+
init_review_receipt();
|
|
61161
61434
|
init_utils2();
|
|
61162
61435
|
init_telemetry();
|
|
61163
61436
|
init_create_tool();
|
|
@@ -61378,11 +61651,11 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
|
|
|
61378
61651
|
safeWarn(`[phase_complete] Completion verify error (non-blocking):`, completionError);
|
|
61379
61652
|
}
|
|
61380
61653
|
try {
|
|
61381
|
-
const driftEvidencePath =
|
|
61654
|
+
const driftEvidencePath = path55.join(dir, ".swarm", "evidence", String(phase), "drift-verifier.json");
|
|
61382
61655
|
let driftVerdictFound = false;
|
|
61383
61656
|
let driftVerdictApproved = false;
|
|
61384
61657
|
try {
|
|
61385
|
-
const driftEvidenceContent =
|
|
61658
|
+
const driftEvidenceContent = fs42.readFileSync(driftEvidencePath, "utf-8");
|
|
61386
61659
|
const driftEvidence = JSON.parse(driftEvidenceContent);
|
|
61387
61660
|
const entries = driftEvidence.entries ?? [];
|
|
61388
61661
|
for (const entry of entries) {
|
|
@@ -61412,14 +61685,14 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
|
|
|
61412
61685
|
driftVerdictFound = false;
|
|
61413
61686
|
}
|
|
61414
61687
|
if (!driftVerdictFound) {
|
|
61415
|
-
const specPath =
|
|
61416
|
-
const specExists =
|
|
61688
|
+
const specPath = path55.join(dir, ".swarm", "spec.md");
|
|
61689
|
+
const specExists = fs42.existsSync(specPath);
|
|
61417
61690
|
if (!specExists) {
|
|
61418
61691
|
let incompleteTaskCount = 0;
|
|
61419
61692
|
let planPhaseFound = false;
|
|
61420
61693
|
try {
|
|
61421
61694
|
const planPath = validateSwarmPath(dir, "plan.json");
|
|
61422
|
-
const planRaw =
|
|
61695
|
+
const planRaw = fs42.readFileSync(planPath, "utf-8");
|
|
61423
61696
|
const plan = JSON.parse(planRaw);
|
|
61424
61697
|
const targetPhase = plan.phases.find((p) => p.id === phase);
|
|
61425
61698
|
if (targetPhase) {
|
|
@@ -61461,32 +61734,10 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
|
|
|
61461
61734
|
safeWarn(`[phase_complete] Drift verifier error (non-blocking):`, driftError);
|
|
61462
61735
|
}
|
|
61463
61736
|
}
|
|
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
|
-
};
|
|
61737
|
+
const knowledgeConfig = KnowledgeConfigSchema.parse(config3.knowledge ?? {});
|
|
61487
61738
|
if (retroFound && retroEntry?.lessons_learned && retroEntry.lessons_learned.length > 0) {
|
|
61488
61739
|
try {
|
|
61489
|
-
const projectName =
|
|
61740
|
+
const projectName = path55.basename(dir);
|
|
61490
61741
|
const curationResult = await curateAndStoreSwarm(retroEntry.lessons_learned, projectName, { phase_number: phase }, dir, knowledgeConfig);
|
|
61491
61742
|
if (curationResult) {
|
|
61492
61743
|
const sessionState = swarmState.agentSessions.get(sessionID);
|
|
@@ -61495,6 +61746,7 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
|
|
|
61495
61746
|
sessionState.pendingAdvisoryMessages.push(`[CURATOR] Knowledge curation: ${curationResult.stored} stored, ${curationResult.skipped} skipped, ${curationResult.rejected} rejected.`);
|
|
61496
61747
|
}
|
|
61497
61748
|
}
|
|
61749
|
+
await updateRetrievalOutcome(dir, `Phase ${phase}`, true);
|
|
61498
61750
|
} catch (error93) {
|
|
61499
61751
|
safeWarn("[phase_complete] Failed to curate lessons from retrospective:", error93);
|
|
61500
61752
|
}
|
|
@@ -61503,7 +61755,41 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
|
|
|
61503
61755
|
try {
|
|
61504
61756
|
const curatorConfig = CuratorConfigSchema.parse(config3.curator ?? {});
|
|
61505
61757
|
if (curatorConfig.enabled && curatorConfig.phase_enabled) {
|
|
61506
|
-
const
|
|
61758
|
+
const llmDelegate = createCuratorLLMDelegate(dir);
|
|
61759
|
+
const curatorResult = await runCuratorPhase(dir, phase, agentsDispatched, curatorConfig, {}, llmDelegate);
|
|
61760
|
+
{
|
|
61761
|
+
const scopeContent = curatorResult.digest?.summary ?? `Phase ${phase} curator analysis`;
|
|
61762
|
+
const complianceWarnings2 = curatorResult.compliance.filter((c) => c.severity === "warning");
|
|
61763
|
+
const receipt = complianceWarnings2.length > 0 ? buildRejectedReceipt({
|
|
61764
|
+
agent: "curator",
|
|
61765
|
+
scopeContent,
|
|
61766
|
+
scopeDescription: "phase-digest",
|
|
61767
|
+
blockingFindings: complianceWarnings2.map((c) => ({
|
|
61768
|
+
location: `phase-${c.phase}`,
|
|
61769
|
+
summary: c.description,
|
|
61770
|
+
severity: c.type === "missing_reviewer" ? "high" : "medium"
|
|
61771
|
+
})),
|
|
61772
|
+
evidenceReferences: [],
|
|
61773
|
+
passConditions: [
|
|
61774
|
+
"resolve all compliance warnings before phase completion"
|
|
61775
|
+
]
|
|
61776
|
+
}) : buildApprovedReceipt({
|
|
61777
|
+
agent: "curator",
|
|
61778
|
+
scopeContent,
|
|
61779
|
+
scopeDescription: "phase-digest",
|
|
61780
|
+
checkedAspects: [
|
|
61781
|
+
"phase_compliance",
|
|
61782
|
+
"knowledge_recommendations",
|
|
61783
|
+
"phase_digest"
|
|
61784
|
+
],
|
|
61785
|
+
validatedClaims: [
|
|
61786
|
+
`phase: ${phase}`,
|
|
61787
|
+
`agents_dispatched: ${agentsDispatched.length}`,
|
|
61788
|
+
`knowledge_recommendations: ${curatorResult.knowledge_recommendations.length}`
|
|
61789
|
+
]
|
|
61790
|
+
});
|
|
61791
|
+
persistReviewReceipt(dir, receipt).catch(() => {});
|
|
61792
|
+
}
|
|
61507
61793
|
const knowledgeResult = await applyCuratorKnowledgeUpdates(dir, curatorResult.knowledge_recommendations, knowledgeConfig);
|
|
61508
61794
|
const callerSessionState = swarmState.agentSessions.get(sessionID);
|
|
61509
61795
|
if (callerSessionState) {
|
|
@@ -61531,7 +61817,7 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
|
|
|
61531
61817
|
let phaseRequiredAgents;
|
|
61532
61818
|
try {
|
|
61533
61819
|
const planPath = validateSwarmPath(dir, "plan.json");
|
|
61534
|
-
const planRaw =
|
|
61820
|
+
const planRaw = fs42.readFileSync(planPath, "utf-8");
|
|
61535
61821
|
const plan = JSON.parse(planRaw);
|
|
61536
61822
|
const phaseObj = plan.phases.find((p) => p.id === phase);
|
|
61537
61823
|
phaseRequiredAgents = phaseObj?.required_agents;
|
|
@@ -61546,7 +61832,7 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
|
|
|
61546
61832
|
if (agentsMissing.length > 0) {
|
|
61547
61833
|
try {
|
|
61548
61834
|
const planPath = validateSwarmPath(dir, "plan.json");
|
|
61549
|
-
const planRaw =
|
|
61835
|
+
const planRaw = fs42.readFileSync(planPath, "utf-8");
|
|
61550
61836
|
const plan = JSON.parse(planRaw);
|
|
61551
61837
|
const targetPhase = plan.phases.find((p) => p.id === phase);
|
|
61552
61838
|
if (targetPhase && targetPhase.tasks.length > 0 && targetPhase.tasks.every((t) => t.status === "completed")) {
|
|
@@ -61577,7 +61863,7 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
|
|
|
61577
61863
|
if (phaseCompleteConfig.regression_sweep?.enforce) {
|
|
61578
61864
|
try {
|
|
61579
61865
|
const planPath = validateSwarmPath(dir, "plan.json");
|
|
61580
|
-
const planRaw =
|
|
61866
|
+
const planRaw = fs42.readFileSync(planPath, "utf-8");
|
|
61581
61867
|
const plan = JSON.parse(planRaw);
|
|
61582
61868
|
const targetPhase = plan.phases.find((p) => p.id === phase);
|
|
61583
61869
|
if (targetPhase) {
|
|
@@ -61615,7 +61901,7 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
|
|
|
61615
61901
|
};
|
|
61616
61902
|
try {
|
|
61617
61903
|
const eventsPath = validateSwarmPath(dir, "events.jsonl");
|
|
61618
|
-
|
|
61904
|
+
fs42.appendFileSync(eventsPath, `${JSON.stringify(event)}
|
|
61619
61905
|
`, "utf-8");
|
|
61620
61906
|
} catch (writeError) {
|
|
61621
61907
|
warnings.push(`Warning: failed to write phase complete event: ${writeError instanceof Error ? writeError.message : String(writeError)}`);
|
|
@@ -61639,12 +61925,12 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
|
|
|
61639
61925
|
}
|
|
61640
61926
|
try {
|
|
61641
61927
|
const planPath = validateSwarmPath(dir, "plan.json");
|
|
61642
|
-
const planJson =
|
|
61928
|
+
const planJson = fs42.readFileSync(planPath, "utf-8");
|
|
61643
61929
|
const plan = JSON.parse(planJson);
|
|
61644
61930
|
const phaseObj = plan.phases.find((p) => p.id === phase);
|
|
61645
61931
|
if (phaseObj) {
|
|
61646
61932
|
phaseObj.status = "completed";
|
|
61647
|
-
|
|
61933
|
+
fs42.writeFileSync(planPath, `${JSON.stringify(plan, null, 2)}
|
|
61648
61934
|
`, "utf-8");
|
|
61649
61935
|
}
|
|
61650
61936
|
} catch (error93) {
|
|
@@ -61711,8 +61997,8 @@ init_dist();
|
|
|
61711
61997
|
init_discovery();
|
|
61712
61998
|
init_utils();
|
|
61713
61999
|
init_create_tool();
|
|
61714
|
-
import * as
|
|
61715
|
-
import * as
|
|
62000
|
+
import * as fs43 from "fs";
|
|
62001
|
+
import * as path56 from "path";
|
|
61716
62002
|
var MAX_OUTPUT_BYTES5 = 52428800;
|
|
61717
62003
|
var AUDIT_TIMEOUT_MS = 120000;
|
|
61718
62004
|
function isValidEcosystem(value) {
|
|
@@ -61730,28 +62016,28 @@ function validateArgs3(args2) {
|
|
|
61730
62016
|
function detectEcosystems(directory) {
|
|
61731
62017
|
const ecosystems = [];
|
|
61732
62018
|
const cwd = directory;
|
|
61733
|
-
if (
|
|
62019
|
+
if (fs43.existsSync(path56.join(cwd, "package.json"))) {
|
|
61734
62020
|
ecosystems.push("npm");
|
|
61735
62021
|
}
|
|
61736
|
-
if (
|
|
62022
|
+
if (fs43.existsSync(path56.join(cwd, "pyproject.toml")) || fs43.existsSync(path56.join(cwd, "requirements.txt"))) {
|
|
61737
62023
|
ecosystems.push("pip");
|
|
61738
62024
|
}
|
|
61739
|
-
if (
|
|
62025
|
+
if (fs43.existsSync(path56.join(cwd, "Cargo.toml"))) {
|
|
61740
62026
|
ecosystems.push("cargo");
|
|
61741
62027
|
}
|
|
61742
|
-
if (
|
|
62028
|
+
if (fs43.existsSync(path56.join(cwd, "go.mod"))) {
|
|
61743
62029
|
ecosystems.push("go");
|
|
61744
62030
|
}
|
|
61745
62031
|
try {
|
|
61746
|
-
const files =
|
|
62032
|
+
const files = fs43.readdirSync(cwd);
|
|
61747
62033
|
if (files.some((f) => f.endsWith(".csproj") || f.endsWith(".sln"))) {
|
|
61748
62034
|
ecosystems.push("dotnet");
|
|
61749
62035
|
}
|
|
61750
62036
|
} catch {}
|
|
61751
|
-
if (
|
|
62037
|
+
if (fs43.existsSync(path56.join(cwd, "Gemfile")) || fs43.existsSync(path56.join(cwd, "Gemfile.lock"))) {
|
|
61752
62038
|
ecosystems.push("ruby");
|
|
61753
62039
|
}
|
|
61754
|
-
if (
|
|
62040
|
+
if (fs43.existsSync(path56.join(cwd, "pubspec.yaml"))) {
|
|
61755
62041
|
ecosystems.push("dart");
|
|
61756
62042
|
}
|
|
61757
62043
|
return ecosystems;
|
|
@@ -62772,8 +63058,8 @@ var SUPPORTED_PARSER_EXTENSIONS = new Set([
|
|
|
62772
63058
|
]);
|
|
62773
63059
|
// src/tools/pre-check-batch.ts
|
|
62774
63060
|
init_dist();
|
|
62775
|
-
import * as
|
|
62776
|
-
import * as
|
|
63061
|
+
import * as fs45 from "fs";
|
|
63062
|
+
import * as path58 from "path";
|
|
62777
63063
|
|
|
62778
63064
|
// node_modules/yocto-queue/index.js
|
|
62779
63065
|
class Node2 {
|
|
@@ -62918,8 +63204,8 @@ function pLimit(concurrency) {
|
|
|
62918
63204
|
},
|
|
62919
63205
|
map: {
|
|
62920
63206
|
async value(iterable, function_) {
|
|
62921
|
-
const
|
|
62922
|
-
return Promise.all(
|
|
63207
|
+
const promises6 = Array.from(iterable, (value, index) => this(function_, value, index));
|
|
63208
|
+
return Promise.all(promises6);
|
|
62923
63209
|
}
|
|
62924
63210
|
}
|
|
62925
63211
|
});
|
|
@@ -63047,8 +63333,8 @@ async function qualityBudget(input, directory) {
|
|
|
63047
63333
|
init_dist();
|
|
63048
63334
|
init_manager();
|
|
63049
63335
|
init_detector();
|
|
63050
|
-
import * as
|
|
63051
|
-
import * as
|
|
63336
|
+
import * as fs44 from "fs";
|
|
63337
|
+
import * as path57 from "path";
|
|
63052
63338
|
import { extname as extname10 } from "path";
|
|
63053
63339
|
|
|
63054
63340
|
// src/sast/rules/c.ts
|
|
@@ -63918,17 +64204,17 @@ var SEVERITY_ORDER = {
|
|
|
63918
64204
|
};
|
|
63919
64205
|
function shouldSkipFile(filePath) {
|
|
63920
64206
|
try {
|
|
63921
|
-
const stats =
|
|
64207
|
+
const stats = fs44.statSync(filePath);
|
|
63922
64208
|
if (stats.size > MAX_FILE_SIZE_BYTES6) {
|
|
63923
64209
|
return { skip: true, reason: "file too large" };
|
|
63924
64210
|
}
|
|
63925
64211
|
if (stats.size === 0) {
|
|
63926
64212
|
return { skip: true, reason: "empty file" };
|
|
63927
64213
|
}
|
|
63928
|
-
const fd =
|
|
64214
|
+
const fd = fs44.openSync(filePath, "r");
|
|
63929
64215
|
const buffer = Buffer.alloc(8192);
|
|
63930
|
-
const bytesRead =
|
|
63931
|
-
|
|
64216
|
+
const bytesRead = fs44.readSync(fd, buffer, 0, 8192, 0);
|
|
64217
|
+
fs44.closeSync(fd);
|
|
63932
64218
|
if (bytesRead > 0) {
|
|
63933
64219
|
let nullCount = 0;
|
|
63934
64220
|
for (let i2 = 0;i2 < bytesRead; i2++) {
|
|
@@ -63967,7 +64253,7 @@ function countBySeverity(findings) {
|
|
|
63967
64253
|
}
|
|
63968
64254
|
function scanFileWithTierA(filePath, language) {
|
|
63969
64255
|
try {
|
|
63970
|
-
const content =
|
|
64256
|
+
const content = fs44.readFileSync(filePath, "utf-8");
|
|
63971
64257
|
const findings = executeRulesSync(filePath, content, language);
|
|
63972
64258
|
return findings.map((f) => ({
|
|
63973
64259
|
rule_id: f.rule_id,
|
|
@@ -64014,8 +64300,8 @@ async function sastScan(input, directory, config3) {
|
|
|
64014
64300
|
_filesSkipped++;
|
|
64015
64301
|
continue;
|
|
64016
64302
|
}
|
|
64017
|
-
const resolvedPath =
|
|
64018
|
-
if (!
|
|
64303
|
+
const resolvedPath = path57.isAbsolute(filePath) ? filePath : path57.resolve(directory, filePath);
|
|
64304
|
+
if (!fs44.existsSync(resolvedPath)) {
|
|
64019
64305
|
_filesSkipped++;
|
|
64020
64306
|
continue;
|
|
64021
64307
|
}
|
|
@@ -64213,18 +64499,18 @@ function validatePath(inputPath, baseDir, workspaceDir) {
|
|
|
64213
64499
|
let resolved;
|
|
64214
64500
|
const isWinAbs = isWindowsAbsolutePath(inputPath);
|
|
64215
64501
|
if (isWinAbs) {
|
|
64216
|
-
resolved =
|
|
64217
|
-
} else if (
|
|
64218
|
-
resolved =
|
|
64502
|
+
resolved = path58.win32.resolve(inputPath);
|
|
64503
|
+
} else if (path58.isAbsolute(inputPath)) {
|
|
64504
|
+
resolved = path58.resolve(inputPath);
|
|
64219
64505
|
} else {
|
|
64220
|
-
resolved =
|
|
64506
|
+
resolved = path58.resolve(baseDir, inputPath);
|
|
64221
64507
|
}
|
|
64222
|
-
const workspaceResolved =
|
|
64508
|
+
const workspaceResolved = path58.resolve(workspaceDir);
|
|
64223
64509
|
let relative8;
|
|
64224
64510
|
if (isWinAbs) {
|
|
64225
|
-
relative8 =
|
|
64511
|
+
relative8 = path58.win32.relative(workspaceResolved, resolved);
|
|
64226
64512
|
} else {
|
|
64227
|
-
relative8 =
|
|
64513
|
+
relative8 = path58.relative(workspaceResolved, resolved);
|
|
64228
64514
|
}
|
|
64229
64515
|
if (relative8.startsWith("..")) {
|
|
64230
64516
|
return "path traversal detected";
|
|
@@ -64285,13 +64571,13 @@ async function runLintWrapped(files, directory, _config) {
|
|
|
64285
64571
|
}
|
|
64286
64572
|
async function runLintOnFiles(linter, files, workspaceDir) {
|
|
64287
64573
|
const isWindows = process.platform === "win32";
|
|
64288
|
-
const binDir =
|
|
64574
|
+
const binDir = path58.join(workspaceDir, "node_modules", ".bin");
|
|
64289
64575
|
const validatedFiles = [];
|
|
64290
64576
|
for (const file3 of files) {
|
|
64291
64577
|
if (typeof file3 !== "string") {
|
|
64292
64578
|
continue;
|
|
64293
64579
|
}
|
|
64294
|
-
const resolvedPath =
|
|
64580
|
+
const resolvedPath = path58.resolve(file3);
|
|
64295
64581
|
const validationError = validatePath(resolvedPath, workspaceDir, workspaceDir);
|
|
64296
64582
|
if (validationError) {
|
|
64297
64583
|
continue;
|
|
@@ -64309,10 +64595,10 @@ async function runLintOnFiles(linter, files, workspaceDir) {
|
|
|
64309
64595
|
}
|
|
64310
64596
|
let command;
|
|
64311
64597
|
if (linter === "biome") {
|
|
64312
|
-
const biomeBin = isWindows ?
|
|
64598
|
+
const biomeBin = isWindows ? path58.join(binDir, "biome.EXE") : path58.join(binDir, "biome");
|
|
64313
64599
|
command = [biomeBin, "check", ...validatedFiles];
|
|
64314
64600
|
} else {
|
|
64315
|
-
const eslintBin = isWindows ?
|
|
64601
|
+
const eslintBin = isWindows ? path58.join(binDir, "eslint.cmd") : path58.join(binDir, "eslint");
|
|
64316
64602
|
command = [eslintBin, ...validatedFiles];
|
|
64317
64603
|
}
|
|
64318
64604
|
try {
|
|
@@ -64449,7 +64735,7 @@ async function runSecretscanWithFiles(files, directory) {
|
|
|
64449
64735
|
skippedFiles++;
|
|
64450
64736
|
continue;
|
|
64451
64737
|
}
|
|
64452
|
-
const resolvedPath =
|
|
64738
|
+
const resolvedPath = path58.resolve(file3);
|
|
64453
64739
|
const validationError = validatePath(resolvedPath, directory, directory);
|
|
64454
64740
|
if (validationError) {
|
|
64455
64741
|
skippedFiles++;
|
|
@@ -64467,14 +64753,14 @@ async function runSecretscanWithFiles(files, directory) {
|
|
|
64467
64753
|
};
|
|
64468
64754
|
}
|
|
64469
64755
|
for (const file3 of validatedFiles) {
|
|
64470
|
-
const ext =
|
|
64756
|
+
const ext = path58.extname(file3).toLowerCase();
|
|
64471
64757
|
if (DEFAULT_EXCLUDE_EXTENSIONS2.has(ext)) {
|
|
64472
64758
|
skippedFiles++;
|
|
64473
64759
|
continue;
|
|
64474
64760
|
}
|
|
64475
64761
|
let stat2;
|
|
64476
64762
|
try {
|
|
64477
|
-
stat2 =
|
|
64763
|
+
stat2 = fs45.statSync(file3);
|
|
64478
64764
|
} catch {
|
|
64479
64765
|
skippedFiles++;
|
|
64480
64766
|
continue;
|
|
@@ -64485,7 +64771,7 @@ async function runSecretscanWithFiles(files, directory) {
|
|
|
64485
64771
|
}
|
|
64486
64772
|
let content;
|
|
64487
64773
|
try {
|
|
64488
|
-
const buffer =
|
|
64774
|
+
const buffer = fs45.readFileSync(file3);
|
|
64489
64775
|
if (buffer.includes(0)) {
|
|
64490
64776
|
skippedFiles++;
|
|
64491
64777
|
continue;
|
|
@@ -64673,7 +64959,7 @@ function classifySastFindings(findings, changedLineRanges, directory) {
|
|
|
64673
64959
|
const preexistingFindings = [];
|
|
64674
64960
|
for (const finding of findings) {
|
|
64675
64961
|
const filePath = finding.location.file;
|
|
64676
|
-
const normalised =
|
|
64962
|
+
const normalised = path58.relative(directory, filePath).replace(/\\/g, "/");
|
|
64677
64963
|
const changedLines = changedLineRanges.get(normalised);
|
|
64678
64964
|
if (changedLines && changedLines.has(finding.location.line)) {
|
|
64679
64965
|
newFindings.push(finding);
|
|
@@ -64724,7 +65010,7 @@ async function runPreCheckBatch(input, workspaceDir, contextDir) {
|
|
|
64724
65010
|
warn(`pre_check_batch: Invalid file path: ${file3}`);
|
|
64725
65011
|
continue;
|
|
64726
65012
|
}
|
|
64727
|
-
changedFiles.push(
|
|
65013
|
+
changedFiles.push(path58.resolve(directory, file3));
|
|
64728
65014
|
}
|
|
64729
65015
|
if (changedFiles.length === 0) {
|
|
64730
65016
|
warn("pre_check_batch: No valid files after validation, skipping all tools (fail-closed)");
|
|
@@ -64912,7 +65198,7 @@ var pre_check_batch = createSwarmTool({
|
|
|
64912
65198
|
};
|
|
64913
65199
|
return JSON.stringify(errorResult, null, 2);
|
|
64914
65200
|
}
|
|
64915
|
-
const resolvedDirectory =
|
|
65201
|
+
const resolvedDirectory = path58.resolve(typedArgs.directory);
|
|
64916
65202
|
const workspaceAnchor = resolvedDirectory;
|
|
64917
65203
|
const dirError = validateDirectory2(resolvedDirectory, workspaceAnchor);
|
|
64918
65204
|
if (dirError) {
|
|
@@ -65018,38 +65304,38 @@ ${paginatedContent}`;
|
|
|
65018
65304
|
});
|
|
65019
65305
|
// src/tools/save-plan.ts
|
|
65020
65306
|
init_tool();
|
|
65021
|
-
import * as
|
|
65022
|
-
import * as
|
|
65307
|
+
import * as fs47 from "fs";
|
|
65308
|
+
import * as path60 from "path";
|
|
65023
65309
|
|
|
65024
65310
|
// src/parallel/file-locks.ts
|
|
65025
|
-
import * as
|
|
65026
|
-
import * as
|
|
65311
|
+
import * as fs46 from "fs";
|
|
65312
|
+
import * as path59 from "path";
|
|
65027
65313
|
var LOCKS_DIR = ".swarm/locks";
|
|
65028
65314
|
var LOCK_TIMEOUT_MS = 5 * 60 * 1000;
|
|
65029
65315
|
function getLockFilePath(directory, filePath) {
|
|
65030
|
-
const normalized =
|
|
65031
|
-
if (!normalized.startsWith(
|
|
65316
|
+
const normalized = path59.resolve(directory, filePath);
|
|
65317
|
+
if (!normalized.startsWith(path59.resolve(directory))) {
|
|
65032
65318
|
throw new Error("Invalid file path: path traversal not allowed");
|
|
65033
65319
|
}
|
|
65034
65320
|
const hash3 = Buffer.from(normalized).toString("base64").replace(/[/+=]/g, "_");
|
|
65035
|
-
return
|
|
65321
|
+
return path59.join(directory, LOCKS_DIR, `${hash3}.lock`);
|
|
65036
65322
|
}
|
|
65037
65323
|
function tryAcquireLock(directory, filePath, agent, taskId) {
|
|
65038
65324
|
const lockPath = getLockFilePath(directory, filePath);
|
|
65039
|
-
const locksDir =
|
|
65040
|
-
if (!
|
|
65041
|
-
|
|
65325
|
+
const locksDir = path59.dirname(lockPath);
|
|
65326
|
+
if (!fs46.existsSync(locksDir)) {
|
|
65327
|
+
fs46.mkdirSync(locksDir, { recursive: true });
|
|
65042
65328
|
}
|
|
65043
|
-
if (
|
|
65329
|
+
if (fs46.existsSync(lockPath)) {
|
|
65044
65330
|
try {
|
|
65045
|
-
const existingLock = JSON.parse(
|
|
65331
|
+
const existingLock = JSON.parse(fs46.readFileSync(lockPath, "utf-8"));
|
|
65046
65332
|
if (Date.now() > existingLock.expiresAt) {
|
|
65047
|
-
|
|
65333
|
+
fs46.unlinkSync(lockPath);
|
|
65048
65334
|
} else {
|
|
65049
65335
|
return { acquired: false, existing: existingLock };
|
|
65050
65336
|
}
|
|
65051
65337
|
} catch {
|
|
65052
|
-
|
|
65338
|
+
fs46.unlinkSync(lockPath);
|
|
65053
65339
|
}
|
|
65054
65340
|
}
|
|
65055
65341
|
const lock = {
|
|
@@ -65060,24 +65346,24 @@ function tryAcquireLock(directory, filePath, agent, taskId) {
|
|
|
65060
65346
|
expiresAt: Date.now() + LOCK_TIMEOUT_MS
|
|
65061
65347
|
};
|
|
65062
65348
|
const tempPath = `${lockPath}.tmp`;
|
|
65063
|
-
|
|
65064
|
-
|
|
65349
|
+
fs46.writeFileSync(tempPath, JSON.stringify(lock, null, 2), "utf-8");
|
|
65350
|
+
fs46.renameSync(tempPath, lockPath);
|
|
65065
65351
|
return { acquired: true, lock };
|
|
65066
65352
|
}
|
|
65067
65353
|
function releaseLock(directory, filePath, taskId) {
|
|
65068
65354
|
const lockPath = getLockFilePath(directory, filePath);
|
|
65069
|
-
if (!
|
|
65355
|
+
if (!fs46.existsSync(lockPath)) {
|
|
65070
65356
|
return true;
|
|
65071
65357
|
}
|
|
65072
65358
|
try {
|
|
65073
|
-
const lock = JSON.parse(
|
|
65359
|
+
const lock = JSON.parse(fs46.readFileSync(lockPath, "utf-8"));
|
|
65074
65360
|
if (lock.taskId === taskId) {
|
|
65075
|
-
|
|
65361
|
+
fs46.unlinkSync(lockPath);
|
|
65076
65362
|
return true;
|
|
65077
65363
|
}
|
|
65078
65364
|
return false;
|
|
65079
65365
|
} catch {
|
|
65080
|
-
|
|
65366
|
+
fs46.unlinkSync(lockPath);
|
|
65081
65367
|
return true;
|
|
65082
65368
|
}
|
|
65083
65369
|
}
|
|
@@ -65202,14 +65488,14 @@ async function executeSavePlan(args2, fallbackDir) {
|
|
|
65202
65488
|
try {
|
|
65203
65489
|
await savePlan(dir, plan);
|
|
65204
65490
|
try {
|
|
65205
|
-
const markerPath =
|
|
65491
|
+
const markerPath = path60.join(dir, ".swarm", ".plan-write-marker");
|
|
65206
65492
|
const marker = JSON.stringify({
|
|
65207
65493
|
source: "save_plan",
|
|
65208
65494
|
timestamp: new Date().toISOString(),
|
|
65209
65495
|
phases_count: plan.phases.length,
|
|
65210
65496
|
tasks_count: tasksCount
|
|
65211
65497
|
});
|
|
65212
|
-
await
|
|
65498
|
+
await fs47.promises.writeFile(markerPath, marker, "utf8");
|
|
65213
65499
|
} catch {}
|
|
65214
65500
|
const warnings = [];
|
|
65215
65501
|
let criticReviewFound = false;
|
|
@@ -65225,7 +65511,7 @@ async function executeSavePlan(args2, fallbackDir) {
|
|
|
65225
65511
|
return {
|
|
65226
65512
|
success: true,
|
|
65227
65513
|
message: "Plan saved successfully",
|
|
65228
|
-
plan_path:
|
|
65514
|
+
plan_path: path60.join(dir, ".swarm", "plan.json"),
|
|
65229
65515
|
phases_count: plan.phases.length,
|
|
65230
65516
|
tasks_count: tasksCount,
|
|
65231
65517
|
...warnings.length > 0 ? { warnings } : {}
|
|
@@ -65267,8 +65553,8 @@ var save_plan = createSwarmTool({
|
|
|
65267
65553
|
// src/tools/sbom-generate.ts
|
|
65268
65554
|
init_dist();
|
|
65269
65555
|
init_manager();
|
|
65270
|
-
import * as
|
|
65271
|
-
import * as
|
|
65556
|
+
import * as fs48 from "fs";
|
|
65557
|
+
import * as path61 from "path";
|
|
65272
65558
|
|
|
65273
65559
|
// src/sbom/detectors/index.ts
|
|
65274
65560
|
init_utils();
|
|
@@ -66116,9 +66402,9 @@ function findManifestFiles(rootDir) {
|
|
|
66116
66402
|
const patterns = [...new Set(allDetectors.flatMap((d) => d.patterns))];
|
|
66117
66403
|
function searchDir(dir) {
|
|
66118
66404
|
try {
|
|
66119
|
-
const entries =
|
|
66405
|
+
const entries = fs48.readdirSync(dir, { withFileTypes: true });
|
|
66120
66406
|
for (const entry of entries) {
|
|
66121
|
-
const fullPath =
|
|
66407
|
+
const fullPath = path61.join(dir, entry.name);
|
|
66122
66408
|
if (entry.name.startsWith(".") || entry.name === "node_modules" || entry.name === "dist" || entry.name === "build" || entry.name === "target") {
|
|
66123
66409
|
continue;
|
|
66124
66410
|
}
|
|
@@ -66127,7 +66413,7 @@ function findManifestFiles(rootDir) {
|
|
|
66127
66413
|
} else if (entry.isFile()) {
|
|
66128
66414
|
for (const pattern of patterns) {
|
|
66129
66415
|
if (simpleGlobToRegex(pattern).test(entry.name)) {
|
|
66130
|
-
manifestFiles.push(
|
|
66416
|
+
manifestFiles.push(path61.relative(rootDir, fullPath));
|
|
66131
66417
|
break;
|
|
66132
66418
|
}
|
|
66133
66419
|
}
|
|
@@ -66143,13 +66429,13 @@ function findManifestFilesInDirs(directories, workingDir) {
|
|
|
66143
66429
|
const patterns = [...new Set(allDetectors.flatMap((d) => d.patterns))];
|
|
66144
66430
|
for (const dir of directories) {
|
|
66145
66431
|
try {
|
|
66146
|
-
const entries =
|
|
66432
|
+
const entries = fs48.readdirSync(dir, { withFileTypes: true });
|
|
66147
66433
|
for (const entry of entries) {
|
|
66148
|
-
const fullPath =
|
|
66434
|
+
const fullPath = path61.join(dir, entry.name);
|
|
66149
66435
|
if (entry.isFile()) {
|
|
66150
66436
|
for (const pattern of patterns) {
|
|
66151
66437
|
if (simpleGlobToRegex(pattern).test(entry.name)) {
|
|
66152
|
-
found.push(
|
|
66438
|
+
found.push(path61.relative(workingDir, fullPath));
|
|
66153
66439
|
break;
|
|
66154
66440
|
}
|
|
66155
66441
|
}
|
|
@@ -66162,11 +66448,11 @@ function findManifestFilesInDirs(directories, workingDir) {
|
|
|
66162
66448
|
function getDirectoriesFromChangedFiles(changedFiles, workingDir) {
|
|
66163
66449
|
const dirs = new Set;
|
|
66164
66450
|
for (const file3 of changedFiles) {
|
|
66165
|
-
let currentDir =
|
|
66451
|
+
let currentDir = path61.dirname(file3);
|
|
66166
66452
|
while (true) {
|
|
66167
|
-
if (currentDir && currentDir !== "." && currentDir !==
|
|
66168
|
-
dirs.add(
|
|
66169
|
-
const parent =
|
|
66453
|
+
if (currentDir && currentDir !== "." && currentDir !== path61.sep) {
|
|
66454
|
+
dirs.add(path61.join(workingDir, currentDir));
|
|
66455
|
+
const parent = path61.dirname(currentDir);
|
|
66170
66456
|
if (parent === currentDir)
|
|
66171
66457
|
break;
|
|
66172
66458
|
currentDir = parent;
|
|
@@ -66180,7 +66466,7 @@ function getDirectoriesFromChangedFiles(changedFiles, workingDir) {
|
|
|
66180
66466
|
}
|
|
66181
66467
|
function ensureOutputDir(outputDir) {
|
|
66182
66468
|
try {
|
|
66183
|
-
|
|
66469
|
+
fs48.mkdirSync(outputDir, { recursive: true });
|
|
66184
66470
|
} catch (error93) {
|
|
66185
66471
|
if (!error93 || error93.code !== "EEXIST") {
|
|
66186
66472
|
throw error93;
|
|
@@ -66250,7 +66536,7 @@ var sbom_generate = createSwarmTool({
|
|
|
66250
66536
|
const changedFiles = obj.changed_files;
|
|
66251
66537
|
const relativeOutputDir = obj.output_dir || DEFAULT_OUTPUT_DIR;
|
|
66252
66538
|
const workingDir = directory;
|
|
66253
|
-
const outputDir =
|
|
66539
|
+
const outputDir = path61.isAbsolute(relativeOutputDir) ? relativeOutputDir : path61.join(workingDir, relativeOutputDir);
|
|
66254
66540
|
let manifestFiles = [];
|
|
66255
66541
|
if (scope === "all") {
|
|
66256
66542
|
manifestFiles = findManifestFiles(workingDir);
|
|
@@ -66273,11 +66559,11 @@ var sbom_generate = createSwarmTool({
|
|
|
66273
66559
|
const processedFiles = [];
|
|
66274
66560
|
for (const manifestFile of manifestFiles) {
|
|
66275
66561
|
try {
|
|
66276
|
-
const fullPath =
|
|
66277
|
-
if (!
|
|
66562
|
+
const fullPath = path61.isAbsolute(manifestFile) ? manifestFile : path61.join(workingDir, manifestFile);
|
|
66563
|
+
if (!fs48.existsSync(fullPath)) {
|
|
66278
66564
|
continue;
|
|
66279
66565
|
}
|
|
66280
|
-
const content =
|
|
66566
|
+
const content = fs48.readFileSync(fullPath, "utf-8");
|
|
66281
66567
|
const components = detectComponents(manifestFile, content);
|
|
66282
66568
|
processedFiles.push(manifestFile);
|
|
66283
66569
|
if (components.length > 0) {
|
|
@@ -66290,8 +66576,8 @@ var sbom_generate = createSwarmTool({
|
|
|
66290
66576
|
const bom = generateCycloneDX(allComponents);
|
|
66291
66577
|
const bomJson = serializeCycloneDX(bom);
|
|
66292
66578
|
const filename = generateSbomFilename();
|
|
66293
|
-
const outputPath =
|
|
66294
|
-
|
|
66579
|
+
const outputPath = path61.join(outputDir, filename);
|
|
66580
|
+
fs48.writeFileSync(outputPath, bomJson, "utf-8");
|
|
66295
66581
|
const verdict = processedFiles.length > 0 ? "pass" : "pass";
|
|
66296
66582
|
try {
|
|
66297
66583
|
const timestamp = new Date().toISOString();
|
|
@@ -66333,8 +66619,8 @@ var sbom_generate = createSwarmTool({
|
|
|
66333
66619
|
// src/tools/schema-drift.ts
|
|
66334
66620
|
init_dist();
|
|
66335
66621
|
init_create_tool();
|
|
66336
|
-
import * as
|
|
66337
|
-
import * as
|
|
66622
|
+
import * as fs49 from "fs";
|
|
66623
|
+
import * as path62 from "path";
|
|
66338
66624
|
var SPEC_CANDIDATES = [
|
|
66339
66625
|
"openapi.json",
|
|
66340
66626
|
"openapi.yaml",
|
|
@@ -66366,28 +66652,28 @@ function normalizePath2(p) {
|
|
|
66366
66652
|
}
|
|
66367
66653
|
function discoverSpecFile(cwd, specFileArg) {
|
|
66368
66654
|
if (specFileArg) {
|
|
66369
|
-
const resolvedPath =
|
|
66370
|
-
const normalizedCwd = cwd.endsWith(
|
|
66655
|
+
const resolvedPath = path62.resolve(cwd, specFileArg);
|
|
66656
|
+
const normalizedCwd = cwd.endsWith(path62.sep) ? cwd : cwd + path62.sep;
|
|
66371
66657
|
if (!resolvedPath.startsWith(normalizedCwd) && resolvedPath !== cwd) {
|
|
66372
66658
|
throw new Error("Invalid spec_file: path traversal detected");
|
|
66373
66659
|
}
|
|
66374
|
-
const ext =
|
|
66660
|
+
const ext = path62.extname(resolvedPath).toLowerCase();
|
|
66375
66661
|
if (!ALLOWED_EXTENSIONS.includes(ext)) {
|
|
66376
66662
|
throw new Error(`Invalid spec_file: must end in .json, .yaml, or .yml, got ${ext}`);
|
|
66377
66663
|
}
|
|
66378
|
-
const stats =
|
|
66664
|
+
const stats = fs49.statSync(resolvedPath);
|
|
66379
66665
|
if (stats.size > MAX_SPEC_SIZE) {
|
|
66380
66666
|
throw new Error(`Invalid spec_file: file exceeds ${MAX_SPEC_SIZE / 1024 / 1024}MB limit`);
|
|
66381
66667
|
}
|
|
66382
|
-
if (!
|
|
66668
|
+
if (!fs49.existsSync(resolvedPath)) {
|
|
66383
66669
|
throw new Error(`Spec file not found: ${resolvedPath}`);
|
|
66384
66670
|
}
|
|
66385
66671
|
return resolvedPath;
|
|
66386
66672
|
}
|
|
66387
66673
|
for (const candidate of SPEC_CANDIDATES) {
|
|
66388
|
-
const candidatePath =
|
|
66389
|
-
if (
|
|
66390
|
-
const stats =
|
|
66674
|
+
const candidatePath = path62.resolve(cwd, candidate);
|
|
66675
|
+
if (fs49.existsSync(candidatePath)) {
|
|
66676
|
+
const stats = fs49.statSync(candidatePath);
|
|
66391
66677
|
if (stats.size <= MAX_SPEC_SIZE) {
|
|
66392
66678
|
return candidatePath;
|
|
66393
66679
|
}
|
|
@@ -66396,8 +66682,8 @@ function discoverSpecFile(cwd, specFileArg) {
|
|
|
66396
66682
|
return null;
|
|
66397
66683
|
}
|
|
66398
66684
|
function parseSpec(specFile) {
|
|
66399
|
-
const content =
|
|
66400
|
-
const ext =
|
|
66685
|
+
const content = fs49.readFileSync(specFile, "utf-8");
|
|
66686
|
+
const ext = path62.extname(specFile).toLowerCase();
|
|
66401
66687
|
if (ext === ".json") {
|
|
66402
66688
|
return parseJsonSpec(content);
|
|
66403
66689
|
}
|
|
@@ -66468,12 +66754,12 @@ function extractRoutes(cwd) {
|
|
|
66468
66754
|
function walkDir(dir) {
|
|
66469
66755
|
let entries;
|
|
66470
66756
|
try {
|
|
66471
|
-
entries =
|
|
66757
|
+
entries = fs49.readdirSync(dir, { withFileTypes: true });
|
|
66472
66758
|
} catch {
|
|
66473
66759
|
return;
|
|
66474
66760
|
}
|
|
66475
66761
|
for (const entry of entries) {
|
|
66476
|
-
const fullPath =
|
|
66762
|
+
const fullPath = path62.join(dir, entry.name);
|
|
66477
66763
|
if (entry.isSymbolicLink()) {
|
|
66478
66764
|
continue;
|
|
66479
66765
|
}
|
|
@@ -66483,7 +66769,7 @@ function extractRoutes(cwd) {
|
|
|
66483
66769
|
}
|
|
66484
66770
|
walkDir(fullPath);
|
|
66485
66771
|
} else if (entry.isFile()) {
|
|
66486
|
-
const ext =
|
|
66772
|
+
const ext = path62.extname(entry.name).toLowerCase();
|
|
66487
66773
|
const baseName = entry.name.toLowerCase();
|
|
66488
66774
|
if (![".ts", ".js", ".mjs"].includes(ext)) {
|
|
66489
66775
|
continue;
|
|
@@ -66501,7 +66787,7 @@ function extractRoutes(cwd) {
|
|
|
66501
66787
|
}
|
|
66502
66788
|
function extractRoutesFromFile(filePath) {
|
|
66503
66789
|
const routes = [];
|
|
66504
|
-
const content =
|
|
66790
|
+
const content = fs49.readFileSync(filePath, "utf-8");
|
|
66505
66791
|
const lines = content.split(/\r?\n/);
|
|
66506
66792
|
const expressRegex = /(?:app|router|server|express)\.(get|post|put|patch|delete|options|head)\s*\(\s*['"`]([^'"`]+)['"`]/g;
|
|
66507
66793
|
const flaskRegex = /@(?:app|blueprint|bp)\.route\s*\(\s*['"]([^'"]+)['"]/g;
|
|
@@ -66652,8 +66938,8 @@ init_secretscan();
|
|
|
66652
66938
|
// src/tools/symbols.ts
|
|
66653
66939
|
init_tool();
|
|
66654
66940
|
init_create_tool();
|
|
66655
|
-
import * as
|
|
66656
|
-
import * as
|
|
66941
|
+
import * as fs50 from "fs";
|
|
66942
|
+
import * as path63 from "path";
|
|
66657
66943
|
var MAX_FILE_SIZE_BYTES7 = 1024 * 1024;
|
|
66658
66944
|
var WINDOWS_RESERVED_NAMES = /^(con|prn|aux|nul|com[1-9]|lpt[1-9])(\.|:|$)/i;
|
|
66659
66945
|
function containsWindowsAttacks(str) {
|
|
@@ -66670,11 +66956,11 @@ function containsWindowsAttacks(str) {
|
|
|
66670
66956
|
}
|
|
66671
66957
|
function isPathInWorkspace(filePath, workspace) {
|
|
66672
66958
|
try {
|
|
66673
|
-
const resolvedPath =
|
|
66674
|
-
const realWorkspace =
|
|
66675
|
-
const realResolvedPath =
|
|
66676
|
-
const relativePath =
|
|
66677
|
-
if (relativePath.startsWith("..") ||
|
|
66959
|
+
const resolvedPath = path63.resolve(workspace, filePath);
|
|
66960
|
+
const realWorkspace = fs50.realpathSync(workspace);
|
|
66961
|
+
const realResolvedPath = fs50.realpathSync(resolvedPath);
|
|
66962
|
+
const relativePath = path63.relative(realWorkspace, realResolvedPath);
|
|
66963
|
+
if (relativePath.startsWith("..") || path63.isAbsolute(relativePath)) {
|
|
66678
66964
|
return false;
|
|
66679
66965
|
}
|
|
66680
66966
|
return true;
|
|
@@ -66686,17 +66972,17 @@ function validatePathForRead(filePath, workspace) {
|
|
|
66686
66972
|
return isPathInWorkspace(filePath, workspace);
|
|
66687
66973
|
}
|
|
66688
66974
|
function extractTSSymbols(filePath, cwd) {
|
|
66689
|
-
const fullPath =
|
|
66975
|
+
const fullPath = path63.join(cwd, filePath);
|
|
66690
66976
|
if (!validatePathForRead(fullPath, cwd)) {
|
|
66691
66977
|
return [];
|
|
66692
66978
|
}
|
|
66693
66979
|
let content;
|
|
66694
66980
|
try {
|
|
66695
|
-
const stats =
|
|
66981
|
+
const stats = fs50.statSync(fullPath);
|
|
66696
66982
|
if (stats.size > MAX_FILE_SIZE_BYTES7) {
|
|
66697
66983
|
throw new Error(`File too large: ${stats.size} bytes (max: ${MAX_FILE_SIZE_BYTES7})`);
|
|
66698
66984
|
}
|
|
66699
|
-
content =
|
|
66985
|
+
content = fs50.readFileSync(fullPath, "utf-8");
|
|
66700
66986
|
} catch {
|
|
66701
66987
|
return [];
|
|
66702
66988
|
}
|
|
@@ -66838,17 +67124,17 @@ function extractTSSymbols(filePath, cwd) {
|
|
|
66838
67124
|
});
|
|
66839
67125
|
}
|
|
66840
67126
|
function extractPythonSymbols(filePath, cwd) {
|
|
66841
|
-
const fullPath =
|
|
67127
|
+
const fullPath = path63.join(cwd, filePath);
|
|
66842
67128
|
if (!validatePathForRead(fullPath, cwd)) {
|
|
66843
67129
|
return [];
|
|
66844
67130
|
}
|
|
66845
67131
|
let content;
|
|
66846
67132
|
try {
|
|
66847
|
-
const stats =
|
|
67133
|
+
const stats = fs50.statSync(fullPath);
|
|
66848
67134
|
if (stats.size > MAX_FILE_SIZE_BYTES7) {
|
|
66849
67135
|
throw new Error(`File too large: ${stats.size} bytes (max: ${MAX_FILE_SIZE_BYTES7})`);
|
|
66850
67136
|
}
|
|
66851
|
-
content =
|
|
67137
|
+
content = fs50.readFileSync(fullPath, "utf-8");
|
|
66852
67138
|
} catch {
|
|
66853
67139
|
return [];
|
|
66854
67140
|
}
|
|
@@ -66921,7 +67207,7 @@ var symbols = createSwarmTool({
|
|
|
66921
67207
|
}, null, 2);
|
|
66922
67208
|
}
|
|
66923
67209
|
const cwd = directory;
|
|
66924
|
-
const ext =
|
|
67210
|
+
const ext = path63.extname(file3);
|
|
66925
67211
|
if (containsControlChars(file3)) {
|
|
66926
67212
|
return JSON.stringify({
|
|
66927
67213
|
file: file3,
|
|
@@ -66992,8 +67278,8 @@ init_test_runner();
|
|
|
66992
67278
|
init_dist();
|
|
66993
67279
|
init_utils();
|
|
66994
67280
|
init_create_tool();
|
|
66995
|
-
import * as
|
|
66996
|
-
import * as
|
|
67281
|
+
import * as fs51 from "fs";
|
|
67282
|
+
import * as path64 from "path";
|
|
66997
67283
|
var MAX_TEXT_LENGTH = 200;
|
|
66998
67284
|
var MAX_FILE_SIZE_BYTES8 = 1024 * 1024;
|
|
66999
67285
|
var SUPPORTED_EXTENSIONS2 = new Set([
|
|
@@ -67058,9 +67344,9 @@ function validatePathsInput(paths, cwd) {
|
|
|
67058
67344
|
return { error: "paths contains path traversal", resolvedPath: null };
|
|
67059
67345
|
}
|
|
67060
67346
|
try {
|
|
67061
|
-
const resolvedPath =
|
|
67062
|
-
const normalizedCwd =
|
|
67063
|
-
const normalizedResolved =
|
|
67347
|
+
const resolvedPath = path64.resolve(paths);
|
|
67348
|
+
const normalizedCwd = path64.resolve(cwd);
|
|
67349
|
+
const normalizedResolved = path64.resolve(resolvedPath);
|
|
67064
67350
|
if (!normalizedResolved.startsWith(normalizedCwd)) {
|
|
67065
67351
|
return {
|
|
67066
67352
|
error: "paths must be within the current working directory",
|
|
@@ -67076,13 +67362,13 @@ function validatePathsInput(paths, cwd) {
|
|
|
67076
67362
|
}
|
|
67077
67363
|
}
|
|
67078
67364
|
function isSupportedExtension(filePath) {
|
|
67079
|
-
const ext =
|
|
67365
|
+
const ext = path64.extname(filePath).toLowerCase();
|
|
67080
67366
|
return SUPPORTED_EXTENSIONS2.has(ext);
|
|
67081
67367
|
}
|
|
67082
67368
|
function findSourceFiles2(dir, files = []) {
|
|
67083
67369
|
let entries;
|
|
67084
67370
|
try {
|
|
67085
|
-
entries =
|
|
67371
|
+
entries = fs51.readdirSync(dir);
|
|
67086
67372
|
} catch {
|
|
67087
67373
|
return files;
|
|
67088
67374
|
}
|
|
@@ -67091,10 +67377,10 @@ function findSourceFiles2(dir, files = []) {
|
|
|
67091
67377
|
if (SKIP_DIRECTORIES4.has(entry)) {
|
|
67092
67378
|
continue;
|
|
67093
67379
|
}
|
|
67094
|
-
const fullPath =
|
|
67380
|
+
const fullPath = path64.join(dir, entry);
|
|
67095
67381
|
let stat2;
|
|
67096
67382
|
try {
|
|
67097
|
-
stat2 =
|
|
67383
|
+
stat2 = fs51.statSync(fullPath);
|
|
67098
67384
|
} catch {
|
|
67099
67385
|
continue;
|
|
67100
67386
|
}
|
|
@@ -67187,7 +67473,7 @@ var todo_extract = createSwarmTool({
|
|
|
67187
67473
|
return JSON.stringify(errorResult, null, 2);
|
|
67188
67474
|
}
|
|
67189
67475
|
const scanPath = resolvedPath;
|
|
67190
|
-
if (!
|
|
67476
|
+
if (!fs51.existsSync(scanPath)) {
|
|
67191
67477
|
const errorResult = {
|
|
67192
67478
|
error: `path not found: ${pathsInput}`,
|
|
67193
67479
|
total: 0,
|
|
@@ -67197,13 +67483,13 @@ var todo_extract = createSwarmTool({
|
|
|
67197
67483
|
return JSON.stringify(errorResult, null, 2);
|
|
67198
67484
|
}
|
|
67199
67485
|
const filesToScan = [];
|
|
67200
|
-
const stat2 =
|
|
67486
|
+
const stat2 = fs51.statSync(scanPath);
|
|
67201
67487
|
if (stat2.isFile()) {
|
|
67202
67488
|
if (isSupportedExtension(scanPath)) {
|
|
67203
67489
|
filesToScan.push(scanPath);
|
|
67204
67490
|
} else {
|
|
67205
67491
|
const errorResult = {
|
|
67206
|
-
error: `unsupported file extension: ${
|
|
67492
|
+
error: `unsupported file extension: ${path64.extname(scanPath)}`,
|
|
67207
67493
|
total: 0,
|
|
67208
67494
|
byPriority: { high: 0, medium: 0, low: 0 },
|
|
67209
67495
|
entries: []
|
|
@@ -67216,11 +67502,11 @@ var todo_extract = createSwarmTool({
|
|
|
67216
67502
|
const allEntries = [];
|
|
67217
67503
|
for (const filePath of filesToScan) {
|
|
67218
67504
|
try {
|
|
67219
|
-
const fileStat =
|
|
67505
|
+
const fileStat = fs51.statSync(filePath);
|
|
67220
67506
|
if (fileStat.size > MAX_FILE_SIZE_BYTES8) {
|
|
67221
67507
|
continue;
|
|
67222
67508
|
}
|
|
67223
|
-
const content =
|
|
67509
|
+
const content = fs51.readFileSync(filePath, "utf-8");
|
|
67224
67510
|
const entries = parseTodoComments(content, filePath, tagsSet);
|
|
67225
67511
|
allEntries.push(...entries);
|
|
67226
67512
|
} catch {}
|
|
@@ -67249,18 +67535,18 @@ var todo_extract = createSwarmTool({
|
|
|
67249
67535
|
init_tool();
|
|
67250
67536
|
init_schema();
|
|
67251
67537
|
init_gate_evidence();
|
|
67252
|
-
import * as
|
|
67253
|
-
import * as
|
|
67538
|
+
import * as fs53 from "fs";
|
|
67539
|
+
import * as path66 from "path";
|
|
67254
67540
|
|
|
67255
67541
|
// src/hooks/diff-scope.ts
|
|
67256
|
-
import * as
|
|
67257
|
-
import * as
|
|
67542
|
+
import * as fs52 from "fs";
|
|
67543
|
+
import * as path65 from "path";
|
|
67258
67544
|
function getDeclaredScope(taskId, directory) {
|
|
67259
67545
|
try {
|
|
67260
|
-
const planPath =
|
|
67261
|
-
if (!
|
|
67546
|
+
const planPath = path65.join(directory, ".swarm", "plan.json");
|
|
67547
|
+
if (!fs52.existsSync(planPath))
|
|
67262
67548
|
return null;
|
|
67263
|
-
const raw =
|
|
67549
|
+
const raw = fs52.readFileSync(planPath, "utf-8");
|
|
67264
67550
|
const plan = JSON.parse(raw);
|
|
67265
67551
|
for (const phase of plan.phases ?? []) {
|
|
67266
67552
|
for (const task of phase.tasks ?? []) {
|
|
@@ -67373,7 +67659,7 @@ var TIER_3_PATTERNS = [
|
|
|
67373
67659
|
];
|
|
67374
67660
|
function matchesTier3Pattern(files) {
|
|
67375
67661
|
for (const file3 of files) {
|
|
67376
|
-
const fileName =
|
|
67662
|
+
const fileName = path66.basename(file3);
|
|
67377
67663
|
for (const pattern of TIER_3_PATTERNS) {
|
|
67378
67664
|
if (pattern.test(fileName)) {
|
|
67379
67665
|
return true;
|
|
@@ -67387,8 +67673,8 @@ function checkReviewerGate(taskId, workingDirectory) {
|
|
|
67387
67673
|
if (hasActiveTurboMode()) {
|
|
67388
67674
|
const resolvedDir2 = workingDirectory;
|
|
67389
67675
|
try {
|
|
67390
|
-
const planPath =
|
|
67391
|
-
const planRaw =
|
|
67676
|
+
const planPath = path66.join(resolvedDir2, ".swarm", "plan.json");
|
|
67677
|
+
const planRaw = fs53.readFileSync(planPath, "utf-8");
|
|
67392
67678
|
const plan = JSON.parse(planRaw);
|
|
67393
67679
|
for (const planPhase of plan.phases ?? []) {
|
|
67394
67680
|
for (const task of planPhase.tasks ?? []) {
|
|
@@ -67454,8 +67740,8 @@ function checkReviewerGate(taskId, workingDirectory) {
|
|
|
67454
67740
|
}
|
|
67455
67741
|
try {
|
|
67456
67742
|
const resolvedDir2 = workingDirectory;
|
|
67457
|
-
const planPath =
|
|
67458
|
-
const planRaw =
|
|
67743
|
+
const planPath = path66.join(resolvedDir2, ".swarm", "plan.json");
|
|
67744
|
+
const planRaw = fs53.readFileSync(planPath, "utf-8");
|
|
67459
67745
|
const plan = JSON.parse(planRaw);
|
|
67460
67746
|
for (const planPhase of plan.phases ?? []) {
|
|
67461
67747
|
for (const task of planPhase.tasks ?? []) {
|
|
@@ -67637,8 +67923,8 @@ async function executeUpdateTaskStatus(args2, fallbackDir) {
|
|
|
67637
67923
|
};
|
|
67638
67924
|
}
|
|
67639
67925
|
}
|
|
67640
|
-
normalizedDir =
|
|
67641
|
-
const pathParts = normalizedDir.split(
|
|
67926
|
+
normalizedDir = path66.normalize(args2.working_directory);
|
|
67927
|
+
const pathParts = normalizedDir.split(path66.sep);
|
|
67642
67928
|
if (pathParts.includes("..")) {
|
|
67643
67929
|
return {
|
|
67644
67930
|
success: false,
|
|
@@ -67648,11 +67934,11 @@ async function executeUpdateTaskStatus(args2, fallbackDir) {
|
|
|
67648
67934
|
]
|
|
67649
67935
|
};
|
|
67650
67936
|
}
|
|
67651
|
-
const resolvedDir =
|
|
67937
|
+
const resolvedDir = path66.resolve(normalizedDir);
|
|
67652
67938
|
try {
|
|
67653
|
-
const realPath =
|
|
67654
|
-
const planPath =
|
|
67655
|
-
if (!
|
|
67939
|
+
const realPath = fs53.realpathSync(resolvedDir);
|
|
67940
|
+
const planPath = path66.join(realPath, ".swarm", "plan.json");
|
|
67941
|
+
if (!fs53.existsSync(planPath)) {
|
|
67656
67942
|
return {
|
|
67657
67943
|
success: false,
|
|
67658
67944
|
message: `Invalid working_directory: plan not found in "${realPath}"`,
|
|
@@ -67685,8 +67971,8 @@ async function executeUpdateTaskStatus(args2, fallbackDir) {
|
|
|
67685
67971
|
recoverTaskStateFromDelegations(args2.task_id);
|
|
67686
67972
|
let phaseRequiresReviewer = true;
|
|
67687
67973
|
try {
|
|
67688
|
-
const planPath =
|
|
67689
|
-
const planRaw =
|
|
67974
|
+
const planPath = path66.join(directory, ".swarm", "plan.json");
|
|
67975
|
+
const planRaw = fs53.readFileSync(planPath, "utf-8");
|
|
67690
67976
|
const plan = JSON.parse(planRaw);
|
|
67691
67977
|
const taskPhase = plan.phases.find((p) => p.tasks.some((t) => t.id === args2.task_id));
|
|
67692
67978
|
if (taskPhase?.required_agents && !taskPhase.required_agents.includes("reviewer")) {
|
|
@@ -67749,8 +68035,8 @@ var update_task_status = createSwarmTool({
|
|
|
67749
68035
|
init_tool();
|
|
67750
68036
|
init_utils2();
|
|
67751
68037
|
init_create_tool();
|
|
67752
|
-
import
|
|
67753
|
-
import
|
|
68038
|
+
import fs54 from "fs";
|
|
68039
|
+
import path67 from "path";
|
|
67754
68040
|
function normalizeVerdict(verdict) {
|
|
67755
68041
|
switch (verdict) {
|
|
67756
68042
|
case "APPROVED":
|
|
@@ -67797,7 +68083,7 @@ async function executeWriteDriftEvidence(args2, directory) {
|
|
|
67797
68083
|
entries: [evidenceEntry]
|
|
67798
68084
|
};
|
|
67799
68085
|
const filename = "drift-verifier.json";
|
|
67800
|
-
const relativePath =
|
|
68086
|
+
const relativePath = path67.join("evidence", String(phase), filename);
|
|
67801
68087
|
let validatedPath;
|
|
67802
68088
|
try {
|
|
67803
68089
|
validatedPath = validateSwarmPath(directory, relativePath);
|
|
@@ -67808,12 +68094,12 @@ async function executeWriteDriftEvidence(args2, directory) {
|
|
|
67808
68094
|
message: error93 instanceof Error ? error93.message : "Failed to validate path"
|
|
67809
68095
|
}, null, 2);
|
|
67810
68096
|
}
|
|
67811
|
-
const evidenceDir =
|
|
68097
|
+
const evidenceDir = path67.dirname(validatedPath);
|
|
67812
68098
|
try {
|
|
67813
|
-
await
|
|
67814
|
-
const tempPath =
|
|
67815
|
-
await
|
|
67816
|
-
await
|
|
68099
|
+
await fs54.promises.mkdir(evidenceDir, { recursive: true });
|
|
68100
|
+
const tempPath = path67.join(evidenceDir, `.${filename}.tmp`);
|
|
68101
|
+
await fs54.promises.writeFile(tempPath, JSON.stringify(evidenceContent, null, 2), "utf-8");
|
|
68102
|
+
await fs54.promises.rename(tempPath, validatedPath);
|
|
67817
68103
|
return JSON.stringify({
|
|
67818
68104
|
success: true,
|
|
67819
68105
|
phase,
|
|
@@ -67891,6 +68177,7 @@ ${footerLines.join(`
|
|
|
67891
68177
|
var _heartbeatTimers = new Map;
|
|
67892
68178
|
var OpenCodeSwarm = async (ctx) => {
|
|
67893
68179
|
const { config: config3, loadedFromFile } = loadPluginConfigWithMeta(ctx.directory);
|
|
68180
|
+
swarmState.opencodeClient = ctx.client;
|
|
67894
68181
|
await loadSnapshot(ctx.directory);
|
|
67895
68182
|
initTelemetry(ctx.directory);
|
|
67896
68183
|
const agents = getAgentConfigs(config3);
|
|
@@ -68001,7 +68288,7 @@ var OpenCodeSwarm = async (ctx) => {
|
|
|
68001
68288
|
const { PreflightTriggerManager: PTM } = await Promise.resolve().then(() => (init_trigger(), exports_trigger));
|
|
68002
68289
|
preflightTriggerManager = new PTM(automationConfig);
|
|
68003
68290
|
const { AutomationStatusArtifact: ASA } = await Promise.resolve().then(() => (init_status_artifact(), exports_status_artifact));
|
|
68004
|
-
const swarmDir =
|
|
68291
|
+
const swarmDir = path68.resolve(ctx.directory, ".swarm");
|
|
68005
68292
|
statusArtifact = new ASA(swarmDir);
|
|
68006
68293
|
statusArtifact.updateConfig(automationConfig.mode, automationConfig.capabilities);
|
|
68007
68294
|
if (automationConfig.capabilities?.evidence_auto_summaries === true) {
|
|
@@ -68333,7 +68620,7 @@ var OpenCodeSwarm = async (ctx) => {
|
|
|
68333
68620
|
} catch {}
|
|
68334
68621
|
return Promise.resolve();
|
|
68335
68622
|
},
|
|
68336
|
-
automationConfig.capabilities?.phase_preflight === true && preflightTriggerManager ? createPhaseMonitorHook(ctx.directory, preflightTriggerManager) : knowledgeConfig.enabled ? createPhaseMonitorHook(ctx.directory) : undefined
|
|
68623
|
+
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
68624
|
].filter(Boolean)),
|
|
68338
68625
|
"experimental.session.compacting": compactionHook["experimental.session.compacting"],
|
|
68339
68626
|
"command.execute.before": safeHook(commandHandler),
|