opencode-swarm 6.41.3 → 6.42.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli/index.js +14 -2
- 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 +741 -441
- 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);
|
|
@@ -32342,7 +32349,7 @@ function darkMatterToKnowledgeEntries(pairs, projectName) {
|
|
|
32342
32349
|
lesson,
|
|
32343
32350
|
category: "architecture",
|
|
32344
32351
|
tags: ["hidden-coupling", "co-change", "dark-matter"],
|
|
32345
|
-
scope: "
|
|
32352
|
+
scope: "global",
|
|
32346
32353
|
confidence,
|
|
32347
32354
|
status: "candidate",
|
|
32348
32355
|
confirmed_by: [],
|
|
@@ -37293,6 +37300,184 @@ var init_gate_evidence = __esm(() => {
|
|
|
37293
37300
|
TASK_ID_PATTERN = /^\d+\.\d+(\.\d+)*$/;
|
|
37294
37301
|
});
|
|
37295
37302
|
|
|
37303
|
+
// src/hooks/review-receipt.ts
|
|
37304
|
+
var exports_review_receipt = {};
|
|
37305
|
+
__export(exports_review_receipt, {
|
|
37306
|
+
resolveReceiptsDir: () => resolveReceiptsDir,
|
|
37307
|
+
resolveReceiptIndexPath: () => resolveReceiptIndexPath,
|
|
37308
|
+
readReceiptsByScopeHash: () => readReceiptsByScopeHash,
|
|
37309
|
+
readReceiptById: () => readReceiptById,
|
|
37310
|
+
readAllReceipts: () => readAllReceipts,
|
|
37311
|
+
persistReviewReceipt: () => persistReviewReceipt,
|
|
37312
|
+
isScopeStale: () => isScopeStale,
|
|
37313
|
+
computeScopeFingerprint: () => computeScopeFingerprint,
|
|
37314
|
+
buildRejectedReceipt: () => buildRejectedReceipt,
|
|
37315
|
+
buildReceiptContextForDrift: () => buildReceiptContextForDrift,
|
|
37316
|
+
buildApprovedReceipt: () => buildApprovedReceipt
|
|
37317
|
+
});
|
|
37318
|
+
import * as crypto4 from "crypto";
|
|
37319
|
+
import * as fs25 from "fs";
|
|
37320
|
+
import * as path36 from "path";
|
|
37321
|
+
function resolveReceiptsDir(directory) {
|
|
37322
|
+
return path36.join(directory, ".swarm", "review-receipts");
|
|
37323
|
+
}
|
|
37324
|
+
function resolveReceiptIndexPath(directory) {
|
|
37325
|
+
return path36.join(resolveReceiptsDir(directory), "index.json");
|
|
37326
|
+
}
|
|
37327
|
+
function buildReceiptFilename(id, date9) {
|
|
37328
|
+
const dateStr = date9.toISOString().slice(0, 10);
|
|
37329
|
+
return `${dateStr}-${id}.json`;
|
|
37330
|
+
}
|
|
37331
|
+
function computeScopeFingerprint(content, scopeDescription) {
|
|
37332
|
+
const hash3 = crypto4.createHash("sha256").update(content, "utf-8").digest("hex");
|
|
37333
|
+
return {
|
|
37334
|
+
hash: hash3,
|
|
37335
|
+
scope_description: scopeDescription,
|
|
37336
|
+
content_length: content.length
|
|
37337
|
+
};
|
|
37338
|
+
}
|
|
37339
|
+
function isScopeStale(receipt, currentContent) {
|
|
37340
|
+
if (currentContent === undefined) {
|
|
37341
|
+
return true;
|
|
37342
|
+
}
|
|
37343
|
+
const currentHash = crypto4.createHash("sha256").update(currentContent, "utf-8").digest("hex");
|
|
37344
|
+
return currentHash !== receipt.scope_fingerprint.hash;
|
|
37345
|
+
}
|
|
37346
|
+
async function readReceiptIndex(directory) {
|
|
37347
|
+
const indexPath = resolveReceiptIndexPath(directory);
|
|
37348
|
+
if (!fs25.existsSync(indexPath)) {
|
|
37349
|
+
return { schema_version: 1, entries: [] };
|
|
37350
|
+
}
|
|
37351
|
+
try {
|
|
37352
|
+
const content = await fs25.promises.readFile(indexPath, "utf-8");
|
|
37353
|
+
const parsed = JSON.parse(content);
|
|
37354
|
+
if (parsed.schema_version !== 1 || !Array.isArray(parsed.entries)) {
|
|
37355
|
+
return { schema_version: 1, entries: [] };
|
|
37356
|
+
}
|
|
37357
|
+
return parsed;
|
|
37358
|
+
} catch {
|
|
37359
|
+
return { schema_version: 1, entries: [] };
|
|
37360
|
+
}
|
|
37361
|
+
}
|
|
37362
|
+
async function writeReceiptIndex(directory, index) {
|
|
37363
|
+
const indexPath = resolveReceiptIndexPath(directory);
|
|
37364
|
+
const dir = path36.dirname(indexPath);
|
|
37365
|
+
await fs25.promises.mkdir(dir, { recursive: true });
|
|
37366
|
+
const tmpPath = `${indexPath}.tmp.${Date.now()}.${Math.random().toString(36).slice(2)}`;
|
|
37367
|
+
await fs25.promises.writeFile(tmpPath, JSON.stringify(index, null, 2), "utf-8");
|
|
37368
|
+
fs25.renameSync(tmpPath, indexPath);
|
|
37369
|
+
}
|
|
37370
|
+
async function persistReviewReceipt(directory, receipt) {
|
|
37371
|
+
const receiptsDir = resolveReceiptsDir(directory);
|
|
37372
|
+
await fs25.promises.mkdir(receiptsDir, { recursive: true });
|
|
37373
|
+
const now = new Date(receipt.reviewed_at);
|
|
37374
|
+
const filename = buildReceiptFilename(receipt.id, now);
|
|
37375
|
+
const receiptPath = path36.join(receiptsDir, filename);
|
|
37376
|
+
const tmpPath = `${receiptPath}.tmp.${Date.now()}.${Math.random().toString(36).slice(2)}`;
|
|
37377
|
+
await fs25.promises.writeFile(tmpPath, JSON.stringify(receipt, null, 2), "utf-8");
|
|
37378
|
+
fs25.renameSync(tmpPath, receiptPath);
|
|
37379
|
+
const index = await readReceiptIndex(directory);
|
|
37380
|
+
const entry = {
|
|
37381
|
+
id: receipt.id,
|
|
37382
|
+
verdict: receipt.verdict,
|
|
37383
|
+
reviewed_at: receipt.reviewed_at,
|
|
37384
|
+
scope_hash: receipt.scope_fingerprint.hash,
|
|
37385
|
+
agent: receipt.reviewer.agent,
|
|
37386
|
+
filename
|
|
37387
|
+
};
|
|
37388
|
+
index.entries.push(entry);
|
|
37389
|
+
await writeReceiptIndex(directory, index);
|
|
37390
|
+
return receiptPath;
|
|
37391
|
+
}
|
|
37392
|
+
async function readReceiptById(directory, receiptId) {
|
|
37393
|
+
const index = await readReceiptIndex(directory);
|
|
37394
|
+
const entry = index.entries.find((e) => e.id === receiptId);
|
|
37395
|
+
if (!entry)
|
|
37396
|
+
return null;
|
|
37397
|
+
const receiptPath = path36.join(resolveReceiptsDir(directory), entry.filename);
|
|
37398
|
+
try {
|
|
37399
|
+
const content = await fs25.promises.readFile(receiptPath, "utf-8");
|
|
37400
|
+
return JSON.parse(content);
|
|
37401
|
+
} catch {
|
|
37402
|
+
return null;
|
|
37403
|
+
}
|
|
37404
|
+
}
|
|
37405
|
+
async function readReceiptsByScopeHash(directory, scopeHash) {
|
|
37406
|
+
const index = await readReceiptIndex(directory);
|
|
37407
|
+
const matching = index.entries.filter((e) => e.scope_hash === scopeHash).sort((a, b) => b.reviewed_at.localeCompare(a.reviewed_at));
|
|
37408
|
+
const receipts = [];
|
|
37409
|
+
for (const entry of matching) {
|
|
37410
|
+
const receiptPath = path36.join(resolveReceiptsDir(directory), entry.filename);
|
|
37411
|
+
try {
|
|
37412
|
+
const content = await fs25.promises.readFile(receiptPath, "utf-8");
|
|
37413
|
+
receipts.push(JSON.parse(content));
|
|
37414
|
+
} catch {}
|
|
37415
|
+
}
|
|
37416
|
+
return receipts;
|
|
37417
|
+
}
|
|
37418
|
+
async function readAllReceipts(directory) {
|
|
37419
|
+
const index = await readReceiptIndex(directory);
|
|
37420
|
+
const sorted = [...index.entries].sort((a, b) => b.reviewed_at.localeCompare(a.reviewed_at));
|
|
37421
|
+
const receipts = [];
|
|
37422
|
+
for (const entry of sorted) {
|
|
37423
|
+
const receiptPath = path36.join(resolveReceiptsDir(directory), entry.filename);
|
|
37424
|
+
try {
|
|
37425
|
+
const content = await fs25.promises.readFile(receiptPath, "utf-8");
|
|
37426
|
+
receipts.push(JSON.parse(content));
|
|
37427
|
+
} catch {}
|
|
37428
|
+
}
|
|
37429
|
+
return receipts;
|
|
37430
|
+
}
|
|
37431
|
+
function buildRejectedReceipt(opts) {
|
|
37432
|
+
return {
|
|
37433
|
+
schema_version: 1,
|
|
37434
|
+
id: crypto4.randomUUID(),
|
|
37435
|
+
receipt_type: "rejected",
|
|
37436
|
+
verdict: "rejected",
|
|
37437
|
+
reviewer: { agent: opts.agent, session_id: opts.sessionId },
|
|
37438
|
+
reviewed_at: new Date().toISOString(),
|
|
37439
|
+
scope_fingerprint: computeScopeFingerprint(opts.scopeContent, opts.scopeDescription),
|
|
37440
|
+
blocking_findings: opts.blockingFindings,
|
|
37441
|
+
evidence_references: opts.evidenceReferences,
|
|
37442
|
+
pass_conditions: opts.passConditions,
|
|
37443
|
+
summary: opts.summary
|
|
37444
|
+
};
|
|
37445
|
+
}
|
|
37446
|
+
function buildApprovedReceipt(opts) {
|
|
37447
|
+
return {
|
|
37448
|
+
schema_version: 1,
|
|
37449
|
+
id: crypto4.randomUUID(),
|
|
37450
|
+
receipt_type: "approved",
|
|
37451
|
+
verdict: "approved",
|
|
37452
|
+
reviewer: { agent: opts.agent, session_id: opts.sessionId },
|
|
37453
|
+
reviewed_at: new Date().toISOString(),
|
|
37454
|
+
scope_fingerprint: computeScopeFingerprint(opts.scopeContent, opts.scopeDescription),
|
|
37455
|
+
checked_aspects: opts.checkedAspects,
|
|
37456
|
+
validated_claims: opts.validatedClaims,
|
|
37457
|
+
caveats: opts.caveats
|
|
37458
|
+
};
|
|
37459
|
+
}
|
|
37460
|
+
function buildReceiptContextForDrift(receipts, currentScopeContent, maxChars = 1000) {
|
|
37461
|
+
if (receipts.length === 0)
|
|
37462
|
+
return "";
|
|
37463
|
+
const lines = ["## Prior Review Receipts (supporting context)"];
|
|
37464
|
+
for (const receipt of receipts) {
|
|
37465
|
+
const stale = receipt.verdict === "approved" ? isScopeStale(receipt, currentScopeContent) : false;
|
|
37466
|
+
const staleTag = stale ? " [SCOPE-STALE \u2014 treat as context only]" : "";
|
|
37467
|
+
if (receipt.verdict === "rejected") {
|
|
37468
|
+
const r = receipt;
|
|
37469
|
+
lines.push(`- REJECTED by ${r.reviewer.agent} at ${r.reviewed_at.slice(0, 10)}: ` + `${r.blocking_findings.length} blocking finding(s). ` + `Pass conditions: ${r.pass_conditions.slice(0, 2).join("; ")}.`);
|
|
37470
|
+
} else {
|
|
37471
|
+
const a = receipt;
|
|
37472
|
+
lines.push(`- APPROVED by ${a.reviewer.agent} at ${a.reviewed_at.slice(0, 10)}${staleTag}: ` + `checked [${a.checked_aspects.join(", ")}]. ` + (a.caveats && a.caveats.length > 0 ? `Caveats: ${a.caveats[0]}.` : "No caveats recorded."));
|
|
37473
|
+
}
|
|
37474
|
+
}
|
|
37475
|
+
lines.push("Note: Approved receipts are supporting evidence only. Stale receipts must not be blindly trusted.");
|
|
37476
|
+
return lines.join(`
|
|
37477
|
+
`).slice(0, maxChars);
|
|
37478
|
+
}
|
|
37479
|
+
var init_review_receipt = () => {};
|
|
37480
|
+
|
|
37296
37481
|
// src/services/preflight-integration.ts
|
|
37297
37482
|
var exports_preflight_integration = {};
|
|
37298
37483
|
__export(exports_preflight_integration, {
|
|
@@ -37368,16 +37553,16 @@ __export(exports_doc_scan, {
|
|
|
37368
37553
|
doc_scan: () => doc_scan,
|
|
37369
37554
|
doc_extract: () => doc_extract
|
|
37370
37555
|
});
|
|
37371
|
-
import * as
|
|
37372
|
-
import * as
|
|
37556
|
+
import * as crypto5 from "crypto";
|
|
37557
|
+
import * as fs28 from "fs";
|
|
37373
37558
|
import { mkdir as mkdir6, readFile as readFile6, writeFile as writeFile5 } from "fs/promises";
|
|
37374
|
-
import * as
|
|
37559
|
+
import * as path40 from "path";
|
|
37375
37560
|
function normalizeSeparators(filePath) {
|
|
37376
37561
|
return filePath.replace(/\\/g, "/");
|
|
37377
37562
|
}
|
|
37378
37563
|
function matchesDocPattern(filePath, patterns) {
|
|
37379
37564
|
const normalizedPath = normalizeSeparators(filePath);
|
|
37380
|
-
const basename5 =
|
|
37565
|
+
const basename5 = path40.basename(filePath);
|
|
37381
37566
|
for (const pattern of patterns) {
|
|
37382
37567
|
if (!pattern.includes("/") && !pattern.includes("\\")) {
|
|
37383
37568
|
if (basename5 === pattern) {
|
|
@@ -37433,7 +37618,7 @@ function stripMarkdown(text) {
|
|
|
37433
37618
|
return text.replace(/\[([^\]]+)\]\([^)]+\)/g, "$1").replace(/\*\*([^*]+)\*\*/g, "$1").replace(/`([^`]+)`/g, "$1").replace(/^\s*[-*\u2022]\s+/gm, "").replace(/^\s*\d+\.\s+/gm, "").trim();
|
|
37434
37619
|
}
|
|
37435
37620
|
async function scanDocIndex(directory) {
|
|
37436
|
-
const manifestPath =
|
|
37621
|
+
const manifestPath = path40.join(directory, ".swarm", "doc-manifest.json");
|
|
37437
37622
|
const defaultPatterns = DocsConfigSchema.parse({}).doc_patterns;
|
|
37438
37623
|
const extraPatterns = [
|
|
37439
37624
|
"ARCHITECTURE.md",
|
|
@@ -37450,8 +37635,8 @@ async function scanDocIndex(directory) {
|
|
|
37450
37635
|
let cacheValid = true;
|
|
37451
37636
|
for (const file3 of existingManifest.files) {
|
|
37452
37637
|
try {
|
|
37453
|
-
const fullPath =
|
|
37454
|
-
const stat2 =
|
|
37638
|
+
const fullPath = path40.join(directory, file3.path);
|
|
37639
|
+
const stat2 = fs28.statSync(fullPath);
|
|
37455
37640
|
if (stat2.mtimeMs > new Date(existingManifest.scanned_at).getTime()) {
|
|
37456
37641
|
cacheValid = false;
|
|
37457
37642
|
break;
|
|
@@ -37469,7 +37654,7 @@ async function scanDocIndex(directory) {
|
|
|
37469
37654
|
const discoveredFiles = [];
|
|
37470
37655
|
let rawEntries;
|
|
37471
37656
|
try {
|
|
37472
|
-
rawEntries =
|
|
37657
|
+
rawEntries = fs28.readdirSync(directory, { recursive: true });
|
|
37473
37658
|
} catch {
|
|
37474
37659
|
const manifest2 = {
|
|
37475
37660
|
schema_version: 1,
|
|
@@ -37480,10 +37665,10 @@ async function scanDocIndex(directory) {
|
|
|
37480
37665
|
}
|
|
37481
37666
|
const entries = rawEntries.filter((e) => typeof e === "string");
|
|
37482
37667
|
for (const entry of entries) {
|
|
37483
|
-
const fullPath =
|
|
37668
|
+
const fullPath = path40.join(directory, entry);
|
|
37484
37669
|
let stat2;
|
|
37485
37670
|
try {
|
|
37486
|
-
stat2 =
|
|
37671
|
+
stat2 = fs28.statSync(fullPath);
|
|
37487
37672
|
} catch {
|
|
37488
37673
|
continue;
|
|
37489
37674
|
}
|
|
@@ -37512,11 +37697,11 @@ async function scanDocIndex(directory) {
|
|
|
37512
37697
|
}
|
|
37513
37698
|
let content;
|
|
37514
37699
|
try {
|
|
37515
|
-
content =
|
|
37700
|
+
content = fs28.readFileSync(fullPath, "utf-8");
|
|
37516
37701
|
} catch {
|
|
37517
37702
|
continue;
|
|
37518
37703
|
}
|
|
37519
|
-
const { title, summary } = extractTitleAndSummary(content,
|
|
37704
|
+
const { title, summary } = extractTitleAndSummary(content, path40.basename(entry));
|
|
37520
37705
|
const lineCount = content.split(`
|
|
37521
37706
|
`).length;
|
|
37522
37707
|
discoveredFiles.push({
|
|
@@ -37542,7 +37727,7 @@ async function scanDocIndex(directory) {
|
|
|
37542
37727
|
files: discoveredFiles
|
|
37543
37728
|
};
|
|
37544
37729
|
try {
|
|
37545
|
-
await mkdir6(
|
|
37730
|
+
await mkdir6(path40.dirname(manifestPath), { recursive: true });
|
|
37546
37731
|
await writeFile5(manifestPath, JSON.stringify(manifest, null, 2), "utf-8");
|
|
37547
37732
|
} catch {}
|
|
37548
37733
|
return { manifest, cached: false };
|
|
@@ -37581,7 +37766,7 @@ function extractConstraintsFromContent(content) {
|
|
|
37581
37766
|
return constraints;
|
|
37582
37767
|
}
|
|
37583
37768
|
async function extractDocConstraints(directory, taskFiles, taskDescription) {
|
|
37584
|
-
const manifestPath =
|
|
37769
|
+
const manifestPath = path40.join(directory, ".swarm", "doc-manifest.json");
|
|
37585
37770
|
let manifest;
|
|
37586
37771
|
try {
|
|
37587
37772
|
const content = await readFile6(manifestPath, "utf-8");
|
|
@@ -37607,7 +37792,7 @@ async function extractDocConstraints(directory, taskFiles, taskDescription) {
|
|
|
37607
37792
|
}
|
|
37608
37793
|
let fullContent;
|
|
37609
37794
|
try {
|
|
37610
|
-
fullContent = await readFile6(
|
|
37795
|
+
fullContent = await readFile6(path40.join(directory, docFile.path), "utf-8");
|
|
37611
37796
|
} catch {
|
|
37612
37797
|
skippedCount++;
|
|
37613
37798
|
continue;
|
|
@@ -37626,11 +37811,11 @@ async function extractDocConstraints(directory, taskFiles, taskDescription) {
|
|
|
37626
37811
|
const duplicate = findNearDuplicate(constraint, existingEntries, DEDUP_THRESHOLD);
|
|
37627
37812
|
if (!duplicate) {
|
|
37628
37813
|
const entry = {
|
|
37629
|
-
id:
|
|
37814
|
+
id: crypto5.randomUUID(),
|
|
37630
37815
|
tier: "swarm",
|
|
37631
37816
|
lesson: constraint,
|
|
37632
37817
|
category: "architecture",
|
|
37633
|
-
tags: ["doc-scan",
|
|
37818
|
+
tags: ["doc-scan", path40.basename(docFile.path)],
|
|
37634
37819
|
scope: "global",
|
|
37635
37820
|
confidence: 0.5,
|
|
37636
37821
|
status: "candidate",
|
|
@@ -37703,9 +37888,9 @@ var init_doc_scan = __esm(() => {
|
|
|
37703
37888
|
}
|
|
37704
37889
|
} catch {}
|
|
37705
37890
|
if (force) {
|
|
37706
|
-
const manifestPath =
|
|
37891
|
+
const manifestPath = path40.join(directory, ".swarm", "doc-manifest.json");
|
|
37707
37892
|
try {
|
|
37708
|
-
|
|
37893
|
+
fs28.unlinkSync(manifestPath);
|
|
37709
37894
|
} catch {}
|
|
37710
37895
|
}
|
|
37711
37896
|
const { manifest, cached: cached3 } = await scanDocIndex(directory);
|
|
@@ -37757,11 +37942,11 @@ __export(exports_curator_drift, {
|
|
|
37757
37942
|
readPriorDriftReports: () => readPriorDriftReports,
|
|
37758
37943
|
buildDriftInjectionText: () => buildDriftInjectionText
|
|
37759
37944
|
});
|
|
37760
|
-
import * as
|
|
37761
|
-
import * as
|
|
37945
|
+
import * as fs31 from "fs";
|
|
37946
|
+
import * as path43 from "path";
|
|
37762
37947
|
async function readPriorDriftReports(directory) {
|
|
37763
|
-
const swarmDir =
|
|
37764
|
-
const entries = await
|
|
37948
|
+
const swarmDir = path43.join(directory, ".swarm");
|
|
37949
|
+
const entries = await fs31.promises.readdir(swarmDir).catch(() => null);
|
|
37765
37950
|
if (entries === null)
|
|
37766
37951
|
return [];
|
|
37767
37952
|
const reportFiles = entries.filter((name2) => name2.startsWith(DRIFT_REPORT_PREFIX) && name2.endsWith(".json")).sort();
|
|
@@ -37787,10 +37972,10 @@ async function readPriorDriftReports(directory) {
|
|
|
37787
37972
|
async function writeDriftReport(directory, report) {
|
|
37788
37973
|
const filename = `${DRIFT_REPORT_PREFIX}${report.phase}.json`;
|
|
37789
37974
|
const filePath = validateSwarmPath(directory, filename);
|
|
37790
|
-
const swarmDir =
|
|
37791
|
-
await
|
|
37975
|
+
const swarmDir = path43.dirname(filePath);
|
|
37976
|
+
await fs31.promises.mkdir(swarmDir, { recursive: true });
|
|
37792
37977
|
try {
|
|
37793
|
-
await
|
|
37978
|
+
await fs31.promises.writeFile(filePath, JSON.stringify(report, null, 2), "utf-8");
|
|
37794
37979
|
} catch (err2) {
|
|
37795
37980
|
throw new Error(`[curator-drift] Failed to write drift report to ${filePath}: ${String(err2)}`);
|
|
37796
37981
|
}
|
|
@@ -39380,11 +39565,11 @@ ${JSON.stringify(symbolNames, null, 2)}`);
|
|
|
39380
39565
|
throw toThrow;
|
|
39381
39566
|
}, "quit_");
|
|
39382
39567
|
var scriptDirectory = "";
|
|
39383
|
-
function locateFile(
|
|
39568
|
+
function locateFile(path51) {
|
|
39384
39569
|
if (Module["locateFile"]) {
|
|
39385
|
-
return Module["locateFile"](
|
|
39570
|
+
return Module["locateFile"](path51, scriptDirectory);
|
|
39386
39571
|
}
|
|
39387
|
-
return scriptDirectory +
|
|
39572
|
+
return scriptDirectory + path51;
|
|
39388
39573
|
}
|
|
39389
39574
|
__name(locateFile, "locateFile");
|
|
39390
39575
|
var readAsync, readBinary;
|
|
@@ -41124,13 +41309,13 @@ ${JSON.stringify(symbolNames, null, 2)}`);
|
|
|
41124
41309
|
});
|
|
41125
41310
|
|
|
41126
41311
|
// src/lang/runtime.ts
|
|
41127
|
-
import * as
|
|
41312
|
+
import * as path51 from "path";
|
|
41128
41313
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
41129
41314
|
async function initTreeSitter() {
|
|
41130
41315
|
if (treeSitterInitialized) {
|
|
41131
41316
|
return;
|
|
41132
41317
|
}
|
|
41133
|
-
const thisDir =
|
|
41318
|
+
const thisDir = path51.dirname(fileURLToPath2(import.meta.url));
|
|
41134
41319
|
const isSource = thisDir.replace(/\\/g, "/").endsWith("/src/lang");
|
|
41135
41320
|
if (isSource) {
|
|
41136
41321
|
await Parser.init();
|
|
@@ -41138,7 +41323,7 @@ async function initTreeSitter() {
|
|
|
41138
41323
|
const grammarsDir = getGrammarsDirAbsolute();
|
|
41139
41324
|
await Parser.init({
|
|
41140
41325
|
locateFile(scriptName) {
|
|
41141
|
-
return
|
|
41326
|
+
return path51.join(grammarsDir, scriptName);
|
|
41142
41327
|
}
|
|
41143
41328
|
});
|
|
41144
41329
|
}
|
|
@@ -41159,9 +41344,9 @@ function getWasmFileName(languageId) {
|
|
|
41159
41344
|
return `tree-sitter-${sanitized}.wasm`;
|
|
41160
41345
|
}
|
|
41161
41346
|
function getGrammarsDirAbsolute() {
|
|
41162
|
-
const thisDir =
|
|
41347
|
+
const thisDir = path51.dirname(fileURLToPath2(import.meta.url));
|
|
41163
41348
|
const isSource = thisDir.replace(/\\/g, "/").endsWith("/src/lang");
|
|
41164
|
-
return isSource ?
|
|
41349
|
+
return isSource ? path51.join(thisDir, "grammars") : path51.join(thisDir, "lang", "grammars");
|
|
41165
41350
|
}
|
|
41166
41351
|
async function loadGrammar(languageId) {
|
|
41167
41352
|
if (typeof languageId !== "string" || languageId.length > 100) {
|
|
@@ -41177,9 +41362,9 @@ async function loadGrammar(languageId) {
|
|
|
41177
41362
|
await initTreeSitter();
|
|
41178
41363
|
const parser = new Parser;
|
|
41179
41364
|
const wasmFileName = getWasmFileName(normalizedId);
|
|
41180
|
-
const wasmPath =
|
|
41181
|
-
const { existsSync:
|
|
41182
|
-
if (!
|
|
41365
|
+
const wasmPath = path51.join(getGrammarsDirAbsolute(), wasmFileName);
|
|
41366
|
+
const { existsSync: existsSync30 } = await import("fs");
|
|
41367
|
+
if (!existsSync30(wasmPath)) {
|
|
41183
41368
|
throw new Error(`Grammar file not found for ${languageId}: ${wasmPath}
|
|
41184
41369
|
Make sure to run 'bun run build' to copy grammar files to dist/lang/grammars/`);
|
|
41185
41370
|
}
|
|
@@ -41224,7 +41409,7 @@ var init_runtime = __esm(() => {
|
|
|
41224
41409
|
});
|
|
41225
41410
|
|
|
41226
41411
|
// src/index.ts
|
|
41227
|
-
import * as
|
|
41412
|
+
import * as path68 from "path";
|
|
41228
41413
|
|
|
41229
41414
|
// src/agents/index.ts
|
|
41230
41415
|
init_config();
|
|
@@ -41245,6 +41430,7 @@ var swarmState = {
|
|
|
41245
41430
|
activeAgent: new Map,
|
|
41246
41431
|
delegationChains: new Map,
|
|
41247
41432
|
pendingEvents: 0,
|
|
41433
|
+
opencodeClient: null,
|
|
41248
41434
|
lastBudgetPct: 0,
|
|
41249
41435
|
agentSessions: new Map,
|
|
41250
41436
|
pendingRehydrations: new Set
|
|
@@ -41750,7 +41936,7 @@ Output to .swarm/plan.md MUST use "## Phase N" headers. Do not write MODE labels
|
|
|
41750
41936
|
1. DELEGATE all coding to {{AGENT_PREFIX}}coder. You do NOT write code.
|
|
41751
41937
|
// IMPORTANT: This list MUST match AGENT_TOOL_MAP['architect'] in src/config/constants.ts
|
|
41752
41938
|
// If you add a tool to the map, add it here. If you remove it from the map, remove it here.
|
|
41753
|
-
YOUR TOOLS: Task (delegation),
|
|
41939
|
+
YOUR TOOLS: Task (delegation), build_check, check_gate_status, checkpoint, co_change_analyzer, completion_verify, complexity_hotspots, curator_analyze, declare_scope, detect_domains, diff, doc_extract, doc_scan, evidence_check, extract_code_blocks, gitingest, imports, knowledgeAdd, knowledge_query, knowledgeRecall, knowledgeRemove, lint, phase_complete, pkg_audit, placeholder_scan, pre_check_batch, quality_budget, retrieve_summary, sast_scan, save_plan, sbom_generate, schema_drift, secretscan, symbols, syntax_check, test_runner, todo_extract, update_task_status, write_drift_evidence, write_retro.
|
|
41754
41940
|
CODER'S TOOLS: write, edit, patch, apply_patch, create_file, insert, replace \u2014 any tool that modifies file contents.
|
|
41755
41941
|
If a tool modifies a file, it is a CODER tool. Delegate.
|
|
41756
41942
|
2. ONE agent per message. Send, STOP, wait for response.
|
|
@@ -45913,7 +46099,9 @@ async function recordLessonsShown(directory, lessonIds, currentPhase) {
|
|
|
45913
46099
|
const content = await readFile3(shownFile, "utf-8");
|
|
45914
46100
|
shownData = JSON.parse(content);
|
|
45915
46101
|
}
|
|
45916
|
-
|
|
46102
|
+
const phaseMatch = /^Phase\s+(\d+)/i.exec(currentPhase);
|
|
46103
|
+
const canonicalKey = phaseMatch ? `Phase ${phaseMatch[1]}` : currentPhase;
|
|
46104
|
+
shownData[canonicalKey] = lessonIds;
|
|
45917
46105
|
await mkdir2(path12.dirname(shownFile), { recursive: true });
|
|
45918
46106
|
await writeFile2(shownFile, JSON.stringify(shownData, null, 2), "utf-8");
|
|
45919
46107
|
} catch {
|
|
@@ -46637,6 +46825,7 @@ async function curateAndStoreSwarm(lessons, projectName, phaseInfo, directory, c
|
|
|
46637
46825
|
stored++;
|
|
46638
46826
|
existingEntries.push(entry);
|
|
46639
46827
|
}
|
|
46828
|
+
await enforceKnowledgeCap(knowledgePath, config3.swarm_max_entries);
|
|
46640
46829
|
await runAutoPromotion(directory, config3);
|
|
46641
46830
|
return { stored, skipped, rejected };
|
|
46642
46831
|
}
|
|
@@ -48003,6 +48192,9 @@ async function checkHivePromotions(swarmEntries, config3) {
|
|
|
48003
48192
|
if (hiveModified) {
|
|
48004
48193
|
await rewriteKnowledge(resolveHiveKnowledgePath(), hiveEntries);
|
|
48005
48194
|
}
|
|
48195
|
+
if (newPromotions > 0 || hiveModified) {
|
|
48196
|
+
await enforceKnowledgeCap(resolveHiveKnowledgePath(), config3.hive_max_entries);
|
|
48197
|
+
}
|
|
48006
48198
|
return {
|
|
48007
48199
|
timestamp: new Date().toISOString(),
|
|
48008
48200
|
new_promotions: newPromotions,
|
|
@@ -52176,6 +52368,43 @@ function maskToolOutput(msg, _threshold) {
|
|
|
52176
52368
|
}
|
|
52177
52369
|
return freedTokens;
|
|
52178
52370
|
}
|
|
52371
|
+
// src/hooks/curator-llm-factory.ts
|
|
52372
|
+
function createCuratorLLMDelegate(directory) {
|
|
52373
|
+
const client = swarmState.opencodeClient;
|
|
52374
|
+
if (!client)
|
|
52375
|
+
return;
|
|
52376
|
+
return async (systemPrompt, userInput) => {
|
|
52377
|
+
let ephemeralSessionId;
|
|
52378
|
+
try {
|
|
52379
|
+
const createResult = await client.session.create({
|
|
52380
|
+
query: { directory }
|
|
52381
|
+
});
|
|
52382
|
+
if (!createResult.data) {
|
|
52383
|
+
throw new Error(`Failed to create curator session: ${JSON.stringify(createResult.error)}`);
|
|
52384
|
+
}
|
|
52385
|
+
ephemeralSessionId = createResult.data.id;
|
|
52386
|
+
const promptResult = await client.session.prompt({
|
|
52387
|
+
path: { id: ephemeralSessionId },
|
|
52388
|
+
body: {
|
|
52389
|
+
agent: "explorer",
|
|
52390
|
+
system: systemPrompt,
|
|
52391
|
+
tools: { write: false, edit: false, patch: false },
|
|
52392
|
+
parts: [{ type: "text", text: userInput }]
|
|
52393
|
+
}
|
|
52394
|
+
});
|
|
52395
|
+
if (!promptResult.data) {
|
|
52396
|
+
throw new Error(`Curator LLM prompt failed: ${JSON.stringify(promptResult.error)}`);
|
|
52397
|
+
}
|
|
52398
|
+
const textParts = promptResult.data.parts.filter((p) => p.type === "text");
|
|
52399
|
+
return textParts.map((p) => p.text).join(`
|
|
52400
|
+
`);
|
|
52401
|
+
} finally {
|
|
52402
|
+
if (ephemeralSessionId) {
|
|
52403
|
+
client.session.delete({ path: { id: ephemeralSessionId } }).catch(() => {});
|
|
52404
|
+
}
|
|
52405
|
+
}
|
|
52406
|
+
};
|
|
52407
|
+
}
|
|
52179
52408
|
// src/hooks/delegation-gate.ts
|
|
52180
52409
|
init_schema();
|
|
52181
52410
|
import * as fs23 from "fs";
|
|
@@ -54198,11 +54427,12 @@ function consolidateSystemMessages(messages) {
|
|
|
54198
54427
|
// src/hooks/phase-monitor.ts
|
|
54199
54428
|
init_schema();
|
|
54200
54429
|
init_manager2();
|
|
54201
|
-
import * as
|
|
54430
|
+
import * as path37 from "path";
|
|
54202
54431
|
init_utils2();
|
|
54203
|
-
function createPhaseMonitorHook(directory, preflightManager, curatorRunner
|
|
54432
|
+
function createPhaseMonitorHook(directory, preflightManager, curatorRunner, llmDelegate) {
|
|
54204
54433
|
let lastKnownPhase = null;
|
|
54205
54434
|
const handler = async (_input, _output) => {
|
|
54435
|
+
const runner = curatorRunner ?? runCuratorInit;
|
|
54206
54436
|
const plan = await loadPlan(directory);
|
|
54207
54437
|
if (!plan)
|
|
54208
54438
|
return;
|
|
@@ -54214,12 +54444,29 @@ function createPhaseMonitorHook(directory, preflightManager, curatorRunner = run
|
|
|
54214
54444
|
const { config: config3 } = loadPluginConfigWithMeta2(directory);
|
|
54215
54445
|
const curatorConfig = CuratorConfigSchema.parse(config3.curator ?? {});
|
|
54216
54446
|
if (curatorConfig.enabled && curatorConfig.init_enabled) {
|
|
54217
|
-
const initResult = await
|
|
54447
|
+
const initResult = await runner(directory, curatorConfig, llmDelegate);
|
|
54218
54448
|
if (initResult.briefing) {
|
|
54219
|
-
const briefingPath =
|
|
54449
|
+
const briefingPath = path37.join(directory, ".swarm", "curator-briefing.md");
|
|
54220
54450
|
const { mkdir: mkdir5, writeFile: writeFile5 } = await import("fs/promises");
|
|
54221
|
-
await mkdir5(
|
|
54451
|
+
await mkdir5(path37.dirname(briefingPath), { recursive: true });
|
|
54222
54452
|
await writeFile5(briefingPath, initResult.briefing, "utf-8");
|
|
54453
|
+
const { buildApprovedReceipt: buildApprovedReceipt2, persistReviewReceipt: persistReviewReceipt2 } = await Promise.resolve().then(() => (init_review_receipt(), exports_review_receipt));
|
|
54454
|
+
const initReceipt = buildApprovedReceipt2({
|
|
54455
|
+
agent: "curator",
|
|
54456
|
+
scopeContent: initResult.briefing,
|
|
54457
|
+
scopeDescription: "curator-init-briefing",
|
|
54458
|
+
checkedAspects: [
|
|
54459
|
+
"knowledge_entries",
|
|
54460
|
+
"prior_phase_summaries",
|
|
54461
|
+
"contradiction_detection"
|
|
54462
|
+
],
|
|
54463
|
+
validatedClaims: [
|
|
54464
|
+
`knowledge_entries_reviewed: ${initResult.knowledge_entries_reviewed}`,
|
|
54465
|
+
`prior_phases_covered: ${initResult.prior_phases_covered}`,
|
|
54466
|
+
`contradictions: ${initResult.contradictions.length}`
|
|
54467
|
+
]
|
|
54468
|
+
});
|
|
54469
|
+
persistReviewReceipt2(directory, initReceipt).catch(() => {});
|
|
54223
54470
|
}
|
|
54224
54471
|
}
|
|
54225
54472
|
} catch {}
|
|
@@ -54324,21 +54571,25 @@ ${originalText}`;
|
|
|
54324
54571
|
})
|
|
54325
54572
|
};
|
|
54326
54573
|
}
|
|
54574
|
+
|
|
54575
|
+
// src/hooks/index.ts
|
|
54576
|
+
init_review_receipt();
|
|
54577
|
+
|
|
54327
54578
|
// src/hooks/system-enhancer.ts
|
|
54328
54579
|
init_constants();
|
|
54329
54580
|
init_schema();
|
|
54330
54581
|
init_manager();
|
|
54331
54582
|
init_detector();
|
|
54332
54583
|
init_manager2();
|
|
54333
|
-
import * as
|
|
54334
|
-
import * as
|
|
54584
|
+
import * as fs29 from "fs";
|
|
54585
|
+
import * as path41 from "path";
|
|
54335
54586
|
|
|
54336
54587
|
// src/services/decision-drift-analyzer.ts
|
|
54337
54588
|
init_utils2();
|
|
54338
54589
|
init_manager2();
|
|
54339
54590
|
init_utils();
|
|
54340
|
-
import * as
|
|
54341
|
-
import * as
|
|
54591
|
+
import * as fs26 from "fs";
|
|
54592
|
+
import * as path38 from "path";
|
|
54342
54593
|
var DEFAULT_DRIFT_CONFIG = {
|
|
54343
54594
|
staleThresholdPhases: 1,
|
|
54344
54595
|
detectContradictions: true,
|
|
@@ -54492,11 +54743,11 @@ async function analyzeDecisionDrift(directory, config3 = {}) {
|
|
|
54492
54743
|
currentPhase = legacyPhase;
|
|
54493
54744
|
}
|
|
54494
54745
|
}
|
|
54495
|
-
const contextPath =
|
|
54746
|
+
const contextPath = path38.join(directory, ".swarm", "context.md");
|
|
54496
54747
|
let contextContent = "";
|
|
54497
54748
|
try {
|
|
54498
|
-
if (
|
|
54499
|
-
contextContent =
|
|
54749
|
+
if (fs26.existsSync(contextPath)) {
|
|
54750
|
+
contextContent = fs26.readFileSync(contextPath, "utf-8");
|
|
54500
54751
|
}
|
|
54501
54752
|
} catch (error93) {
|
|
54502
54753
|
log("[DecisionDriftAnalyzer] context file read failed", {
|
|
@@ -54621,8 +54872,8 @@ init_utils();
|
|
|
54621
54872
|
// src/hooks/adversarial-detector.ts
|
|
54622
54873
|
init_constants();
|
|
54623
54874
|
init_schema();
|
|
54624
|
-
import * as
|
|
54625
|
-
import * as
|
|
54875
|
+
import * as fs27 from "fs/promises";
|
|
54876
|
+
import * as path39 from "path";
|
|
54626
54877
|
function safeGet(obj, key) {
|
|
54627
54878
|
if (!obj || !Object.hasOwn(obj, key))
|
|
54628
54879
|
return;
|
|
@@ -54836,10 +55087,10 @@ async function handleDebuggingSpiral(match, taskId, directory) {
|
|
|
54836
55087
|
let eventLogged = false;
|
|
54837
55088
|
let checkpointCreated = false;
|
|
54838
55089
|
try {
|
|
54839
|
-
const swarmDir =
|
|
54840
|
-
await
|
|
54841
|
-
const eventsPath =
|
|
54842
|
-
await
|
|
55090
|
+
const swarmDir = path39.join(directory, ".swarm");
|
|
55091
|
+
await fs27.mkdir(swarmDir, { recursive: true });
|
|
55092
|
+
const eventsPath = path39.join(swarmDir, "events.jsonl");
|
|
55093
|
+
await fs27.appendFile(eventsPath, `${formatDebuggingSpiralEvent(match, taskId)}
|
|
54843
55094
|
`);
|
|
54844
55095
|
eventLogged = true;
|
|
54845
55096
|
} catch {}
|
|
@@ -55220,7 +55471,7 @@ function createSystemEnhancerHook(config3, directory) {
|
|
|
55220
55471
|
} catch {}
|
|
55221
55472
|
try {
|
|
55222
55473
|
const darkMatterPath = validateSwarmPath(directory, "dark-matter.md");
|
|
55223
|
-
if (!
|
|
55474
|
+
if (!fs29.existsSync(darkMatterPath)) {
|
|
55224
55475
|
const {
|
|
55225
55476
|
detectDarkMatter: detectDarkMatter2,
|
|
55226
55477
|
formatDarkMatterOutput: formatDarkMatterOutput2,
|
|
@@ -55228,15 +55479,14 @@ function createSystemEnhancerHook(config3, directory) {
|
|
|
55228
55479
|
} = await Promise.resolve().then(() => (init_co_change_analyzer(), exports_co_change_analyzer));
|
|
55229
55480
|
const darkMatter = await detectDarkMatter2(directory, {
|
|
55230
55481
|
minCommits: 20,
|
|
55231
|
-
minCoChanges: 3
|
|
55232
|
-
npmiThreshold: 0.3
|
|
55482
|
+
minCoChanges: 3
|
|
55233
55483
|
});
|
|
55234
55484
|
if (darkMatter && darkMatter.length > 0) {
|
|
55235
55485
|
const darkMatterReport = formatDarkMatterOutput2(darkMatter);
|
|
55236
|
-
await
|
|
55486
|
+
await fs29.promises.writeFile(darkMatterPath, darkMatterReport, "utf-8");
|
|
55237
55487
|
warn(`[system-enhancer] Dark matter scan complete: ${darkMatter.length} co-change patterns found`);
|
|
55238
55488
|
try {
|
|
55239
|
-
const projectName =
|
|
55489
|
+
const projectName = path41.basename(path41.resolve(directory));
|
|
55240
55490
|
const knowledgeEntries = darkMatterToKnowledgeEntries2(darkMatter, projectName);
|
|
55241
55491
|
const knowledgePath = resolveSwarmKnowledgePath(directory);
|
|
55242
55492
|
const existingEntries = await readKnowledge(knowledgePath);
|
|
@@ -55255,6 +55505,19 @@ function createSystemEnhancerHook(config3, directory) {
|
|
|
55255
55505
|
}
|
|
55256
55506
|
}
|
|
55257
55507
|
}
|
|
55508
|
+
try {
|
|
55509
|
+
const knowledgePath = resolveSwarmKnowledgePath(directory);
|
|
55510
|
+
const allEntries = await readKnowledge(knowledgePath);
|
|
55511
|
+
const stale = allEntries.filter((e) => e.scope === "project" && e.auto_generated === true && Array.isArray(e.tags) && e.tags.includes("dark-matter"));
|
|
55512
|
+
if (stale.length > 0) {
|
|
55513
|
+
for (const e of stale) {
|
|
55514
|
+
e.scope = "global";
|
|
55515
|
+
e.updated_at = new Date().toISOString();
|
|
55516
|
+
}
|
|
55517
|
+
await rewriteKnowledge(knowledgePath, allEntries);
|
|
55518
|
+
warn(`[system-enhancer] Repaired ${stale.length} dark matter knowledge entries (scope: 'project' \u2192 'global')`);
|
|
55519
|
+
}
|
|
55520
|
+
} catch {}
|
|
55258
55521
|
} catch {}
|
|
55259
55522
|
const scoringEnabled = config3.context_budget?.scoring?.enabled === true;
|
|
55260
55523
|
if (!scoringEnabled) {
|
|
@@ -55287,11 +55550,11 @@ function createSystemEnhancerHook(config3, directory) {
|
|
|
55287
55550
|
if (handoffContent) {
|
|
55288
55551
|
const handoffPath = validateSwarmPath(directory, "handoff.md");
|
|
55289
55552
|
const consumedPath = validateSwarmPath(directory, "handoff-consumed.md");
|
|
55290
|
-
if (
|
|
55553
|
+
if (fs29.existsSync(consumedPath)) {
|
|
55291
55554
|
warn("Duplicate handoff detected: handoff-consumed.md already exists");
|
|
55292
|
-
|
|
55555
|
+
fs29.unlinkSync(consumedPath);
|
|
55293
55556
|
}
|
|
55294
|
-
|
|
55557
|
+
fs29.renameSync(handoffPath, consumedPath);
|
|
55295
55558
|
const handoffBlock = `## HANDOFF \u2014 Resuming from model switch
|
|
55296
55559
|
The previous model's session ended. Here is your starting context:
|
|
55297
55560
|
|
|
@@ -55572,11 +55835,11 @@ ${budgetWarning}`);
|
|
|
55572
55835
|
if (handoffContent) {
|
|
55573
55836
|
const handoffPath = validateSwarmPath(directory, "handoff.md");
|
|
55574
55837
|
const consumedPath = validateSwarmPath(directory, "handoff-consumed.md");
|
|
55575
|
-
if (
|
|
55838
|
+
if (fs29.existsSync(consumedPath)) {
|
|
55576
55839
|
warn("Duplicate handoff detected: handoff-consumed.md already exists");
|
|
55577
|
-
|
|
55840
|
+
fs29.unlinkSync(consumedPath);
|
|
55578
55841
|
}
|
|
55579
|
-
|
|
55842
|
+
fs29.renameSync(handoffPath, consumedPath);
|
|
55580
55843
|
const handoffBlock = `## HANDOFF \u2014 Resuming from model switch
|
|
55581
55844
|
The previous model's session ended. Here is your starting context:
|
|
55582
55845
|
|
|
@@ -56346,8 +56609,8 @@ function isReadTool(toolName) {
|
|
|
56346
56609
|
}
|
|
56347
56610
|
|
|
56348
56611
|
// src/hooks/incremental-verify.ts
|
|
56349
|
-
import * as
|
|
56350
|
-
import * as
|
|
56612
|
+
import * as fs30 from "fs";
|
|
56613
|
+
import * as path42 from "path";
|
|
56351
56614
|
|
|
56352
56615
|
// src/hooks/spawn-helper.ts
|
|
56353
56616
|
import { spawn } from "child_process";
|
|
@@ -56422,21 +56685,21 @@ function spawnAsync(command, cwd, timeoutMs) {
|
|
|
56422
56685
|
// src/hooks/incremental-verify.ts
|
|
56423
56686
|
var emittedSkipAdvisories = new Set;
|
|
56424
56687
|
function detectPackageManager(projectDir) {
|
|
56425
|
-
if (
|
|
56688
|
+
if (fs30.existsSync(path42.join(projectDir, "bun.lockb")))
|
|
56426
56689
|
return "bun";
|
|
56427
|
-
if (
|
|
56690
|
+
if (fs30.existsSync(path42.join(projectDir, "pnpm-lock.yaml")))
|
|
56428
56691
|
return "pnpm";
|
|
56429
|
-
if (
|
|
56692
|
+
if (fs30.existsSync(path42.join(projectDir, "yarn.lock")))
|
|
56430
56693
|
return "yarn";
|
|
56431
|
-
if (
|
|
56694
|
+
if (fs30.existsSync(path42.join(projectDir, "package-lock.json")))
|
|
56432
56695
|
return "npm";
|
|
56433
56696
|
return "bun";
|
|
56434
56697
|
}
|
|
56435
56698
|
function detectTypecheckCommand(projectDir) {
|
|
56436
|
-
const pkgPath =
|
|
56437
|
-
if (
|
|
56699
|
+
const pkgPath = path42.join(projectDir, "package.json");
|
|
56700
|
+
if (fs30.existsSync(pkgPath)) {
|
|
56438
56701
|
try {
|
|
56439
|
-
const pkg = JSON.parse(
|
|
56702
|
+
const pkg = JSON.parse(fs30.readFileSync(pkgPath, "utf8"));
|
|
56440
56703
|
const scripts = pkg.scripts;
|
|
56441
56704
|
if (scripts?.typecheck) {
|
|
56442
56705
|
const pm = detectPackageManager(projectDir);
|
|
@@ -56450,8 +56713,8 @@ function detectTypecheckCommand(projectDir) {
|
|
|
56450
56713
|
...pkg.dependencies,
|
|
56451
56714
|
...pkg.devDependencies
|
|
56452
56715
|
};
|
|
56453
|
-
if (!deps?.typescript && !
|
|
56454
|
-
const hasTSMarkers = deps?.typescript ||
|
|
56716
|
+
if (!deps?.typescript && !fs30.existsSync(path42.join(projectDir, "tsconfig.json"))) {}
|
|
56717
|
+
const hasTSMarkers = deps?.typescript || fs30.existsSync(path42.join(projectDir, "tsconfig.json"));
|
|
56455
56718
|
if (hasTSMarkers) {
|
|
56456
56719
|
return { command: ["npx", "tsc", "--noEmit"], language: "typescript" };
|
|
56457
56720
|
}
|
|
@@ -56459,17 +56722,17 @@ function detectTypecheckCommand(projectDir) {
|
|
|
56459
56722
|
return null;
|
|
56460
56723
|
}
|
|
56461
56724
|
}
|
|
56462
|
-
if (
|
|
56725
|
+
if (fs30.existsSync(path42.join(projectDir, "go.mod"))) {
|
|
56463
56726
|
return { command: ["go", "vet", "./..."], language: "go" };
|
|
56464
56727
|
}
|
|
56465
|
-
if (
|
|
56728
|
+
if (fs30.existsSync(path42.join(projectDir, "Cargo.toml"))) {
|
|
56466
56729
|
return { command: ["cargo", "check"], language: "rust" };
|
|
56467
56730
|
}
|
|
56468
|
-
if (
|
|
56731
|
+
if (fs30.existsSync(path42.join(projectDir, "pyproject.toml")) || fs30.existsSync(path42.join(projectDir, "requirements.txt")) || fs30.existsSync(path42.join(projectDir, "setup.py"))) {
|
|
56469
56732
|
return { command: null, language: "python" };
|
|
56470
56733
|
}
|
|
56471
56734
|
try {
|
|
56472
|
-
const entries =
|
|
56735
|
+
const entries = fs30.readdirSync(projectDir);
|
|
56473
56736
|
if (entries.some((f) => f.endsWith(".csproj") || f.endsWith(".sln"))) {
|
|
56474
56737
|
return {
|
|
56475
56738
|
command: ["dotnet", "build", "--no-restore"],
|
|
@@ -56649,19 +56912,7 @@ function sanitizeLessonForContext(text) {
|
|
|
56649
56912
|
}
|
|
56650
56913
|
function isOrchestratorAgent(agentName) {
|
|
56651
56914
|
const stripped = stripKnownSwarmPrefix(agentName);
|
|
56652
|
-
|
|
56653
|
-
"coder",
|
|
56654
|
-
"reviewer",
|
|
56655
|
-
"test_engineer",
|
|
56656
|
-
"security_reviewer",
|
|
56657
|
-
"integration_analyst",
|
|
56658
|
-
"docs_writer",
|
|
56659
|
-
"designer",
|
|
56660
|
-
"critic",
|
|
56661
|
-
"docs",
|
|
56662
|
-
"explorer"
|
|
56663
|
-
]);
|
|
56664
|
-
return !nonOrchestratorAgents.has(stripped.toLowerCase());
|
|
56915
|
+
return stripped.toLowerCase() === "architect";
|
|
56665
56916
|
}
|
|
56666
56917
|
function injectKnowledgeMessage(output, text) {
|
|
56667
56918
|
if (!output.messages)
|
|
@@ -56778,7 +57029,7 @@ ${injectionText}`;
|
|
|
56778
57029
|
// src/hooks/scope-guard.ts
|
|
56779
57030
|
init_constants();
|
|
56780
57031
|
init_schema();
|
|
56781
|
-
import * as
|
|
57032
|
+
import * as path44 from "path";
|
|
56782
57033
|
var WRITE_TOOLS = new Set([
|
|
56783
57034
|
"write",
|
|
56784
57035
|
"edit",
|
|
@@ -56840,13 +57091,13 @@ function createScopeGuardHook(config3, directory, injectAdvisory) {
|
|
|
56840
57091
|
}
|
|
56841
57092
|
function isFileInScope(filePath, scopeEntries, directory) {
|
|
56842
57093
|
const dir = directory ?? process.cwd();
|
|
56843
|
-
const resolvedFile =
|
|
57094
|
+
const resolvedFile = path44.resolve(dir, filePath);
|
|
56844
57095
|
return scopeEntries.some((scope) => {
|
|
56845
|
-
const resolvedScope =
|
|
57096
|
+
const resolvedScope = path44.resolve(dir, scope);
|
|
56846
57097
|
if (resolvedFile === resolvedScope)
|
|
56847
57098
|
return true;
|
|
56848
|
-
const rel =
|
|
56849
|
-
return rel.length > 0 && !rel.startsWith("..") && !
|
|
57099
|
+
const rel = path44.relative(resolvedScope, resolvedFile);
|
|
57100
|
+
return rel.length > 0 && !rel.startsWith("..") && !path44.isAbsolute(rel);
|
|
56850
57101
|
});
|
|
56851
57102
|
}
|
|
56852
57103
|
|
|
@@ -56895,8 +57146,8 @@ function createSelfReviewHook(config3, injectAdvisory) {
|
|
|
56895
57146
|
}
|
|
56896
57147
|
|
|
56897
57148
|
// src/hooks/slop-detector.ts
|
|
56898
|
-
import * as
|
|
56899
|
-
import * as
|
|
57149
|
+
import * as fs32 from "fs";
|
|
57150
|
+
import * as path45 from "path";
|
|
56900
57151
|
var WRITE_EDIT_TOOLS = new Set([
|
|
56901
57152
|
"write",
|
|
56902
57153
|
"edit",
|
|
@@ -56941,12 +57192,12 @@ function checkBoilerplateExplosion(content, taskDescription, threshold) {
|
|
|
56941
57192
|
function walkFiles(dir, exts, deadline) {
|
|
56942
57193
|
const results = [];
|
|
56943
57194
|
try {
|
|
56944
|
-
for (const entry of
|
|
57195
|
+
for (const entry of fs32.readdirSync(dir, { withFileTypes: true })) {
|
|
56945
57196
|
if (deadline !== undefined && Date.now() > deadline)
|
|
56946
57197
|
break;
|
|
56947
57198
|
if (entry.isSymbolicLink())
|
|
56948
57199
|
continue;
|
|
56949
|
-
const full =
|
|
57200
|
+
const full = path45.join(dir, entry.name);
|
|
56950
57201
|
if (entry.isDirectory()) {
|
|
56951
57202
|
if (entry.name === "node_modules" || entry.name === ".git")
|
|
56952
57203
|
continue;
|
|
@@ -56961,7 +57212,7 @@ function walkFiles(dir, exts, deadline) {
|
|
|
56961
57212
|
return results;
|
|
56962
57213
|
}
|
|
56963
57214
|
function checkDeadExports(content, projectDir, startTime) {
|
|
56964
|
-
const hasPackageJson =
|
|
57215
|
+
const hasPackageJson = fs32.existsSync(path45.join(projectDir, "package.json"));
|
|
56965
57216
|
if (!hasPackageJson)
|
|
56966
57217
|
return null;
|
|
56967
57218
|
const exportMatches = content.matchAll(/^\+(?:export)\s+(?:function|class|const|type|interface)\s+(\w{3,})/gm);
|
|
@@ -56984,7 +57235,7 @@ function checkDeadExports(content, projectDir, startTime) {
|
|
|
56984
57235
|
if (found || Date.now() - startTime > 480)
|
|
56985
57236
|
break;
|
|
56986
57237
|
try {
|
|
56987
|
-
const text =
|
|
57238
|
+
const text = fs32.readFileSync(file3, "utf-8");
|
|
56988
57239
|
if (importPattern.test(text))
|
|
56989
57240
|
found = true;
|
|
56990
57241
|
importPattern.lastIndex = 0;
|
|
@@ -57117,7 +57368,7 @@ Review before proceeding.`;
|
|
|
57117
57368
|
|
|
57118
57369
|
// src/hooks/steering-consumed.ts
|
|
57119
57370
|
init_utils2();
|
|
57120
|
-
import * as
|
|
57371
|
+
import * as fs33 from "fs";
|
|
57121
57372
|
function recordSteeringConsumed(directory, directiveId) {
|
|
57122
57373
|
try {
|
|
57123
57374
|
const eventsPath = validateSwarmPath(directory, "events.jsonl");
|
|
@@ -57126,7 +57377,7 @@ function recordSteeringConsumed(directory, directiveId) {
|
|
|
57126
57377
|
directiveId,
|
|
57127
57378
|
timestamp: new Date().toISOString()
|
|
57128
57379
|
};
|
|
57129
|
-
|
|
57380
|
+
fs33.appendFileSync(eventsPath, `${JSON.stringify(event)}
|
|
57130
57381
|
`, "utf-8");
|
|
57131
57382
|
} catch {}
|
|
57132
57383
|
}
|
|
@@ -57171,7 +57422,7 @@ init_config_doctor();
|
|
|
57171
57422
|
|
|
57172
57423
|
// src/session/snapshot-reader.ts
|
|
57173
57424
|
init_utils2();
|
|
57174
|
-
import { renameSync as
|
|
57425
|
+
import { renameSync as renameSync12 } from "fs";
|
|
57175
57426
|
var TRANSIENT_SESSION_FIELDS = [
|
|
57176
57427
|
{ name: "revisionLimitHit", resetValue: false },
|
|
57177
57428
|
{ name: "coderRevisions", resetValue: 0 },
|
|
@@ -57282,7 +57533,7 @@ async function readSnapshot(directory) {
|
|
|
57282
57533
|
if (parsed.version !== 1 && parsed.version !== 2) {
|
|
57283
57534
|
try {
|
|
57284
57535
|
const quarantinePath = validateSwarmPath(directory, "session/state.json.quarantine");
|
|
57285
|
-
|
|
57536
|
+
renameSync12(resolvedPath, quarantinePath);
|
|
57286
57537
|
} catch {}
|
|
57287
57538
|
return null;
|
|
57288
57539
|
}
|
|
@@ -57539,8 +57790,8 @@ init_dist();
|
|
|
57539
57790
|
init_manager();
|
|
57540
57791
|
init_create_tool();
|
|
57541
57792
|
init_resolve_working_directory();
|
|
57542
|
-
import * as
|
|
57543
|
-
import * as
|
|
57793
|
+
import * as fs34 from "fs";
|
|
57794
|
+
import * as path46 from "path";
|
|
57544
57795
|
var EVIDENCE_DIR = ".swarm/evidence";
|
|
57545
57796
|
var TASK_ID_PATTERN2 = /^\d+\.\d+(\.\d+)*$/;
|
|
57546
57797
|
function isValidTaskId3(taskId) {
|
|
@@ -57557,18 +57808,18 @@ function isValidTaskId3(taskId) {
|
|
|
57557
57808
|
return TASK_ID_PATTERN2.test(taskId);
|
|
57558
57809
|
}
|
|
57559
57810
|
function isPathWithinSwarm(filePath, workspaceRoot) {
|
|
57560
|
-
const normalizedWorkspace =
|
|
57561
|
-
const swarmPath =
|
|
57562
|
-
const normalizedPath =
|
|
57811
|
+
const normalizedWorkspace = path46.resolve(workspaceRoot);
|
|
57812
|
+
const swarmPath = path46.join(normalizedWorkspace, ".swarm", "evidence");
|
|
57813
|
+
const normalizedPath = path46.resolve(filePath);
|
|
57563
57814
|
return normalizedPath.startsWith(swarmPath);
|
|
57564
57815
|
}
|
|
57565
57816
|
function readEvidenceFile(evidencePath) {
|
|
57566
|
-
if (!
|
|
57817
|
+
if (!fs34.existsSync(evidencePath)) {
|
|
57567
57818
|
return null;
|
|
57568
57819
|
}
|
|
57569
57820
|
let content;
|
|
57570
57821
|
try {
|
|
57571
|
-
content =
|
|
57822
|
+
content = fs34.readFileSync(evidencePath, "utf-8");
|
|
57572
57823
|
} catch {
|
|
57573
57824
|
return null;
|
|
57574
57825
|
}
|
|
@@ -57640,7 +57891,7 @@ var check_gate_status = createSwarmTool({
|
|
|
57640
57891
|
};
|
|
57641
57892
|
return JSON.stringify(errorResult, null, 2);
|
|
57642
57893
|
}
|
|
57643
|
-
const evidencePath =
|
|
57894
|
+
const evidencePath = path46.join(directory, EVIDENCE_DIR, `${taskIdInput}.json`);
|
|
57644
57895
|
if (!isPathWithinSwarm(evidencePath, directory)) {
|
|
57645
57896
|
const errorResult = {
|
|
57646
57897
|
taskId: taskIdInput,
|
|
@@ -57733,8 +57984,8 @@ init_co_change_analyzer();
|
|
|
57733
57984
|
// src/tools/completion-verify.ts
|
|
57734
57985
|
init_dist();
|
|
57735
57986
|
init_utils2();
|
|
57736
|
-
import * as
|
|
57737
|
-
import * as
|
|
57987
|
+
import * as fs35 from "fs";
|
|
57988
|
+
import * as path47 from "path";
|
|
57738
57989
|
init_create_tool();
|
|
57739
57990
|
init_resolve_working_directory();
|
|
57740
57991
|
function extractMatches(regex, text) {
|
|
@@ -57830,7 +58081,7 @@ async function executeCompletionVerify(args2, directory) {
|
|
|
57830
58081
|
let plan;
|
|
57831
58082
|
try {
|
|
57832
58083
|
const planPath = validateSwarmPath(directory, "plan.json");
|
|
57833
|
-
const planRaw =
|
|
58084
|
+
const planRaw = fs35.readFileSync(planPath, "utf-8");
|
|
57834
58085
|
plan = JSON.parse(planRaw);
|
|
57835
58086
|
} catch {
|
|
57836
58087
|
const result2 = {
|
|
@@ -57888,10 +58139,10 @@ async function executeCompletionVerify(args2, directory) {
|
|
|
57888
58139
|
let hasFileReadFailure = false;
|
|
57889
58140
|
for (const filePath of fileTargets) {
|
|
57890
58141
|
const normalizedPath = filePath.replace(/\\/g, "/");
|
|
57891
|
-
const resolvedPath =
|
|
57892
|
-
const projectRoot =
|
|
57893
|
-
const relative6 =
|
|
57894
|
-
const withinProject = relative6 === "" || !relative6.startsWith("..") && !
|
|
58142
|
+
const resolvedPath = path47.resolve(directory, normalizedPath);
|
|
58143
|
+
const projectRoot = path47.resolve(directory);
|
|
58144
|
+
const relative6 = path47.relative(projectRoot, resolvedPath);
|
|
58145
|
+
const withinProject = relative6 === "" || !relative6.startsWith("..") && !path47.isAbsolute(relative6);
|
|
57895
58146
|
if (!withinProject) {
|
|
57896
58147
|
blockedTasks.push({
|
|
57897
58148
|
task_id: task.id,
|
|
@@ -57904,7 +58155,7 @@ async function executeCompletionVerify(args2, directory) {
|
|
|
57904
58155
|
}
|
|
57905
58156
|
let fileContent;
|
|
57906
58157
|
try {
|
|
57907
|
-
fileContent =
|
|
58158
|
+
fileContent = fs35.readFileSync(resolvedPath, "utf-8");
|
|
57908
58159
|
} catch {
|
|
57909
58160
|
blockedTasks.push({
|
|
57910
58161
|
task_id: task.id,
|
|
@@ -57946,9 +58197,9 @@ async function executeCompletionVerify(args2, directory) {
|
|
|
57946
58197
|
blockedTasks
|
|
57947
58198
|
};
|
|
57948
58199
|
try {
|
|
57949
|
-
const evidenceDir =
|
|
57950
|
-
const evidencePath =
|
|
57951
|
-
|
|
58200
|
+
const evidenceDir = path47.join(directory, ".swarm", "evidence", `${phase}`);
|
|
58201
|
+
const evidencePath = path47.join(evidenceDir, "completion-verify.json");
|
|
58202
|
+
fs35.mkdirSync(evidenceDir, { recursive: true });
|
|
57952
58203
|
const evidenceBundle = {
|
|
57953
58204
|
schema_version: "1.0.0",
|
|
57954
58205
|
task_id: "completion-verify",
|
|
@@ -57969,7 +58220,7 @@ async function executeCompletionVerify(args2, directory) {
|
|
|
57969
58220
|
}
|
|
57970
58221
|
]
|
|
57971
58222
|
};
|
|
57972
|
-
|
|
58223
|
+
fs35.writeFileSync(evidencePath, JSON.stringify(evidenceBundle, null, 2), "utf-8");
|
|
57973
58224
|
} catch {}
|
|
57974
58225
|
return JSON.stringify(result, null, 2);
|
|
57975
58226
|
}
|
|
@@ -58023,12 +58274,12 @@ var completion_verify = createSwarmTool({
|
|
|
58023
58274
|
});
|
|
58024
58275
|
// src/tools/complexity-hotspots.ts
|
|
58025
58276
|
init_dist();
|
|
58026
|
-
import * as
|
|
58027
|
-
import * as
|
|
58277
|
+
import * as fs37 from "fs";
|
|
58278
|
+
import * as path49 from "path";
|
|
58028
58279
|
|
|
58029
58280
|
// src/quality/metrics.ts
|
|
58030
|
-
import * as
|
|
58031
|
-
import * as
|
|
58281
|
+
import * as fs36 from "fs";
|
|
58282
|
+
import * as path48 from "path";
|
|
58032
58283
|
var MAX_FILE_SIZE_BYTES2 = 256 * 1024;
|
|
58033
58284
|
var MIN_DUPLICATION_LINES = 10;
|
|
58034
58285
|
function estimateCyclomaticComplexity(content) {
|
|
@@ -58066,11 +58317,11 @@ function estimateCyclomaticComplexity(content) {
|
|
|
58066
58317
|
}
|
|
58067
58318
|
function getComplexityForFile(filePath) {
|
|
58068
58319
|
try {
|
|
58069
|
-
const stat2 =
|
|
58320
|
+
const stat2 = fs36.statSync(filePath);
|
|
58070
58321
|
if (stat2.size > MAX_FILE_SIZE_BYTES2) {
|
|
58071
58322
|
return null;
|
|
58072
58323
|
}
|
|
58073
|
-
const content =
|
|
58324
|
+
const content = fs36.readFileSync(filePath, "utf-8");
|
|
58074
58325
|
return estimateCyclomaticComplexity(content);
|
|
58075
58326
|
} catch {
|
|
58076
58327
|
return null;
|
|
@@ -58080,8 +58331,8 @@ async function computeComplexityDelta(files, workingDir) {
|
|
|
58080
58331
|
let totalComplexity = 0;
|
|
58081
58332
|
const analyzedFiles = [];
|
|
58082
58333
|
for (const file3 of files) {
|
|
58083
|
-
const fullPath =
|
|
58084
|
-
if (!
|
|
58334
|
+
const fullPath = path48.isAbsolute(file3) ? file3 : path48.join(workingDir, file3);
|
|
58335
|
+
if (!fs36.existsSync(fullPath)) {
|
|
58085
58336
|
continue;
|
|
58086
58337
|
}
|
|
58087
58338
|
const complexity = getComplexityForFile(fullPath);
|
|
@@ -58202,8 +58453,8 @@ function countGoExports(content) {
|
|
|
58202
58453
|
}
|
|
58203
58454
|
function getExportCountForFile(filePath) {
|
|
58204
58455
|
try {
|
|
58205
|
-
const content =
|
|
58206
|
-
const ext =
|
|
58456
|
+
const content = fs36.readFileSync(filePath, "utf-8");
|
|
58457
|
+
const ext = path48.extname(filePath).toLowerCase();
|
|
58207
58458
|
switch (ext) {
|
|
58208
58459
|
case ".ts":
|
|
58209
58460
|
case ".tsx":
|
|
@@ -58229,8 +58480,8 @@ async function computePublicApiDelta(files, workingDir) {
|
|
|
58229
58480
|
let totalExports = 0;
|
|
58230
58481
|
const analyzedFiles = [];
|
|
58231
58482
|
for (const file3 of files) {
|
|
58232
|
-
const fullPath =
|
|
58233
|
-
if (!
|
|
58483
|
+
const fullPath = path48.isAbsolute(file3) ? file3 : path48.join(workingDir, file3);
|
|
58484
|
+
if (!fs36.existsSync(fullPath)) {
|
|
58234
58485
|
continue;
|
|
58235
58486
|
}
|
|
58236
58487
|
const exports = getExportCountForFile(fullPath);
|
|
@@ -58263,16 +58514,16 @@ async function computeDuplicationRatio(files, workingDir) {
|
|
|
58263
58514
|
let duplicateLines = 0;
|
|
58264
58515
|
const analyzedFiles = [];
|
|
58265
58516
|
for (const file3 of files) {
|
|
58266
|
-
const fullPath =
|
|
58267
|
-
if (!
|
|
58517
|
+
const fullPath = path48.isAbsolute(file3) ? file3 : path48.join(workingDir, file3);
|
|
58518
|
+
if (!fs36.existsSync(fullPath)) {
|
|
58268
58519
|
continue;
|
|
58269
58520
|
}
|
|
58270
58521
|
try {
|
|
58271
|
-
const stat2 =
|
|
58522
|
+
const stat2 = fs36.statSync(fullPath);
|
|
58272
58523
|
if (stat2.size > MAX_FILE_SIZE_BYTES2) {
|
|
58273
58524
|
continue;
|
|
58274
58525
|
}
|
|
58275
|
-
const content =
|
|
58526
|
+
const content = fs36.readFileSync(fullPath, "utf-8");
|
|
58276
58527
|
const lines = content.split(`
|
|
58277
58528
|
`).filter((line) => line.trim().length > 0);
|
|
58278
58529
|
if (lines.length < MIN_DUPLICATION_LINES) {
|
|
@@ -58296,8 +58547,8 @@ function countCodeLines(content) {
|
|
|
58296
58547
|
return lines.length;
|
|
58297
58548
|
}
|
|
58298
58549
|
function isTestFile(filePath) {
|
|
58299
|
-
const basename7 =
|
|
58300
|
-
const _ext =
|
|
58550
|
+
const basename7 = path48.basename(filePath);
|
|
58551
|
+
const _ext = path48.extname(filePath).toLowerCase();
|
|
58301
58552
|
const testPatterns = [
|
|
58302
58553
|
".test.",
|
|
58303
58554
|
".spec.",
|
|
@@ -58378,8 +58629,8 @@ function matchGlobSegment(globSegments, pathSegments) {
|
|
|
58378
58629
|
}
|
|
58379
58630
|
return gIndex === globSegments.length && pIndex === pathSegments.length;
|
|
58380
58631
|
}
|
|
58381
|
-
function matchesGlobSegment(
|
|
58382
|
-
const normalizedPath =
|
|
58632
|
+
function matchesGlobSegment(path49, glob) {
|
|
58633
|
+
const normalizedPath = path49.replace(/\\/g, "/");
|
|
58383
58634
|
const normalizedGlob = glob.replace(/\\/g, "/");
|
|
58384
58635
|
if (normalizedPath.includes("//")) {
|
|
58385
58636
|
return false;
|
|
@@ -58410,8 +58661,8 @@ function simpleGlobToRegex2(glob) {
|
|
|
58410
58661
|
function hasGlobstar(glob) {
|
|
58411
58662
|
return glob.includes("**");
|
|
58412
58663
|
}
|
|
58413
|
-
function globMatches(
|
|
58414
|
-
const normalizedPath =
|
|
58664
|
+
function globMatches(path49, glob) {
|
|
58665
|
+
const normalizedPath = path49.replace(/\\/g, "/");
|
|
58415
58666
|
if (!glob || glob === "") {
|
|
58416
58667
|
if (normalizedPath.includes("//")) {
|
|
58417
58668
|
return false;
|
|
@@ -58447,31 +58698,31 @@ function shouldExcludeFile(filePath, excludeGlobs) {
|
|
|
58447
58698
|
async function computeTestToCodeRatio(workingDir, enforceGlobs, excludeGlobs) {
|
|
58448
58699
|
let testLines = 0;
|
|
58449
58700
|
let codeLines = 0;
|
|
58450
|
-
const srcDir =
|
|
58451
|
-
if (
|
|
58701
|
+
const srcDir = path48.join(workingDir, "src");
|
|
58702
|
+
if (fs36.existsSync(srcDir)) {
|
|
58452
58703
|
await scanDirectoryForLines(srcDir, enforceGlobs, excludeGlobs, false, (lines) => {
|
|
58453
58704
|
codeLines += lines;
|
|
58454
58705
|
});
|
|
58455
58706
|
}
|
|
58456
58707
|
const possibleSrcDirs = ["lib", "app", "source", "core"];
|
|
58457
58708
|
for (const dir of possibleSrcDirs) {
|
|
58458
|
-
const dirPath =
|
|
58459
|
-
if (
|
|
58709
|
+
const dirPath = path48.join(workingDir, dir);
|
|
58710
|
+
if (fs36.existsSync(dirPath)) {
|
|
58460
58711
|
await scanDirectoryForLines(dirPath, enforceGlobs, excludeGlobs, false, (lines) => {
|
|
58461
58712
|
codeLines += lines;
|
|
58462
58713
|
});
|
|
58463
58714
|
}
|
|
58464
58715
|
}
|
|
58465
|
-
const testsDir =
|
|
58466
|
-
if (
|
|
58716
|
+
const testsDir = path48.join(workingDir, "tests");
|
|
58717
|
+
if (fs36.existsSync(testsDir)) {
|
|
58467
58718
|
await scanDirectoryForLines(testsDir, ["**"], ["node_modules", "dist"], true, (lines) => {
|
|
58468
58719
|
testLines += lines;
|
|
58469
58720
|
});
|
|
58470
58721
|
}
|
|
58471
58722
|
const possibleTestDirs = ["test", "__tests__", "specs"];
|
|
58472
58723
|
for (const dir of possibleTestDirs) {
|
|
58473
|
-
const dirPath =
|
|
58474
|
-
if (
|
|
58724
|
+
const dirPath = path48.join(workingDir, dir);
|
|
58725
|
+
if (fs36.existsSync(dirPath) && dirPath !== testsDir) {
|
|
58475
58726
|
await scanDirectoryForLines(dirPath, ["**"], ["node_modules", "dist"], true, (lines) => {
|
|
58476
58727
|
testLines += lines;
|
|
58477
58728
|
});
|
|
@@ -58483,9 +58734,9 @@ async function computeTestToCodeRatio(workingDir, enforceGlobs, excludeGlobs) {
|
|
|
58483
58734
|
}
|
|
58484
58735
|
async function scanDirectoryForLines(dirPath, includeGlobs, excludeGlobs, isTestScan, callback) {
|
|
58485
58736
|
try {
|
|
58486
|
-
const entries =
|
|
58737
|
+
const entries = fs36.readdirSync(dirPath, { withFileTypes: true });
|
|
58487
58738
|
for (const entry of entries) {
|
|
58488
|
-
const fullPath =
|
|
58739
|
+
const fullPath = path48.join(dirPath, entry.name);
|
|
58489
58740
|
if (entry.isDirectory()) {
|
|
58490
58741
|
if (entry.name === "node_modules" || entry.name === "dist" || entry.name === "build" || entry.name === ".git") {
|
|
58491
58742
|
continue;
|
|
@@ -58493,7 +58744,7 @@ async function scanDirectoryForLines(dirPath, includeGlobs, excludeGlobs, isTest
|
|
|
58493
58744
|
await scanDirectoryForLines(fullPath, includeGlobs, excludeGlobs, isTestScan, callback);
|
|
58494
58745
|
} else if (entry.isFile()) {
|
|
58495
58746
|
const relativePath = fullPath.replace(`${dirPath}/`, "");
|
|
58496
|
-
const ext =
|
|
58747
|
+
const ext = path48.extname(entry.name).toLowerCase();
|
|
58497
58748
|
const validExts = [
|
|
58498
58749
|
".ts",
|
|
58499
58750
|
".tsx",
|
|
@@ -58529,7 +58780,7 @@ async function scanDirectoryForLines(dirPath, includeGlobs, excludeGlobs, isTest
|
|
|
58529
58780
|
continue;
|
|
58530
58781
|
}
|
|
58531
58782
|
try {
|
|
58532
|
-
const content =
|
|
58783
|
+
const content = fs36.readFileSync(fullPath, "utf-8");
|
|
58533
58784
|
const lines = countCodeLines(content);
|
|
58534
58785
|
callback(lines);
|
|
58535
58786
|
} catch {}
|
|
@@ -58730,11 +58981,11 @@ async function getGitChurn(days, directory) {
|
|
|
58730
58981
|
}
|
|
58731
58982
|
function getComplexityForFile2(filePath) {
|
|
58732
58983
|
try {
|
|
58733
|
-
const stat2 =
|
|
58984
|
+
const stat2 = fs37.statSync(filePath);
|
|
58734
58985
|
if (stat2.size > MAX_FILE_SIZE_BYTES3) {
|
|
58735
58986
|
return null;
|
|
58736
58987
|
}
|
|
58737
|
-
const content =
|
|
58988
|
+
const content = fs37.readFileSync(filePath, "utf-8");
|
|
58738
58989
|
return estimateCyclomaticComplexity(content);
|
|
58739
58990
|
} catch {
|
|
58740
58991
|
return null;
|
|
@@ -58745,7 +58996,7 @@ async function analyzeHotspots(days, topN, extensions, directory) {
|
|
|
58745
58996
|
const extSet = new Set(extensions.map((e) => e.startsWith(".") ? e : `.${e}`));
|
|
58746
58997
|
const filteredChurn = new Map;
|
|
58747
58998
|
for (const [file3, count] of churnMap) {
|
|
58748
|
-
const ext =
|
|
58999
|
+
const ext = path49.extname(file3).toLowerCase();
|
|
58749
59000
|
if (extSet.has(ext)) {
|
|
58750
59001
|
filteredChurn.set(file3, count);
|
|
58751
59002
|
}
|
|
@@ -58755,8 +59006,8 @@ async function analyzeHotspots(days, topN, extensions, directory) {
|
|
|
58755
59006
|
let analyzedFiles = 0;
|
|
58756
59007
|
for (const [file3, churnCount] of filteredChurn) {
|
|
58757
59008
|
let fullPath = file3;
|
|
58758
|
-
if (!
|
|
58759
|
-
fullPath =
|
|
59009
|
+
if (!fs37.existsSync(fullPath)) {
|
|
59010
|
+
fullPath = path49.join(cwd, file3);
|
|
58760
59011
|
}
|
|
58761
59012
|
const complexity = getComplexityForFile2(fullPath);
|
|
58762
59013
|
if (complexity !== null) {
|
|
@@ -58905,6 +59156,7 @@ var complexity_hotspots = createSwarmTool({
|
|
|
58905
59156
|
init_dist();
|
|
58906
59157
|
init_config();
|
|
58907
59158
|
init_schema();
|
|
59159
|
+
init_review_receipt();
|
|
58908
59160
|
init_create_tool();
|
|
58909
59161
|
var curator_analyze = createSwarmTool({
|
|
58910
59162
|
description: "Run curator phase analysis and optionally apply knowledge recommendations. " + "Call this after reviewing a phase to apply knowledge updates. " + "If recommendations is provided, applies them via applyCuratorKnowledgeUpdates.",
|
|
@@ -58940,7 +59192,40 @@ var curator_analyze = createSwarmTool({
|
|
|
58940
59192
|
const { config: config3 } = loadPluginConfigWithMeta(directory);
|
|
58941
59193
|
const curatorConfig = CuratorConfigSchema.parse(config3.curator ?? {});
|
|
58942
59194
|
const knowledgeConfig = KnowledgeConfigSchema.parse(config3.knowledge ?? {});
|
|
58943
|
-
const
|
|
59195
|
+
const llmDelegate = createCuratorLLMDelegate(directory);
|
|
59196
|
+
const curatorResult = await runCuratorPhase(directory, typedArgs.phase, [], curatorConfig, {}, llmDelegate);
|
|
59197
|
+
{
|
|
59198
|
+
const scopeContent = curatorResult.digest?.summary ?? `Phase ${typedArgs.phase} curator analysis`;
|
|
59199
|
+
const complianceWarnings = curatorResult.compliance.filter((c) => c.severity === "warning");
|
|
59200
|
+
const receipt = complianceWarnings.length > 0 ? buildRejectedReceipt({
|
|
59201
|
+
agent: "curator",
|
|
59202
|
+
scopeContent,
|
|
59203
|
+
scopeDescription: "phase-digest",
|
|
59204
|
+
blockingFindings: complianceWarnings.map((c) => ({
|
|
59205
|
+
location: `phase-${c.phase}`,
|
|
59206
|
+
summary: c.description,
|
|
59207
|
+
severity: c.type === "missing_reviewer" ? "high" : "medium"
|
|
59208
|
+
})),
|
|
59209
|
+
evidenceReferences: [],
|
|
59210
|
+
passConditions: [
|
|
59211
|
+
"resolve all compliance warnings before phase completion"
|
|
59212
|
+
]
|
|
59213
|
+
}) : buildApprovedReceipt({
|
|
59214
|
+
agent: "curator",
|
|
59215
|
+
scopeContent,
|
|
59216
|
+
scopeDescription: "phase-digest",
|
|
59217
|
+
checkedAspects: [
|
|
59218
|
+
"phase_compliance",
|
|
59219
|
+
"knowledge_recommendations",
|
|
59220
|
+
"phase_digest"
|
|
59221
|
+
],
|
|
59222
|
+
validatedClaims: [
|
|
59223
|
+
`phase: ${typedArgs.phase}`,
|
|
59224
|
+
`knowledge_recommendations: ${curatorResult.knowledge_recommendations.length}`
|
|
59225
|
+
]
|
|
59226
|
+
});
|
|
59227
|
+
persistReviewReceipt(directory, receipt).catch(() => {});
|
|
59228
|
+
}
|
|
58944
59229
|
let applied = 0;
|
|
58945
59230
|
let skipped = 0;
|
|
58946
59231
|
if (typedArgs.recommendations && typedArgs.recommendations.length > 0) {
|
|
@@ -58964,8 +59249,8 @@ var curator_analyze = createSwarmTool({
|
|
|
58964
59249
|
});
|
|
58965
59250
|
// src/tools/declare-scope.ts
|
|
58966
59251
|
init_tool();
|
|
58967
|
-
import * as
|
|
58968
|
-
import * as
|
|
59252
|
+
import * as fs38 from "fs";
|
|
59253
|
+
import * as path50 from "path";
|
|
58969
59254
|
init_create_tool();
|
|
58970
59255
|
function validateTaskIdFormat(taskId) {
|
|
58971
59256
|
const taskIdPattern = /^\d+\.\d+(\.\d+)*$/;
|
|
@@ -59044,8 +59329,8 @@ async function executeDeclareScope(args2, fallbackDir) {
|
|
|
59044
59329
|
};
|
|
59045
59330
|
}
|
|
59046
59331
|
}
|
|
59047
|
-
normalizedDir =
|
|
59048
|
-
const pathParts = normalizedDir.split(
|
|
59332
|
+
normalizedDir = path50.normalize(args2.working_directory);
|
|
59333
|
+
const pathParts = normalizedDir.split(path50.sep);
|
|
59049
59334
|
if (pathParts.includes("..")) {
|
|
59050
59335
|
return {
|
|
59051
59336
|
success: false,
|
|
@@ -59055,11 +59340,11 @@ async function executeDeclareScope(args2, fallbackDir) {
|
|
|
59055
59340
|
]
|
|
59056
59341
|
};
|
|
59057
59342
|
}
|
|
59058
|
-
const resolvedDir =
|
|
59343
|
+
const resolvedDir = path50.resolve(normalizedDir);
|
|
59059
59344
|
try {
|
|
59060
|
-
const realPath =
|
|
59061
|
-
const planPath2 =
|
|
59062
|
-
if (!
|
|
59345
|
+
const realPath = fs38.realpathSync(resolvedDir);
|
|
59346
|
+
const planPath2 = path50.join(realPath, ".swarm", "plan.json");
|
|
59347
|
+
if (!fs38.existsSync(planPath2)) {
|
|
59063
59348
|
return {
|
|
59064
59349
|
success: false,
|
|
59065
59350
|
message: `Invalid working_directory: plan not found in "${realPath}"`,
|
|
@@ -59082,8 +59367,8 @@ async function executeDeclareScope(args2, fallbackDir) {
|
|
|
59082
59367
|
console.warn("[declare-scope] fallbackDir is undefined, falling back to process.cwd()");
|
|
59083
59368
|
}
|
|
59084
59369
|
const directory = normalizedDir || fallbackDir;
|
|
59085
|
-
const planPath =
|
|
59086
|
-
if (!
|
|
59370
|
+
const planPath = path50.resolve(directory, ".swarm", "plan.json");
|
|
59371
|
+
if (!fs38.existsSync(planPath)) {
|
|
59087
59372
|
return {
|
|
59088
59373
|
success: false,
|
|
59089
59374
|
message: "No plan found",
|
|
@@ -59092,7 +59377,7 @@ async function executeDeclareScope(args2, fallbackDir) {
|
|
|
59092
59377
|
}
|
|
59093
59378
|
let planContent;
|
|
59094
59379
|
try {
|
|
59095
|
-
planContent = JSON.parse(
|
|
59380
|
+
planContent = JSON.parse(fs38.readFileSync(planPath, "utf-8"));
|
|
59096
59381
|
} catch {
|
|
59097
59382
|
return {
|
|
59098
59383
|
success: false,
|
|
@@ -59124,8 +59409,8 @@ async function executeDeclareScope(args2, fallbackDir) {
|
|
|
59124
59409
|
const normalizeErrors = [];
|
|
59125
59410
|
const dir = normalizedDir || fallbackDir || process.cwd();
|
|
59126
59411
|
const mergedFiles = rawMergedFiles.map((file3) => {
|
|
59127
|
-
if (
|
|
59128
|
-
const relativePath =
|
|
59412
|
+
if (path50.isAbsolute(file3)) {
|
|
59413
|
+
const relativePath = path50.relative(dir, file3).replace(/\\/g, "/");
|
|
59129
59414
|
if (relativePath.startsWith("..")) {
|
|
59130
59415
|
normalizeErrors.push(`Path '${file3}' resolves outside the project directory`);
|
|
59131
59416
|
return file3;
|
|
@@ -59451,20 +59736,20 @@ function validateBase(base) {
|
|
|
59451
59736
|
function validatePaths(paths) {
|
|
59452
59737
|
if (!paths)
|
|
59453
59738
|
return null;
|
|
59454
|
-
for (const
|
|
59455
|
-
if (!
|
|
59739
|
+
for (const path52 of paths) {
|
|
59740
|
+
if (!path52 || path52.length === 0) {
|
|
59456
59741
|
return "empty path not allowed";
|
|
59457
59742
|
}
|
|
59458
|
-
if (
|
|
59743
|
+
if (path52.length > MAX_PATH_LENGTH) {
|
|
59459
59744
|
return `path exceeds maximum length of ${MAX_PATH_LENGTH}`;
|
|
59460
59745
|
}
|
|
59461
|
-
if (SHELL_METACHARACTERS2.test(
|
|
59746
|
+
if (SHELL_METACHARACTERS2.test(path52)) {
|
|
59462
59747
|
return "path contains shell metacharacters";
|
|
59463
59748
|
}
|
|
59464
|
-
if (
|
|
59749
|
+
if (path52.startsWith("-")) {
|
|
59465
59750
|
return 'path cannot start with "-" (option-like arguments not allowed)';
|
|
59466
59751
|
}
|
|
59467
|
-
if (CONTROL_CHAR_PATTERN2.test(
|
|
59752
|
+
if (CONTROL_CHAR_PATTERN2.test(path52)) {
|
|
59468
59753
|
return "path contains control characters";
|
|
59469
59754
|
}
|
|
59470
59755
|
}
|
|
@@ -59545,8 +59830,8 @@ var diff = createSwarmTool({
|
|
|
59545
59830
|
if (parts2.length >= 3) {
|
|
59546
59831
|
const additions = parseInt(parts2[0], 10) || 0;
|
|
59547
59832
|
const deletions = parseInt(parts2[1], 10) || 0;
|
|
59548
|
-
const
|
|
59549
|
-
files.push({ path:
|
|
59833
|
+
const path52 = parts2[2];
|
|
59834
|
+
files.push({ path: path52, additions, deletions });
|
|
59550
59835
|
}
|
|
59551
59836
|
}
|
|
59552
59837
|
const contractChanges = [];
|
|
@@ -59828,8 +60113,8 @@ Use these as DOMAIN values when delegating to @sme.`;
|
|
|
59828
60113
|
// src/tools/evidence-check.ts
|
|
59829
60114
|
init_dist();
|
|
59830
60115
|
init_create_tool();
|
|
59831
|
-
import * as
|
|
59832
|
-
import * as
|
|
60116
|
+
import * as fs39 from "fs";
|
|
60117
|
+
import * as path52 from "path";
|
|
59833
60118
|
var MAX_FILE_SIZE_BYTES4 = 1024 * 1024;
|
|
59834
60119
|
var MAX_EVIDENCE_FILES = 1000;
|
|
59835
60120
|
var EVIDENCE_DIR2 = ".swarm/evidence";
|
|
@@ -59856,9 +60141,9 @@ function validateRequiredTypes(input) {
|
|
|
59856
60141
|
return null;
|
|
59857
60142
|
}
|
|
59858
60143
|
function isPathWithinSwarm2(filePath, cwd) {
|
|
59859
|
-
const normalizedCwd =
|
|
59860
|
-
const swarmPath =
|
|
59861
|
-
const normalizedPath =
|
|
60144
|
+
const normalizedCwd = path52.resolve(cwd);
|
|
60145
|
+
const swarmPath = path52.join(normalizedCwd, ".swarm");
|
|
60146
|
+
const normalizedPath = path52.resolve(filePath);
|
|
59862
60147
|
return normalizedPath.startsWith(swarmPath);
|
|
59863
60148
|
}
|
|
59864
60149
|
function parseCompletedTasks(planContent) {
|
|
@@ -59874,12 +60159,12 @@ function parseCompletedTasks(planContent) {
|
|
|
59874
60159
|
}
|
|
59875
60160
|
function readEvidenceFiles(evidenceDir, _cwd) {
|
|
59876
60161
|
const evidence = [];
|
|
59877
|
-
if (!
|
|
60162
|
+
if (!fs39.existsSync(evidenceDir) || !fs39.statSync(evidenceDir).isDirectory()) {
|
|
59878
60163
|
return evidence;
|
|
59879
60164
|
}
|
|
59880
60165
|
let files;
|
|
59881
60166
|
try {
|
|
59882
|
-
files =
|
|
60167
|
+
files = fs39.readdirSync(evidenceDir);
|
|
59883
60168
|
} catch {
|
|
59884
60169
|
return evidence;
|
|
59885
60170
|
}
|
|
@@ -59888,14 +60173,14 @@ function readEvidenceFiles(evidenceDir, _cwd) {
|
|
|
59888
60173
|
if (!VALID_EVIDENCE_FILENAME_REGEX.test(filename)) {
|
|
59889
60174
|
continue;
|
|
59890
60175
|
}
|
|
59891
|
-
const filePath =
|
|
60176
|
+
const filePath = path52.join(evidenceDir, filename);
|
|
59892
60177
|
try {
|
|
59893
|
-
const resolvedPath =
|
|
59894
|
-
const evidenceDirResolved =
|
|
60178
|
+
const resolvedPath = path52.resolve(filePath);
|
|
60179
|
+
const evidenceDirResolved = path52.resolve(evidenceDir);
|
|
59895
60180
|
if (!resolvedPath.startsWith(evidenceDirResolved)) {
|
|
59896
60181
|
continue;
|
|
59897
60182
|
}
|
|
59898
|
-
const stat2 =
|
|
60183
|
+
const stat2 = fs39.lstatSync(filePath);
|
|
59899
60184
|
if (!stat2.isFile()) {
|
|
59900
60185
|
continue;
|
|
59901
60186
|
}
|
|
@@ -59904,7 +60189,7 @@ function readEvidenceFiles(evidenceDir, _cwd) {
|
|
|
59904
60189
|
}
|
|
59905
60190
|
let fileStat;
|
|
59906
60191
|
try {
|
|
59907
|
-
fileStat =
|
|
60192
|
+
fileStat = fs39.statSync(filePath);
|
|
59908
60193
|
if (fileStat.size > MAX_FILE_SIZE_BYTES4) {
|
|
59909
60194
|
continue;
|
|
59910
60195
|
}
|
|
@@ -59913,7 +60198,7 @@ function readEvidenceFiles(evidenceDir, _cwd) {
|
|
|
59913
60198
|
}
|
|
59914
60199
|
let content;
|
|
59915
60200
|
try {
|
|
59916
|
-
content =
|
|
60201
|
+
content = fs39.readFileSync(filePath, "utf-8");
|
|
59917
60202
|
} catch {
|
|
59918
60203
|
continue;
|
|
59919
60204
|
}
|
|
@@ -60009,7 +60294,7 @@ var evidence_check = createSwarmTool({
|
|
|
60009
60294
|
return JSON.stringify(errorResult, null, 2);
|
|
60010
60295
|
}
|
|
60011
60296
|
const requiredTypes = requiredTypesValue.split(",").map((t) => t.trim()).filter((t) => t.length > 0).map(normalizeEvidenceType);
|
|
60012
|
-
const planPath =
|
|
60297
|
+
const planPath = path52.join(cwd, PLAN_FILE);
|
|
60013
60298
|
if (!isPathWithinSwarm2(planPath, cwd)) {
|
|
60014
60299
|
const errorResult = {
|
|
60015
60300
|
error: "plan file path validation failed",
|
|
@@ -60023,7 +60308,7 @@ var evidence_check = createSwarmTool({
|
|
|
60023
60308
|
}
|
|
60024
60309
|
let planContent;
|
|
60025
60310
|
try {
|
|
60026
|
-
planContent =
|
|
60311
|
+
planContent = fs39.readFileSync(planPath, "utf-8");
|
|
60027
60312
|
} catch {
|
|
60028
60313
|
const result2 = {
|
|
60029
60314
|
message: "No completed tasks found in plan.",
|
|
@@ -60041,7 +60326,7 @@ var evidence_check = createSwarmTool({
|
|
|
60041
60326
|
};
|
|
60042
60327
|
return JSON.stringify(result2, null, 2);
|
|
60043
60328
|
}
|
|
60044
|
-
const evidenceDir =
|
|
60329
|
+
const evidenceDir = path52.join(cwd, EVIDENCE_DIR2);
|
|
60045
60330
|
const evidence = readEvidenceFiles(evidenceDir, cwd);
|
|
60046
60331
|
const { tasksWithFullEvidence, gaps } = analyzeGaps(completedTasks, evidence, requiredTypes);
|
|
60047
60332
|
const completeness = completedTasks.length > 0 ? Math.round(tasksWithFullEvidence.length / completedTasks.length * 100) / 100 : 1;
|
|
@@ -60058,8 +60343,8 @@ var evidence_check = createSwarmTool({
|
|
|
60058
60343
|
// src/tools/file-extractor.ts
|
|
60059
60344
|
init_tool();
|
|
60060
60345
|
init_create_tool();
|
|
60061
|
-
import * as
|
|
60062
|
-
import * as
|
|
60346
|
+
import * as fs40 from "fs";
|
|
60347
|
+
import * as path53 from "path";
|
|
60063
60348
|
var EXT_MAP = {
|
|
60064
60349
|
python: ".py",
|
|
60065
60350
|
py: ".py",
|
|
@@ -60121,8 +60406,8 @@ var extract_code_blocks = createSwarmTool({
|
|
|
60121
60406
|
execute: async (args2, directory) => {
|
|
60122
60407
|
const { content, output_dir, prefix } = args2;
|
|
60123
60408
|
const targetDir = output_dir || directory;
|
|
60124
|
-
if (!
|
|
60125
|
-
|
|
60409
|
+
if (!fs40.existsSync(targetDir)) {
|
|
60410
|
+
fs40.mkdirSync(targetDir, { recursive: true });
|
|
60126
60411
|
}
|
|
60127
60412
|
if (!content) {
|
|
60128
60413
|
return "Error: content is required";
|
|
@@ -60140,16 +60425,16 @@ var extract_code_blocks = createSwarmTool({
|
|
|
60140
60425
|
if (prefix) {
|
|
60141
60426
|
filename = `${prefix}_${filename}`;
|
|
60142
60427
|
}
|
|
60143
|
-
let filepath =
|
|
60144
|
-
const base =
|
|
60145
|
-
const ext =
|
|
60428
|
+
let filepath = path53.join(targetDir, filename);
|
|
60429
|
+
const base = path53.basename(filepath, path53.extname(filepath));
|
|
60430
|
+
const ext = path53.extname(filepath);
|
|
60146
60431
|
let counter = 1;
|
|
60147
|
-
while (
|
|
60148
|
-
filepath =
|
|
60432
|
+
while (fs40.existsSync(filepath)) {
|
|
60433
|
+
filepath = path53.join(targetDir, `${base}_${counter}${ext}`);
|
|
60149
60434
|
counter++;
|
|
60150
60435
|
}
|
|
60151
60436
|
try {
|
|
60152
|
-
|
|
60437
|
+
fs40.writeFileSync(filepath, code.trim(), "utf-8");
|
|
60153
60438
|
savedFiles.push(filepath);
|
|
60154
60439
|
} catch (error93) {
|
|
60155
60440
|
errors5.push(`Failed to save ${filename}: ${error93 instanceof Error ? error93.message : String(error93)}`);
|
|
@@ -60265,8 +60550,8 @@ var gitingest = createSwarmTool({
|
|
|
60265
60550
|
// src/tools/imports.ts
|
|
60266
60551
|
init_dist();
|
|
60267
60552
|
init_create_tool();
|
|
60268
|
-
import * as
|
|
60269
|
-
import * as
|
|
60553
|
+
import * as fs41 from "fs";
|
|
60554
|
+
import * as path54 from "path";
|
|
60270
60555
|
var MAX_FILE_PATH_LENGTH2 = 500;
|
|
60271
60556
|
var MAX_SYMBOL_LENGTH = 256;
|
|
60272
60557
|
var MAX_FILE_SIZE_BYTES5 = 1024 * 1024;
|
|
@@ -60314,7 +60599,7 @@ function validateSymbolInput(symbol3) {
|
|
|
60314
60599
|
return null;
|
|
60315
60600
|
}
|
|
60316
60601
|
function isBinaryFile2(filePath, buffer) {
|
|
60317
|
-
const ext =
|
|
60602
|
+
const ext = path54.extname(filePath).toLowerCase();
|
|
60318
60603
|
if (ext === ".json" || ext === ".md" || ext === ".txt") {
|
|
60319
60604
|
return false;
|
|
60320
60605
|
}
|
|
@@ -60338,15 +60623,15 @@ function parseImports(content, targetFile, targetSymbol) {
|
|
|
60338
60623
|
const imports = [];
|
|
60339
60624
|
let _resolvedTarget;
|
|
60340
60625
|
try {
|
|
60341
|
-
_resolvedTarget =
|
|
60626
|
+
_resolvedTarget = path54.resolve(targetFile);
|
|
60342
60627
|
} catch {
|
|
60343
60628
|
_resolvedTarget = targetFile;
|
|
60344
60629
|
}
|
|
60345
|
-
const targetBasename =
|
|
60630
|
+
const targetBasename = path54.basename(targetFile, path54.extname(targetFile));
|
|
60346
60631
|
const targetWithExt = targetFile;
|
|
60347
60632
|
const targetWithoutExt = targetFile.replace(/\.(ts|tsx|js|jsx|mjs|cjs)$/i, "");
|
|
60348
|
-
const normalizedTargetWithExt =
|
|
60349
|
-
const normalizedTargetWithoutExt =
|
|
60633
|
+
const normalizedTargetWithExt = path54.normalize(targetWithExt).replace(/\\/g, "/");
|
|
60634
|
+
const normalizedTargetWithoutExt = path54.normalize(targetWithoutExt).replace(/\\/g, "/");
|
|
60350
60635
|
const importRegex = /import\s+(?:\{[\s\S]*?\}|(?:\*\s+as\s+\w+)|\w+)\s+from\s+['"`]([^'"`]+)['"`]|import\s+['"`]([^'"`]+)['"`]|require\s*\(\s*['"`]([^'"`]+)['"`]\s*\)/g;
|
|
60351
60636
|
for (let match = importRegex.exec(content);match !== null; match = importRegex.exec(content)) {
|
|
60352
60637
|
const modulePath = match[1] || match[2] || match[3];
|
|
@@ -60369,9 +60654,9 @@ function parseImports(content, targetFile, targetSymbol) {
|
|
|
60369
60654
|
}
|
|
60370
60655
|
const _normalizedModule = modulePath.replace(/^\.\//, "").replace(/^\.\.\\/, "../");
|
|
60371
60656
|
let isMatch = false;
|
|
60372
|
-
const _targetDir =
|
|
60373
|
-
const targetExt =
|
|
60374
|
-
const targetBasenameNoExt =
|
|
60657
|
+
const _targetDir = path54.dirname(targetFile);
|
|
60658
|
+
const targetExt = path54.extname(targetFile);
|
|
60659
|
+
const targetBasenameNoExt = path54.basename(targetFile, targetExt);
|
|
60375
60660
|
const moduleNormalized = modulePath.replace(/\\/g, "/").replace(/^\.\//, "");
|
|
60376
60661
|
const moduleName = modulePath.split(/[/\\]/).pop() || "";
|
|
60377
60662
|
const moduleNameNoExt = moduleName.replace(/\.(ts|tsx|js|jsx|mjs|cjs)$/i, "");
|
|
@@ -60428,7 +60713,7 @@ var SKIP_DIRECTORIES3 = new Set([
|
|
|
60428
60713
|
function findSourceFiles(dir, files = [], stats = { skippedDirs: [], skippedFiles: 0, fileErrors: [] }) {
|
|
60429
60714
|
let entries;
|
|
60430
60715
|
try {
|
|
60431
|
-
entries =
|
|
60716
|
+
entries = fs41.readdirSync(dir);
|
|
60432
60717
|
} catch (e) {
|
|
60433
60718
|
stats.fileErrors.push({
|
|
60434
60719
|
path: dir,
|
|
@@ -60439,13 +60724,13 @@ function findSourceFiles(dir, files = [], stats = { skippedDirs: [], skippedFile
|
|
|
60439
60724
|
entries.sort((a, b) => a.toLowerCase().localeCompare(b.toLowerCase()));
|
|
60440
60725
|
for (const entry of entries) {
|
|
60441
60726
|
if (SKIP_DIRECTORIES3.has(entry)) {
|
|
60442
|
-
stats.skippedDirs.push(
|
|
60727
|
+
stats.skippedDirs.push(path54.join(dir, entry));
|
|
60443
60728
|
continue;
|
|
60444
60729
|
}
|
|
60445
|
-
const fullPath =
|
|
60730
|
+
const fullPath = path54.join(dir, entry);
|
|
60446
60731
|
let stat2;
|
|
60447
60732
|
try {
|
|
60448
|
-
stat2 =
|
|
60733
|
+
stat2 = fs41.statSync(fullPath);
|
|
60449
60734
|
} catch (e) {
|
|
60450
60735
|
stats.fileErrors.push({
|
|
60451
60736
|
path: fullPath,
|
|
@@ -60456,7 +60741,7 @@ function findSourceFiles(dir, files = [], stats = { skippedDirs: [], skippedFile
|
|
|
60456
60741
|
if (stat2.isDirectory()) {
|
|
60457
60742
|
findSourceFiles(fullPath, files, stats);
|
|
60458
60743
|
} else if (stat2.isFile()) {
|
|
60459
|
-
const ext =
|
|
60744
|
+
const ext = path54.extname(fullPath).toLowerCase();
|
|
60460
60745
|
if (SUPPORTED_EXTENSIONS.includes(ext)) {
|
|
60461
60746
|
files.push(fullPath);
|
|
60462
60747
|
}
|
|
@@ -60513,8 +60798,8 @@ var imports = createSwarmTool({
|
|
|
60513
60798
|
return JSON.stringify(errorResult, null, 2);
|
|
60514
60799
|
}
|
|
60515
60800
|
try {
|
|
60516
|
-
const targetFile =
|
|
60517
|
-
if (!
|
|
60801
|
+
const targetFile = path54.resolve(file3);
|
|
60802
|
+
if (!fs41.existsSync(targetFile)) {
|
|
60518
60803
|
const errorResult = {
|
|
60519
60804
|
error: `target file not found: ${file3}`,
|
|
60520
60805
|
target: file3,
|
|
@@ -60524,7 +60809,7 @@ var imports = createSwarmTool({
|
|
|
60524
60809
|
};
|
|
60525
60810
|
return JSON.stringify(errorResult, null, 2);
|
|
60526
60811
|
}
|
|
60527
|
-
const targetStat =
|
|
60812
|
+
const targetStat = fs41.statSync(targetFile);
|
|
60528
60813
|
if (!targetStat.isFile()) {
|
|
60529
60814
|
const errorResult = {
|
|
60530
60815
|
error: "target must be a file, not a directory",
|
|
@@ -60535,7 +60820,7 @@ var imports = createSwarmTool({
|
|
|
60535
60820
|
};
|
|
60536
60821
|
return JSON.stringify(errorResult, null, 2);
|
|
60537
60822
|
}
|
|
60538
|
-
const baseDir =
|
|
60823
|
+
const baseDir = path54.dirname(targetFile);
|
|
60539
60824
|
const scanStats = {
|
|
60540
60825
|
skippedDirs: [],
|
|
60541
60826
|
skippedFiles: 0,
|
|
@@ -60550,12 +60835,12 @@ var imports = createSwarmTool({
|
|
|
60550
60835
|
if (consumers.length >= MAX_CONSUMERS)
|
|
60551
60836
|
break;
|
|
60552
60837
|
try {
|
|
60553
|
-
const stat2 =
|
|
60838
|
+
const stat2 = fs41.statSync(filePath);
|
|
60554
60839
|
if (stat2.size > MAX_FILE_SIZE_BYTES5) {
|
|
60555
60840
|
skippedFileCount++;
|
|
60556
60841
|
continue;
|
|
60557
60842
|
}
|
|
60558
|
-
const buffer =
|
|
60843
|
+
const buffer = fs41.readFileSync(filePath);
|
|
60559
60844
|
if (isBinaryFile2(filePath, buffer)) {
|
|
60560
60845
|
skippedFileCount++;
|
|
60561
60846
|
continue;
|
|
@@ -60622,7 +60907,7 @@ var imports = createSwarmTool({
|
|
|
60622
60907
|
init_dist();
|
|
60623
60908
|
init_config();
|
|
60624
60909
|
init_knowledge_store();
|
|
60625
|
-
import { randomUUID as
|
|
60910
|
+
import { randomUUID as randomUUID5 } from "crypto";
|
|
60626
60911
|
init_manager2();
|
|
60627
60912
|
init_create_tool();
|
|
60628
60913
|
var VALID_CATEGORIES2 = [
|
|
@@ -60697,7 +60982,7 @@ var knowledgeAdd = createSwarmTool({
|
|
|
60697
60982
|
project_name = plan?.title ?? "";
|
|
60698
60983
|
} catch {}
|
|
60699
60984
|
const entry = {
|
|
60700
|
-
id:
|
|
60985
|
+
id: randomUUID5(),
|
|
60701
60986
|
tier: "swarm",
|
|
60702
60987
|
lesson,
|
|
60703
60988
|
category,
|
|
@@ -60755,7 +61040,7 @@ init_dist();
|
|
|
60755
61040
|
init_config();
|
|
60756
61041
|
init_knowledge_store();
|
|
60757
61042
|
init_create_tool();
|
|
60758
|
-
import { existsSync as
|
|
61043
|
+
import { existsSync as existsSync33 } from "fs";
|
|
60759
61044
|
var DEFAULT_LIMIT = 10;
|
|
60760
61045
|
var MAX_LESSON_LENGTH = 200;
|
|
60761
61046
|
var VALID_CATEGORIES3 = [
|
|
@@ -60824,14 +61109,14 @@ function validateLimit(limit) {
|
|
|
60824
61109
|
}
|
|
60825
61110
|
async function readSwarmKnowledge(directory) {
|
|
60826
61111
|
const swarmPath = resolveSwarmKnowledgePath(directory);
|
|
60827
|
-
if (!
|
|
61112
|
+
if (!existsSync33(swarmPath)) {
|
|
60828
61113
|
return [];
|
|
60829
61114
|
}
|
|
60830
61115
|
return readKnowledge(swarmPath);
|
|
60831
61116
|
}
|
|
60832
61117
|
async function readHiveKnowledge() {
|
|
60833
61118
|
const hivePath = resolveHiveKnowledgePath();
|
|
60834
|
-
if (!
|
|
61119
|
+
if (!existsSync33(hivePath)) {
|
|
60835
61120
|
return [];
|
|
60836
61121
|
}
|
|
60837
61122
|
return readKnowledge(hivePath);
|
|
@@ -61144,8 +61429,9 @@ init_dist();
|
|
|
61144
61429
|
init_config();
|
|
61145
61430
|
init_schema();
|
|
61146
61431
|
init_manager();
|
|
61147
|
-
import * as
|
|
61148
|
-
import * as
|
|
61432
|
+
import * as fs42 from "fs";
|
|
61433
|
+
import * as path55 from "path";
|
|
61434
|
+
init_review_receipt();
|
|
61149
61435
|
init_utils2();
|
|
61150
61436
|
init_telemetry();
|
|
61151
61437
|
init_create_tool();
|
|
@@ -61366,11 +61652,11 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
|
|
|
61366
61652
|
safeWarn(`[phase_complete] Completion verify error (non-blocking):`, completionError);
|
|
61367
61653
|
}
|
|
61368
61654
|
try {
|
|
61369
|
-
const driftEvidencePath =
|
|
61655
|
+
const driftEvidencePath = path55.join(dir, ".swarm", "evidence", String(phase), "drift-verifier.json");
|
|
61370
61656
|
let driftVerdictFound = false;
|
|
61371
61657
|
let driftVerdictApproved = false;
|
|
61372
61658
|
try {
|
|
61373
|
-
const driftEvidenceContent =
|
|
61659
|
+
const driftEvidenceContent = fs42.readFileSync(driftEvidencePath, "utf-8");
|
|
61374
61660
|
const driftEvidence = JSON.parse(driftEvidenceContent);
|
|
61375
61661
|
const entries = driftEvidence.entries ?? [];
|
|
61376
61662
|
for (const entry of entries) {
|
|
@@ -61400,14 +61686,14 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
|
|
|
61400
61686
|
driftVerdictFound = false;
|
|
61401
61687
|
}
|
|
61402
61688
|
if (!driftVerdictFound) {
|
|
61403
|
-
const specPath =
|
|
61404
|
-
const specExists =
|
|
61689
|
+
const specPath = path55.join(dir, ".swarm", "spec.md");
|
|
61690
|
+
const specExists = fs42.existsSync(specPath);
|
|
61405
61691
|
if (!specExists) {
|
|
61406
61692
|
let incompleteTaskCount = 0;
|
|
61407
61693
|
let planPhaseFound = false;
|
|
61408
61694
|
try {
|
|
61409
61695
|
const planPath = validateSwarmPath(dir, "plan.json");
|
|
61410
|
-
const planRaw =
|
|
61696
|
+
const planRaw = fs42.readFileSync(planPath, "utf-8");
|
|
61411
61697
|
const plan = JSON.parse(planRaw);
|
|
61412
61698
|
const targetPhase = plan.phases.find((p) => p.id === phase);
|
|
61413
61699
|
if (targetPhase) {
|
|
@@ -61449,32 +61735,10 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
|
|
|
61449
61735
|
safeWarn(`[phase_complete] Drift verifier error (non-blocking):`, driftError);
|
|
61450
61736
|
}
|
|
61451
61737
|
}
|
|
61452
|
-
const knowledgeConfig = {
|
|
61453
|
-
enabled: true,
|
|
61454
|
-
swarm_max_entries: 100,
|
|
61455
|
-
hive_max_entries: 200,
|
|
61456
|
-
auto_promote_days: 90,
|
|
61457
|
-
max_inject_count: 5,
|
|
61458
|
-
dedup_threshold: 0.6,
|
|
61459
|
-
scope_filter: ["global"],
|
|
61460
|
-
hive_enabled: true,
|
|
61461
|
-
rejected_max_entries: 20,
|
|
61462
|
-
validation_enabled: true,
|
|
61463
|
-
evergreen_confidence: 0.9,
|
|
61464
|
-
evergreen_utility: 0.8,
|
|
61465
|
-
low_utility_threshold: 0.3,
|
|
61466
|
-
min_retrievals_for_utility: 3,
|
|
61467
|
-
schema_version: 1,
|
|
61468
|
-
same_project_weight: 1,
|
|
61469
|
-
cross_project_weight: 0.5,
|
|
61470
|
-
min_encounter_score: 0.1,
|
|
61471
|
-
initial_encounter_score: 1,
|
|
61472
|
-
encounter_increment: 0.1,
|
|
61473
|
-
max_encounter_score: 10
|
|
61474
|
-
};
|
|
61738
|
+
const knowledgeConfig = KnowledgeConfigSchema.parse(config3.knowledge ?? {});
|
|
61475
61739
|
if (retroFound && retroEntry?.lessons_learned && retroEntry.lessons_learned.length > 0) {
|
|
61476
61740
|
try {
|
|
61477
|
-
const projectName =
|
|
61741
|
+
const projectName = path55.basename(dir);
|
|
61478
61742
|
const curationResult = await curateAndStoreSwarm(retroEntry.lessons_learned, projectName, { phase_number: phase }, dir, knowledgeConfig);
|
|
61479
61743
|
if (curationResult) {
|
|
61480
61744
|
const sessionState = swarmState.agentSessions.get(sessionID);
|
|
@@ -61483,6 +61747,7 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
|
|
|
61483
61747
|
sessionState.pendingAdvisoryMessages.push(`[CURATOR] Knowledge curation: ${curationResult.stored} stored, ${curationResult.skipped} skipped, ${curationResult.rejected} rejected.`);
|
|
61484
61748
|
}
|
|
61485
61749
|
}
|
|
61750
|
+
await updateRetrievalOutcome(dir, `Phase ${phase}`, true);
|
|
61486
61751
|
} catch (error93) {
|
|
61487
61752
|
safeWarn("[phase_complete] Failed to curate lessons from retrospective:", error93);
|
|
61488
61753
|
}
|
|
@@ -61491,7 +61756,41 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
|
|
|
61491
61756
|
try {
|
|
61492
61757
|
const curatorConfig = CuratorConfigSchema.parse(config3.curator ?? {});
|
|
61493
61758
|
if (curatorConfig.enabled && curatorConfig.phase_enabled) {
|
|
61494
|
-
const
|
|
61759
|
+
const llmDelegate = createCuratorLLMDelegate(dir);
|
|
61760
|
+
const curatorResult = await runCuratorPhase(dir, phase, agentsDispatched, curatorConfig, {}, llmDelegate);
|
|
61761
|
+
{
|
|
61762
|
+
const scopeContent = curatorResult.digest?.summary ?? `Phase ${phase} curator analysis`;
|
|
61763
|
+
const complianceWarnings2 = curatorResult.compliance.filter((c) => c.severity === "warning");
|
|
61764
|
+
const receipt = complianceWarnings2.length > 0 ? buildRejectedReceipt({
|
|
61765
|
+
agent: "curator",
|
|
61766
|
+
scopeContent,
|
|
61767
|
+
scopeDescription: "phase-digest",
|
|
61768
|
+
blockingFindings: complianceWarnings2.map((c) => ({
|
|
61769
|
+
location: `phase-${c.phase}`,
|
|
61770
|
+
summary: c.description,
|
|
61771
|
+
severity: c.type === "missing_reviewer" ? "high" : "medium"
|
|
61772
|
+
})),
|
|
61773
|
+
evidenceReferences: [],
|
|
61774
|
+
passConditions: [
|
|
61775
|
+
"resolve all compliance warnings before phase completion"
|
|
61776
|
+
]
|
|
61777
|
+
}) : buildApprovedReceipt({
|
|
61778
|
+
agent: "curator",
|
|
61779
|
+
scopeContent,
|
|
61780
|
+
scopeDescription: "phase-digest",
|
|
61781
|
+
checkedAspects: [
|
|
61782
|
+
"phase_compliance",
|
|
61783
|
+
"knowledge_recommendations",
|
|
61784
|
+
"phase_digest"
|
|
61785
|
+
],
|
|
61786
|
+
validatedClaims: [
|
|
61787
|
+
`phase: ${phase}`,
|
|
61788
|
+
`agents_dispatched: ${agentsDispatched.length}`,
|
|
61789
|
+
`knowledge_recommendations: ${curatorResult.knowledge_recommendations.length}`
|
|
61790
|
+
]
|
|
61791
|
+
});
|
|
61792
|
+
persistReviewReceipt(dir, receipt).catch(() => {});
|
|
61793
|
+
}
|
|
61495
61794
|
const knowledgeResult = await applyCuratorKnowledgeUpdates(dir, curatorResult.knowledge_recommendations, knowledgeConfig);
|
|
61496
61795
|
const callerSessionState = swarmState.agentSessions.get(sessionID);
|
|
61497
61796
|
if (callerSessionState) {
|
|
@@ -61519,7 +61818,7 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
|
|
|
61519
61818
|
let phaseRequiredAgents;
|
|
61520
61819
|
try {
|
|
61521
61820
|
const planPath = validateSwarmPath(dir, "plan.json");
|
|
61522
|
-
const planRaw =
|
|
61821
|
+
const planRaw = fs42.readFileSync(planPath, "utf-8");
|
|
61523
61822
|
const plan = JSON.parse(planRaw);
|
|
61524
61823
|
const phaseObj = plan.phases.find((p) => p.id === phase);
|
|
61525
61824
|
phaseRequiredAgents = phaseObj?.required_agents;
|
|
@@ -61534,7 +61833,7 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
|
|
|
61534
61833
|
if (agentsMissing.length > 0) {
|
|
61535
61834
|
try {
|
|
61536
61835
|
const planPath = validateSwarmPath(dir, "plan.json");
|
|
61537
|
-
const planRaw =
|
|
61836
|
+
const planRaw = fs42.readFileSync(planPath, "utf-8");
|
|
61538
61837
|
const plan = JSON.parse(planRaw);
|
|
61539
61838
|
const targetPhase = plan.phases.find((p) => p.id === phase);
|
|
61540
61839
|
if (targetPhase && targetPhase.tasks.length > 0 && targetPhase.tasks.every((t) => t.status === "completed")) {
|
|
@@ -61565,7 +61864,7 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
|
|
|
61565
61864
|
if (phaseCompleteConfig.regression_sweep?.enforce) {
|
|
61566
61865
|
try {
|
|
61567
61866
|
const planPath = validateSwarmPath(dir, "plan.json");
|
|
61568
|
-
const planRaw =
|
|
61867
|
+
const planRaw = fs42.readFileSync(planPath, "utf-8");
|
|
61569
61868
|
const plan = JSON.parse(planRaw);
|
|
61570
61869
|
const targetPhase = plan.phases.find((p) => p.id === phase);
|
|
61571
61870
|
if (targetPhase) {
|
|
@@ -61603,7 +61902,7 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
|
|
|
61603
61902
|
};
|
|
61604
61903
|
try {
|
|
61605
61904
|
const eventsPath = validateSwarmPath(dir, "events.jsonl");
|
|
61606
|
-
|
|
61905
|
+
fs42.appendFileSync(eventsPath, `${JSON.stringify(event)}
|
|
61607
61906
|
`, "utf-8");
|
|
61608
61907
|
} catch (writeError) {
|
|
61609
61908
|
warnings.push(`Warning: failed to write phase complete event: ${writeError instanceof Error ? writeError.message : String(writeError)}`);
|
|
@@ -61627,12 +61926,12 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
|
|
|
61627
61926
|
}
|
|
61628
61927
|
try {
|
|
61629
61928
|
const planPath = validateSwarmPath(dir, "plan.json");
|
|
61630
|
-
const planJson =
|
|
61929
|
+
const planJson = fs42.readFileSync(planPath, "utf-8");
|
|
61631
61930
|
const plan = JSON.parse(planJson);
|
|
61632
61931
|
const phaseObj = plan.phases.find((p) => p.id === phase);
|
|
61633
61932
|
if (phaseObj) {
|
|
61634
61933
|
phaseObj.status = "completed";
|
|
61635
|
-
|
|
61934
|
+
fs42.writeFileSync(planPath, `${JSON.stringify(plan, null, 2)}
|
|
61636
61935
|
`, "utf-8");
|
|
61637
61936
|
}
|
|
61638
61937
|
} catch (error93) {
|
|
@@ -61699,8 +61998,8 @@ init_dist();
|
|
|
61699
61998
|
init_discovery();
|
|
61700
61999
|
init_utils();
|
|
61701
62000
|
init_create_tool();
|
|
61702
|
-
import * as
|
|
61703
|
-
import * as
|
|
62001
|
+
import * as fs43 from "fs";
|
|
62002
|
+
import * as path56 from "path";
|
|
61704
62003
|
var MAX_OUTPUT_BYTES5 = 52428800;
|
|
61705
62004
|
var AUDIT_TIMEOUT_MS = 120000;
|
|
61706
62005
|
function isValidEcosystem(value) {
|
|
@@ -61718,28 +62017,28 @@ function validateArgs3(args2) {
|
|
|
61718
62017
|
function detectEcosystems(directory) {
|
|
61719
62018
|
const ecosystems = [];
|
|
61720
62019
|
const cwd = directory;
|
|
61721
|
-
if (
|
|
62020
|
+
if (fs43.existsSync(path56.join(cwd, "package.json"))) {
|
|
61722
62021
|
ecosystems.push("npm");
|
|
61723
62022
|
}
|
|
61724
|
-
if (
|
|
62023
|
+
if (fs43.existsSync(path56.join(cwd, "pyproject.toml")) || fs43.existsSync(path56.join(cwd, "requirements.txt"))) {
|
|
61725
62024
|
ecosystems.push("pip");
|
|
61726
62025
|
}
|
|
61727
|
-
if (
|
|
62026
|
+
if (fs43.existsSync(path56.join(cwd, "Cargo.toml"))) {
|
|
61728
62027
|
ecosystems.push("cargo");
|
|
61729
62028
|
}
|
|
61730
|
-
if (
|
|
62029
|
+
if (fs43.existsSync(path56.join(cwd, "go.mod"))) {
|
|
61731
62030
|
ecosystems.push("go");
|
|
61732
62031
|
}
|
|
61733
62032
|
try {
|
|
61734
|
-
const files =
|
|
62033
|
+
const files = fs43.readdirSync(cwd);
|
|
61735
62034
|
if (files.some((f) => f.endsWith(".csproj") || f.endsWith(".sln"))) {
|
|
61736
62035
|
ecosystems.push("dotnet");
|
|
61737
62036
|
}
|
|
61738
62037
|
} catch {}
|
|
61739
|
-
if (
|
|
62038
|
+
if (fs43.existsSync(path56.join(cwd, "Gemfile")) || fs43.existsSync(path56.join(cwd, "Gemfile.lock"))) {
|
|
61740
62039
|
ecosystems.push("ruby");
|
|
61741
62040
|
}
|
|
61742
|
-
if (
|
|
62041
|
+
if (fs43.existsSync(path56.join(cwd, "pubspec.yaml"))) {
|
|
61743
62042
|
ecosystems.push("dart");
|
|
61744
62043
|
}
|
|
61745
62044
|
return ecosystems;
|
|
@@ -62760,8 +63059,8 @@ var SUPPORTED_PARSER_EXTENSIONS = new Set([
|
|
|
62760
63059
|
]);
|
|
62761
63060
|
// src/tools/pre-check-batch.ts
|
|
62762
63061
|
init_dist();
|
|
62763
|
-
import * as
|
|
62764
|
-
import * as
|
|
63062
|
+
import * as fs45 from "fs";
|
|
63063
|
+
import * as path58 from "path";
|
|
62765
63064
|
|
|
62766
63065
|
// node_modules/yocto-queue/index.js
|
|
62767
63066
|
class Node2 {
|
|
@@ -62906,8 +63205,8 @@ function pLimit(concurrency) {
|
|
|
62906
63205
|
},
|
|
62907
63206
|
map: {
|
|
62908
63207
|
async value(iterable, function_) {
|
|
62909
|
-
const
|
|
62910
|
-
return Promise.all(
|
|
63208
|
+
const promises6 = Array.from(iterable, (value, index) => this(function_, value, index));
|
|
63209
|
+
return Promise.all(promises6);
|
|
62911
63210
|
}
|
|
62912
63211
|
}
|
|
62913
63212
|
});
|
|
@@ -63035,8 +63334,8 @@ async function qualityBudget(input, directory) {
|
|
|
63035
63334
|
init_dist();
|
|
63036
63335
|
init_manager();
|
|
63037
63336
|
init_detector();
|
|
63038
|
-
import * as
|
|
63039
|
-
import * as
|
|
63337
|
+
import * as fs44 from "fs";
|
|
63338
|
+
import * as path57 from "path";
|
|
63040
63339
|
import { extname as extname10 } from "path";
|
|
63041
63340
|
|
|
63042
63341
|
// src/sast/rules/c.ts
|
|
@@ -63906,17 +64205,17 @@ var SEVERITY_ORDER = {
|
|
|
63906
64205
|
};
|
|
63907
64206
|
function shouldSkipFile(filePath) {
|
|
63908
64207
|
try {
|
|
63909
|
-
const stats =
|
|
64208
|
+
const stats = fs44.statSync(filePath);
|
|
63910
64209
|
if (stats.size > MAX_FILE_SIZE_BYTES6) {
|
|
63911
64210
|
return { skip: true, reason: "file too large" };
|
|
63912
64211
|
}
|
|
63913
64212
|
if (stats.size === 0) {
|
|
63914
64213
|
return { skip: true, reason: "empty file" };
|
|
63915
64214
|
}
|
|
63916
|
-
const fd =
|
|
64215
|
+
const fd = fs44.openSync(filePath, "r");
|
|
63917
64216
|
const buffer = Buffer.alloc(8192);
|
|
63918
|
-
const bytesRead =
|
|
63919
|
-
|
|
64217
|
+
const bytesRead = fs44.readSync(fd, buffer, 0, 8192, 0);
|
|
64218
|
+
fs44.closeSync(fd);
|
|
63920
64219
|
if (bytesRead > 0) {
|
|
63921
64220
|
let nullCount = 0;
|
|
63922
64221
|
for (let i2 = 0;i2 < bytesRead; i2++) {
|
|
@@ -63955,7 +64254,7 @@ function countBySeverity(findings) {
|
|
|
63955
64254
|
}
|
|
63956
64255
|
function scanFileWithTierA(filePath, language) {
|
|
63957
64256
|
try {
|
|
63958
|
-
const content =
|
|
64257
|
+
const content = fs44.readFileSync(filePath, "utf-8");
|
|
63959
64258
|
const findings = executeRulesSync(filePath, content, language);
|
|
63960
64259
|
return findings.map((f) => ({
|
|
63961
64260
|
rule_id: f.rule_id,
|
|
@@ -64002,8 +64301,8 @@ async function sastScan(input, directory, config3) {
|
|
|
64002
64301
|
_filesSkipped++;
|
|
64003
64302
|
continue;
|
|
64004
64303
|
}
|
|
64005
|
-
const resolvedPath =
|
|
64006
|
-
if (!
|
|
64304
|
+
const resolvedPath = path57.isAbsolute(filePath) ? filePath : path57.resolve(directory, filePath);
|
|
64305
|
+
if (!fs44.existsSync(resolvedPath)) {
|
|
64007
64306
|
_filesSkipped++;
|
|
64008
64307
|
continue;
|
|
64009
64308
|
}
|
|
@@ -64201,18 +64500,18 @@ function validatePath(inputPath, baseDir, workspaceDir) {
|
|
|
64201
64500
|
let resolved;
|
|
64202
64501
|
const isWinAbs = isWindowsAbsolutePath(inputPath);
|
|
64203
64502
|
if (isWinAbs) {
|
|
64204
|
-
resolved =
|
|
64205
|
-
} else if (
|
|
64206
|
-
resolved =
|
|
64503
|
+
resolved = path58.win32.resolve(inputPath);
|
|
64504
|
+
} else if (path58.isAbsolute(inputPath)) {
|
|
64505
|
+
resolved = path58.resolve(inputPath);
|
|
64207
64506
|
} else {
|
|
64208
|
-
resolved =
|
|
64507
|
+
resolved = path58.resolve(baseDir, inputPath);
|
|
64209
64508
|
}
|
|
64210
|
-
const workspaceResolved =
|
|
64509
|
+
const workspaceResolved = path58.resolve(workspaceDir);
|
|
64211
64510
|
let relative8;
|
|
64212
64511
|
if (isWinAbs) {
|
|
64213
|
-
relative8 =
|
|
64512
|
+
relative8 = path58.win32.relative(workspaceResolved, resolved);
|
|
64214
64513
|
} else {
|
|
64215
|
-
relative8 =
|
|
64514
|
+
relative8 = path58.relative(workspaceResolved, resolved);
|
|
64216
64515
|
}
|
|
64217
64516
|
if (relative8.startsWith("..")) {
|
|
64218
64517
|
return "path traversal detected";
|
|
@@ -64273,13 +64572,13 @@ async function runLintWrapped(files, directory, _config) {
|
|
|
64273
64572
|
}
|
|
64274
64573
|
async function runLintOnFiles(linter, files, workspaceDir) {
|
|
64275
64574
|
const isWindows = process.platform === "win32";
|
|
64276
|
-
const binDir =
|
|
64575
|
+
const binDir = path58.join(workspaceDir, "node_modules", ".bin");
|
|
64277
64576
|
const validatedFiles = [];
|
|
64278
64577
|
for (const file3 of files) {
|
|
64279
64578
|
if (typeof file3 !== "string") {
|
|
64280
64579
|
continue;
|
|
64281
64580
|
}
|
|
64282
|
-
const resolvedPath =
|
|
64581
|
+
const resolvedPath = path58.resolve(file3);
|
|
64283
64582
|
const validationError = validatePath(resolvedPath, workspaceDir, workspaceDir);
|
|
64284
64583
|
if (validationError) {
|
|
64285
64584
|
continue;
|
|
@@ -64297,10 +64596,10 @@ async function runLintOnFiles(linter, files, workspaceDir) {
|
|
|
64297
64596
|
}
|
|
64298
64597
|
let command;
|
|
64299
64598
|
if (linter === "biome") {
|
|
64300
|
-
const biomeBin = isWindows ?
|
|
64599
|
+
const biomeBin = isWindows ? path58.join(binDir, "biome.EXE") : path58.join(binDir, "biome");
|
|
64301
64600
|
command = [biomeBin, "check", ...validatedFiles];
|
|
64302
64601
|
} else {
|
|
64303
|
-
const eslintBin = isWindows ?
|
|
64602
|
+
const eslintBin = isWindows ? path58.join(binDir, "eslint.cmd") : path58.join(binDir, "eslint");
|
|
64304
64603
|
command = [eslintBin, ...validatedFiles];
|
|
64305
64604
|
}
|
|
64306
64605
|
try {
|
|
@@ -64437,7 +64736,7 @@ async function runSecretscanWithFiles(files, directory) {
|
|
|
64437
64736
|
skippedFiles++;
|
|
64438
64737
|
continue;
|
|
64439
64738
|
}
|
|
64440
|
-
const resolvedPath =
|
|
64739
|
+
const resolvedPath = path58.resolve(file3);
|
|
64441
64740
|
const validationError = validatePath(resolvedPath, directory, directory);
|
|
64442
64741
|
if (validationError) {
|
|
64443
64742
|
skippedFiles++;
|
|
@@ -64455,14 +64754,14 @@ async function runSecretscanWithFiles(files, directory) {
|
|
|
64455
64754
|
};
|
|
64456
64755
|
}
|
|
64457
64756
|
for (const file3 of validatedFiles) {
|
|
64458
|
-
const ext =
|
|
64757
|
+
const ext = path58.extname(file3).toLowerCase();
|
|
64459
64758
|
if (DEFAULT_EXCLUDE_EXTENSIONS2.has(ext)) {
|
|
64460
64759
|
skippedFiles++;
|
|
64461
64760
|
continue;
|
|
64462
64761
|
}
|
|
64463
64762
|
let stat2;
|
|
64464
64763
|
try {
|
|
64465
|
-
stat2 =
|
|
64764
|
+
stat2 = fs45.statSync(file3);
|
|
64466
64765
|
} catch {
|
|
64467
64766
|
skippedFiles++;
|
|
64468
64767
|
continue;
|
|
@@ -64473,7 +64772,7 @@ async function runSecretscanWithFiles(files, directory) {
|
|
|
64473
64772
|
}
|
|
64474
64773
|
let content;
|
|
64475
64774
|
try {
|
|
64476
|
-
const buffer =
|
|
64775
|
+
const buffer = fs45.readFileSync(file3);
|
|
64477
64776
|
if (buffer.includes(0)) {
|
|
64478
64777
|
skippedFiles++;
|
|
64479
64778
|
continue;
|
|
@@ -64661,7 +64960,7 @@ function classifySastFindings(findings, changedLineRanges, directory) {
|
|
|
64661
64960
|
const preexistingFindings = [];
|
|
64662
64961
|
for (const finding of findings) {
|
|
64663
64962
|
const filePath = finding.location.file;
|
|
64664
|
-
const normalised =
|
|
64963
|
+
const normalised = path58.relative(directory, filePath).replace(/\\/g, "/");
|
|
64665
64964
|
const changedLines = changedLineRanges.get(normalised);
|
|
64666
64965
|
if (changedLines && changedLines.has(finding.location.line)) {
|
|
64667
64966
|
newFindings.push(finding);
|
|
@@ -64712,7 +65011,7 @@ async function runPreCheckBatch(input, workspaceDir, contextDir) {
|
|
|
64712
65011
|
warn(`pre_check_batch: Invalid file path: ${file3}`);
|
|
64713
65012
|
continue;
|
|
64714
65013
|
}
|
|
64715
|
-
changedFiles.push(
|
|
65014
|
+
changedFiles.push(path58.resolve(directory, file3));
|
|
64716
65015
|
}
|
|
64717
65016
|
if (changedFiles.length === 0) {
|
|
64718
65017
|
warn("pre_check_batch: No valid files after validation, skipping all tools (fail-closed)");
|
|
@@ -64900,7 +65199,7 @@ var pre_check_batch = createSwarmTool({
|
|
|
64900
65199
|
};
|
|
64901
65200
|
return JSON.stringify(errorResult, null, 2);
|
|
64902
65201
|
}
|
|
64903
|
-
const resolvedDirectory =
|
|
65202
|
+
const resolvedDirectory = path58.resolve(typedArgs.directory);
|
|
64904
65203
|
const workspaceAnchor = resolvedDirectory;
|
|
64905
65204
|
const dirError = validateDirectory2(resolvedDirectory, workspaceAnchor);
|
|
64906
65205
|
if (dirError) {
|
|
@@ -65006,38 +65305,38 @@ ${paginatedContent}`;
|
|
|
65006
65305
|
});
|
|
65007
65306
|
// src/tools/save-plan.ts
|
|
65008
65307
|
init_tool();
|
|
65009
|
-
import * as
|
|
65010
|
-
import * as
|
|
65308
|
+
import * as fs47 from "fs";
|
|
65309
|
+
import * as path60 from "path";
|
|
65011
65310
|
|
|
65012
65311
|
// src/parallel/file-locks.ts
|
|
65013
|
-
import * as
|
|
65014
|
-
import * as
|
|
65312
|
+
import * as fs46 from "fs";
|
|
65313
|
+
import * as path59 from "path";
|
|
65015
65314
|
var LOCKS_DIR = ".swarm/locks";
|
|
65016
65315
|
var LOCK_TIMEOUT_MS = 5 * 60 * 1000;
|
|
65017
65316
|
function getLockFilePath(directory, filePath) {
|
|
65018
|
-
const normalized =
|
|
65019
|
-
if (!normalized.startsWith(
|
|
65317
|
+
const normalized = path59.resolve(directory, filePath);
|
|
65318
|
+
if (!normalized.startsWith(path59.resolve(directory))) {
|
|
65020
65319
|
throw new Error("Invalid file path: path traversal not allowed");
|
|
65021
65320
|
}
|
|
65022
65321
|
const hash3 = Buffer.from(normalized).toString("base64").replace(/[/+=]/g, "_");
|
|
65023
|
-
return
|
|
65322
|
+
return path59.join(directory, LOCKS_DIR, `${hash3}.lock`);
|
|
65024
65323
|
}
|
|
65025
65324
|
function tryAcquireLock(directory, filePath, agent, taskId) {
|
|
65026
65325
|
const lockPath = getLockFilePath(directory, filePath);
|
|
65027
|
-
const locksDir =
|
|
65028
|
-
if (!
|
|
65029
|
-
|
|
65326
|
+
const locksDir = path59.dirname(lockPath);
|
|
65327
|
+
if (!fs46.existsSync(locksDir)) {
|
|
65328
|
+
fs46.mkdirSync(locksDir, { recursive: true });
|
|
65030
65329
|
}
|
|
65031
|
-
if (
|
|
65330
|
+
if (fs46.existsSync(lockPath)) {
|
|
65032
65331
|
try {
|
|
65033
|
-
const existingLock = JSON.parse(
|
|
65332
|
+
const existingLock = JSON.parse(fs46.readFileSync(lockPath, "utf-8"));
|
|
65034
65333
|
if (Date.now() > existingLock.expiresAt) {
|
|
65035
|
-
|
|
65334
|
+
fs46.unlinkSync(lockPath);
|
|
65036
65335
|
} else {
|
|
65037
65336
|
return { acquired: false, existing: existingLock };
|
|
65038
65337
|
}
|
|
65039
65338
|
} catch {
|
|
65040
|
-
|
|
65339
|
+
fs46.unlinkSync(lockPath);
|
|
65041
65340
|
}
|
|
65042
65341
|
}
|
|
65043
65342
|
const lock = {
|
|
@@ -65048,24 +65347,24 @@ function tryAcquireLock(directory, filePath, agent, taskId) {
|
|
|
65048
65347
|
expiresAt: Date.now() + LOCK_TIMEOUT_MS
|
|
65049
65348
|
};
|
|
65050
65349
|
const tempPath = `${lockPath}.tmp`;
|
|
65051
|
-
|
|
65052
|
-
|
|
65350
|
+
fs46.writeFileSync(tempPath, JSON.stringify(lock, null, 2), "utf-8");
|
|
65351
|
+
fs46.renameSync(tempPath, lockPath);
|
|
65053
65352
|
return { acquired: true, lock };
|
|
65054
65353
|
}
|
|
65055
65354
|
function releaseLock(directory, filePath, taskId) {
|
|
65056
65355
|
const lockPath = getLockFilePath(directory, filePath);
|
|
65057
|
-
if (!
|
|
65356
|
+
if (!fs46.existsSync(lockPath)) {
|
|
65058
65357
|
return true;
|
|
65059
65358
|
}
|
|
65060
65359
|
try {
|
|
65061
|
-
const lock = JSON.parse(
|
|
65360
|
+
const lock = JSON.parse(fs46.readFileSync(lockPath, "utf-8"));
|
|
65062
65361
|
if (lock.taskId === taskId) {
|
|
65063
|
-
|
|
65362
|
+
fs46.unlinkSync(lockPath);
|
|
65064
65363
|
return true;
|
|
65065
65364
|
}
|
|
65066
65365
|
return false;
|
|
65067
65366
|
} catch {
|
|
65068
|
-
|
|
65367
|
+
fs46.unlinkSync(lockPath);
|
|
65069
65368
|
return true;
|
|
65070
65369
|
}
|
|
65071
65370
|
}
|
|
@@ -65190,14 +65489,14 @@ async function executeSavePlan(args2, fallbackDir) {
|
|
|
65190
65489
|
try {
|
|
65191
65490
|
await savePlan(dir, plan);
|
|
65192
65491
|
try {
|
|
65193
|
-
const markerPath =
|
|
65492
|
+
const markerPath = path60.join(dir, ".swarm", ".plan-write-marker");
|
|
65194
65493
|
const marker = JSON.stringify({
|
|
65195
65494
|
source: "save_plan",
|
|
65196
65495
|
timestamp: new Date().toISOString(),
|
|
65197
65496
|
phases_count: plan.phases.length,
|
|
65198
65497
|
tasks_count: tasksCount
|
|
65199
65498
|
});
|
|
65200
|
-
await
|
|
65499
|
+
await fs47.promises.writeFile(markerPath, marker, "utf8");
|
|
65201
65500
|
} catch {}
|
|
65202
65501
|
const warnings = [];
|
|
65203
65502
|
let criticReviewFound = false;
|
|
@@ -65213,7 +65512,7 @@ async function executeSavePlan(args2, fallbackDir) {
|
|
|
65213
65512
|
return {
|
|
65214
65513
|
success: true,
|
|
65215
65514
|
message: "Plan saved successfully",
|
|
65216
|
-
plan_path:
|
|
65515
|
+
plan_path: path60.join(dir, ".swarm", "plan.json"),
|
|
65217
65516
|
phases_count: plan.phases.length,
|
|
65218
65517
|
tasks_count: tasksCount,
|
|
65219
65518
|
...warnings.length > 0 ? { warnings } : {}
|
|
@@ -65255,8 +65554,8 @@ var save_plan = createSwarmTool({
|
|
|
65255
65554
|
// src/tools/sbom-generate.ts
|
|
65256
65555
|
init_dist();
|
|
65257
65556
|
init_manager();
|
|
65258
|
-
import * as
|
|
65259
|
-
import * as
|
|
65557
|
+
import * as fs48 from "fs";
|
|
65558
|
+
import * as path61 from "path";
|
|
65260
65559
|
|
|
65261
65560
|
// src/sbom/detectors/index.ts
|
|
65262
65561
|
init_utils();
|
|
@@ -66104,9 +66403,9 @@ function findManifestFiles(rootDir) {
|
|
|
66104
66403
|
const patterns = [...new Set(allDetectors.flatMap((d) => d.patterns))];
|
|
66105
66404
|
function searchDir(dir) {
|
|
66106
66405
|
try {
|
|
66107
|
-
const entries =
|
|
66406
|
+
const entries = fs48.readdirSync(dir, { withFileTypes: true });
|
|
66108
66407
|
for (const entry of entries) {
|
|
66109
|
-
const fullPath =
|
|
66408
|
+
const fullPath = path61.join(dir, entry.name);
|
|
66110
66409
|
if (entry.name.startsWith(".") || entry.name === "node_modules" || entry.name === "dist" || entry.name === "build" || entry.name === "target") {
|
|
66111
66410
|
continue;
|
|
66112
66411
|
}
|
|
@@ -66115,7 +66414,7 @@ function findManifestFiles(rootDir) {
|
|
|
66115
66414
|
} else if (entry.isFile()) {
|
|
66116
66415
|
for (const pattern of patterns) {
|
|
66117
66416
|
if (simpleGlobToRegex(pattern).test(entry.name)) {
|
|
66118
|
-
manifestFiles.push(
|
|
66417
|
+
manifestFiles.push(path61.relative(rootDir, fullPath));
|
|
66119
66418
|
break;
|
|
66120
66419
|
}
|
|
66121
66420
|
}
|
|
@@ -66131,13 +66430,13 @@ function findManifestFilesInDirs(directories, workingDir) {
|
|
|
66131
66430
|
const patterns = [...new Set(allDetectors.flatMap((d) => d.patterns))];
|
|
66132
66431
|
for (const dir of directories) {
|
|
66133
66432
|
try {
|
|
66134
|
-
const entries =
|
|
66433
|
+
const entries = fs48.readdirSync(dir, { withFileTypes: true });
|
|
66135
66434
|
for (const entry of entries) {
|
|
66136
|
-
const fullPath =
|
|
66435
|
+
const fullPath = path61.join(dir, entry.name);
|
|
66137
66436
|
if (entry.isFile()) {
|
|
66138
66437
|
for (const pattern of patterns) {
|
|
66139
66438
|
if (simpleGlobToRegex(pattern).test(entry.name)) {
|
|
66140
|
-
found.push(
|
|
66439
|
+
found.push(path61.relative(workingDir, fullPath));
|
|
66141
66440
|
break;
|
|
66142
66441
|
}
|
|
66143
66442
|
}
|
|
@@ -66150,11 +66449,11 @@ function findManifestFilesInDirs(directories, workingDir) {
|
|
|
66150
66449
|
function getDirectoriesFromChangedFiles(changedFiles, workingDir) {
|
|
66151
66450
|
const dirs = new Set;
|
|
66152
66451
|
for (const file3 of changedFiles) {
|
|
66153
|
-
let currentDir =
|
|
66452
|
+
let currentDir = path61.dirname(file3);
|
|
66154
66453
|
while (true) {
|
|
66155
|
-
if (currentDir && currentDir !== "." && currentDir !==
|
|
66156
|
-
dirs.add(
|
|
66157
|
-
const parent =
|
|
66454
|
+
if (currentDir && currentDir !== "." && currentDir !== path61.sep) {
|
|
66455
|
+
dirs.add(path61.join(workingDir, currentDir));
|
|
66456
|
+
const parent = path61.dirname(currentDir);
|
|
66158
66457
|
if (parent === currentDir)
|
|
66159
66458
|
break;
|
|
66160
66459
|
currentDir = parent;
|
|
@@ -66168,7 +66467,7 @@ function getDirectoriesFromChangedFiles(changedFiles, workingDir) {
|
|
|
66168
66467
|
}
|
|
66169
66468
|
function ensureOutputDir(outputDir) {
|
|
66170
66469
|
try {
|
|
66171
|
-
|
|
66470
|
+
fs48.mkdirSync(outputDir, { recursive: true });
|
|
66172
66471
|
} catch (error93) {
|
|
66173
66472
|
if (!error93 || error93.code !== "EEXIST") {
|
|
66174
66473
|
throw error93;
|
|
@@ -66238,7 +66537,7 @@ var sbom_generate = createSwarmTool({
|
|
|
66238
66537
|
const changedFiles = obj.changed_files;
|
|
66239
66538
|
const relativeOutputDir = obj.output_dir || DEFAULT_OUTPUT_DIR;
|
|
66240
66539
|
const workingDir = directory;
|
|
66241
|
-
const outputDir =
|
|
66540
|
+
const outputDir = path61.isAbsolute(relativeOutputDir) ? relativeOutputDir : path61.join(workingDir, relativeOutputDir);
|
|
66242
66541
|
let manifestFiles = [];
|
|
66243
66542
|
if (scope === "all") {
|
|
66244
66543
|
manifestFiles = findManifestFiles(workingDir);
|
|
@@ -66261,11 +66560,11 @@ var sbom_generate = createSwarmTool({
|
|
|
66261
66560
|
const processedFiles = [];
|
|
66262
66561
|
for (const manifestFile of manifestFiles) {
|
|
66263
66562
|
try {
|
|
66264
|
-
const fullPath =
|
|
66265
|
-
if (!
|
|
66563
|
+
const fullPath = path61.isAbsolute(manifestFile) ? manifestFile : path61.join(workingDir, manifestFile);
|
|
66564
|
+
if (!fs48.existsSync(fullPath)) {
|
|
66266
66565
|
continue;
|
|
66267
66566
|
}
|
|
66268
|
-
const content =
|
|
66567
|
+
const content = fs48.readFileSync(fullPath, "utf-8");
|
|
66269
66568
|
const components = detectComponents(manifestFile, content);
|
|
66270
66569
|
processedFiles.push(manifestFile);
|
|
66271
66570
|
if (components.length > 0) {
|
|
@@ -66278,8 +66577,8 @@ var sbom_generate = createSwarmTool({
|
|
|
66278
66577
|
const bom = generateCycloneDX(allComponents);
|
|
66279
66578
|
const bomJson = serializeCycloneDX(bom);
|
|
66280
66579
|
const filename = generateSbomFilename();
|
|
66281
|
-
const outputPath =
|
|
66282
|
-
|
|
66580
|
+
const outputPath = path61.join(outputDir, filename);
|
|
66581
|
+
fs48.writeFileSync(outputPath, bomJson, "utf-8");
|
|
66283
66582
|
const verdict = processedFiles.length > 0 ? "pass" : "pass";
|
|
66284
66583
|
try {
|
|
66285
66584
|
const timestamp = new Date().toISOString();
|
|
@@ -66321,8 +66620,8 @@ var sbom_generate = createSwarmTool({
|
|
|
66321
66620
|
// src/tools/schema-drift.ts
|
|
66322
66621
|
init_dist();
|
|
66323
66622
|
init_create_tool();
|
|
66324
|
-
import * as
|
|
66325
|
-
import * as
|
|
66623
|
+
import * as fs49 from "fs";
|
|
66624
|
+
import * as path62 from "path";
|
|
66326
66625
|
var SPEC_CANDIDATES = [
|
|
66327
66626
|
"openapi.json",
|
|
66328
66627
|
"openapi.yaml",
|
|
@@ -66354,28 +66653,28 @@ function normalizePath2(p) {
|
|
|
66354
66653
|
}
|
|
66355
66654
|
function discoverSpecFile(cwd, specFileArg) {
|
|
66356
66655
|
if (specFileArg) {
|
|
66357
|
-
const resolvedPath =
|
|
66358
|
-
const normalizedCwd = cwd.endsWith(
|
|
66656
|
+
const resolvedPath = path62.resolve(cwd, specFileArg);
|
|
66657
|
+
const normalizedCwd = cwd.endsWith(path62.sep) ? cwd : cwd + path62.sep;
|
|
66359
66658
|
if (!resolvedPath.startsWith(normalizedCwd) && resolvedPath !== cwd) {
|
|
66360
66659
|
throw new Error("Invalid spec_file: path traversal detected");
|
|
66361
66660
|
}
|
|
66362
|
-
const ext =
|
|
66661
|
+
const ext = path62.extname(resolvedPath).toLowerCase();
|
|
66363
66662
|
if (!ALLOWED_EXTENSIONS.includes(ext)) {
|
|
66364
66663
|
throw new Error(`Invalid spec_file: must end in .json, .yaml, or .yml, got ${ext}`);
|
|
66365
66664
|
}
|
|
66366
|
-
const stats =
|
|
66665
|
+
const stats = fs49.statSync(resolvedPath);
|
|
66367
66666
|
if (stats.size > MAX_SPEC_SIZE) {
|
|
66368
66667
|
throw new Error(`Invalid spec_file: file exceeds ${MAX_SPEC_SIZE / 1024 / 1024}MB limit`);
|
|
66369
66668
|
}
|
|
66370
|
-
if (!
|
|
66669
|
+
if (!fs49.existsSync(resolvedPath)) {
|
|
66371
66670
|
throw new Error(`Spec file not found: ${resolvedPath}`);
|
|
66372
66671
|
}
|
|
66373
66672
|
return resolvedPath;
|
|
66374
66673
|
}
|
|
66375
66674
|
for (const candidate of SPEC_CANDIDATES) {
|
|
66376
|
-
const candidatePath =
|
|
66377
|
-
if (
|
|
66378
|
-
const stats =
|
|
66675
|
+
const candidatePath = path62.resolve(cwd, candidate);
|
|
66676
|
+
if (fs49.existsSync(candidatePath)) {
|
|
66677
|
+
const stats = fs49.statSync(candidatePath);
|
|
66379
66678
|
if (stats.size <= MAX_SPEC_SIZE) {
|
|
66380
66679
|
return candidatePath;
|
|
66381
66680
|
}
|
|
@@ -66384,8 +66683,8 @@ function discoverSpecFile(cwd, specFileArg) {
|
|
|
66384
66683
|
return null;
|
|
66385
66684
|
}
|
|
66386
66685
|
function parseSpec(specFile) {
|
|
66387
|
-
const content =
|
|
66388
|
-
const ext =
|
|
66686
|
+
const content = fs49.readFileSync(specFile, "utf-8");
|
|
66687
|
+
const ext = path62.extname(specFile).toLowerCase();
|
|
66389
66688
|
if (ext === ".json") {
|
|
66390
66689
|
return parseJsonSpec(content);
|
|
66391
66690
|
}
|
|
@@ -66456,12 +66755,12 @@ function extractRoutes(cwd) {
|
|
|
66456
66755
|
function walkDir(dir) {
|
|
66457
66756
|
let entries;
|
|
66458
66757
|
try {
|
|
66459
|
-
entries =
|
|
66758
|
+
entries = fs49.readdirSync(dir, { withFileTypes: true });
|
|
66460
66759
|
} catch {
|
|
66461
66760
|
return;
|
|
66462
66761
|
}
|
|
66463
66762
|
for (const entry of entries) {
|
|
66464
|
-
const fullPath =
|
|
66763
|
+
const fullPath = path62.join(dir, entry.name);
|
|
66465
66764
|
if (entry.isSymbolicLink()) {
|
|
66466
66765
|
continue;
|
|
66467
66766
|
}
|
|
@@ -66471,7 +66770,7 @@ function extractRoutes(cwd) {
|
|
|
66471
66770
|
}
|
|
66472
66771
|
walkDir(fullPath);
|
|
66473
66772
|
} else if (entry.isFile()) {
|
|
66474
|
-
const ext =
|
|
66773
|
+
const ext = path62.extname(entry.name).toLowerCase();
|
|
66475
66774
|
const baseName = entry.name.toLowerCase();
|
|
66476
66775
|
if (![".ts", ".js", ".mjs"].includes(ext)) {
|
|
66477
66776
|
continue;
|
|
@@ -66489,7 +66788,7 @@ function extractRoutes(cwd) {
|
|
|
66489
66788
|
}
|
|
66490
66789
|
function extractRoutesFromFile(filePath) {
|
|
66491
66790
|
const routes = [];
|
|
66492
|
-
const content =
|
|
66791
|
+
const content = fs49.readFileSync(filePath, "utf-8");
|
|
66493
66792
|
const lines = content.split(/\r?\n/);
|
|
66494
66793
|
const expressRegex = /(?:app|router|server|express)\.(get|post|put|patch|delete|options|head)\s*\(\s*['"`]([^'"`]+)['"`]/g;
|
|
66495
66794
|
const flaskRegex = /@(?:app|blueprint|bp)\.route\s*\(\s*['"]([^'"]+)['"]/g;
|
|
@@ -66640,8 +66939,8 @@ init_secretscan();
|
|
|
66640
66939
|
// src/tools/symbols.ts
|
|
66641
66940
|
init_tool();
|
|
66642
66941
|
init_create_tool();
|
|
66643
|
-
import * as
|
|
66644
|
-
import * as
|
|
66942
|
+
import * as fs50 from "fs";
|
|
66943
|
+
import * as path63 from "path";
|
|
66645
66944
|
var MAX_FILE_SIZE_BYTES7 = 1024 * 1024;
|
|
66646
66945
|
var WINDOWS_RESERVED_NAMES = /^(con|prn|aux|nul|com[1-9]|lpt[1-9])(\.|:|$)/i;
|
|
66647
66946
|
function containsWindowsAttacks(str) {
|
|
@@ -66658,11 +66957,11 @@ function containsWindowsAttacks(str) {
|
|
|
66658
66957
|
}
|
|
66659
66958
|
function isPathInWorkspace(filePath, workspace) {
|
|
66660
66959
|
try {
|
|
66661
|
-
const resolvedPath =
|
|
66662
|
-
const realWorkspace =
|
|
66663
|
-
const realResolvedPath =
|
|
66664
|
-
const relativePath =
|
|
66665
|
-
if (relativePath.startsWith("..") ||
|
|
66960
|
+
const resolvedPath = path63.resolve(workspace, filePath);
|
|
66961
|
+
const realWorkspace = fs50.realpathSync(workspace);
|
|
66962
|
+
const realResolvedPath = fs50.realpathSync(resolvedPath);
|
|
66963
|
+
const relativePath = path63.relative(realWorkspace, realResolvedPath);
|
|
66964
|
+
if (relativePath.startsWith("..") || path63.isAbsolute(relativePath)) {
|
|
66666
66965
|
return false;
|
|
66667
66966
|
}
|
|
66668
66967
|
return true;
|
|
@@ -66674,17 +66973,17 @@ function validatePathForRead(filePath, workspace) {
|
|
|
66674
66973
|
return isPathInWorkspace(filePath, workspace);
|
|
66675
66974
|
}
|
|
66676
66975
|
function extractTSSymbols(filePath, cwd) {
|
|
66677
|
-
const fullPath =
|
|
66976
|
+
const fullPath = path63.join(cwd, filePath);
|
|
66678
66977
|
if (!validatePathForRead(fullPath, cwd)) {
|
|
66679
66978
|
return [];
|
|
66680
66979
|
}
|
|
66681
66980
|
let content;
|
|
66682
66981
|
try {
|
|
66683
|
-
const stats =
|
|
66982
|
+
const stats = fs50.statSync(fullPath);
|
|
66684
66983
|
if (stats.size > MAX_FILE_SIZE_BYTES7) {
|
|
66685
66984
|
throw new Error(`File too large: ${stats.size} bytes (max: ${MAX_FILE_SIZE_BYTES7})`);
|
|
66686
66985
|
}
|
|
66687
|
-
content =
|
|
66986
|
+
content = fs50.readFileSync(fullPath, "utf-8");
|
|
66688
66987
|
} catch {
|
|
66689
66988
|
return [];
|
|
66690
66989
|
}
|
|
@@ -66826,17 +67125,17 @@ function extractTSSymbols(filePath, cwd) {
|
|
|
66826
67125
|
});
|
|
66827
67126
|
}
|
|
66828
67127
|
function extractPythonSymbols(filePath, cwd) {
|
|
66829
|
-
const fullPath =
|
|
67128
|
+
const fullPath = path63.join(cwd, filePath);
|
|
66830
67129
|
if (!validatePathForRead(fullPath, cwd)) {
|
|
66831
67130
|
return [];
|
|
66832
67131
|
}
|
|
66833
67132
|
let content;
|
|
66834
67133
|
try {
|
|
66835
|
-
const stats =
|
|
67134
|
+
const stats = fs50.statSync(fullPath);
|
|
66836
67135
|
if (stats.size > MAX_FILE_SIZE_BYTES7) {
|
|
66837
67136
|
throw new Error(`File too large: ${stats.size} bytes (max: ${MAX_FILE_SIZE_BYTES7})`);
|
|
66838
67137
|
}
|
|
66839
|
-
content =
|
|
67138
|
+
content = fs50.readFileSync(fullPath, "utf-8");
|
|
66840
67139
|
} catch {
|
|
66841
67140
|
return [];
|
|
66842
67141
|
}
|
|
@@ -66909,7 +67208,7 @@ var symbols = createSwarmTool({
|
|
|
66909
67208
|
}, null, 2);
|
|
66910
67209
|
}
|
|
66911
67210
|
const cwd = directory;
|
|
66912
|
-
const ext =
|
|
67211
|
+
const ext = path63.extname(file3);
|
|
66913
67212
|
if (containsControlChars(file3)) {
|
|
66914
67213
|
return JSON.stringify({
|
|
66915
67214
|
file: file3,
|
|
@@ -66980,8 +67279,8 @@ init_test_runner();
|
|
|
66980
67279
|
init_dist();
|
|
66981
67280
|
init_utils();
|
|
66982
67281
|
init_create_tool();
|
|
66983
|
-
import * as
|
|
66984
|
-
import * as
|
|
67282
|
+
import * as fs51 from "fs";
|
|
67283
|
+
import * as path64 from "path";
|
|
66985
67284
|
var MAX_TEXT_LENGTH = 200;
|
|
66986
67285
|
var MAX_FILE_SIZE_BYTES8 = 1024 * 1024;
|
|
66987
67286
|
var SUPPORTED_EXTENSIONS2 = new Set([
|
|
@@ -67046,9 +67345,9 @@ function validatePathsInput(paths, cwd) {
|
|
|
67046
67345
|
return { error: "paths contains path traversal", resolvedPath: null };
|
|
67047
67346
|
}
|
|
67048
67347
|
try {
|
|
67049
|
-
const resolvedPath =
|
|
67050
|
-
const normalizedCwd =
|
|
67051
|
-
const normalizedResolved =
|
|
67348
|
+
const resolvedPath = path64.resolve(paths);
|
|
67349
|
+
const normalizedCwd = path64.resolve(cwd);
|
|
67350
|
+
const normalizedResolved = path64.resolve(resolvedPath);
|
|
67052
67351
|
if (!normalizedResolved.startsWith(normalizedCwd)) {
|
|
67053
67352
|
return {
|
|
67054
67353
|
error: "paths must be within the current working directory",
|
|
@@ -67064,13 +67363,13 @@ function validatePathsInput(paths, cwd) {
|
|
|
67064
67363
|
}
|
|
67065
67364
|
}
|
|
67066
67365
|
function isSupportedExtension(filePath) {
|
|
67067
|
-
const ext =
|
|
67366
|
+
const ext = path64.extname(filePath).toLowerCase();
|
|
67068
67367
|
return SUPPORTED_EXTENSIONS2.has(ext);
|
|
67069
67368
|
}
|
|
67070
67369
|
function findSourceFiles2(dir, files = []) {
|
|
67071
67370
|
let entries;
|
|
67072
67371
|
try {
|
|
67073
|
-
entries =
|
|
67372
|
+
entries = fs51.readdirSync(dir);
|
|
67074
67373
|
} catch {
|
|
67075
67374
|
return files;
|
|
67076
67375
|
}
|
|
@@ -67079,10 +67378,10 @@ function findSourceFiles2(dir, files = []) {
|
|
|
67079
67378
|
if (SKIP_DIRECTORIES4.has(entry)) {
|
|
67080
67379
|
continue;
|
|
67081
67380
|
}
|
|
67082
|
-
const fullPath =
|
|
67381
|
+
const fullPath = path64.join(dir, entry);
|
|
67083
67382
|
let stat2;
|
|
67084
67383
|
try {
|
|
67085
|
-
stat2 =
|
|
67384
|
+
stat2 = fs51.statSync(fullPath);
|
|
67086
67385
|
} catch {
|
|
67087
67386
|
continue;
|
|
67088
67387
|
}
|
|
@@ -67175,7 +67474,7 @@ var todo_extract = createSwarmTool({
|
|
|
67175
67474
|
return JSON.stringify(errorResult, null, 2);
|
|
67176
67475
|
}
|
|
67177
67476
|
const scanPath = resolvedPath;
|
|
67178
|
-
if (!
|
|
67477
|
+
if (!fs51.existsSync(scanPath)) {
|
|
67179
67478
|
const errorResult = {
|
|
67180
67479
|
error: `path not found: ${pathsInput}`,
|
|
67181
67480
|
total: 0,
|
|
@@ -67185,13 +67484,13 @@ var todo_extract = createSwarmTool({
|
|
|
67185
67484
|
return JSON.stringify(errorResult, null, 2);
|
|
67186
67485
|
}
|
|
67187
67486
|
const filesToScan = [];
|
|
67188
|
-
const stat2 =
|
|
67487
|
+
const stat2 = fs51.statSync(scanPath);
|
|
67189
67488
|
if (stat2.isFile()) {
|
|
67190
67489
|
if (isSupportedExtension(scanPath)) {
|
|
67191
67490
|
filesToScan.push(scanPath);
|
|
67192
67491
|
} else {
|
|
67193
67492
|
const errorResult = {
|
|
67194
|
-
error: `unsupported file extension: ${
|
|
67493
|
+
error: `unsupported file extension: ${path64.extname(scanPath)}`,
|
|
67195
67494
|
total: 0,
|
|
67196
67495
|
byPriority: { high: 0, medium: 0, low: 0 },
|
|
67197
67496
|
entries: []
|
|
@@ -67204,11 +67503,11 @@ var todo_extract = createSwarmTool({
|
|
|
67204
67503
|
const allEntries = [];
|
|
67205
67504
|
for (const filePath of filesToScan) {
|
|
67206
67505
|
try {
|
|
67207
|
-
const fileStat =
|
|
67506
|
+
const fileStat = fs51.statSync(filePath);
|
|
67208
67507
|
if (fileStat.size > MAX_FILE_SIZE_BYTES8) {
|
|
67209
67508
|
continue;
|
|
67210
67509
|
}
|
|
67211
|
-
const content =
|
|
67510
|
+
const content = fs51.readFileSync(filePath, "utf-8");
|
|
67212
67511
|
const entries = parseTodoComments(content, filePath, tagsSet);
|
|
67213
67512
|
allEntries.push(...entries);
|
|
67214
67513
|
} catch {}
|
|
@@ -67237,18 +67536,18 @@ var todo_extract = createSwarmTool({
|
|
|
67237
67536
|
init_tool();
|
|
67238
67537
|
init_schema();
|
|
67239
67538
|
init_gate_evidence();
|
|
67240
|
-
import * as
|
|
67241
|
-
import * as
|
|
67539
|
+
import * as fs53 from "fs";
|
|
67540
|
+
import * as path66 from "path";
|
|
67242
67541
|
|
|
67243
67542
|
// src/hooks/diff-scope.ts
|
|
67244
|
-
import * as
|
|
67245
|
-
import * as
|
|
67543
|
+
import * as fs52 from "fs";
|
|
67544
|
+
import * as path65 from "path";
|
|
67246
67545
|
function getDeclaredScope(taskId, directory) {
|
|
67247
67546
|
try {
|
|
67248
|
-
const planPath =
|
|
67249
|
-
if (!
|
|
67547
|
+
const planPath = path65.join(directory, ".swarm", "plan.json");
|
|
67548
|
+
if (!fs52.existsSync(planPath))
|
|
67250
67549
|
return null;
|
|
67251
|
-
const raw =
|
|
67550
|
+
const raw = fs52.readFileSync(planPath, "utf-8");
|
|
67252
67551
|
const plan = JSON.parse(raw);
|
|
67253
67552
|
for (const phase of plan.phases ?? []) {
|
|
67254
67553
|
for (const task of phase.tasks ?? []) {
|
|
@@ -67361,7 +67660,7 @@ var TIER_3_PATTERNS = [
|
|
|
67361
67660
|
];
|
|
67362
67661
|
function matchesTier3Pattern(files) {
|
|
67363
67662
|
for (const file3 of files) {
|
|
67364
|
-
const fileName =
|
|
67663
|
+
const fileName = path66.basename(file3);
|
|
67365
67664
|
for (const pattern of TIER_3_PATTERNS) {
|
|
67366
67665
|
if (pattern.test(fileName)) {
|
|
67367
67666
|
return true;
|
|
@@ -67375,8 +67674,8 @@ function checkReviewerGate(taskId, workingDirectory) {
|
|
|
67375
67674
|
if (hasActiveTurboMode()) {
|
|
67376
67675
|
const resolvedDir2 = workingDirectory;
|
|
67377
67676
|
try {
|
|
67378
|
-
const planPath =
|
|
67379
|
-
const planRaw =
|
|
67677
|
+
const planPath = path66.join(resolvedDir2, ".swarm", "plan.json");
|
|
67678
|
+
const planRaw = fs53.readFileSync(planPath, "utf-8");
|
|
67380
67679
|
const plan = JSON.parse(planRaw);
|
|
67381
67680
|
for (const planPhase of plan.phases ?? []) {
|
|
67382
67681
|
for (const task of planPhase.tasks ?? []) {
|
|
@@ -67442,8 +67741,8 @@ function checkReviewerGate(taskId, workingDirectory) {
|
|
|
67442
67741
|
}
|
|
67443
67742
|
try {
|
|
67444
67743
|
const resolvedDir2 = workingDirectory;
|
|
67445
|
-
const planPath =
|
|
67446
|
-
const planRaw =
|
|
67744
|
+
const planPath = path66.join(resolvedDir2, ".swarm", "plan.json");
|
|
67745
|
+
const planRaw = fs53.readFileSync(planPath, "utf-8");
|
|
67447
67746
|
const plan = JSON.parse(planRaw);
|
|
67448
67747
|
for (const planPhase of plan.phases ?? []) {
|
|
67449
67748
|
for (const task of planPhase.tasks ?? []) {
|
|
@@ -67625,8 +67924,8 @@ async function executeUpdateTaskStatus(args2, fallbackDir) {
|
|
|
67625
67924
|
};
|
|
67626
67925
|
}
|
|
67627
67926
|
}
|
|
67628
|
-
normalizedDir =
|
|
67629
|
-
const pathParts = normalizedDir.split(
|
|
67927
|
+
normalizedDir = path66.normalize(args2.working_directory);
|
|
67928
|
+
const pathParts = normalizedDir.split(path66.sep);
|
|
67630
67929
|
if (pathParts.includes("..")) {
|
|
67631
67930
|
return {
|
|
67632
67931
|
success: false,
|
|
@@ -67636,11 +67935,11 @@ async function executeUpdateTaskStatus(args2, fallbackDir) {
|
|
|
67636
67935
|
]
|
|
67637
67936
|
};
|
|
67638
67937
|
}
|
|
67639
|
-
const resolvedDir =
|
|
67938
|
+
const resolvedDir = path66.resolve(normalizedDir);
|
|
67640
67939
|
try {
|
|
67641
|
-
const realPath =
|
|
67642
|
-
const planPath =
|
|
67643
|
-
if (!
|
|
67940
|
+
const realPath = fs53.realpathSync(resolvedDir);
|
|
67941
|
+
const planPath = path66.join(realPath, ".swarm", "plan.json");
|
|
67942
|
+
if (!fs53.existsSync(planPath)) {
|
|
67644
67943
|
return {
|
|
67645
67944
|
success: false,
|
|
67646
67945
|
message: `Invalid working_directory: plan not found in "${realPath}"`,
|
|
@@ -67673,8 +67972,8 @@ async function executeUpdateTaskStatus(args2, fallbackDir) {
|
|
|
67673
67972
|
recoverTaskStateFromDelegations(args2.task_id);
|
|
67674
67973
|
let phaseRequiresReviewer = true;
|
|
67675
67974
|
try {
|
|
67676
|
-
const planPath =
|
|
67677
|
-
const planRaw =
|
|
67975
|
+
const planPath = path66.join(directory, ".swarm", "plan.json");
|
|
67976
|
+
const planRaw = fs53.readFileSync(planPath, "utf-8");
|
|
67678
67977
|
const plan = JSON.parse(planRaw);
|
|
67679
67978
|
const taskPhase = plan.phases.find((p) => p.tasks.some((t) => t.id === args2.task_id));
|
|
67680
67979
|
if (taskPhase?.required_agents && !taskPhase.required_agents.includes("reviewer")) {
|
|
@@ -67737,8 +68036,8 @@ var update_task_status = createSwarmTool({
|
|
|
67737
68036
|
init_tool();
|
|
67738
68037
|
init_utils2();
|
|
67739
68038
|
init_create_tool();
|
|
67740
|
-
import
|
|
67741
|
-
import
|
|
68039
|
+
import fs54 from "fs";
|
|
68040
|
+
import path67 from "path";
|
|
67742
68041
|
function normalizeVerdict(verdict) {
|
|
67743
68042
|
switch (verdict) {
|
|
67744
68043
|
case "APPROVED":
|
|
@@ -67785,7 +68084,7 @@ async function executeWriteDriftEvidence(args2, directory) {
|
|
|
67785
68084
|
entries: [evidenceEntry]
|
|
67786
68085
|
};
|
|
67787
68086
|
const filename = "drift-verifier.json";
|
|
67788
|
-
const relativePath =
|
|
68087
|
+
const relativePath = path67.join("evidence", String(phase), filename);
|
|
67789
68088
|
let validatedPath;
|
|
67790
68089
|
try {
|
|
67791
68090
|
validatedPath = validateSwarmPath(directory, relativePath);
|
|
@@ -67796,12 +68095,12 @@ async function executeWriteDriftEvidence(args2, directory) {
|
|
|
67796
68095
|
message: error93 instanceof Error ? error93.message : "Failed to validate path"
|
|
67797
68096
|
}, null, 2);
|
|
67798
68097
|
}
|
|
67799
|
-
const evidenceDir =
|
|
68098
|
+
const evidenceDir = path67.dirname(validatedPath);
|
|
67800
68099
|
try {
|
|
67801
|
-
await
|
|
67802
|
-
const tempPath =
|
|
67803
|
-
await
|
|
67804
|
-
await
|
|
68100
|
+
await fs54.promises.mkdir(evidenceDir, { recursive: true });
|
|
68101
|
+
const tempPath = path67.join(evidenceDir, `.${filename}.tmp`);
|
|
68102
|
+
await fs54.promises.writeFile(tempPath, JSON.stringify(evidenceContent, null, 2), "utf-8");
|
|
68103
|
+
await fs54.promises.rename(tempPath, validatedPath);
|
|
67805
68104
|
return JSON.stringify({
|
|
67806
68105
|
success: true,
|
|
67807
68106
|
phase,
|
|
@@ -67879,6 +68178,7 @@ ${footerLines.join(`
|
|
|
67879
68178
|
var _heartbeatTimers = new Map;
|
|
67880
68179
|
var OpenCodeSwarm = async (ctx) => {
|
|
67881
68180
|
const { config: config3, loadedFromFile } = loadPluginConfigWithMeta(ctx.directory);
|
|
68181
|
+
swarmState.opencodeClient = ctx.client;
|
|
67882
68182
|
await loadSnapshot(ctx.directory);
|
|
67883
68183
|
initTelemetry(ctx.directory);
|
|
67884
68184
|
const agents = getAgentConfigs(config3);
|
|
@@ -67989,7 +68289,7 @@ var OpenCodeSwarm = async (ctx) => {
|
|
|
67989
68289
|
const { PreflightTriggerManager: PTM } = await Promise.resolve().then(() => (init_trigger(), exports_trigger));
|
|
67990
68290
|
preflightTriggerManager = new PTM(automationConfig);
|
|
67991
68291
|
const { AutomationStatusArtifact: ASA } = await Promise.resolve().then(() => (init_status_artifact(), exports_status_artifact));
|
|
67992
|
-
const swarmDir =
|
|
68292
|
+
const swarmDir = path68.resolve(ctx.directory, ".swarm");
|
|
67993
68293
|
statusArtifact = new ASA(swarmDir);
|
|
67994
68294
|
statusArtifact.updateConfig(automationConfig.mode, automationConfig.capabilities);
|
|
67995
68295
|
if (automationConfig.capabilities?.evidence_auto_summaries === true) {
|
|
@@ -68321,7 +68621,7 @@ var OpenCodeSwarm = async (ctx) => {
|
|
|
68321
68621
|
} catch {}
|
|
68322
68622
|
return Promise.resolve();
|
|
68323
68623
|
},
|
|
68324
|
-
automationConfig.capabilities?.phase_preflight === true && preflightTriggerManager ? createPhaseMonitorHook(ctx.directory, preflightTriggerManager) : knowledgeConfig.enabled ? createPhaseMonitorHook(ctx.directory) : undefined
|
|
68624
|
+
automationConfig.capabilities?.phase_preflight === true && preflightTriggerManager ? createPhaseMonitorHook(ctx.directory, preflightTriggerManager, undefined, createCuratorLLMDelegate(ctx.directory)) : knowledgeConfig.enabled ? createPhaseMonitorHook(ctx.directory, undefined, undefined, createCuratorLLMDelegate(ctx.directory)) : undefined
|
|
68325
68625
|
].filter(Boolean)),
|
|
68326
68626
|
"experimental.session.compacting": compactionHook["experimental.session.compacting"],
|
|
68327
68627
|
"command.execute.before": safeHook(commandHandler),
|