opencode-swarm 7.30.0 → 7.31.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 +448 -489
- package/dist/hooks/knowledge-store.d.ts +12 -0
- package/dist/index.js +989 -932
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -48,7 +48,7 @@ var package_default;
|
|
|
48
48
|
var init_package = __esm(() => {
|
|
49
49
|
package_default = {
|
|
50
50
|
name: "opencode-swarm",
|
|
51
|
-
version: "7.
|
|
51
|
+
version: "7.31.0",
|
|
52
52
|
description: "Architect-centric agentic swarm plugin for OpenCode - hub-and-spoke orchestration with SME consultation, code generation, and QA review",
|
|
53
53
|
main: "dist/index.js",
|
|
54
54
|
types: "dist/index.d.ts",
|
|
@@ -54966,6 +54966,9 @@ function resolveSwarmKnowledgePath(directory) {
|
|
|
54966
54966
|
function resolveSwarmRejectedPath(directory) {
|
|
54967
54967
|
return path16.join(directory, ".swarm", "knowledge-rejected.jsonl");
|
|
54968
54968
|
}
|
|
54969
|
+
function resolveSwarmRetractionsPath(directory) {
|
|
54970
|
+
return path16.join(directory, ".swarm", "knowledge-retractions.jsonl");
|
|
54971
|
+
}
|
|
54969
54972
|
function resolveHiveKnowledgePath() {
|
|
54970
54973
|
const platform = process.platform;
|
|
54971
54974
|
const home = process.env.HOME || os3.homedir();
|
|
@@ -55064,6 +55067,12 @@ function normalizeEntry(raw) {
|
|
|
55064
55067
|
async function readRejectedLessons(directory) {
|
|
55065
55068
|
return readKnowledge(resolveSwarmRejectedPath(directory));
|
|
55066
55069
|
}
|
|
55070
|
+
async function readRetractionRecords(directory) {
|
|
55071
|
+
return readKnowledge(resolveSwarmRetractionsPath(directory));
|
|
55072
|
+
}
|
|
55073
|
+
async function appendRetractionRecord(directory, record3) {
|
|
55074
|
+
await appendKnowledge(resolveSwarmRetractionsPath(directory), record3);
|
|
55075
|
+
}
|
|
55067
55076
|
async function appendKnowledge(filePath, entry) {
|
|
55068
55077
|
await mkdir3(path16.dirname(filePath), { recursive: true });
|
|
55069
55078
|
await appendFile3(filePath, `${JSON.stringify(entry)}
|
|
@@ -57221,337 +57230,6 @@ var init_hive_promoter = __esm(() => {
|
|
|
57221
57230
|
init_utils2();
|
|
57222
57231
|
});
|
|
57223
57232
|
|
|
57224
|
-
// src/hooks/knowledge-reader.ts
|
|
57225
|
-
import { existsSync as existsSync12 } from "node:fs";
|
|
57226
|
-
import { mkdir as mkdir6, readFile as readFile7, writeFile as writeFile6 } from "node:fs/promises";
|
|
57227
|
-
import * as path21 from "node:path";
|
|
57228
|
-
function inferCategoriesFromPhase(phaseDescription) {
|
|
57229
|
-
const lower = phaseDescription.toLowerCase();
|
|
57230
|
-
const patterns = [
|
|
57231
|
-
{
|
|
57232
|
-
pattern: /\b(?:test|qa|quality|verification|validation)\b/,
|
|
57233
|
-
categories: ["testing", "debugging"]
|
|
57234
|
-
},
|
|
57235
|
-
{
|
|
57236
|
-
pattern: /\b(?:implement|build|develop|coding|code)\b/,
|
|
57237
|
-
categories: ["tooling", "architecture", "debugging"]
|
|
57238
|
-
},
|
|
57239
|
-
{
|
|
57240
|
-
pattern: /\b(?:integrat|deploy|ci|cd|release|publish)\b/,
|
|
57241
|
-
categories: ["integration", "tooling", "performance"]
|
|
57242
|
-
},
|
|
57243
|
-
{
|
|
57244
|
-
pattern: /\b(?:plan|design|architect|spec|requirement)\b/,
|
|
57245
|
-
categories: ["architecture", "process"]
|
|
57246
|
-
},
|
|
57247
|
-
{
|
|
57248
|
-
pattern: /\b(?:review|refactor|cleanup|polish|optimi)\b/,
|
|
57249
|
-
categories: ["performance", "architecture", "process"]
|
|
57250
|
-
},
|
|
57251
|
-
{
|
|
57252
|
-
pattern: /\b(?:secur|audit|harden|compliance)\b/,
|
|
57253
|
-
categories: ["security", "testing"]
|
|
57254
|
-
},
|
|
57255
|
-
{
|
|
57256
|
-
pattern: /\b(?:setup|config|scaffold|init|bootstrap)\b/,
|
|
57257
|
-
categories: ["tooling", "other"]
|
|
57258
|
-
},
|
|
57259
|
-
{
|
|
57260
|
-
pattern: /\b(?:doc|readme|changelog)\b/,
|
|
57261
|
-
categories: ["process", "tooling"]
|
|
57262
|
-
}
|
|
57263
|
-
];
|
|
57264
|
-
for (const { pattern, categories } of patterns) {
|
|
57265
|
-
if (pattern.test(lower)) {
|
|
57266
|
-
return categories;
|
|
57267
|
-
}
|
|
57268
|
-
}
|
|
57269
|
-
return ["process", "tooling"];
|
|
57270
|
-
}
|
|
57271
|
-
async function recordLessonsShown(directory, lessonIds, currentPhase) {
|
|
57272
|
-
const shownFile = path21.join(directory, ".swarm", ".knowledge-shown.json");
|
|
57273
|
-
try {
|
|
57274
|
-
let shownData = {};
|
|
57275
|
-
if (existsSync12(shownFile)) {
|
|
57276
|
-
const content = await readFile7(shownFile, "utf-8");
|
|
57277
|
-
shownData = JSON.parse(content);
|
|
57278
|
-
}
|
|
57279
|
-
const phaseMatch = /^Phase\s+(\d+)/i.exec(currentPhase);
|
|
57280
|
-
const canonicalKey = phaseMatch ? `Phase ${phaseMatch[1]}` : currentPhase;
|
|
57281
|
-
shownData[canonicalKey] = lessonIds;
|
|
57282
|
-
await mkdir6(path21.dirname(shownFile), { recursive: true });
|
|
57283
|
-
await writeFile6(shownFile, JSON.stringify(shownData, null, 2), "utf-8");
|
|
57284
|
-
} catch {
|
|
57285
|
-
warn("[swarm] Knowledge: failed to record shown lessons");
|
|
57286
|
-
}
|
|
57287
|
-
}
|
|
57288
|
-
async function readMergedKnowledge(directory, config3, context) {
|
|
57289
|
-
const swarmPath = resolveSwarmKnowledgePath(directory);
|
|
57290
|
-
const swarmEntries = await readKnowledge(swarmPath);
|
|
57291
|
-
let hiveEntries = [];
|
|
57292
|
-
if (config3.hive_enabled !== false) {
|
|
57293
|
-
const hivePath = resolveHiveKnowledgePath();
|
|
57294
|
-
hiveEntries = await readKnowledge(hivePath);
|
|
57295
|
-
}
|
|
57296
|
-
const seenLessons = new Set;
|
|
57297
|
-
const merged = [];
|
|
57298
|
-
for (const entry of hiveEntries) {
|
|
57299
|
-
const normalized = normalize2(entry.lesson);
|
|
57300
|
-
seenLessons.add(normalized);
|
|
57301
|
-
merged.push({
|
|
57302
|
-
...entry,
|
|
57303
|
-
relevanceScore: { category: 0, confidence: 0, keywords: 0 },
|
|
57304
|
-
finalScore: 0
|
|
57305
|
-
});
|
|
57306
|
-
}
|
|
57307
|
-
for (const entry of swarmEntries) {
|
|
57308
|
-
const normalized = normalize2(entry.lesson);
|
|
57309
|
-
if (seenLessons.has(normalized)) {
|
|
57310
|
-
continue;
|
|
57311
|
-
}
|
|
57312
|
-
const swarmBigrams = wordBigrams(normalized);
|
|
57313
|
-
const isHiveNearDup = hiveEntries.some((hiveEntry) => jaccardBigram(swarmBigrams, wordBigrams(normalize2(hiveEntry.lesson))) >= JACCARD_THRESHOLD);
|
|
57314
|
-
if (isHiveNearDup)
|
|
57315
|
-
continue;
|
|
57316
|
-
const isSwarmNearDup = merged.some((m) => m.tier === "swarm" && jaccardBigram(swarmBigrams, wordBigrams(normalize2(m.lesson))) >= JACCARD_THRESHOLD);
|
|
57317
|
-
if (isSwarmNearDup)
|
|
57318
|
-
continue;
|
|
57319
|
-
seenLessons.add(normalized);
|
|
57320
|
-
merged.push({
|
|
57321
|
-
...entry,
|
|
57322
|
-
relevanceScore: { category: 0, confidence: 0, keywords: 0 },
|
|
57323
|
-
finalScore: 0
|
|
57324
|
-
});
|
|
57325
|
-
}
|
|
57326
|
-
const scopeFilter = config3.scope_filter ?? ["global"];
|
|
57327
|
-
const filtered = merged.filter((entry) => scopeFilter.some((pattern) => (entry.scope ?? "global") === pattern) && entry.status !== "archived");
|
|
57328
|
-
const ranked = filtered.map((entry) => {
|
|
57329
|
-
let categoryScore = 0;
|
|
57330
|
-
if (context?.currentPhase) {
|
|
57331
|
-
const phaseCategories = inferCategoriesFromPhase(context.currentPhase);
|
|
57332
|
-
if (phaseCategories.includes(entry.category)) {
|
|
57333
|
-
categoryScore = 1;
|
|
57334
|
-
} else if (entry.category === "process") {
|
|
57335
|
-
categoryScore = 0.5;
|
|
57336
|
-
}
|
|
57337
|
-
} else {
|
|
57338
|
-
categoryScore = 0.5;
|
|
57339
|
-
}
|
|
57340
|
-
const confidenceScore = entry.confidence;
|
|
57341
|
-
let keywordsScore = 0;
|
|
57342
|
-
if (context?.techStack && entry.tags.length > 0) {
|
|
57343
|
-
const matchingTags = entry.tags.filter((t) => context.techStack.some((s) => t.toLowerCase().includes(s.toLowerCase()) || s.toLowerCase().includes(t.toLowerCase()))).length;
|
|
57344
|
-
keywordsScore = Math.min(matchingTags / Math.max(entry.tags.length, 1), 1);
|
|
57345
|
-
} else if (entry.tags.length === 0) {
|
|
57346
|
-
keywordsScore = 0.5;
|
|
57347
|
-
}
|
|
57348
|
-
const tierBoost = entry.tier === "hive" ? HIVE_TIER_BOOST : 0;
|
|
57349
|
-
const isSameProjectSource = context?.projectName && entry.tier === "hive" && "source_project" in entry && entry.source_project === context.projectName;
|
|
57350
|
-
const sameProjectPenalty = isSameProjectSource ? SAME_PROJECT_PENALTY : 0;
|
|
57351
|
-
const finalScore = categoryScore * 0.4 + confidenceScore * 0.35 + keywordsScore * 0.25 + tierBoost + sameProjectPenalty;
|
|
57352
|
-
const relevanceScore = {
|
|
57353
|
-
category: categoryScore,
|
|
57354
|
-
confidence: confidenceScore,
|
|
57355
|
-
keywords: keywordsScore
|
|
57356
|
-
};
|
|
57357
|
-
return {
|
|
57358
|
-
...entry,
|
|
57359
|
-
relevanceScore,
|
|
57360
|
-
finalScore: Math.min(Math.max(finalScore, 0), 1)
|
|
57361
|
-
};
|
|
57362
|
-
});
|
|
57363
|
-
ranked.sort((a, b) => {
|
|
57364
|
-
const scoreDiff = b.finalScore - a.finalScore;
|
|
57365
|
-
if (Math.abs(scoreDiff) > 0.001)
|
|
57366
|
-
return scoreDiff;
|
|
57367
|
-
const dateA = new Date(a.created_at).getTime();
|
|
57368
|
-
const dateB = new Date(b.created_at).getTime();
|
|
57369
|
-
return dateB - dateA;
|
|
57370
|
-
});
|
|
57371
|
-
const maxInject = config3.max_inject_count ?? 5;
|
|
57372
|
-
const topN = ranked.slice(0, maxInject);
|
|
57373
|
-
if (topN.length > 0 && context?.currentPhase) {
|
|
57374
|
-
recordLessonsShown(directory, topN.map((e) => e.id), context.currentPhase).catch((err2) => {
|
|
57375
|
-
warn("[knowledge-reader] recordLessonsShown unexpected rejection:", err2);
|
|
57376
|
-
});
|
|
57377
|
-
}
|
|
57378
|
-
return topN;
|
|
57379
|
-
}
|
|
57380
|
-
async function updateRetrievalOutcome(directory, phaseInfo, phaseSucceeded) {
|
|
57381
|
-
const shownFile = path21.join(directory, ".swarm", ".knowledge-shown.json");
|
|
57382
|
-
try {
|
|
57383
|
-
if (!existsSync12(shownFile)) {
|
|
57384
|
-
return;
|
|
57385
|
-
}
|
|
57386
|
-
const content = await readFile7(shownFile, "utf-8");
|
|
57387
|
-
const shownData = JSON.parse(content);
|
|
57388
|
-
const shownIds = shownData[phaseInfo];
|
|
57389
|
-
if (!shownIds || shownIds.length === 0) {
|
|
57390
|
-
return;
|
|
57391
|
-
}
|
|
57392
|
-
const swarmPath = resolveSwarmKnowledgePath(directory);
|
|
57393
|
-
const entries = await readKnowledge(swarmPath);
|
|
57394
|
-
let updated = false;
|
|
57395
|
-
const foundInSwarm = new Set;
|
|
57396
|
-
for (const entry of entries) {
|
|
57397
|
-
if (shownIds.includes(entry.id)) {
|
|
57398
|
-
const ro = entry.retrieval_outcomes;
|
|
57399
|
-
if (phaseSucceeded) {
|
|
57400
|
-
ro.succeeded_after_shown_count = (ro.succeeded_after_shown_count ?? 0) + 1;
|
|
57401
|
-
} else {
|
|
57402
|
-
ro.failed_after_shown_count = (ro.failed_after_shown_count ?? 0) + 1;
|
|
57403
|
-
}
|
|
57404
|
-
updated = true;
|
|
57405
|
-
foundInSwarm.add(entry.id);
|
|
57406
|
-
}
|
|
57407
|
-
}
|
|
57408
|
-
if (updated) {
|
|
57409
|
-
await rewriteKnowledge(swarmPath, entries);
|
|
57410
|
-
}
|
|
57411
|
-
const remainingIds = shownIds.filter((id) => !foundInSwarm.has(id));
|
|
57412
|
-
if (remainingIds.length === 0) {
|
|
57413
|
-
delete shownData[phaseInfo];
|
|
57414
|
-
await writeFile6(shownFile, JSON.stringify(shownData, null, 2), "utf-8");
|
|
57415
|
-
return;
|
|
57416
|
-
}
|
|
57417
|
-
const hivePath = resolveHiveKnowledgePath();
|
|
57418
|
-
const hiveEntries = await readKnowledge(hivePath);
|
|
57419
|
-
let hiveUpdated = false;
|
|
57420
|
-
for (const entry of hiveEntries) {
|
|
57421
|
-
if (remainingIds.includes(entry.id)) {
|
|
57422
|
-
const ro = entry.retrieval_outcomes;
|
|
57423
|
-
if (phaseSucceeded) {
|
|
57424
|
-
ro.succeeded_after_shown_count = (ro.succeeded_after_shown_count ?? 0) + 1;
|
|
57425
|
-
} else {
|
|
57426
|
-
ro.failed_after_shown_count = (ro.failed_after_shown_count ?? 0) + 1;
|
|
57427
|
-
}
|
|
57428
|
-
hiveUpdated = true;
|
|
57429
|
-
}
|
|
57430
|
-
}
|
|
57431
|
-
if (hiveUpdated) {
|
|
57432
|
-
await rewriteKnowledge(hivePath, hiveEntries);
|
|
57433
|
-
}
|
|
57434
|
-
delete shownData[phaseInfo];
|
|
57435
|
-
await writeFile6(shownFile, JSON.stringify(shownData, null, 2), "utf-8");
|
|
57436
|
-
} catch {
|
|
57437
|
-
warn("[swarm] Knowledge: failed to update retrieval outcomes");
|
|
57438
|
-
}
|
|
57439
|
-
}
|
|
57440
|
-
function lc(s) {
|
|
57441
|
-
return (s ?? "").toLowerCase();
|
|
57442
|
-
}
|
|
57443
|
-
function anyMatch(haystack, needles) {
|
|
57444
|
-
if (needles.length === 0)
|
|
57445
|
-
return false;
|
|
57446
|
-
const hay = haystack.map(lc);
|
|
57447
|
-
return needles.some((n) => hay.some((h) => h.includes(lc(n))));
|
|
57448
|
-
}
|
|
57449
|
-
function tokenizeContext(ctx) {
|
|
57450
|
-
const parts2 = [];
|
|
57451
|
-
if (ctx.taskTitle)
|
|
57452
|
-
parts2.push(ctx.taskTitle);
|
|
57453
|
-
if (ctx.taskDescription)
|
|
57454
|
-
parts2.push(ctx.taskDescription);
|
|
57455
|
-
if (ctx.lastUserMessage)
|
|
57456
|
-
parts2.push(ctx.lastUserMessage);
|
|
57457
|
-
if (ctx.currentAction)
|
|
57458
|
-
parts2.push(ctx.currentAction);
|
|
57459
|
-
if (ctx.currentTool)
|
|
57460
|
-
parts2.push(ctx.currentTool);
|
|
57461
|
-
if (ctx.targetAgent)
|
|
57462
|
-
parts2.push(ctx.targetAgent);
|
|
57463
|
-
if (ctx.declaredScope)
|
|
57464
|
-
parts2.push(ctx.declaredScope);
|
|
57465
|
-
if (ctx.recentReviewerFailures)
|
|
57466
|
-
parts2.push(...ctx.recentReviewerFailures);
|
|
57467
|
-
if (ctx.recentTestFailures)
|
|
57468
|
-
parts2.push(...ctx.recentTestFailures);
|
|
57469
|
-
if (ctx.recentToolErrors)
|
|
57470
|
-
parts2.push(...ctx.recentToolErrors);
|
|
57471
|
-
if (ctx.planConstraints)
|
|
57472
|
-
parts2.push(...ctx.planConstraints);
|
|
57473
|
-
if (ctx.filePaths)
|
|
57474
|
-
parts2.push(...ctx.filePaths);
|
|
57475
|
-
return parts2.map(lc);
|
|
57476
|
-
}
|
|
57477
|
-
function scoreDirectiveAgainstContext(entry, ctx) {
|
|
57478
|
-
const haystack = tokenizeContext(ctx);
|
|
57479
|
-
const triggerHit = entry.triggers && entry.triggers.length > 0 ? anyMatch(haystack, entry.triggers) : false;
|
|
57480
|
-
const actionHit = entry.applies_to_tools && entry.applies_to_tools.length > 0 ? entry.applies_to_tools.map(lc).some((t) => t === lc(ctx.currentTool) || t === lc(ctx.currentAction)) : false;
|
|
57481
|
-
const agentHit = entry.applies_to_agents && entry.applies_to_agents.length > 0 ? entry.applies_to_agents.map(lc).some((a) => a === lc(ctx.targetAgent)) : false;
|
|
57482
|
-
let score = 0;
|
|
57483
|
-
if (triggerHit)
|
|
57484
|
-
score += 0.5;
|
|
57485
|
-
if (actionHit)
|
|
57486
|
-
score += 0.35;
|
|
57487
|
-
if (agentHit)
|
|
57488
|
-
score += 0.25;
|
|
57489
|
-
if (entry.directive_priority === "critical")
|
|
57490
|
-
score += 0.4;
|
|
57491
|
-
else if (entry.directive_priority === "high")
|
|
57492
|
-
score += 0.2;
|
|
57493
|
-
else if (entry.directive_priority === "medium")
|
|
57494
|
-
score += 0.1;
|
|
57495
|
-
return { triggerHit, actionHit, agentHit, score: Math.min(1, score) };
|
|
57496
|
-
}
|
|
57497
|
-
async function readContextualKnowledge(directory, config3, ctx) {
|
|
57498
|
-
const projected = {
|
|
57499
|
-
projectName: ctx.projectName ?? "unknown",
|
|
57500
|
-
currentPhase: ctx.currentPhase ?? "Phase 0",
|
|
57501
|
-
techStack: ctx.techStack,
|
|
57502
|
-
recentErrors: [
|
|
57503
|
-
...ctx.recentReviewerFailures ?? [],
|
|
57504
|
-
...ctx.recentTestFailures ?? [],
|
|
57505
|
-
...ctx.recentToolErrors ?? []
|
|
57506
|
-
]
|
|
57507
|
-
};
|
|
57508
|
-
const wideCfg = {
|
|
57509
|
-
...config3,
|
|
57510
|
-
max_inject_count: Math.max(20, config3.max_inject_count ?? 5)
|
|
57511
|
-
};
|
|
57512
|
-
const candidates = await readMergedKnowledge(directory, wideCfg, projected) ?? [];
|
|
57513
|
-
const minConf = typeof config3.directive_min_confidence === "number" ? config3.directive_min_confidence : DIRECTIVE_BOOST_MIN_CONFIDENCE;
|
|
57514
|
-
const rescored = candidates.map((entry) => {
|
|
57515
|
-
const ds = scoreDirectiveAgainstContext(entry, ctx);
|
|
57516
|
-
const confBoost = entry.confidence >= minConf && (ds.actionHit || ds.agentHit) ? 0.25 : 0;
|
|
57517
|
-
const generatedSkillBoost = entry.generated_skill_path && entry.status !== "archived" ? 0.05 : 0;
|
|
57518
|
-
const finalScore = Math.min(1, entry.finalScore + ds.score + confBoost + generatedSkillBoost);
|
|
57519
|
-
return {
|
|
57520
|
-
...entry,
|
|
57521
|
-
finalScore,
|
|
57522
|
-
__directive: ds
|
|
57523
|
-
};
|
|
57524
|
-
});
|
|
57525
|
-
rescored.sort((a, b) => b.finalScore - a.finalScore);
|
|
57526
|
-
const max = config3.max_inject_count ?? 5;
|
|
57527
|
-
const top = [];
|
|
57528
|
-
const seen = new Set;
|
|
57529
|
-
for (const e of rescored) {
|
|
57530
|
-
if (top.length >= max)
|
|
57531
|
-
break;
|
|
57532
|
-
const ds = e.__directive;
|
|
57533
|
-
const isCritical = e.directive_priority === "critical" && (ds.triggerHit || ds.actionHit || ds.agentHit);
|
|
57534
|
-
if (isCritical && !seen.has(e.id)) {
|
|
57535
|
-
top.push(e);
|
|
57536
|
-
seen.add(e.id);
|
|
57537
|
-
}
|
|
57538
|
-
}
|
|
57539
|
-
for (const e of rescored) {
|
|
57540
|
-
if (top.length >= max)
|
|
57541
|
-
break;
|
|
57542
|
-
if (!seen.has(e.id)) {
|
|
57543
|
-
top.push(e);
|
|
57544
|
-
seen.add(e.id);
|
|
57545
|
-
}
|
|
57546
|
-
}
|
|
57547
|
-
return top.map(({ __directive: _d, ...rest }) => rest);
|
|
57548
|
-
}
|
|
57549
|
-
var JACCARD_THRESHOLD = 0.6, HIVE_TIER_BOOST = 0.05, SAME_PROJECT_PENALTY = -0.05, DIRECTIVE_BOOST_MIN_CONFIDENCE = 0.75;
|
|
57550
|
-
var init_knowledge_reader = __esm(() => {
|
|
57551
|
-
init_logger();
|
|
57552
|
-
init_knowledge_store();
|
|
57553
|
-
});
|
|
57554
|
-
|
|
57555
57233
|
// src/hooks/knowledge-curator.ts
|
|
57556
57234
|
function pruneSeenRetroSections() {
|
|
57557
57235
|
const cutoff = Date.now() - 86400000;
|
|
@@ -57668,17 +57346,39 @@ function extractRetractionsAndLessons(allLessons) {
|
|
|
57668
57346
|
async function processRetractions(retractions, directory) {
|
|
57669
57347
|
if (retractions.length === 0)
|
|
57670
57348
|
return;
|
|
57671
|
-
const
|
|
57672
|
-
const
|
|
57349
|
+
const swarmEntries = await readKnowledge(resolveSwarmKnowledgePath(directory)) ?? [];
|
|
57350
|
+
const hiveEntries = await readKnowledge(resolveHiveKnowledgePath()) ?? [];
|
|
57351
|
+
const existingRetractions = await readRetractionRecords(directory);
|
|
57352
|
+
const existingSuppressedLessons = new Set(existingRetractions.map((record3) => record3.normalized_lesson).filter((value) => typeof value === "string" && value.length > 0));
|
|
57673
57353
|
for (const retractionText of retractions) {
|
|
57674
57354
|
const normalizedRetraction = normalize2(retractionText);
|
|
57675
|
-
|
|
57355
|
+
const matchedSwarmIds = [];
|
|
57356
|
+
const matchedHiveIds = [];
|
|
57357
|
+
for (const entry of swarmEntries) {
|
|
57676
57358
|
const normalizedLesson = normalize2(entry.lesson);
|
|
57677
57359
|
if (normalizedLesson === normalizedRetraction) {
|
|
57360
|
+
matchedSwarmIds.push(entry.id);
|
|
57678
57361
|
await quarantineEntry(directory, entry.id, `Retracted by architect: ${retractionText}`, "architect");
|
|
57679
57362
|
console.info(`[knowledge-curator] Quarantined entry ${entry.id}: "${entry.lesson}"`);
|
|
57680
57363
|
}
|
|
57681
57364
|
}
|
|
57365
|
+
for (const entry of hiveEntries) {
|
|
57366
|
+
if (normalize2(entry.lesson) === normalizedRetraction) {
|
|
57367
|
+
matchedHiveIds.push(entry.id);
|
|
57368
|
+
}
|
|
57369
|
+
}
|
|
57370
|
+
if (!existingSuppressedLessons.has(normalizedRetraction)) {
|
|
57371
|
+
await appendRetractionRecord(directory, {
|
|
57372
|
+
id: crypto.randomUUID(),
|
|
57373
|
+
retracted_lesson: retractionText,
|
|
57374
|
+
normalized_lesson: normalizedRetraction,
|
|
57375
|
+
recorded_at: new Date().toISOString(),
|
|
57376
|
+
reported_by: "architect",
|
|
57377
|
+
matched_swarm_ids: matchedSwarmIds,
|
|
57378
|
+
matched_hive_ids: matchedHiveIds
|
|
57379
|
+
});
|
|
57380
|
+
existingSuppressedLessons.add(normalizedRetraction);
|
|
57381
|
+
}
|
|
57682
57382
|
}
|
|
57683
57383
|
}
|
|
57684
57384
|
async function curateAndStoreSwarm(lessons, projectName, phaseInfo, directory, config3) {
|
|
@@ -57845,7 +57545,6 @@ function createKnowledgeCuratorHook(directory, config3) {
|
|
|
57845
57545
|
const projectName2 = evidenceData.project_name ?? "unknown";
|
|
57846
57546
|
const phaseNumber2 = typeof evidenceData.phase_number === "number" ? evidenceData.phase_number : 1;
|
|
57847
57547
|
await _internals15.curateAndStoreSwarm(lessons, projectName2, { phase_number: phaseNumber2 }, directory, config3);
|
|
57848
|
-
await updateRetrievalOutcome(directory, `Phase ${phaseNumber2}`, true);
|
|
57849
57548
|
return;
|
|
57850
57549
|
}
|
|
57851
57550
|
const planContent = await readSwarmFileAsync(directory, "plan.md");
|
|
@@ -57868,13 +57567,11 @@ function createKnowledgeCuratorHook(directory, config3) {
|
|
|
57868
57567
|
const phaseMatch = /^Phase:\s*(\d+)/m.exec(planContent);
|
|
57869
57568
|
const phaseNumber = phaseMatch ? parseInt(phaseMatch[1], 10) : 1;
|
|
57870
57569
|
await _internals15.curateAndStoreSwarm(normalLessons, projectName, { phase_number: phaseNumber }, directory, config3);
|
|
57871
|
-
await updateRetrievalOutcome(directory, `Phase ${phaseNumber}`, true);
|
|
57872
57570
|
};
|
|
57873
57571
|
return safeHook(handler);
|
|
57874
57572
|
}
|
|
57875
57573
|
var seenRetroSections, _internals15;
|
|
57876
57574
|
var init_knowledge_curator = __esm(() => {
|
|
57877
|
-
init_knowledge_reader();
|
|
57878
57575
|
init_knowledge_store();
|
|
57879
57576
|
init_knowledge_validator();
|
|
57880
57577
|
init_utils2();
|
|
@@ -57997,9 +57694,9 @@ var init_skill_improver_llm_factory = __esm(() => {
|
|
|
57997
57694
|
});
|
|
57998
57695
|
|
|
57999
57696
|
// src/services/skill-improver-quota.ts
|
|
58000
|
-
import { existsSync as
|
|
58001
|
-
import { mkdir as
|
|
58002
|
-
import * as
|
|
57697
|
+
import { existsSync as existsSync12 } from "node:fs";
|
|
57698
|
+
import { mkdir as mkdir6, readFile as readFile7, rename as rename4, writeFile as writeFile6 } from "node:fs/promises";
|
|
57699
|
+
import * as path21 from "node:path";
|
|
58003
57700
|
async function acquireLock(dir) {
|
|
58004
57701
|
const acquire = import_proper_lockfile5.default.lock(dir, LOCK_RETRY_OPTS);
|
|
58005
57702
|
let timer;
|
|
@@ -58017,7 +57714,7 @@ async function acquireLock(dir) {
|
|
|
58017
57714
|
}
|
|
58018
57715
|
}
|
|
58019
57716
|
function resolveQuotaPath(directory) {
|
|
58020
|
-
return
|
|
57717
|
+
return path21.join(directory, ".swarm", "skill-improver-quota.json");
|
|
58021
57718
|
}
|
|
58022
57719
|
function todayKey(window2, now = new Date) {
|
|
58023
57720
|
if (window2 === "utc") {
|
|
@@ -58029,10 +57726,10 @@ function todayKey(window2, now = new Date) {
|
|
|
58029
57726
|
return `${yr}-${m}-${d}`;
|
|
58030
57727
|
}
|
|
58031
57728
|
async function readState(filePath) {
|
|
58032
|
-
if (!
|
|
57729
|
+
if (!existsSync12(filePath))
|
|
58033
57730
|
return null;
|
|
58034
57731
|
try {
|
|
58035
|
-
const raw = await
|
|
57732
|
+
const raw = await readFile7(filePath, "utf-8");
|
|
58036
57733
|
const parsed = JSON.parse(raw);
|
|
58037
57734
|
if (typeof parsed.date !== "string" || typeof parsed.calls_used !== "number" || typeof parsed.max_calls !== "number" || parsed.window !== "utc" && parsed.window !== "local") {
|
|
58038
57735
|
return null;
|
|
@@ -58043,9 +57740,9 @@ async function readState(filePath) {
|
|
|
58043
57740
|
}
|
|
58044
57741
|
}
|
|
58045
57742
|
async function writeState(filePath, state) {
|
|
58046
|
-
await
|
|
57743
|
+
await mkdir6(path21.dirname(filePath), { recursive: true });
|
|
58047
57744
|
const tmp = `${filePath}.tmp-${process.pid}`;
|
|
58048
|
-
await
|
|
57745
|
+
await writeFile6(tmp, JSON.stringify(state, null, 2), "utf-8");
|
|
58049
57746
|
await rename4(tmp, filePath);
|
|
58050
57747
|
}
|
|
58051
57748
|
async function getQuotaState(directory, opts) {
|
|
@@ -58066,10 +57763,10 @@ async function getQuotaState(directory, opts) {
|
|
|
58066
57763
|
}
|
|
58067
57764
|
async function reserveQuota(directory, opts) {
|
|
58068
57765
|
const filePath = resolveQuotaPath(directory);
|
|
58069
|
-
await
|
|
57766
|
+
await mkdir6(path21.dirname(filePath), { recursive: true });
|
|
58070
57767
|
let release = null;
|
|
58071
57768
|
try {
|
|
58072
|
-
release = await acquireLock(
|
|
57769
|
+
release = await acquireLock(path21.dirname(filePath));
|
|
58073
57770
|
const state = await getQuotaState(directory, opts);
|
|
58074
57771
|
if (state.calls_used + opts.nCalls > opts.maxCalls) {
|
|
58075
57772
|
return {
|
|
@@ -58096,10 +57793,10 @@ async function reserveQuota(directory, opts) {
|
|
|
58096
57793
|
}
|
|
58097
57794
|
async function releaseQuota(directory, opts) {
|
|
58098
57795
|
const filePath = resolveQuotaPath(directory);
|
|
58099
|
-
await
|
|
57796
|
+
await mkdir6(path21.dirname(filePath), { recursive: true });
|
|
58100
57797
|
let release = null;
|
|
58101
57798
|
try {
|
|
58102
|
-
release = await acquireLock(
|
|
57799
|
+
release = await acquireLock(path21.dirname(filePath));
|
|
58103
57800
|
const state = await getQuotaState(directory, opts);
|
|
58104
57801
|
const next = {
|
|
58105
57802
|
...state,
|
|
@@ -58131,22 +57828,22 @@ var init_skill_improver_quota = __esm(() => {
|
|
|
58131
57828
|
});
|
|
58132
57829
|
|
|
58133
57830
|
// src/services/skill-improver.ts
|
|
58134
|
-
import { existsSync as
|
|
58135
|
-
import { mkdir as
|
|
58136
|
-
import * as
|
|
57831
|
+
import { existsSync as existsSync13 } from "node:fs";
|
|
57832
|
+
import { mkdir as mkdir7, rename as rename5, writeFile as writeFile7 } from "node:fs/promises";
|
|
57833
|
+
import * as path22 from "node:path";
|
|
58137
57834
|
function timestampSlug(d) {
|
|
58138
57835
|
return d.toISOString().replace(/[:.]/g, "-");
|
|
58139
57836
|
}
|
|
58140
57837
|
async function atomicWrite4(p, content) {
|
|
58141
|
-
await
|
|
57838
|
+
await mkdir7(path22.dirname(p), { recursive: true });
|
|
58142
57839
|
const tmp = `${p}.tmp-${process.pid}-${Date.now()}`;
|
|
58143
|
-
await
|
|
57840
|
+
await writeFile7(tmp, content, "utf-8");
|
|
58144
57841
|
await rename5(tmp, p);
|
|
58145
57842
|
}
|
|
58146
57843
|
async function gatherInventory(directory) {
|
|
58147
57844
|
const swarm = await readKnowledge(resolveSwarmKnowledgePath(directory));
|
|
58148
57845
|
const hivePath = resolveHiveKnowledgePath();
|
|
58149
|
-
const hive =
|
|
57846
|
+
const hive = existsSync13(hivePath) ? await readKnowledge(hivePath) : [];
|
|
58150
57847
|
const archived = [...swarm, ...hive].filter((e) => e.status === "archived").length;
|
|
58151
57848
|
const skills = await listSkills(directory);
|
|
58152
57849
|
const matureCandidates = swarm.concat(hive).filter((e) => e.status !== "archived" && e.confidence >= 0.85 && !e.generated_skill_slug && (e.confirmed_by ?? []).length >= 2);
|
|
@@ -58419,8 +58116,8 @@ async function runSkillImprover(req) {
|
|
|
58419
58116
|
}
|
|
58420
58117
|
throw err2;
|
|
58421
58118
|
}
|
|
58422
|
-
const proposalDir =
|
|
58423
|
-
const proposalFile =
|
|
58119
|
+
const proposalDir = path22.join(req.directory, ".swarm", "skill-improver", "proposals");
|
|
58120
|
+
const proposalFile = path22.join(proposalDir, `${timestampSlug(now)}.md`);
|
|
58424
58121
|
const finalBody = source === "llm" ? buildLLMProposalFrame({
|
|
58425
58122
|
body: body2,
|
|
58426
58123
|
targets,
|
|
@@ -58816,7 +58513,7 @@ var init_write_retro = __esm(() => {
|
|
|
58816
58513
|
|
|
58817
58514
|
// src/commands/close.ts
|
|
58818
58515
|
import { promises as fs13 } from "node:fs";
|
|
58819
|
-
import
|
|
58516
|
+
import path23 from "node:path";
|
|
58820
58517
|
async function runAbortableSkillReview(req, timeoutMs) {
|
|
58821
58518
|
const controller = new AbortController;
|
|
58822
58519
|
let timeout;
|
|
@@ -58872,10 +58569,10 @@ function guaranteeAllPlansComplete(planData) {
|
|
|
58872
58569
|
}
|
|
58873
58570
|
async function handleCloseCommand(directory, args2, options = {}) {
|
|
58874
58571
|
const planPath = validateSwarmPath(directory, "plan.json");
|
|
58875
|
-
const swarmDir =
|
|
58572
|
+
const swarmDir = path23.join(directory, ".swarm");
|
|
58876
58573
|
let planExists = false;
|
|
58877
58574
|
let planData = {
|
|
58878
|
-
title:
|
|
58575
|
+
title: path23.basename(directory) || "Ad-hoc session",
|
|
58879
58576
|
phases: []
|
|
58880
58577
|
};
|
|
58881
58578
|
try {
|
|
@@ -58984,7 +58681,7 @@ async function handleCloseCommand(directory, args2, options = {}) {
|
|
|
58984
58681
|
warnings.push(`Session retrospective write threw: ${retroError instanceof Error ? retroError.message : String(retroError)}`);
|
|
58985
58682
|
}
|
|
58986
58683
|
}
|
|
58987
|
-
const lessonsFilePath =
|
|
58684
|
+
const lessonsFilePath = path23.join(swarmDir, "close-lessons.md");
|
|
58988
58685
|
let explicitLessons = [];
|
|
58989
58686
|
try {
|
|
58990
58687
|
const lessonsText = await fs13.readFile(lessonsFilePath, "utf-8");
|
|
@@ -58993,11 +58690,11 @@ async function handleCloseCommand(directory, args2, options = {}) {
|
|
|
58993
58690
|
} catch {}
|
|
58994
58691
|
const retroLessons = [];
|
|
58995
58692
|
try {
|
|
58996
|
-
const evidenceDir =
|
|
58693
|
+
const evidenceDir = path23.join(swarmDir, "evidence");
|
|
58997
58694
|
const evidenceEntries = await fs13.readdir(evidenceDir);
|
|
58998
58695
|
const retroDirs = evidenceEntries.filter((e) => e.startsWith("retro-")).sort((a, b) => a.localeCompare(b, undefined, { numeric: true }));
|
|
58999
58696
|
for (const retroDir of retroDirs) {
|
|
59000
|
-
const evidencePath =
|
|
58697
|
+
const evidencePath = path23.join(evidenceDir, retroDir, "evidence.json");
|
|
59001
58698
|
try {
|
|
59002
58699
|
const content = await fs13.readFile(evidencePath, "utf-8");
|
|
59003
58700
|
const parsed = JSON.parse(content);
|
|
@@ -59122,7 +58819,7 @@ async function handleCloseCommand(directory, args2, options = {}) {
|
|
|
59122
58819
|
}
|
|
59123
58820
|
const timestamp = new Date().toISOString().replace(/[:.]/g, "-");
|
|
59124
58821
|
const suffix = Math.random().toString(36).slice(2, 8);
|
|
59125
|
-
const archiveDir =
|
|
58822
|
+
const archiveDir = path23.join(swarmDir, "archive", `swarm-${timestamp}-${suffix}`);
|
|
59126
58823
|
let archiveResult = "";
|
|
59127
58824
|
let archivedFileCount = 0;
|
|
59128
58825
|
const archivedActiveStateFiles = new Set;
|
|
@@ -59130,8 +58827,8 @@ async function handleCloseCommand(directory, args2, options = {}) {
|
|
|
59130
58827
|
try {
|
|
59131
58828
|
await fs13.mkdir(archiveDir, { recursive: true });
|
|
59132
58829
|
for (const artifact of ARCHIVE_ARTIFACTS) {
|
|
59133
|
-
const srcPath =
|
|
59134
|
-
const destPath =
|
|
58830
|
+
const srcPath = path23.join(swarmDir, artifact);
|
|
58831
|
+
const destPath = path23.join(archiveDir, artifact);
|
|
59135
58832
|
try {
|
|
59136
58833
|
await fs13.copyFile(srcPath, destPath);
|
|
59137
58834
|
archivedFileCount++;
|
|
@@ -59141,22 +58838,22 @@ async function handleCloseCommand(directory, args2, options = {}) {
|
|
|
59141
58838
|
} catch {}
|
|
59142
58839
|
}
|
|
59143
58840
|
for (const dirName of ACTIVE_STATE_DIRS_TO_CLEAN) {
|
|
59144
|
-
const srcDir =
|
|
59145
|
-
const destDir =
|
|
58841
|
+
const srcDir = path23.join(swarmDir, dirName);
|
|
58842
|
+
const destDir = path23.join(archiveDir, dirName);
|
|
59146
58843
|
try {
|
|
59147
58844
|
const entries = await fs13.readdir(srcDir);
|
|
59148
58845
|
if (entries.length > 0) {
|
|
59149
58846
|
await fs13.mkdir(destDir, { recursive: true });
|
|
59150
58847
|
for (const entry of entries) {
|
|
59151
|
-
const srcEntry =
|
|
59152
|
-
const destEntry =
|
|
58848
|
+
const srcEntry = path23.join(srcDir, entry);
|
|
58849
|
+
const destEntry = path23.join(destDir, entry);
|
|
59153
58850
|
try {
|
|
59154
58851
|
const stat3 = await fs13.stat(srcEntry);
|
|
59155
58852
|
if (stat3.isDirectory()) {
|
|
59156
58853
|
await fs13.mkdir(destEntry, { recursive: true });
|
|
59157
58854
|
const subEntries = await fs13.readdir(srcEntry);
|
|
59158
58855
|
for (const sub of subEntries) {
|
|
59159
|
-
await fs13.copyFile(
|
|
58856
|
+
await fs13.copyFile(path23.join(srcEntry, sub), path23.join(destEntry, sub)).catch(() => {});
|
|
59160
58857
|
}
|
|
59161
58858
|
} else {
|
|
59162
58859
|
await fs13.copyFile(srcEntry, destEntry);
|
|
@@ -59188,7 +58885,7 @@ async function handleCloseCommand(directory, args2, options = {}) {
|
|
|
59188
58885
|
warnings.push(`Preserved ${artifact} because it was not successfully archived.`);
|
|
59189
58886
|
continue;
|
|
59190
58887
|
}
|
|
59191
|
-
const filePath =
|
|
58888
|
+
const filePath = path23.join(swarmDir, artifact);
|
|
59192
58889
|
try {
|
|
59193
58890
|
await fs13.unlink(filePath);
|
|
59194
58891
|
cleanedFiles.push(artifact);
|
|
@@ -59201,7 +58898,7 @@ async function handleCloseCommand(directory, args2, options = {}) {
|
|
|
59201
58898
|
if (!archivedActiveStateDirs.has(dirName)) {
|
|
59202
58899
|
continue;
|
|
59203
58900
|
}
|
|
59204
|
-
const dirPath =
|
|
58901
|
+
const dirPath = path23.join(swarmDir, dirName);
|
|
59205
58902
|
try {
|
|
59206
58903
|
await fs13.rm(dirPath, { recursive: true, force: true });
|
|
59207
58904
|
cleanedFiles.push(`${dirName}/`);
|
|
@@ -59212,23 +58909,23 @@ async function handleCloseCommand(directory, args2, options = {}) {
|
|
|
59212
58909
|
const configBackups = swarmFiles.filter((f) => f.startsWith("config-backup-") && f.endsWith(".json"));
|
|
59213
58910
|
for (const backup of configBackups) {
|
|
59214
58911
|
try {
|
|
59215
|
-
await fs13.unlink(
|
|
58912
|
+
await fs13.unlink(path23.join(swarmDir, backup));
|
|
59216
58913
|
configBackupsRemoved++;
|
|
59217
58914
|
} catch {}
|
|
59218
58915
|
}
|
|
59219
58916
|
const ledgerSiblings = swarmFiles.filter((f) => (f.startsWith("plan-ledger.archived-") || f.startsWith("plan-ledger.backup-")) && f.endsWith(".jsonl"));
|
|
59220
58917
|
for (const sibling of ledgerSiblings) {
|
|
59221
58918
|
try {
|
|
59222
|
-
await fs13.unlink(
|
|
58919
|
+
await fs13.unlink(path23.join(swarmDir, sibling));
|
|
59223
58920
|
} catch {}
|
|
59224
58921
|
}
|
|
59225
58922
|
} catch {}
|
|
59226
58923
|
let swarmPlanFilesRemoved = 0;
|
|
59227
58924
|
const candidates = [
|
|
59228
|
-
|
|
59229
|
-
|
|
59230
|
-
|
|
59231
|
-
|
|
58925
|
+
path23.join(directory, ".swarm", "SWARM_PLAN.json"),
|
|
58926
|
+
path23.join(directory, ".swarm", "SWARM_PLAN.md"),
|
|
58927
|
+
path23.join(directory, "SWARM_PLAN.json"),
|
|
58928
|
+
path23.join(directory, "SWARM_PLAN.md")
|
|
59232
58929
|
];
|
|
59233
58930
|
for (const candidate of candidates) {
|
|
59234
58931
|
try {
|
|
@@ -59236,12 +58933,12 @@ async function handleCloseCommand(directory, args2, options = {}) {
|
|
|
59236
58933
|
swarmPlanFilesRemoved++;
|
|
59237
58934
|
} catch (err2) {
|
|
59238
58935
|
if (err2?.code !== "ENOENT") {
|
|
59239
|
-
warnings.push(`Failed to remove ${
|
|
58936
|
+
warnings.push(`Failed to remove ${path23.basename(candidate)}: ${err2 instanceof Error ? err2.message : String(err2)}`);
|
|
59240
58937
|
}
|
|
59241
58938
|
}
|
|
59242
58939
|
}
|
|
59243
58940
|
clearAllScopes(directory);
|
|
59244
|
-
const contextPath =
|
|
58941
|
+
const contextPath = path23.join(swarmDir, "context.md");
|
|
59245
58942
|
const contextContent = [
|
|
59246
58943
|
"# Context",
|
|
59247
58944
|
"",
|
|
@@ -59460,14 +59157,14 @@ var init_close = __esm(() => {
|
|
|
59460
59157
|
|
|
59461
59158
|
// src/commands/config.ts
|
|
59462
59159
|
import * as os4 from "node:os";
|
|
59463
|
-
import * as
|
|
59160
|
+
import * as path24 from "node:path";
|
|
59464
59161
|
function getUserConfigDir2() {
|
|
59465
|
-
return process.env.XDG_CONFIG_HOME ||
|
|
59162
|
+
return process.env.XDG_CONFIG_HOME || path24.join(os4.homedir(), ".config");
|
|
59466
59163
|
}
|
|
59467
59164
|
async function handleConfigCommand(directory, _args) {
|
|
59468
59165
|
const config3 = loadPluginConfig(directory);
|
|
59469
|
-
const userConfigPath =
|
|
59470
|
-
const projectConfigPath =
|
|
59166
|
+
const userConfigPath = path24.join(getUserConfigDir2(), "opencode", "opencode-swarm.json");
|
|
59167
|
+
const projectConfigPath = path24.join(directory, ".opencode", "opencode-swarm.json");
|
|
59471
59168
|
const lines = [
|
|
59472
59169
|
"## Swarm Configuration",
|
|
59473
59170
|
"",
|
|
@@ -59604,8 +59301,8 @@ __export(exports_co_change_analyzer, {
|
|
|
59604
59301
|
});
|
|
59605
59302
|
import * as child_process3 from "node:child_process";
|
|
59606
59303
|
import { randomUUID as randomUUID2 } from "node:crypto";
|
|
59607
|
-
import { readdir as readdir2, readFile as
|
|
59608
|
-
import * as
|
|
59304
|
+
import { readdir as readdir2, readFile as readFile8, stat as stat3 } from "node:fs/promises";
|
|
59305
|
+
import * as path25 from "node:path";
|
|
59609
59306
|
import { promisify } from "node:util";
|
|
59610
59307
|
function getExecFileAsync() {
|
|
59611
59308
|
return promisify(child_process3.execFile);
|
|
@@ -59707,7 +59404,7 @@ async function scanSourceFiles(dir) {
|
|
|
59707
59404
|
try {
|
|
59708
59405
|
const entries = await readdir2(dir, { withFileTypes: true });
|
|
59709
59406
|
for (const entry of entries) {
|
|
59710
|
-
const fullPath =
|
|
59407
|
+
const fullPath = path25.join(dir, entry.name);
|
|
59711
59408
|
if (entry.isDirectory()) {
|
|
59712
59409
|
if (skipDirs.has(entry.name)) {
|
|
59713
59410
|
continue;
|
|
@@ -59715,7 +59412,7 @@ async function scanSourceFiles(dir) {
|
|
|
59715
59412
|
const subFiles = await scanSourceFiles(fullPath);
|
|
59716
59413
|
results.push(...subFiles);
|
|
59717
59414
|
} else if (entry.isFile()) {
|
|
59718
|
-
const ext =
|
|
59415
|
+
const ext = path25.extname(entry.name);
|
|
59719
59416
|
if ([".ts", ".tsx", ".js", ".jsx", ".mjs"].includes(ext)) {
|
|
59720
59417
|
results.push(fullPath);
|
|
59721
59418
|
}
|
|
@@ -59729,7 +59426,7 @@ async function getStaticEdges(directory) {
|
|
|
59729
59426
|
const sourceFiles = await scanSourceFiles(directory);
|
|
59730
59427
|
for (const sourceFile of sourceFiles) {
|
|
59731
59428
|
try {
|
|
59732
|
-
const content = await
|
|
59429
|
+
const content = await readFile8(sourceFile, "utf-8");
|
|
59733
59430
|
const importRegex = /(?:import|require)\s*(?:\(?\s*['"`]|.*?from\s+['"`])([^'"`]+)['"`]/g;
|
|
59734
59431
|
for (let match = importRegex.exec(content);match !== null; match = importRegex.exec(content)) {
|
|
59735
59432
|
const importPath = match[1].trim();
|
|
@@ -59737,8 +59434,8 @@ async function getStaticEdges(directory) {
|
|
|
59737
59434
|
continue;
|
|
59738
59435
|
}
|
|
59739
59436
|
try {
|
|
59740
|
-
const sourceDir =
|
|
59741
|
-
const resolvedPath =
|
|
59437
|
+
const sourceDir = path25.dirname(sourceFile);
|
|
59438
|
+
const resolvedPath = path25.resolve(sourceDir, importPath);
|
|
59742
59439
|
const extensions = [
|
|
59743
59440
|
"",
|
|
59744
59441
|
".ts",
|
|
@@ -59763,8 +59460,8 @@ async function getStaticEdges(directory) {
|
|
|
59763
59460
|
if (!targetFile) {
|
|
59764
59461
|
continue;
|
|
59765
59462
|
}
|
|
59766
|
-
const relSource =
|
|
59767
|
-
const relTarget =
|
|
59463
|
+
const relSource = path25.relative(directory, sourceFile).replace(/\\/g, "/");
|
|
59464
|
+
const relTarget = path25.relative(directory, targetFile).replace(/\\/g, "/");
|
|
59768
59465
|
const [key] = relSource < relTarget ? [`${relSource}::${relTarget}`, relSource, relTarget] : [`${relTarget}::${relSource}`, relTarget, relSource];
|
|
59769
59466
|
edges.add(key);
|
|
59770
59467
|
} catch {}
|
|
@@ -59776,7 +59473,7 @@ async function getStaticEdges(directory) {
|
|
|
59776
59473
|
function isTestImplementationPair(fileA, fileB) {
|
|
59777
59474
|
const testPatterns = [".test.ts", ".test.js", ".spec.ts", ".spec.js"];
|
|
59778
59475
|
const getBaseName = (filePath) => {
|
|
59779
|
-
const base =
|
|
59476
|
+
const base = path25.basename(filePath);
|
|
59780
59477
|
for (const pattern of testPatterns) {
|
|
59781
59478
|
if (base.endsWith(pattern)) {
|
|
59782
59479
|
return base.slice(0, -pattern.length);
|
|
@@ -59786,16 +59483,16 @@ function isTestImplementationPair(fileA, fileB) {
|
|
|
59786
59483
|
};
|
|
59787
59484
|
const baseA = getBaseName(fileA);
|
|
59788
59485
|
const baseB = getBaseName(fileB);
|
|
59789
|
-
return baseA === baseB && baseA !==
|
|
59486
|
+
return baseA === baseB && baseA !== path25.basename(fileA) && baseA !== path25.basename(fileB);
|
|
59790
59487
|
}
|
|
59791
59488
|
function hasSharedPrefix(fileA, fileB) {
|
|
59792
|
-
const dirA =
|
|
59793
|
-
const dirB =
|
|
59489
|
+
const dirA = path25.dirname(fileA);
|
|
59490
|
+
const dirB = path25.dirname(fileB);
|
|
59794
59491
|
if (dirA !== dirB) {
|
|
59795
59492
|
return false;
|
|
59796
59493
|
}
|
|
59797
|
-
const baseA =
|
|
59798
|
-
const baseB =
|
|
59494
|
+
const baseA = path25.basename(fileA).replace(/\.(ts|js|tsx|jsx|mjs)$/, "");
|
|
59495
|
+
const baseB = path25.basename(fileB).replace(/\.(ts|js|tsx|jsx|mjs)$/, "");
|
|
59799
59496
|
if (baseA.startsWith(baseB) || baseB.startsWith(baseA)) {
|
|
59800
59497
|
return true;
|
|
59801
59498
|
}
|
|
@@ -59849,8 +59546,8 @@ function darkMatterToKnowledgeEntries(pairs, projectName) {
|
|
|
59849
59546
|
const entries = [];
|
|
59850
59547
|
const now = new Date().toISOString();
|
|
59851
59548
|
for (const pair of pairs.slice(0, 10)) {
|
|
59852
|
-
const baseA =
|
|
59853
|
-
const baseB =
|
|
59549
|
+
const baseA = path25.basename(pair.fileA);
|
|
59550
|
+
const baseB = path25.basename(pair.fileB);
|
|
59854
59551
|
let lesson = `Files ${pair.fileA} and ${pair.fileB} co-change with NPMI=${pair.npmi.toFixed(3)} but have no import relationship. This hidden coupling suggests a shared architectural concern — changes to one likely require changes to the other.`;
|
|
59855
59552
|
if (lesson.length > 280) {
|
|
59856
59553
|
lesson = `Files ${baseA} and ${baseB} co-change with NPMI=${pair.npmi.toFixed(3)} but have no import relationship. This hidden coupling suggests a shared architectural concern — changes to one likely require changes to the other.`;
|
|
@@ -59952,7 +59649,7 @@ var init_co_change_analyzer = __esm(() => {
|
|
|
59952
59649
|
});
|
|
59953
59650
|
|
|
59954
59651
|
// src/commands/dark-matter.ts
|
|
59955
|
-
import
|
|
59652
|
+
import path26 from "node:path";
|
|
59956
59653
|
async function handleDarkMatterCommand(directory, args2) {
|
|
59957
59654
|
const options = {};
|
|
59958
59655
|
for (let i2 = 0;i2 < args2.length; i2++) {
|
|
@@ -59984,7 +59681,7 @@ Ensure this is a git repository with commit history.`;
|
|
|
59984
59681
|
const output = formatDarkMatterOutput(pairs);
|
|
59985
59682
|
if (pairs.length > 0) {
|
|
59986
59683
|
try {
|
|
59987
|
-
const projectName =
|
|
59684
|
+
const projectName = path26.basename(path26.resolve(directory));
|
|
59988
59685
|
const entries = darkMatterToKnowledgeEntries(pairs, projectName);
|
|
59989
59686
|
if (entries.length > 0) {
|
|
59990
59687
|
const knowledgePath = resolveSwarmKnowledgePath(directory);
|
|
@@ -60121,49 +59818,49 @@ var init_deep_dive = __esm(() => {
|
|
|
60121
59818
|
|
|
60122
59819
|
// src/config/cache-paths.ts
|
|
60123
59820
|
import * as os5 from "node:os";
|
|
60124
|
-
import * as
|
|
59821
|
+
import * as path27 from "node:path";
|
|
60125
59822
|
function getPluginConfigDir() {
|
|
60126
|
-
return
|
|
59823
|
+
return path27.join(process.env.XDG_CONFIG_HOME || path27.join(os5.homedir(), ".config"), "opencode");
|
|
60127
59824
|
}
|
|
60128
59825
|
function getPluginCachePaths() {
|
|
60129
|
-
const cacheBase = process.env.XDG_CACHE_HOME ||
|
|
59826
|
+
const cacheBase = process.env.XDG_CACHE_HOME || path27.join(os5.homedir(), ".cache");
|
|
60130
59827
|
const configDir = getPluginConfigDir();
|
|
60131
59828
|
const paths = [
|
|
60132
|
-
|
|
60133
|
-
|
|
60134
|
-
|
|
59829
|
+
path27.join(cacheBase, "opencode", "node_modules", "opencode-swarm"),
|
|
59830
|
+
path27.join(cacheBase, "opencode", "packages", "opencode-swarm@latest"),
|
|
59831
|
+
path27.join(configDir, "node_modules", "opencode-swarm")
|
|
60135
59832
|
];
|
|
60136
59833
|
if (process.platform === "darwin") {
|
|
60137
|
-
const libCaches =
|
|
60138
|
-
paths.push(
|
|
59834
|
+
const libCaches = path27.join(os5.homedir(), "Library", "Caches");
|
|
59835
|
+
paths.push(path27.join(libCaches, "opencode", "node_modules", "opencode-swarm"), path27.join(libCaches, "opencode", "packages", "opencode-swarm@latest"));
|
|
60139
59836
|
}
|
|
60140
59837
|
if (process.platform === "win32") {
|
|
60141
|
-
const localAppData = process.env.LOCALAPPDATA ||
|
|
60142
|
-
const appData = process.env.APPDATA ||
|
|
60143
|
-
paths.push(
|
|
59838
|
+
const localAppData = process.env.LOCALAPPDATA || path27.join(os5.homedir(), "AppData", "Local");
|
|
59839
|
+
const appData = process.env.APPDATA || path27.join(os5.homedir(), "AppData", "Roaming");
|
|
59840
|
+
paths.push(path27.join(localAppData, "opencode", "node_modules", "opencode-swarm"), path27.join(localAppData, "opencode", "packages", "opencode-swarm@latest"), path27.join(appData, "opencode", "node_modules", "opencode-swarm"));
|
|
60144
59841
|
}
|
|
60145
59842
|
return paths;
|
|
60146
59843
|
}
|
|
60147
59844
|
var init_cache_paths = () => {};
|
|
60148
59845
|
|
|
60149
59846
|
// src/services/version-check.ts
|
|
60150
|
-
import { existsSync as
|
|
59847
|
+
import { existsSync as existsSync14, mkdirSync as mkdirSync10, readFileSync as readFileSync7, writeFileSync as writeFileSync4 } from "node:fs";
|
|
60151
59848
|
import { homedir as homedir5 } from "node:os";
|
|
60152
|
-
import { join as
|
|
59849
|
+
import { join as join25 } from "node:path";
|
|
60153
59850
|
function cacheDir() {
|
|
60154
59851
|
const xdg = process.env.XDG_CACHE_HOME;
|
|
60155
|
-
const base = xdg && xdg.length > 0 ? xdg :
|
|
60156
|
-
return
|
|
59852
|
+
const base = xdg && xdg.length > 0 ? xdg : join25(homedir5(), ".cache");
|
|
59853
|
+
return join25(base, "opencode-swarm");
|
|
60157
59854
|
}
|
|
60158
59855
|
function cacheFile() {
|
|
60159
|
-
return
|
|
59856
|
+
return join25(cacheDir(), "version-check.json");
|
|
60160
59857
|
}
|
|
60161
59858
|
function readVersionCache() {
|
|
60162
59859
|
try {
|
|
60163
|
-
const
|
|
60164
|
-
if (!
|
|
59860
|
+
const path28 = cacheFile();
|
|
59861
|
+
if (!existsSync14(path28))
|
|
60165
59862
|
return null;
|
|
60166
|
-
const raw = readFileSync7(
|
|
59863
|
+
const raw = readFileSync7(path28, "utf-8");
|
|
60167
59864
|
const parsed = JSON.parse(raw);
|
|
60168
59865
|
if (typeof parsed?.checkedAt !== "number")
|
|
60169
59866
|
return null;
|
|
@@ -60260,8 +59957,8 @@ var init_version_check = __esm(() => {
|
|
|
60260
59957
|
|
|
60261
59958
|
// src/services/diagnose-service.ts
|
|
60262
59959
|
import * as child_process4 from "node:child_process";
|
|
60263
|
-
import { existsSync as
|
|
60264
|
-
import
|
|
59960
|
+
import { existsSync as existsSync15, readdirSync as readdirSync4, readFileSync as readFileSync8, statSync as statSync7 } from "node:fs";
|
|
59961
|
+
import path28 from "node:path";
|
|
60265
59962
|
import { fileURLToPath } from "node:url";
|
|
60266
59963
|
function validateTaskDag(plan) {
|
|
60267
59964
|
const allTaskIds = new Set;
|
|
@@ -60494,7 +60191,7 @@ async function checkConfigBackups(directory) {
|
|
|
60494
60191
|
}
|
|
60495
60192
|
async function checkGitRepository(directory) {
|
|
60496
60193
|
try {
|
|
60497
|
-
if (!
|
|
60194
|
+
if (!existsSync15(directory) || !statSync7(directory).isDirectory()) {
|
|
60498
60195
|
return {
|
|
60499
60196
|
name: "Git Repository",
|
|
60500
60197
|
status: "❌",
|
|
@@ -60558,8 +60255,8 @@ async function checkSpecStaleness(directory, plan) {
|
|
|
60558
60255
|
};
|
|
60559
60256
|
}
|
|
60560
60257
|
async function checkConfigParseability(directory) {
|
|
60561
|
-
const configPath =
|
|
60562
|
-
if (!
|
|
60258
|
+
const configPath = path28.join(directory, ".opencode/opencode-swarm.json");
|
|
60259
|
+
if (!existsSync15(configPath)) {
|
|
60563
60260
|
return {
|
|
60564
60261
|
name: "Config Parseability",
|
|
60565
60262
|
status: "✅",
|
|
@@ -60587,7 +60284,7 @@ function resolveGrammarDir(thisDir) {
|
|
|
60587
60284
|
const normalized = thisDir.replace(/\\/g, "/");
|
|
60588
60285
|
const isSource = normalized.endsWith("/src/services");
|
|
60589
60286
|
const isCliBundle = normalized.endsWith("/cli");
|
|
60590
|
-
return isSource || isCliBundle ?
|
|
60287
|
+
return isSource || isCliBundle ? path28.join(thisDir, "..", "lang", "grammars") : path28.join(thisDir, "lang", "grammars");
|
|
60591
60288
|
}
|
|
60592
60289
|
async function checkGrammarWasmFiles() {
|
|
60593
60290
|
const grammarFiles = [
|
|
@@ -60611,14 +60308,14 @@ async function checkGrammarWasmFiles() {
|
|
|
60611
60308
|
"tree-sitter-ini.wasm",
|
|
60612
60309
|
"tree-sitter-regex.wasm"
|
|
60613
60310
|
];
|
|
60614
|
-
const thisDir =
|
|
60311
|
+
const thisDir = path28.dirname(fileURLToPath(import.meta.url));
|
|
60615
60312
|
const grammarDir = resolveGrammarDir(thisDir);
|
|
60616
60313
|
const missing = [];
|
|
60617
|
-
if (!
|
|
60314
|
+
if (!existsSync15(path28.join(grammarDir, "tree-sitter.wasm"))) {
|
|
60618
60315
|
missing.push("tree-sitter.wasm (core runtime)");
|
|
60619
60316
|
}
|
|
60620
60317
|
for (const file3 of grammarFiles) {
|
|
60621
|
-
if (!
|
|
60318
|
+
if (!existsSync15(path28.join(grammarDir, file3))) {
|
|
60622
60319
|
missing.push(file3);
|
|
60623
60320
|
}
|
|
60624
60321
|
}
|
|
@@ -60636,8 +60333,8 @@ async function checkGrammarWasmFiles() {
|
|
|
60636
60333
|
};
|
|
60637
60334
|
}
|
|
60638
60335
|
async function checkCheckpointManifest(directory) {
|
|
60639
|
-
const manifestPath =
|
|
60640
|
-
if (!
|
|
60336
|
+
const manifestPath = path28.join(directory, ".swarm/checkpoints.json");
|
|
60337
|
+
if (!existsSync15(manifestPath)) {
|
|
60641
60338
|
return {
|
|
60642
60339
|
name: "Checkpoint Manifest",
|
|
60643
60340
|
status: "✅",
|
|
@@ -60688,8 +60385,8 @@ async function checkCheckpointManifest(directory) {
|
|
|
60688
60385
|
}
|
|
60689
60386
|
}
|
|
60690
60387
|
async function checkEventStreamIntegrity(directory) {
|
|
60691
|
-
const eventsPath =
|
|
60692
|
-
if (!
|
|
60388
|
+
const eventsPath = path28.join(directory, ".swarm/events.jsonl");
|
|
60389
|
+
if (!existsSync15(eventsPath)) {
|
|
60693
60390
|
return {
|
|
60694
60391
|
name: "Event Stream",
|
|
60695
60392
|
status: "✅",
|
|
@@ -60729,8 +60426,8 @@ async function checkEventStreamIntegrity(directory) {
|
|
|
60729
60426
|
}
|
|
60730
60427
|
}
|
|
60731
60428
|
async function checkSteeringDirectives(directory) {
|
|
60732
|
-
const eventsPath =
|
|
60733
|
-
if (!
|
|
60429
|
+
const eventsPath = path28.join(directory, ".swarm/events.jsonl");
|
|
60430
|
+
if (!existsSync15(eventsPath)) {
|
|
60734
60431
|
return {
|
|
60735
60432
|
name: "Steering Directives",
|
|
60736
60433
|
status: "✅",
|
|
@@ -60785,8 +60482,8 @@ async function checkCurator(directory) {
|
|
|
60785
60482
|
detail: "Disabled (enable via curator.enabled)"
|
|
60786
60483
|
};
|
|
60787
60484
|
}
|
|
60788
|
-
const summaryPath =
|
|
60789
|
-
if (!
|
|
60485
|
+
const summaryPath = path28.join(directory, ".swarm/curator-summary.json");
|
|
60486
|
+
if (!existsSync15(summaryPath)) {
|
|
60790
60487
|
return {
|
|
60791
60488
|
name: "Curator",
|
|
60792
60489
|
status: "✅",
|
|
@@ -60951,8 +60648,8 @@ async function getDiagnoseData(directory) {
|
|
|
60951
60648
|
checks5.push(await checkSteeringDirectives(directory));
|
|
60952
60649
|
checks5.push(await checkCurator(directory));
|
|
60953
60650
|
try {
|
|
60954
|
-
const evidenceDir =
|
|
60955
|
-
const snapshotFiles =
|
|
60651
|
+
const evidenceDir = path28.join(directory, ".swarm", "evidence");
|
|
60652
|
+
const snapshotFiles = existsSync15(evidenceDir) ? readdirSync4(evidenceDir).filter((f) => f.startsWith("agent-tools-") && f.endsWith(".json")) : [];
|
|
60956
60653
|
if (snapshotFiles.length > 0) {
|
|
60957
60654
|
const latest = snapshotFiles.sort().pop();
|
|
60958
60655
|
checks5.push({
|
|
@@ -60985,11 +60682,11 @@ async function getDiagnoseData(directory) {
|
|
|
60985
60682
|
const cacheRows = [];
|
|
60986
60683
|
for (const cachePath of cachePaths) {
|
|
60987
60684
|
try {
|
|
60988
|
-
if (!
|
|
60685
|
+
if (!existsSync15(cachePath)) {
|
|
60989
60686
|
cacheRows.push(`⬜ ${cachePath} — absent`);
|
|
60990
60687
|
continue;
|
|
60991
60688
|
}
|
|
60992
|
-
const pkgJsonPath =
|
|
60689
|
+
const pkgJsonPath = path28.join(cachePath, "package.json");
|
|
60993
60690
|
try {
|
|
60994
60691
|
const raw = readFileSync8(pkgJsonPath, "utf-8");
|
|
60995
60692
|
const parsed = JSON.parse(raw);
|
|
@@ -61079,13 +60776,13 @@ __export(exports_config_doctor, {
|
|
|
61079
60776
|
import * as crypto3 from "node:crypto";
|
|
61080
60777
|
import * as fs14 from "node:fs";
|
|
61081
60778
|
import * as os6 from "node:os";
|
|
61082
|
-
import * as
|
|
60779
|
+
import * as path29 from "node:path";
|
|
61083
60780
|
function getUserConfigDir3() {
|
|
61084
|
-
return process.env.XDG_CONFIG_HOME ||
|
|
60781
|
+
return process.env.XDG_CONFIG_HOME || path29.join(os6.homedir(), ".config");
|
|
61085
60782
|
}
|
|
61086
60783
|
function getConfigPaths(directory) {
|
|
61087
|
-
const userConfigPath =
|
|
61088
|
-
const projectConfigPath =
|
|
60784
|
+
const userConfigPath = path29.join(getUserConfigDir3(), "opencode", "opencode-swarm.json");
|
|
60785
|
+
const projectConfigPath = path29.join(directory, ".opencode", "opencode-swarm.json");
|
|
61089
60786
|
return { userConfigPath, projectConfigPath };
|
|
61090
60787
|
}
|
|
61091
60788
|
function computeHash(content) {
|
|
@@ -61110,9 +60807,9 @@ function isValidConfigPath(configPath, directory) {
|
|
|
61110
60807
|
const normalizedUser = userConfigPath.replace(/\\/g, "/");
|
|
61111
60808
|
const normalizedProject = projectConfigPath.replace(/\\/g, "/");
|
|
61112
60809
|
try {
|
|
61113
|
-
const resolvedConfig =
|
|
61114
|
-
const resolvedUser =
|
|
61115
|
-
const resolvedProject =
|
|
60810
|
+
const resolvedConfig = path29.resolve(configPath);
|
|
60811
|
+
const resolvedUser = path29.resolve(normalizedUser);
|
|
60812
|
+
const resolvedProject = path29.resolve(normalizedProject);
|
|
61116
60813
|
return resolvedConfig === resolvedUser || resolvedConfig === resolvedProject;
|
|
61117
60814
|
} catch {
|
|
61118
60815
|
return false;
|
|
@@ -61152,12 +60849,12 @@ function createConfigBackup(directory) {
|
|
|
61152
60849
|
};
|
|
61153
60850
|
}
|
|
61154
60851
|
function writeBackupArtifact(directory, backup) {
|
|
61155
|
-
const swarmDir =
|
|
60852
|
+
const swarmDir = path29.join(directory, ".swarm");
|
|
61156
60853
|
if (!fs14.existsSync(swarmDir)) {
|
|
61157
60854
|
fs14.mkdirSync(swarmDir, { recursive: true });
|
|
61158
60855
|
}
|
|
61159
60856
|
const backupFilename = `config-backup-${backup.createdAt}.json`;
|
|
61160
|
-
const backupPath =
|
|
60857
|
+
const backupPath = path29.join(swarmDir, backupFilename);
|
|
61161
60858
|
const artifact = {
|
|
61162
60859
|
createdAt: backup.createdAt,
|
|
61163
60860
|
configPath: backup.configPath,
|
|
@@ -61187,7 +60884,7 @@ function restoreFromBackup(backupPath, directory) {
|
|
|
61187
60884
|
return null;
|
|
61188
60885
|
}
|
|
61189
60886
|
const targetPath = artifact.configPath;
|
|
61190
|
-
const targetDir =
|
|
60887
|
+
const targetDir = path29.dirname(targetPath);
|
|
61191
60888
|
if (!fs14.existsSync(targetDir)) {
|
|
61192
60889
|
fs14.mkdirSync(targetDir, { recursive: true });
|
|
61193
60890
|
}
|
|
@@ -61218,9 +60915,9 @@ function readConfigFromFile(directory) {
|
|
|
61218
60915
|
return null;
|
|
61219
60916
|
}
|
|
61220
60917
|
}
|
|
61221
|
-
function validateConfigKey(
|
|
60918
|
+
function validateConfigKey(path30, value, _config) {
|
|
61222
60919
|
const findings = [];
|
|
61223
|
-
switch (
|
|
60920
|
+
switch (path30) {
|
|
61224
60921
|
case "agents": {
|
|
61225
60922
|
if (value !== undefined) {
|
|
61226
60923
|
findings.push({
|
|
@@ -61457,27 +61154,27 @@ function validateConfigKey(path31, value, _config) {
|
|
|
61457
61154
|
}
|
|
61458
61155
|
return findings;
|
|
61459
61156
|
}
|
|
61460
|
-
function walkConfigAndValidate(obj,
|
|
61157
|
+
function walkConfigAndValidate(obj, path30, config3, findings) {
|
|
61461
61158
|
if (obj === null || obj === undefined) {
|
|
61462
61159
|
return;
|
|
61463
61160
|
}
|
|
61464
|
-
if (
|
|
61465
|
-
const keyFindings = validateConfigKey(
|
|
61161
|
+
if (path30 && typeof obj === "object" && !Array.isArray(obj)) {
|
|
61162
|
+
const keyFindings = validateConfigKey(path30, obj, config3);
|
|
61466
61163
|
findings.push(...keyFindings);
|
|
61467
61164
|
}
|
|
61468
61165
|
if (typeof obj !== "object") {
|
|
61469
|
-
const keyFindings = validateConfigKey(
|
|
61166
|
+
const keyFindings = validateConfigKey(path30, obj, config3);
|
|
61470
61167
|
findings.push(...keyFindings);
|
|
61471
61168
|
return;
|
|
61472
61169
|
}
|
|
61473
61170
|
if (Array.isArray(obj)) {
|
|
61474
61171
|
obj.forEach((item, index) => {
|
|
61475
|
-
walkConfigAndValidate(item, `${
|
|
61172
|
+
walkConfigAndValidate(item, `${path30}[${index}]`, config3, findings);
|
|
61476
61173
|
});
|
|
61477
61174
|
return;
|
|
61478
61175
|
}
|
|
61479
61176
|
for (const [key, value] of Object.entries(obj)) {
|
|
61480
|
-
const newPath =
|
|
61177
|
+
const newPath = path30 ? `${path30}.${key}` : key;
|
|
61481
61178
|
walkConfigAndValidate(value, newPath, config3, findings);
|
|
61482
61179
|
}
|
|
61483
61180
|
}
|
|
@@ -61597,7 +61294,7 @@ function applySafeAutoFixes(directory, result) {
|
|
|
61597
61294
|
}
|
|
61598
61295
|
}
|
|
61599
61296
|
if (appliedFixes.length > 0) {
|
|
61600
|
-
const configDir =
|
|
61297
|
+
const configDir = path29.dirname(configPath);
|
|
61601
61298
|
if (!fs14.existsSync(configDir)) {
|
|
61602
61299
|
fs14.mkdirSync(configDir, { recursive: true });
|
|
61603
61300
|
}
|
|
@@ -61607,12 +61304,12 @@ function applySafeAutoFixes(directory, result) {
|
|
|
61607
61304
|
return { appliedFixes, updatedConfigPath };
|
|
61608
61305
|
}
|
|
61609
61306
|
function writeDoctorArtifact(directory, result) {
|
|
61610
|
-
const swarmDir =
|
|
61307
|
+
const swarmDir = path29.join(directory, ".swarm");
|
|
61611
61308
|
if (!fs14.existsSync(swarmDir)) {
|
|
61612
61309
|
fs14.mkdirSync(swarmDir, { recursive: true });
|
|
61613
61310
|
}
|
|
61614
61311
|
const artifactFilename = "config-doctor.json";
|
|
61615
|
-
const artifactPath =
|
|
61312
|
+
const artifactPath = path29.join(swarmDir, artifactFilename);
|
|
61616
61313
|
const guiOutput = {
|
|
61617
61314
|
timestamp: result.timestamp,
|
|
61618
61315
|
summary: result.summary,
|
|
@@ -61708,17 +61405,17 @@ function detectStraySwarmDirs(projectRoot) {
|
|
|
61708
61405
|
if (!entry.isDirectory())
|
|
61709
61406
|
continue;
|
|
61710
61407
|
const name2 = entry.name;
|
|
61711
|
-
const fullPath =
|
|
61408
|
+
const fullPath = path29.join(dir, name2);
|
|
61712
61409
|
if (SKIP_DIRS.has(name2))
|
|
61713
61410
|
continue;
|
|
61714
|
-
const gitPath =
|
|
61411
|
+
const gitPath = path29.join(fullPath, ".git");
|
|
61715
61412
|
try {
|
|
61716
61413
|
const gitStat = fs14.statSync(gitPath);
|
|
61717
61414
|
if (gitStat.isFile() || gitStat.isDirectory())
|
|
61718
61415
|
continue;
|
|
61719
61416
|
} catch {}
|
|
61720
61417
|
if (name2 === ".swarm") {
|
|
61721
|
-
const parentDir =
|
|
61418
|
+
const parentDir = path29.dirname(fullPath);
|
|
61722
61419
|
if (parentDir === projectRoot)
|
|
61723
61420
|
continue;
|
|
61724
61421
|
let contents = [];
|
|
@@ -61728,7 +61425,7 @@ function detectStraySwarmDirs(projectRoot) {
|
|
|
61728
61425
|
contents = ["<unreadable>"];
|
|
61729
61426
|
}
|
|
61730
61427
|
findings.push({
|
|
61731
|
-
path:
|
|
61428
|
+
path: path29.relative(projectRoot, fullPath).replace(/\\/g, "/"),
|
|
61732
61429
|
absolutePath: fullPath,
|
|
61733
61430
|
contents: contents.slice(0, MAX_CONTENTS_ENTRIES),
|
|
61734
61431
|
totalEntries: contents.length
|
|
@@ -61746,21 +61443,21 @@ function removeStraySwarmDir(projectRoot, strayPath) {
|
|
|
61746
61443
|
let canonicalStray;
|
|
61747
61444
|
try {
|
|
61748
61445
|
canonicalRoot = fs14.realpathSync(projectRoot);
|
|
61749
|
-
canonicalStray = fs14.realpathSync(
|
|
61446
|
+
canonicalStray = fs14.realpathSync(path29.isAbsolute(strayPath) ? strayPath : path29.resolve(projectRoot, strayPath));
|
|
61750
61447
|
} catch (err2) {
|
|
61751
61448
|
return {
|
|
61752
61449
|
success: false,
|
|
61753
61450
|
message: `Failed to resolve paths: ${err2 instanceof Error ? err2.message : String(err2)}`
|
|
61754
61451
|
};
|
|
61755
61452
|
}
|
|
61756
|
-
const rootSwarm =
|
|
61453
|
+
const rootSwarm = path29.join(canonicalRoot, ".swarm");
|
|
61757
61454
|
if (canonicalStray === rootSwarm || canonicalStray === canonicalRoot) {
|
|
61758
61455
|
return {
|
|
61759
61456
|
success: false,
|
|
61760
61457
|
message: "Refusing to remove root .swarm/ directory"
|
|
61761
61458
|
};
|
|
61762
61459
|
}
|
|
61763
|
-
if (!canonicalStray.startsWith(canonicalRoot +
|
|
61460
|
+
if (!canonicalStray.startsWith(canonicalRoot + path29.sep)) {
|
|
61764
61461
|
return {
|
|
61765
61462
|
success: false,
|
|
61766
61463
|
message: "Path is outside project root — refusing to remove"
|
|
@@ -62849,7 +62546,7 @@ var init_profiles = __esm(() => {
|
|
|
62849
62546
|
|
|
62850
62547
|
// src/lang/detector.ts
|
|
62851
62548
|
import { access as access3, readdir as readdir3 } from "node:fs/promises";
|
|
62852
|
-
import { extname as extname2, join as
|
|
62549
|
+
import { extname as extname2, join as join27 } from "node:path";
|
|
62853
62550
|
function getProfileForFile(filePath) {
|
|
62854
62551
|
const ext = extname2(filePath);
|
|
62855
62552
|
if (!ext)
|
|
@@ -62871,7 +62568,7 @@ async function detectProjectLanguages(projectDir) {
|
|
|
62871
62568
|
if (detectFile.includes("*") || detectFile.includes("?"))
|
|
62872
62569
|
continue;
|
|
62873
62570
|
try {
|
|
62874
|
-
await access3(
|
|
62571
|
+
await access3(join27(dir, detectFile));
|
|
62875
62572
|
detected.add(profile.id);
|
|
62876
62573
|
break;
|
|
62877
62574
|
} catch {}
|
|
@@ -62892,7 +62589,7 @@ async function detectProjectLanguages(projectDir) {
|
|
|
62892
62589
|
const topEntries = await readdir3(projectDir, { withFileTypes: true });
|
|
62893
62590
|
for (const entry of topEntries) {
|
|
62894
62591
|
if (entry.isDirectory() && !entry.name.startsWith(".") && entry.name !== "node_modules") {
|
|
62895
|
-
await scanDir(
|
|
62592
|
+
await scanDir(join27(projectDir, entry.name));
|
|
62896
62593
|
}
|
|
62897
62594
|
}
|
|
62898
62595
|
} catch {}
|
|
@@ -62911,7 +62608,7 @@ var init_detector = __esm(() => {
|
|
|
62911
62608
|
|
|
62912
62609
|
// src/build/discovery.ts
|
|
62913
62610
|
import * as fs15 from "node:fs";
|
|
62914
|
-
import * as
|
|
62611
|
+
import * as path30 from "node:path";
|
|
62915
62612
|
function isCommandAvailable(command) {
|
|
62916
62613
|
if (toolchainCache.has(command)) {
|
|
62917
62614
|
return toolchainCache.get(command);
|
|
@@ -62946,11 +62643,11 @@ function findBuildFiles(workingDir, patterns) {
|
|
|
62946
62643
|
const regex = simpleGlobToRegex(pattern);
|
|
62947
62644
|
const matches = files.filter((f) => regex.test(f));
|
|
62948
62645
|
if (matches.length > 0) {
|
|
62949
|
-
return
|
|
62646
|
+
return path30.join(dir, matches[0]);
|
|
62950
62647
|
}
|
|
62951
62648
|
} catch {}
|
|
62952
62649
|
} else {
|
|
62953
|
-
const filePath =
|
|
62650
|
+
const filePath = path30.join(workingDir, pattern);
|
|
62954
62651
|
if (fs15.existsSync(filePath)) {
|
|
62955
62652
|
return filePath;
|
|
62956
62653
|
}
|
|
@@ -62959,7 +62656,7 @@ function findBuildFiles(workingDir, patterns) {
|
|
|
62959
62656
|
return null;
|
|
62960
62657
|
}
|
|
62961
62658
|
function getRepoDefinedScripts(workingDir, scripts) {
|
|
62962
|
-
const packageJsonPath =
|
|
62659
|
+
const packageJsonPath = path30.join(workingDir, "package.json");
|
|
62963
62660
|
if (!fs15.existsSync(packageJsonPath)) {
|
|
62964
62661
|
return [];
|
|
62965
62662
|
}
|
|
@@ -63000,7 +62697,7 @@ function findAllBuildFiles(workingDir) {
|
|
|
63000
62697
|
const regex = simpleGlobToRegex(pattern);
|
|
63001
62698
|
findFilesRecursive(workingDir, regex, allBuildFiles);
|
|
63002
62699
|
} else {
|
|
63003
|
-
const filePath =
|
|
62700
|
+
const filePath = path30.join(workingDir, pattern);
|
|
63004
62701
|
if (fs15.existsSync(filePath)) {
|
|
63005
62702
|
allBuildFiles.add(filePath);
|
|
63006
62703
|
}
|
|
@@ -63013,7 +62710,7 @@ function findFilesRecursive(dir, regex, results) {
|
|
|
63013
62710
|
try {
|
|
63014
62711
|
const entries = fs15.readdirSync(dir, { withFileTypes: true });
|
|
63015
62712
|
for (const entry of entries) {
|
|
63016
|
-
const fullPath =
|
|
62713
|
+
const fullPath = path30.join(dir, entry.name);
|
|
63017
62714
|
if (entry.isDirectory() && !["node_modules", ".git", "dist", "build", "target"].includes(entry.name)) {
|
|
63018
62715
|
findFilesRecursive(fullPath, regex, results);
|
|
63019
62716
|
} else if (entry.isFile() && regex.test(entry.name)) {
|
|
@@ -63036,7 +62733,7 @@ async function discoverBuildCommandsFromProfiles(workingDir) {
|
|
|
63036
62733
|
let foundCommand = false;
|
|
63037
62734
|
for (const cmd of sortedCommands) {
|
|
63038
62735
|
if (cmd.detectFile) {
|
|
63039
|
-
const detectFilePath =
|
|
62736
|
+
const detectFilePath = path30.join(workingDir, cmd.detectFile);
|
|
63040
62737
|
if (!fs15.existsSync(detectFilePath)) {
|
|
63041
62738
|
continue;
|
|
63042
62739
|
}
|
|
@@ -63282,7 +62979,7 @@ __export(exports_tool_doctor, {
|
|
|
63282
62979
|
getBinaryReadinessAdvisory: () => getBinaryReadinessAdvisory
|
|
63283
62980
|
});
|
|
63284
62981
|
import * as fs16 from "node:fs";
|
|
63285
|
-
import * as
|
|
62982
|
+
import * as path31 from "node:path";
|
|
63286
62983
|
function extractRegisteredToolKeys(indexPath) {
|
|
63287
62984
|
const registeredKeys = new Set;
|
|
63288
62985
|
try {
|
|
@@ -63349,8 +63046,8 @@ function getBinaryReadinessAdvisory() {
|
|
|
63349
63046
|
}
|
|
63350
63047
|
function runToolDoctor(_directory, pluginRoot) {
|
|
63351
63048
|
const findings = [];
|
|
63352
|
-
const resolvedPluginRoot = pluginRoot ??
|
|
63353
|
-
const indexPath =
|
|
63049
|
+
const resolvedPluginRoot = pluginRoot ?? path31.resolve(import.meta.dir, "..", "..");
|
|
63050
|
+
const indexPath = path31.join(resolvedPluginRoot, "src", "index.ts");
|
|
63354
63051
|
if (!fs16.existsSync(indexPath)) {
|
|
63355
63052
|
return {
|
|
63356
63053
|
findings: [
|
|
@@ -64096,12 +63793,12 @@ var init_export = __esm(() => {
|
|
|
64096
63793
|
|
|
64097
63794
|
// src/full-auto/state.ts
|
|
64098
63795
|
import * as fs17 from "node:fs";
|
|
64099
|
-
import * as
|
|
63796
|
+
import * as path32 from "node:path";
|
|
64100
63797
|
function nowISO() {
|
|
64101
63798
|
return new Date().toISOString();
|
|
64102
63799
|
}
|
|
64103
63800
|
function ensureSwarmDir(directory) {
|
|
64104
|
-
const swarmDir =
|
|
63801
|
+
const swarmDir = path32.resolve(directory, ".swarm");
|
|
64105
63802
|
if (!fs17.existsSync(swarmDir)) {
|
|
64106
63803
|
fs17.mkdirSync(swarmDir, { recursive: true });
|
|
64107
63804
|
}
|
|
@@ -64916,7 +64613,7 @@ var init_handoff_service = __esm(() => {
|
|
|
64916
64613
|
|
|
64917
64614
|
// src/session/snapshot-writer.ts
|
|
64918
64615
|
import { closeSync as closeSync3, fsyncSync as fsyncSync2, mkdirSync as mkdirSync13, openSync as openSync3, renameSync as renameSync9 } from "node:fs";
|
|
64919
|
-
import * as
|
|
64616
|
+
import * as path33 from "node:path";
|
|
64920
64617
|
function serializeAgentSession(s) {
|
|
64921
64618
|
const gateLog = {};
|
|
64922
64619
|
const rawGateLog = s.gateLog ?? new Map;
|
|
@@ -65013,7 +64710,7 @@ async function writeSnapshot(directory, state) {
|
|
|
65013
64710
|
}
|
|
65014
64711
|
const content = JSON.stringify(snapshot, null, 2);
|
|
65015
64712
|
const resolvedPath = validateSwarmPath(directory, "session/state.json");
|
|
65016
|
-
const dir =
|
|
64713
|
+
const dir = path33.dirname(resolvedPath);
|
|
65017
64714
|
mkdirSync13(dir, { recursive: true });
|
|
65018
64715
|
const tempPath = `${resolvedPath}.tmp.${Date.now()}.${Math.random().toString(36).slice(2)}`;
|
|
65019
64716
|
await bunWrite(tempPath, content);
|
|
@@ -65470,9 +65167,9 @@ var init_issue = __esm(() => {
|
|
|
65470
65167
|
|
|
65471
65168
|
// src/hooks/knowledge-migrator.ts
|
|
65472
65169
|
import { randomUUID as randomUUID3 } from "node:crypto";
|
|
65473
|
-
import { existsSync as
|
|
65474
|
-
import { mkdir as
|
|
65475
|
-
import * as
|
|
65170
|
+
import { existsSync as existsSync20, readFileSync as readFileSync13 } from "node:fs";
|
|
65171
|
+
import { mkdir as mkdir8, readFile as readFile9, writeFile as writeFile8 } from "node:fs/promises";
|
|
65172
|
+
import * as path34 from "node:path";
|
|
65476
65173
|
async function migrateKnowledgeToExternal(_directory, _config) {
|
|
65477
65174
|
return {
|
|
65478
65175
|
migrated: false,
|
|
@@ -65483,10 +65180,10 @@ async function migrateKnowledgeToExternal(_directory, _config) {
|
|
|
65483
65180
|
};
|
|
65484
65181
|
}
|
|
65485
65182
|
async function migrateContextToKnowledge(directory, config3) {
|
|
65486
|
-
const sentinelPath =
|
|
65487
|
-
const contextPath =
|
|
65183
|
+
const sentinelPath = path34.join(directory, ".swarm", ".knowledge-migrated");
|
|
65184
|
+
const contextPath = path34.join(directory, ".swarm", "context.md");
|
|
65488
65185
|
const knowledgePath = resolveSwarmKnowledgePath(directory);
|
|
65489
|
-
if (
|
|
65186
|
+
if (existsSync20(sentinelPath)) {
|
|
65490
65187
|
return {
|
|
65491
65188
|
migrated: false,
|
|
65492
65189
|
entriesMigrated: 0,
|
|
@@ -65495,7 +65192,7 @@ async function migrateContextToKnowledge(directory, config3) {
|
|
|
65495
65192
|
skippedReason: "sentinel-exists"
|
|
65496
65193
|
};
|
|
65497
65194
|
}
|
|
65498
|
-
if (!
|
|
65195
|
+
if (!existsSync20(contextPath)) {
|
|
65499
65196
|
return {
|
|
65500
65197
|
migrated: false,
|
|
65501
65198
|
entriesMigrated: 0,
|
|
@@ -65504,7 +65201,7 @@ async function migrateContextToKnowledge(directory, config3) {
|
|
|
65504
65201
|
skippedReason: "no-context-file"
|
|
65505
65202
|
};
|
|
65506
65203
|
}
|
|
65507
|
-
const contextContent = await
|
|
65204
|
+
const contextContent = await readFile9(contextPath, "utf-8");
|
|
65508
65205
|
if (contextContent.trim().length === 0) {
|
|
65509
65206
|
return {
|
|
65510
65207
|
migrated: false,
|
|
@@ -65680,8 +65377,8 @@ function truncateLesson(text) {
|
|
|
65680
65377
|
return `${text.slice(0, 277)}...`;
|
|
65681
65378
|
}
|
|
65682
65379
|
function inferProjectName(directory) {
|
|
65683
|
-
const packageJsonPath =
|
|
65684
|
-
if (
|
|
65380
|
+
const packageJsonPath = path34.join(directory, "package.json");
|
|
65381
|
+
if (existsSync20(packageJsonPath)) {
|
|
65685
65382
|
try {
|
|
65686
65383
|
const pkg = JSON.parse(readFileSync13(packageJsonPath, "utf-8"));
|
|
65687
65384
|
if (pkg.name && typeof pkg.name === "string") {
|
|
@@ -65689,7 +65386,7 @@ function inferProjectName(directory) {
|
|
|
65689
65386
|
}
|
|
65690
65387
|
} catch {}
|
|
65691
65388
|
}
|
|
65692
|
-
return
|
|
65389
|
+
return path34.basename(directory);
|
|
65693
65390
|
}
|
|
65694
65391
|
async function writeSentinel(sentinelPath, migrated, dropped) {
|
|
65695
65392
|
const sentinel = {
|
|
@@ -65701,8 +65398,8 @@ async function writeSentinel(sentinelPath, migrated, dropped) {
|
|
|
65701
65398
|
schema_version: 1,
|
|
65702
65399
|
migration_tool: "knowledge-migrator.ts"
|
|
65703
65400
|
};
|
|
65704
|
-
await
|
|
65705
|
-
await
|
|
65401
|
+
await mkdir8(path34.dirname(sentinelPath), { recursive: true });
|
|
65402
|
+
await writeFile8(sentinelPath, JSON.stringify(sentinel, null, 2), "utf-8");
|
|
65706
65403
|
}
|
|
65707
65404
|
var _internals23;
|
|
65708
65405
|
var init_knowledge_migrator = __esm(() => {
|
|
@@ -65723,7 +65420,7 @@ var init_knowledge_migrator = __esm(() => {
|
|
|
65723
65420
|
});
|
|
65724
65421
|
|
|
65725
65422
|
// src/commands/knowledge.ts
|
|
65726
|
-
import { join as
|
|
65423
|
+
import { join as join31 } from "node:path";
|
|
65727
65424
|
function resolveEntryByPrefix(entries, inputId) {
|
|
65728
65425
|
const exact = entries.find((e) => e.id === inputId);
|
|
65729
65426
|
if (exact)
|
|
@@ -65774,7 +65471,7 @@ async function handleKnowledgeRestoreCommand(directory, args2) {
|
|
|
65774
65471
|
return "Invalid entry ID. IDs must be 1-64 characters: letters, digits, hyphens, underscores only.";
|
|
65775
65472
|
}
|
|
65776
65473
|
try {
|
|
65777
|
-
const quarantinePath =
|
|
65474
|
+
const quarantinePath = join31(directory, ".swarm", "knowledge-quarantined.jsonl");
|
|
65778
65475
|
const entries = await readKnowledge(quarantinePath);
|
|
65779
65476
|
const resolved = resolveEntryByPrefix(entries, inputId);
|
|
65780
65477
|
if ("error" in resolved) {
|
|
@@ -66198,7 +65895,7 @@ var init_pr_review = __esm(() => {
|
|
|
66198
65895
|
|
|
66199
65896
|
// src/utils/path-security.ts
|
|
66200
65897
|
import * as fs18 from "node:fs";
|
|
66201
|
-
import * as
|
|
65898
|
+
import * as path35 from "node:path";
|
|
66202
65899
|
function containsPathTraversal(str) {
|
|
66203
65900
|
if (/\.\.[/\\]/.test(str))
|
|
66204
65901
|
return true;
|
|
@@ -66249,17 +65946,17 @@ function validateSymlinkBoundary(targetPath, rootPath) {
|
|
|
66249
65946
|
try {
|
|
66250
65947
|
realTarget = fs18.realpathSync(targetPath);
|
|
66251
65948
|
} catch {
|
|
66252
|
-
realTarget =
|
|
65949
|
+
realTarget = path35.normalize(targetPath);
|
|
66253
65950
|
}
|
|
66254
65951
|
let realRoot;
|
|
66255
65952
|
try {
|
|
66256
65953
|
realRoot = fs18.realpathSync(rootPath);
|
|
66257
65954
|
} catch {
|
|
66258
|
-
realRoot =
|
|
65955
|
+
realRoot = path35.normalize(rootPath);
|
|
66259
65956
|
}
|
|
66260
|
-
const normalizedTarget =
|
|
66261
|
-
const normalizedRoot =
|
|
66262
|
-
if (!normalizedTarget.startsWith(normalizedRoot +
|
|
65957
|
+
const normalizedTarget = path35.normalize(realTarget);
|
|
65958
|
+
const normalizedRoot = path35.normalize(realRoot);
|
|
65959
|
+
if (!normalizedTarget.startsWith(normalizedRoot + path35.sep) && normalizedTarget !== normalizedRoot) {
|
|
66263
65960
|
throw new Error(`Symlink resolution escaped boundary: ${realTarget} is not within ${realRoot}`);
|
|
66264
65961
|
}
|
|
66265
65962
|
}
|
|
@@ -66267,7 +65964,7 @@ var init_path_security = () => {};
|
|
|
66267
65964
|
|
|
66268
65965
|
// src/tools/lint.ts
|
|
66269
65966
|
import * as fs19 from "node:fs";
|
|
66270
|
-
import * as
|
|
65967
|
+
import * as path36 from "node:path";
|
|
66271
65968
|
function validateArgs(args2) {
|
|
66272
65969
|
if (typeof args2 !== "object" || args2 === null)
|
|
66273
65970
|
return false;
|
|
@@ -66278,9 +65975,9 @@ function validateArgs(args2) {
|
|
|
66278
65975
|
}
|
|
66279
65976
|
function getLinterCommand(linter, mode, projectDir) {
|
|
66280
65977
|
const isWindows = process.platform === "win32";
|
|
66281
|
-
const binDir =
|
|
66282
|
-
const biomeBin = isWindows ?
|
|
66283
|
-
const eslintBin = isWindows ?
|
|
65978
|
+
const binDir = path36.join(projectDir, "node_modules", ".bin");
|
|
65979
|
+
const biomeBin = isWindows ? path36.join(binDir, "biome.EXE") : path36.join(binDir, "biome");
|
|
65980
|
+
const eslintBin = isWindows ? path36.join(binDir, "eslint.cmd") : path36.join(binDir, "eslint");
|
|
66284
65981
|
switch (linter) {
|
|
66285
65982
|
case "biome":
|
|
66286
65983
|
if (mode === "fix") {
|
|
@@ -66296,7 +65993,7 @@ function getLinterCommand(linter, mode, projectDir) {
|
|
|
66296
65993
|
}
|
|
66297
65994
|
function getAdditionalLinterCommand(linter, mode, cwd) {
|
|
66298
65995
|
const gradlewName = process.platform === "win32" ? "gradlew.bat" : "gradlew";
|
|
66299
|
-
const gradlew = fs19.existsSync(
|
|
65996
|
+
const gradlew = fs19.existsSync(path36.join(cwd, gradlewName)) ? path36.join(cwd, gradlewName) : null;
|
|
66300
65997
|
switch (linter) {
|
|
66301
65998
|
case "ruff":
|
|
66302
65999
|
return mode === "fix" ? ["ruff", "check", "--fix", "."] : ["ruff", "check", "."];
|
|
@@ -66330,10 +66027,10 @@ function getAdditionalLinterCommand(linter, mode, cwd) {
|
|
|
66330
66027
|
}
|
|
66331
66028
|
}
|
|
66332
66029
|
function detectRuff(cwd) {
|
|
66333
|
-
if (fs19.existsSync(
|
|
66030
|
+
if (fs19.existsSync(path36.join(cwd, "ruff.toml")))
|
|
66334
66031
|
return isCommandAvailable("ruff");
|
|
66335
66032
|
try {
|
|
66336
|
-
const pyproject =
|
|
66033
|
+
const pyproject = path36.join(cwd, "pyproject.toml");
|
|
66337
66034
|
if (fs19.existsSync(pyproject)) {
|
|
66338
66035
|
const content = fs19.readFileSync(pyproject, "utf-8");
|
|
66339
66036
|
if (content.includes("[tool.ruff]"))
|
|
@@ -66343,19 +66040,19 @@ function detectRuff(cwd) {
|
|
|
66343
66040
|
return false;
|
|
66344
66041
|
}
|
|
66345
66042
|
function detectClippy(cwd) {
|
|
66346
|
-
return fs19.existsSync(
|
|
66043
|
+
return fs19.existsSync(path36.join(cwd, "Cargo.toml")) && isCommandAvailable("cargo");
|
|
66347
66044
|
}
|
|
66348
66045
|
function detectGolangciLint(cwd) {
|
|
66349
|
-
return fs19.existsSync(
|
|
66046
|
+
return fs19.existsSync(path36.join(cwd, "go.mod")) && isCommandAvailable("golangci-lint");
|
|
66350
66047
|
}
|
|
66351
66048
|
function detectCheckstyle(cwd) {
|
|
66352
|
-
const hasMaven = fs19.existsSync(
|
|
66353
|
-
const hasGradle = fs19.existsSync(
|
|
66354
|
-
const hasBinary = hasMaven && isCommandAvailable("mvn") || hasGradle && (fs19.existsSync(
|
|
66049
|
+
const hasMaven = fs19.existsSync(path36.join(cwd, "pom.xml"));
|
|
66050
|
+
const hasGradle = fs19.existsSync(path36.join(cwd, "build.gradle")) || fs19.existsSync(path36.join(cwd, "build.gradle.kts"));
|
|
66051
|
+
const hasBinary = hasMaven && isCommandAvailable("mvn") || hasGradle && (fs19.existsSync(path36.join(cwd, "gradlew")) || isCommandAvailable("gradle"));
|
|
66355
66052
|
return (hasMaven || hasGradle) && hasBinary;
|
|
66356
66053
|
}
|
|
66357
66054
|
function detectKtlint(cwd) {
|
|
66358
|
-
const hasKotlin = fs19.existsSync(
|
|
66055
|
+
const hasKotlin = fs19.existsSync(path36.join(cwd, "build.gradle.kts")) || fs19.existsSync(path36.join(cwd, "build.gradle")) || (() => {
|
|
66359
66056
|
try {
|
|
66360
66057
|
return fs19.readdirSync(cwd).some((f) => f.endsWith(".kt") || f.endsWith(".kts"));
|
|
66361
66058
|
} catch {
|
|
@@ -66374,11 +66071,11 @@ function detectDotnetFormat(cwd) {
|
|
|
66374
66071
|
}
|
|
66375
66072
|
}
|
|
66376
66073
|
function detectCppcheck(cwd) {
|
|
66377
|
-
if (fs19.existsSync(
|
|
66074
|
+
if (fs19.existsSync(path36.join(cwd, "CMakeLists.txt"))) {
|
|
66378
66075
|
return isCommandAvailable("cppcheck");
|
|
66379
66076
|
}
|
|
66380
66077
|
try {
|
|
66381
|
-
const dirsToCheck = [cwd,
|
|
66078
|
+
const dirsToCheck = [cwd, path36.join(cwd, "src")];
|
|
66382
66079
|
const hasCpp = dirsToCheck.some((dir) => {
|
|
66383
66080
|
try {
|
|
66384
66081
|
return fs19.readdirSync(dir).some((f) => /\.(c|cpp|cc|cxx|h|hpp)$/.test(f));
|
|
@@ -66392,13 +66089,13 @@ function detectCppcheck(cwd) {
|
|
|
66392
66089
|
}
|
|
66393
66090
|
}
|
|
66394
66091
|
function detectSwiftlint(cwd) {
|
|
66395
|
-
return fs19.existsSync(
|
|
66092
|
+
return fs19.existsSync(path36.join(cwd, "Package.swift")) && isCommandAvailable("swiftlint");
|
|
66396
66093
|
}
|
|
66397
66094
|
function detectDartAnalyze(cwd) {
|
|
66398
|
-
return fs19.existsSync(
|
|
66095
|
+
return fs19.existsSync(path36.join(cwd, "pubspec.yaml")) && (isCommandAvailable("dart") || isCommandAvailable("flutter"));
|
|
66399
66096
|
}
|
|
66400
66097
|
function detectRubocop(cwd) {
|
|
66401
|
-
return (fs19.existsSync(
|
|
66098
|
+
return (fs19.existsSync(path36.join(cwd, "Gemfile")) || fs19.existsSync(path36.join(cwd, "gems.rb")) || fs19.existsSync(path36.join(cwd, ".rubocop.yml"))) && (isCommandAvailable("rubocop") || isCommandAvailable("bundle"));
|
|
66402
66099
|
}
|
|
66403
66100
|
function detectAdditionalLinter(cwd) {
|
|
66404
66101
|
if (detectRuff(cwd))
|
|
@@ -66426,10 +66123,10 @@ function detectAdditionalLinter(cwd) {
|
|
|
66426
66123
|
function resolveLinterBinPath(linter, projectDir) {
|
|
66427
66124
|
const isWindows = process.platform === "win32";
|
|
66428
66125
|
const binName = linter === "biome" ? isWindows ? "biome.EXE" : "biome" : isWindows ? "eslint.cmd" : "eslint";
|
|
66429
|
-
const localBin =
|
|
66126
|
+
const localBin = path36.join(projectDir, "node_modules", ".bin", binName);
|
|
66430
66127
|
if (fs19.existsSync(localBin))
|
|
66431
66128
|
return localBin;
|
|
66432
|
-
const ancestor = findBinInAncestors(
|
|
66129
|
+
const ancestor = findBinInAncestors(path36.dirname(projectDir), binName);
|
|
66433
66130
|
if (ancestor)
|
|
66434
66131
|
return ancestor;
|
|
66435
66132
|
const fromPath = findBinInEnvPath(binName);
|
|
@@ -66440,10 +66137,10 @@ function resolveLinterBinPath(linter, projectDir) {
|
|
|
66440
66137
|
function findBinInAncestors(startDir, binName) {
|
|
66441
66138
|
let dir = startDir;
|
|
66442
66139
|
while (true) {
|
|
66443
|
-
const candidate =
|
|
66140
|
+
const candidate = path36.join(dir, "node_modules", ".bin", binName);
|
|
66444
66141
|
if (fs19.existsSync(candidate))
|
|
66445
66142
|
return candidate;
|
|
66446
|
-
const parent =
|
|
66143
|
+
const parent = path36.dirname(dir);
|
|
66447
66144
|
if (parent === dir)
|
|
66448
66145
|
break;
|
|
66449
66146
|
dir = parent;
|
|
@@ -66452,10 +66149,10 @@ function findBinInAncestors(startDir, binName) {
|
|
|
66452
66149
|
}
|
|
66453
66150
|
function findBinInEnvPath(binName) {
|
|
66454
66151
|
const searchPath = process.env.PATH ?? "";
|
|
66455
|
-
for (const dir of searchPath.split(
|
|
66152
|
+
for (const dir of searchPath.split(path36.delimiter)) {
|
|
66456
66153
|
if (!dir)
|
|
66457
66154
|
continue;
|
|
66458
|
-
const candidate =
|
|
66155
|
+
const candidate = path36.join(dir, binName);
|
|
66459
66156
|
if (fs19.existsSync(candidate))
|
|
66460
66157
|
return candidate;
|
|
66461
66158
|
}
|
|
@@ -66468,13 +66165,13 @@ async function detectAvailableLinter(directory) {
|
|
|
66468
66165
|
return null;
|
|
66469
66166
|
const projectDir = directory;
|
|
66470
66167
|
const isWindows = process.platform === "win32";
|
|
66471
|
-
const biomeBin = isWindows ?
|
|
66472
|
-
const eslintBin = isWindows ?
|
|
66168
|
+
const biomeBin = isWindows ? path36.join(projectDir, "node_modules", ".bin", "biome.EXE") : path36.join(projectDir, "node_modules", ".bin", "biome");
|
|
66169
|
+
const eslintBin = isWindows ? path36.join(projectDir, "node_modules", ".bin", "eslint.cmd") : path36.join(projectDir, "node_modules", ".bin", "eslint");
|
|
66473
66170
|
const localResult = await _detectAvailableLinter(projectDir, biomeBin, eslintBin);
|
|
66474
66171
|
if (localResult)
|
|
66475
66172
|
return localResult;
|
|
66476
|
-
const biomeAncestor = findBinInAncestors(
|
|
66477
|
-
const eslintAncestor = findBinInAncestors(
|
|
66173
|
+
const biomeAncestor = findBinInAncestors(path36.dirname(projectDir), isWindows ? "biome.EXE" : "biome");
|
|
66174
|
+
const eslintAncestor = findBinInAncestors(path36.dirname(projectDir), isWindows ? "eslint.cmd" : "eslint");
|
|
66478
66175
|
if (biomeAncestor || eslintAncestor) {
|
|
66479
66176
|
return _detectAvailableLinter(projectDir, biomeAncestor ?? biomeBin, eslintAncestor ?? eslintBin);
|
|
66480
66177
|
}
|
|
@@ -66697,7 +66394,7 @@ For Rust: rustup component add clippy`
|
|
|
66697
66394
|
|
|
66698
66395
|
// src/tools/secretscan.ts
|
|
66699
66396
|
import * as fs20 from "node:fs";
|
|
66700
|
-
import * as
|
|
66397
|
+
import * as path37 from "node:path";
|
|
66701
66398
|
function calculateShannonEntropy(str) {
|
|
66702
66399
|
if (str.length === 0)
|
|
66703
66400
|
return 0;
|
|
@@ -66745,7 +66442,7 @@ function isGlobOrPathPattern(pattern) {
|
|
|
66745
66442
|
return pattern.includes("/") || pattern.includes("\\") || /[*?[\]{}]/.test(pattern);
|
|
66746
66443
|
}
|
|
66747
66444
|
function loadSecretScanIgnore(scanDir) {
|
|
66748
|
-
const ignorePath =
|
|
66445
|
+
const ignorePath = path37.join(scanDir, ".secretscanignore");
|
|
66749
66446
|
try {
|
|
66750
66447
|
if (!fs20.existsSync(ignorePath))
|
|
66751
66448
|
return [];
|
|
@@ -66768,7 +66465,7 @@ function isExcluded(entry, relPath, exactNames, globPatterns) {
|
|
|
66768
66465
|
if (exactNames.has(entry))
|
|
66769
66466
|
return true;
|
|
66770
66467
|
for (const pattern of globPatterns) {
|
|
66771
|
-
if (
|
|
66468
|
+
if (path37.matchesGlob(relPath, pattern))
|
|
66772
66469
|
return true;
|
|
66773
66470
|
}
|
|
66774
66471
|
return false;
|
|
@@ -66789,7 +66486,7 @@ function validateDirectoryInput(dir) {
|
|
|
66789
66486
|
return null;
|
|
66790
66487
|
}
|
|
66791
66488
|
function isBinaryFile(filePath, buffer) {
|
|
66792
|
-
const ext =
|
|
66489
|
+
const ext = path37.extname(filePath).toLowerCase();
|
|
66793
66490
|
if (DEFAULT_EXCLUDE_EXTENSIONS.has(ext)) {
|
|
66794
66491
|
return true;
|
|
66795
66492
|
}
|
|
@@ -66925,9 +66622,9 @@ function isSymlinkLoop(realPath, visited) {
|
|
|
66925
66622
|
return false;
|
|
66926
66623
|
}
|
|
66927
66624
|
function isPathWithinScope(realPath, scanDir) {
|
|
66928
|
-
const resolvedScanDir =
|
|
66929
|
-
const resolvedRealPath =
|
|
66930
|
-
return resolvedRealPath === resolvedScanDir || resolvedRealPath.startsWith(resolvedScanDir +
|
|
66625
|
+
const resolvedScanDir = path37.resolve(scanDir);
|
|
66626
|
+
const resolvedRealPath = path37.resolve(realPath);
|
|
66627
|
+
return resolvedRealPath === resolvedScanDir || resolvedRealPath.startsWith(resolvedScanDir + path37.sep) || resolvedRealPath.startsWith(`${resolvedScanDir}/`) || resolvedRealPath.startsWith(`${resolvedScanDir}\\`);
|
|
66931
66628
|
}
|
|
66932
66629
|
function findScannableFiles(dir, excludeExact, excludeGlobs, scanDir, visited, stats = {
|
|
66933
66630
|
skippedDirs: 0,
|
|
@@ -66953,8 +66650,8 @@ function findScannableFiles(dir, excludeExact, excludeGlobs, scanDir, visited, s
|
|
|
66953
66650
|
return a.localeCompare(b);
|
|
66954
66651
|
});
|
|
66955
66652
|
for (const entry of entries) {
|
|
66956
|
-
const fullPath =
|
|
66957
|
-
const relPath =
|
|
66653
|
+
const fullPath = path37.join(dir, entry);
|
|
66654
|
+
const relPath = path37.relative(scanDir, fullPath).replace(/\\/g, "/");
|
|
66958
66655
|
if (isExcluded(entry, relPath, excludeExact, excludeGlobs)) {
|
|
66959
66656
|
stats.skippedDirs++;
|
|
66960
66657
|
continue;
|
|
@@ -66989,7 +66686,7 @@ function findScannableFiles(dir, excludeExact, excludeGlobs, scanDir, visited, s
|
|
|
66989
66686
|
const subFiles = findScannableFiles(fullPath, excludeExact, excludeGlobs, scanDir, visited, stats);
|
|
66990
66687
|
files.push(...subFiles);
|
|
66991
66688
|
} else if (lstat.isFile()) {
|
|
66992
|
-
const ext =
|
|
66689
|
+
const ext = path37.extname(fullPath).toLowerCase();
|
|
66993
66690
|
if (!DEFAULT_EXCLUDE_EXTENSIONS.has(ext)) {
|
|
66994
66691
|
files.push(fullPath);
|
|
66995
66692
|
} else {
|
|
@@ -67249,7 +66946,7 @@ var init_secretscan = __esm(() => {
|
|
|
67249
66946
|
}
|
|
67250
66947
|
}
|
|
67251
66948
|
try {
|
|
67252
|
-
const _scanDirRaw =
|
|
66949
|
+
const _scanDirRaw = path37.resolve(directory);
|
|
67253
66950
|
const scanDir = (() => {
|
|
67254
66951
|
try {
|
|
67255
66952
|
return fs20.realpathSync(_scanDirRaw);
|
|
@@ -67396,7 +67093,7 @@ var init_secretscan = __esm(() => {
|
|
|
67396
67093
|
|
|
67397
67094
|
// src/lang/default-backend.ts
|
|
67398
67095
|
import * as fs21 from "node:fs";
|
|
67399
|
-
import * as
|
|
67096
|
+
import * as path38 from "node:path";
|
|
67400
67097
|
function detectFileExists(dir, pattern) {
|
|
67401
67098
|
if (pattern.includes("*") || pattern.includes("?")) {
|
|
67402
67099
|
try {
|
|
@@ -67408,7 +67105,7 @@ function detectFileExists(dir, pattern) {
|
|
|
67408
67105
|
}
|
|
67409
67106
|
}
|
|
67410
67107
|
try {
|
|
67411
|
-
fs21.accessSync(
|
|
67108
|
+
fs21.accessSync(path38.join(dir, pattern));
|
|
67412
67109
|
return true;
|
|
67413
67110
|
} catch {
|
|
67414
67111
|
return false;
|
|
@@ -67536,8 +67233,8 @@ function defaultBuildTestCommand(profile, framework, files, dir = ".", opts = {}
|
|
|
67536
67233
|
return ["mvn", "test"];
|
|
67537
67234
|
case "gradle": {
|
|
67538
67235
|
const isWindows = process.platform === "win32";
|
|
67539
|
-
const hasGradlewBat = fs21.existsSync(
|
|
67540
|
-
const hasGradlew = fs21.existsSync(
|
|
67236
|
+
const hasGradlewBat = fs21.existsSync(path38.join(dir, "gradlew.bat"));
|
|
67237
|
+
const hasGradlew = fs21.existsSync(path38.join(dir, "gradlew"));
|
|
67541
67238
|
if (hasGradlewBat && isWindows)
|
|
67542
67239
|
return ["gradlew.bat", "test"];
|
|
67543
67240
|
if (hasGradlew)
|
|
@@ -67554,7 +67251,7 @@ function defaultBuildTestCommand(profile, framework, files, dir = ".", opts = {}
|
|
|
67554
67251
|
"cmake-build-release",
|
|
67555
67252
|
"out"
|
|
67556
67253
|
];
|
|
67557
|
-
const actualBuildDir = buildDirCandidates.find((d) => fs21.existsSync(
|
|
67254
|
+
const actualBuildDir = buildDirCandidates.find((d) => fs21.existsSync(path38.join(dir, d, "CMakeCache.txt"))) ?? "build";
|
|
67558
67255
|
return ["ctest", "--test-dir", actualBuildDir];
|
|
67559
67256
|
}
|
|
67560
67257
|
case "swift-test":
|
|
@@ -67841,17 +67538,17 @@ async function defaultSelectBuildCommand(profile, dir) {
|
|
|
67841
67538
|
return null;
|
|
67842
67539
|
}
|
|
67843
67540
|
async function defaultTestFilesFor(profile, sourceFile, dir) {
|
|
67844
|
-
const ext =
|
|
67541
|
+
const ext = path38.extname(sourceFile);
|
|
67845
67542
|
if (!profile.extensions.includes(ext))
|
|
67846
67543
|
return [];
|
|
67847
|
-
const base =
|
|
67848
|
-
const rel =
|
|
67849
|
-
const relDir =
|
|
67544
|
+
const base = path38.basename(sourceFile, ext);
|
|
67545
|
+
const rel = path38.relative(dir, sourceFile);
|
|
67546
|
+
const relDir = path38.dirname(rel);
|
|
67850
67547
|
const stripSrc = relDir.replace(/^src(\/|\\)/, "");
|
|
67851
67548
|
const candidates = new Set;
|
|
67852
67549
|
for (const tDir of ["tests", "test", "__tests__", "spec"]) {
|
|
67853
67550
|
for (const suffix of ["", "_test", ".test", "_spec", ".spec"]) {
|
|
67854
|
-
candidates.add(
|
|
67551
|
+
candidates.add(path38.join(dir, tDir, stripSrc, `${base}${suffix}${ext}`));
|
|
67855
67552
|
}
|
|
67856
67553
|
}
|
|
67857
67554
|
const existing = [];
|
|
@@ -67892,7 +67589,7 @@ var init_default_backend = __esm(() => {
|
|
|
67892
67589
|
|
|
67893
67590
|
// src/lang/backends/go.ts
|
|
67894
67591
|
import * as fs22 from "node:fs";
|
|
67895
|
-
import * as
|
|
67592
|
+
import * as path39 from "node:path";
|
|
67896
67593
|
function extractImports(_sourceFile, source) {
|
|
67897
67594
|
const out2 = new Set;
|
|
67898
67595
|
IMPORT_REGEX_SINGLE.lastIndex = 0;
|
|
@@ -67918,7 +67615,7 @@ function extractImports(_sourceFile, source) {
|
|
|
67918
67615
|
async function selectFramework(dir) {
|
|
67919
67616
|
let content;
|
|
67920
67617
|
try {
|
|
67921
|
-
content = fs22.readFileSync(
|
|
67618
|
+
content = fs22.readFileSync(path39.join(dir, "go.mod"), "utf-8");
|
|
67922
67619
|
} catch {
|
|
67923
67620
|
return null;
|
|
67924
67621
|
}
|
|
@@ -67939,16 +67636,16 @@ async function selectFramework(dir) {
|
|
|
67939
67636
|
async function selectEntryPoints(dir) {
|
|
67940
67637
|
const points = [];
|
|
67941
67638
|
try {
|
|
67942
|
-
fs22.accessSync(
|
|
67639
|
+
fs22.accessSync(path39.join(dir, "main.go"));
|
|
67943
67640
|
points.push("main.go");
|
|
67944
67641
|
} catch {}
|
|
67945
67642
|
try {
|
|
67946
|
-
const cmdDir =
|
|
67643
|
+
const cmdDir = path39.join(dir, "cmd");
|
|
67947
67644
|
const subdirs = fs22.readdirSync(cmdDir, { withFileTypes: true }).filter((d) => d.isDirectory());
|
|
67948
67645
|
for (const sub of subdirs) {
|
|
67949
|
-
const main =
|
|
67646
|
+
const main = path39.join("cmd", sub.name, "main.go");
|
|
67950
67647
|
try {
|
|
67951
|
-
fs22.accessSync(
|
|
67648
|
+
fs22.accessSync(path39.join(dir, main));
|
|
67952
67649
|
points.push(main);
|
|
67953
67650
|
} catch {}
|
|
67954
67651
|
}
|
|
@@ -67979,7 +67676,7 @@ var init_go = __esm(() => {
|
|
|
67979
67676
|
|
|
67980
67677
|
// src/lang/backends/python.ts
|
|
67981
67678
|
import * as fs23 from "node:fs";
|
|
67982
|
-
import * as
|
|
67679
|
+
import * as path40 from "node:path";
|
|
67983
67680
|
function parseImportTargets(rawTargets) {
|
|
67984
67681
|
const cleaned = rawTargets.replace(/[()]/g, "").split(`
|
|
67985
67682
|
`).map((line) => line.replace(/#.*$/, "").replace(/\\\s*$/, "")).join(" ");
|
|
@@ -68039,7 +67736,7 @@ async function selectFramework2(dir) {
|
|
|
68039
67736
|
];
|
|
68040
67737
|
for (const candidate of ["pyproject.toml", "requirements.txt", "setup.py"]) {
|
|
68041
67738
|
try {
|
|
68042
|
-
const content = fs23.readFileSync(
|
|
67739
|
+
const content = fs23.readFileSync(path40.join(dir, candidate), "utf-8");
|
|
68043
67740
|
const lower = content.toLowerCase();
|
|
68044
67741
|
for (const [pkg, name2] of candidates) {
|
|
68045
67742
|
if (lower.includes(pkg)) {
|
|
@@ -68053,7 +67750,7 @@ async function selectFramework2(dir) {
|
|
|
68053
67750
|
async function selectEntryPoints2(dir) {
|
|
68054
67751
|
const points = new Set;
|
|
68055
67752
|
try {
|
|
68056
|
-
const content = fs23.readFileSync(
|
|
67753
|
+
const content = fs23.readFileSync(path40.join(dir, "pyproject.toml"), "utf-8");
|
|
68057
67754
|
const scriptsBlock = content.match(/\[project\.scripts\][\s\S]*?(?=\n\[|$)/);
|
|
68058
67755
|
if (scriptsBlock) {
|
|
68059
67756
|
for (const line of scriptsBlock[0].split(`
|
|
@@ -68068,7 +67765,7 @@ async function selectEntryPoints2(dir) {
|
|
|
68068
67765
|
} catch {}
|
|
68069
67766
|
for (const name2 of ["manage.py", "main.py", "app.py", "__main__.py"]) {
|
|
68070
67767
|
try {
|
|
68071
|
-
fs23.accessSync(
|
|
67768
|
+
fs23.accessSync(path40.join(dir, name2));
|
|
68072
67769
|
points.add(name2);
|
|
68073
67770
|
} catch {}
|
|
68074
67771
|
}
|
|
@@ -68097,7 +67794,7 @@ var init_python = __esm(() => {
|
|
|
68097
67794
|
|
|
68098
67795
|
// src/test-impact/analyzer.ts
|
|
68099
67796
|
import fs24 from "node:fs";
|
|
68100
|
-
import
|
|
67797
|
+
import path41 from "node:path";
|
|
68101
67798
|
function normalizePath(p) {
|
|
68102
67799
|
return p.replace(/\\/g, "/");
|
|
68103
67800
|
}
|
|
@@ -68118,8 +67815,8 @@ function resolveRelativeImport(fromDir, importPath) {
|
|
|
68118
67815
|
if (!importPath.startsWith(".")) {
|
|
68119
67816
|
return null;
|
|
68120
67817
|
}
|
|
68121
|
-
const resolved =
|
|
68122
|
-
if (
|
|
67818
|
+
const resolved = path41.resolve(fromDir, importPath);
|
|
67819
|
+
if (path41.extname(resolved)) {
|
|
68123
67820
|
if (fs24.existsSync(resolved) && fs24.statSync(resolved).isFile()) {
|
|
68124
67821
|
return normalizePath(resolved);
|
|
68125
67822
|
}
|
|
@@ -68139,20 +67836,20 @@ function resolvePythonImport(fromDir, module2) {
|
|
|
68139
67836
|
const leadingDots = module2.match(/^\.+/)?.[0].length ?? 0;
|
|
68140
67837
|
let baseDir = fromDir;
|
|
68141
67838
|
for (let i2 = 1;i2 < leadingDots; i2++) {
|
|
68142
|
-
baseDir =
|
|
67839
|
+
baseDir = path41.dirname(baseDir);
|
|
68143
67840
|
}
|
|
68144
67841
|
const rest = module2.slice(leadingDots);
|
|
68145
67842
|
if (rest.length === 0) {
|
|
68146
|
-
const initPath =
|
|
67843
|
+
const initPath = path41.join(baseDir, "__init__.py");
|
|
68147
67844
|
if (fs24.existsSync(initPath) && fs24.statSync(initPath).isFile()) {
|
|
68148
67845
|
return normalizePath(initPath);
|
|
68149
67846
|
}
|
|
68150
67847
|
return null;
|
|
68151
67848
|
}
|
|
68152
|
-
const subpath = rest.replace(/\./g,
|
|
67849
|
+
const subpath = rest.replace(/\./g, path41.sep);
|
|
68153
67850
|
const candidates = [
|
|
68154
|
-
`${
|
|
68155
|
-
|
|
67851
|
+
`${path41.join(baseDir, subpath)}.py`,
|
|
67852
|
+
path41.join(baseDir, subpath, "__init__.py")
|
|
68156
67853
|
];
|
|
68157
67854
|
for (const c of candidates) {
|
|
68158
67855
|
if (fs24.existsSync(c) && fs24.statSync(c).isFile())
|
|
@@ -68161,7 +67858,7 @@ function resolvePythonImport(fromDir, module2) {
|
|
|
68161
67858
|
return null;
|
|
68162
67859
|
}
|
|
68163
67860
|
function findGoModule(fromDir) {
|
|
68164
|
-
const resolved =
|
|
67861
|
+
const resolved = path41.resolve(fromDir);
|
|
68165
67862
|
let cur = resolved;
|
|
68166
67863
|
const walked = [];
|
|
68167
67864
|
for (let i2 = 0;i2 < 16; i2++) {
|
|
@@ -68173,7 +67870,7 @@ function findGoModule(fromDir) {
|
|
|
68173
67870
|
}
|
|
68174
67871
|
walked.push(cur);
|
|
68175
67872
|
try {
|
|
68176
|
-
const goMod =
|
|
67873
|
+
const goMod = path41.join(cur, "go.mod");
|
|
68177
67874
|
const content = fs24.readFileSync(goMod, "utf-8");
|
|
68178
67875
|
const moduleMatch = content.match(/^\s*module\s+"?([^"\s/]+(?:\/[^"\s]+)*)"?/m);
|
|
68179
67876
|
if (moduleMatch) {
|
|
@@ -68184,10 +67881,10 @@ function findGoModule(fromDir) {
|
|
|
68184
67881
|
}
|
|
68185
67882
|
} catch {}
|
|
68186
67883
|
try {
|
|
68187
|
-
fs24.accessSync(
|
|
67884
|
+
fs24.accessSync(path41.join(cur, ".git"));
|
|
68188
67885
|
break;
|
|
68189
67886
|
} catch {}
|
|
68190
|
-
const parent =
|
|
67887
|
+
const parent = path41.dirname(cur);
|
|
68191
67888
|
if (parent === cur)
|
|
68192
67889
|
break;
|
|
68193
67890
|
cur = parent;
|
|
@@ -68199,12 +67896,12 @@ function findGoModule(fromDir) {
|
|
|
68199
67896
|
function resolveGoImport(fromDir, importPath) {
|
|
68200
67897
|
let dir = null;
|
|
68201
67898
|
if (importPath.startsWith(".")) {
|
|
68202
|
-
dir =
|
|
67899
|
+
dir = path41.resolve(fromDir, importPath);
|
|
68203
67900
|
} else {
|
|
68204
67901
|
const mod = findGoModule(fromDir);
|
|
68205
67902
|
if (mod && (importPath === mod.modulePath || importPath.startsWith(`${mod.modulePath}/`))) {
|
|
68206
67903
|
const subpath = importPath.slice(mod.modulePath.length);
|
|
68207
|
-
dir =
|
|
67904
|
+
dir = path41.join(mod.moduleRoot, subpath);
|
|
68208
67905
|
}
|
|
68209
67906
|
}
|
|
68210
67907
|
if (dir === null)
|
|
@@ -68212,7 +67909,7 @@ function resolveGoImport(fromDir, importPath) {
|
|
|
68212
67909
|
if (!fs24.existsSync(dir) || !fs24.statSync(dir).isDirectory())
|
|
68213
67910
|
return [];
|
|
68214
67911
|
try {
|
|
68215
|
-
return fs24.readdirSync(dir).filter((f) => f.endsWith(".go") && !f.endsWith("_test.go")).map((f) => normalizePath(
|
|
67912
|
+
return fs24.readdirSync(dir).filter((f) => f.endsWith(".go") && !f.endsWith("_test.go")).map((f) => normalizePath(path41.join(dir, f)));
|
|
68216
67913
|
} catch {
|
|
68217
67914
|
return [];
|
|
68218
67915
|
}
|
|
@@ -68251,15 +67948,15 @@ function findTestFilesSync(cwd) {
|
|
|
68251
67948
|
for (const entry of entries) {
|
|
68252
67949
|
if (entry.isDirectory()) {
|
|
68253
67950
|
if (!skipDirs.has(entry.name)) {
|
|
68254
|
-
walk(
|
|
67951
|
+
walk(path41.join(dir, entry.name), visitedInodes);
|
|
68255
67952
|
}
|
|
68256
67953
|
} else if (entry.isFile()) {
|
|
68257
67954
|
const name2 = entry.name;
|
|
68258
67955
|
const isTsTest = /\.(test|spec)\.(ts|tsx|js|jsx)$/.test(name2) || dir.includes("__tests__") && /\.(ts|tsx|js|jsx)$/.test(name2);
|
|
68259
|
-
const isPyTest = /^test_.+\.py$/.test(name2) || /.+_test\.py$/.test(name2) || dir.includes(`${
|
|
67956
|
+
const isPyTest = /^test_.+\.py$/.test(name2) || /.+_test\.py$/.test(name2) || dir.includes(`${path41.sep}tests${path41.sep}`) && name2.endsWith(".py");
|
|
68260
67957
|
const isGoTest = /.+_test\.go$/.test(name2);
|
|
68261
67958
|
if (isTsTest || isPyTest || isGoTest) {
|
|
68262
|
-
testFiles.push(normalizePath(
|
|
67959
|
+
testFiles.push(normalizePath(path41.join(dir, entry.name)));
|
|
68263
67960
|
}
|
|
68264
67961
|
}
|
|
68265
67962
|
}
|
|
@@ -68284,8 +67981,8 @@ function extractImports3(content) {
|
|
|
68284
67981
|
];
|
|
68285
67982
|
}
|
|
68286
67983
|
function addImpactEdgesForTestFile(testFile, content, impactMap) {
|
|
68287
|
-
const ext =
|
|
68288
|
-
const testDir =
|
|
67984
|
+
const ext = path41.extname(testFile).toLowerCase();
|
|
67985
|
+
const testDir = path41.dirname(testFile);
|
|
68289
67986
|
function addEdge(source) {
|
|
68290
67987
|
if (!impactMap[source])
|
|
68291
67988
|
impactMap[source] = [];
|
|
@@ -68344,7 +68041,7 @@ async function buildImpactMap(cwd) {
|
|
|
68344
68041
|
return impactMap;
|
|
68345
68042
|
}
|
|
68346
68043
|
async function loadImpactMap(cwd, options) {
|
|
68347
|
-
const cachePath =
|
|
68044
|
+
const cachePath = path41.join(cwd, ".swarm", "cache", "impact-map.json");
|
|
68348
68045
|
if (fs24.existsSync(cachePath)) {
|
|
68349
68046
|
try {
|
|
68350
68047
|
const content = fs24.readFileSync(cachePath, "utf-8");
|
|
@@ -68377,12 +68074,12 @@ async function loadImpactMap(cwd, options) {
|
|
|
68377
68074
|
return _internals29.buildImpactMap(cwd);
|
|
68378
68075
|
}
|
|
68379
68076
|
async function saveImpactMap(cwd, impactMap) {
|
|
68380
|
-
if (!
|
|
68077
|
+
if (!path41.isAbsolute(cwd)) {
|
|
68381
68078
|
throw new Error(`saveImpactMap requires an absolute project root path, got: "${cwd}"`);
|
|
68382
68079
|
}
|
|
68383
68080
|
_internals29.validateProjectRoot(cwd);
|
|
68384
|
-
const cacheDir2 =
|
|
68385
|
-
const cachePath =
|
|
68081
|
+
const cacheDir2 = path41.join(cwd, ".swarm", "cache");
|
|
68082
|
+
const cachePath = path41.join(cacheDir2, "impact-map.json");
|
|
68386
68083
|
if (!fs24.existsSync(cacheDir2)) {
|
|
68387
68084
|
fs24.mkdirSync(cacheDir2, { recursive: true });
|
|
68388
68085
|
}
|
|
@@ -68414,7 +68111,7 @@ async function analyzeImpact(changedFiles, cwd, budget) {
|
|
|
68414
68111
|
budgetExceeded = true;
|
|
68415
68112
|
break;
|
|
68416
68113
|
}
|
|
68417
|
-
const normalizedChanged = normalizePath(
|
|
68114
|
+
const normalizedChanged = normalizePath(path41.resolve(changedFile));
|
|
68418
68115
|
const tests = impactMap[normalizedChanged];
|
|
68419
68116
|
if (tests && tests.length > 0) {
|
|
68420
68117
|
for (const test of tests) {
|
|
@@ -68707,15 +68404,15 @@ var FLAKY_THRESHOLD = 0.3, MIN_RUNS_FOR_QUARANTINE = 5, MAX_HISTORY_RUNS = 20;
|
|
|
68707
68404
|
|
|
68708
68405
|
// src/test-impact/history-store.ts
|
|
68709
68406
|
import fs25 from "node:fs";
|
|
68710
|
-
import
|
|
68407
|
+
import path42 from "node:path";
|
|
68711
68408
|
function getHistoryPath(workingDir) {
|
|
68712
68409
|
if (!workingDir) {
|
|
68713
68410
|
throw new Error("getHistoryPath requires a working directory — project root must be provided by the caller");
|
|
68714
68411
|
}
|
|
68715
|
-
if (!
|
|
68412
|
+
if (!path42.isAbsolute(workingDir)) {
|
|
68716
68413
|
throw new Error(`getHistoryPath requires an absolute project root path, got: "${workingDir}"`);
|
|
68717
68414
|
}
|
|
68718
|
-
return
|
|
68415
|
+
return path42.join(workingDir, ".swarm", "cache", "test-history.jsonl");
|
|
68719
68416
|
}
|
|
68720
68417
|
function sanitizeErrorMessage(errorMessage) {
|
|
68721
68418
|
if (errorMessage === undefined) {
|
|
@@ -68802,7 +68499,7 @@ function batchAppendTestRuns(records, workingDir) {
|
|
|
68802
68499
|
}
|
|
68803
68500
|
}
|
|
68804
68501
|
const historyPath = getHistoryPath(workingDir);
|
|
68805
|
-
const historyDir =
|
|
68502
|
+
const historyDir = path42.dirname(historyPath);
|
|
68806
68503
|
_internals30.validateProjectRoot(workingDir);
|
|
68807
68504
|
if (!fs25.existsSync(historyDir)) {
|
|
68808
68505
|
fs25.mkdirSync(historyDir, { recursive: true });
|
|
@@ -68898,7 +68595,7 @@ var init_history_store = __esm(() => {
|
|
|
68898
68595
|
|
|
68899
68596
|
// src/tools/resolve-working-directory.ts
|
|
68900
68597
|
import * as fs26 from "node:fs";
|
|
68901
|
-
import * as
|
|
68598
|
+
import * as path43 from "node:path";
|
|
68902
68599
|
function resolveWorkingDirectory(workingDirectory, fallbackDirectory) {
|
|
68903
68600
|
if (workingDirectory == null || workingDirectory === "") {
|
|
68904
68601
|
return { success: true, directory: fallbackDirectory };
|
|
@@ -68918,15 +68615,15 @@ function resolveWorkingDirectory(workingDirectory, fallbackDirectory) {
|
|
|
68918
68615
|
};
|
|
68919
68616
|
}
|
|
68920
68617
|
}
|
|
68921
|
-
const normalizedDir =
|
|
68922
|
-
const pathParts = normalizedDir.split(
|
|
68618
|
+
const normalizedDir = path43.normalize(workingDirectory);
|
|
68619
|
+
const pathParts = normalizedDir.split(path43.sep);
|
|
68923
68620
|
if (pathParts.includes("..")) {
|
|
68924
68621
|
return {
|
|
68925
68622
|
success: false,
|
|
68926
68623
|
message: "Invalid working_directory: path traversal sequences (..) are not allowed"
|
|
68927
68624
|
};
|
|
68928
68625
|
}
|
|
68929
|
-
const resolvedDir =
|
|
68626
|
+
const resolvedDir = path43.resolve(normalizedDir);
|
|
68930
68627
|
let statResult;
|
|
68931
68628
|
try {
|
|
68932
68629
|
statResult = fs26.statSync(resolvedDir);
|
|
@@ -68942,7 +68639,7 @@ function resolveWorkingDirectory(workingDirectory, fallbackDirectory) {
|
|
|
68942
68639
|
message: `Invalid working_directory: path "${resolvedDir}" is not a directory`
|
|
68943
68640
|
};
|
|
68944
68641
|
}
|
|
68945
|
-
const resolvedFallback =
|
|
68642
|
+
const resolvedFallback = path43.resolve(fallbackDirectory);
|
|
68946
68643
|
let fallbackExists = false;
|
|
68947
68644
|
try {
|
|
68948
68645
|
fs26.statSync(resolvedFallback);
|
|
@@ -68952,7 +68649,7 @@ function resolveWorkingDirectory(workingDirectory, fallbackDirectory) {
|
|
|
68952
68649
|
}
|
|
68953
68650
|
if (workingDirectory != null && workingDirectory !== "") {
|
|
68954
68651
|
if (fallbackExists) {
|
|
68955
|
-
const isSubdirectory = resolvedDir.startsWith(resolvedFallback +
|
|
68652
|
+
const isSubdirectory = resolvedDir.startsWith(resolvedFallback + path43.sep);
|
|
68956
68653
|
if (isSubdirectory) {
|
|
68957
68654
|
return {
|
|
68958
68655
|
success: false,
|
|
@@ -69007,10 +68704,10 @@ var init_registry_backend = __esm(() => {
|
|
|
69007
68704
|
|
|
69008
68705
|
// src/lang/backends/typescript.ts
|
|
69009
68706
|
import * as fs27 from "node:fs";
|
|
69010
|
-
import * as
|
|
68707
|
+
import * as path44 from "node:path";
|
|
69011
68708
|
function readPackageJsonRaw(dir) {
|
|
69012
68709
|
try {
|
|
69013
|
-
const content = fs27.readFileSync(
|
|
68710
|
+
const content = fs27.readFileSync(path44.join(dir, "package.json"), "utf-8");
|
|
69014
68711
|
return JSON.parse(content);
|
|
69015
68712
|
} catch {
|
|
69016
68713
|
return null;
|
|
@@ -69230,7 +68927,7 @@ __export(exports_dispatch, {
|
|
|
69230
68927
|
_internals: () => _internals32
|
|
69231
68928
|
});
|
|
69232
68929
|
import * as fs28 from "node:fs";
|
|
69233
|
-
import * as
|
|
68930
|
+
import * as path45 from "node:path";
|
|
69234
68931
|
function safeReaddirSet(dir) {
|
|
69235
68932
|
try {
|
|
69236
68933
|
return new Set(fs28.readdirSync(dir));
|
|
@@ -69247,14 +68944,14 @@ function manifestHash(dir) {
|
|
|
69247
68944
|
if (!entries.has(name2))
|
|
69248
68945
|
continue;
|
|
69249
68946
|
try {
|
|
69250
|
-
const stat4 = fs28.statSync(
|
|
68947
|
+
const stat4 = fs28.statSync(path45.join(dir, name2));
|
|
69251
68948
|
parts2.push(`${name2}:${stat4.size}:${stat4.mtimeMs}:${stat4.ino}`);
|
|
69252
68949
|
} catch {}
|
|
69253
68950
|
}
|
|
69254
68951
|
return parts2.join("|");
|
|
69255
68952
|
}
|
|
69256
68953
|
function findManifestRoot(start2) {
|
|
69257
|
-
const resolved =
|
|
68954
|
+
const resolved = path45.resolve(start2);
|
|
69258
68955
|
const cached3 = manifestRootCache.get(resolved);
|
|
69259
68956
|
if (cached3 !== undefined)
|
|
69260
68957
|
return cached3;
|
|
@@ -69273,7 +68970,7 @@ function findManifestRoot(start2) {
|
|
|
69273
68970
|
return cur;
|
|
69274
68971
|
}
|
|
69275
68972
|
}
|
|
69276
|
-
const parent =
|
|
68973
|
+
const parent = path45.dirname(cur);
|
|
69277
68974
|
if (parent === cur)
|
|
69278
68975
|
break;
|
|
69279
68976
|
cur = parent;
|
|
@@ -69383,13 +69080,13 @@ var init_dispatch = __esm(() => {
|
|
|
69383
69080
|
|
|
69384
69081
|
// src/tools/test-runner.ts
|
|
69385
69082
|
import * as fs29 from "node:fs";
|
|
69386
|
-
import * as
|
|
69083
|
+
import * as path46 from "node:path";
|
|
69387
69084
|
async function estimateFanOut(sourceFiles, cwd) {
|
|
69388
69085
|
try {
|
|
69389
69086
|
const impactMap = await loadImpactMap(cwd, { skipRebuild: true });
|
|
69390
69087
|
const uniqueTestFiles = new Set;
|
|
69391
69088
|
for (const sourceFile of sourceFiles) {
|
|
69392
|
-
const resolvedPath =
|
|
69089
|
+
const resolvedPath = path46.resolve(cwd, sourceFile);
|
|
69393
69090
|
const normalizedPath = resolvedPath.replace(/\\/g, "/");
|
|
69394
69091
|
const testFiles = impactMap[normalizedPath];
|
|
69395
69092
|
if (testFiles) {
|
|
@@ -69467,14 +69164,14 @@ function hasDevDependency(devDeps, ...patterns) {
|
|
|
69467
69164
|
return hasPackageJsonDependency(devDeps, ...patterns);
|
|
69468
69165
|
}
|
|
69469
69166
|
function detectGoTest(cwd) {
|
|
69470
|
-
return fs29.existsSync(
|
|
69167
|
+
return fs29.existsSync(path46.join(cwd, "go.mod")) && isCommandAvailable("go");
|
|
69471
69168
|
}
|
|
69472
69169
|
function detectJavaMaven(cwd) {
|
|
69473
|
-
return fs29.existsSync(
|
|
69170
|
+
return fs29.existsSync(path46.join(cwd, "pom.xml")) && isCommandAvailable("mvn");
|
|
69474
69171
|
}
|
|
69475
69172
|
function detectGradle(cwd) {
|
|
69476
|
-
const hasBuildFile = fs29.existsSync(
|
|
69477
|
-
const hasGradlew = fs29.existsSync(
|
|
69173
|
+
const hasBuildFile = fs29.existsSync(path46.join(cwd, "build.gradle")) || fs29.existsSync(path46.join(cwd, "build.gradle.kts"));
|
|
69174
|
+
const hasGradlew = fs29.existsSync(path46.join(cwd, "gradlew")) || fs29.existsSync(path46.join(cwd, "gradlew.bat"));
|
|
69478
69175
|
return hasBuildFile && (hasGradlew || isCommandAvailable("gradle"));
|
|
69479
69176
|
}
|
|
69480
69177
|
function detectDotnetTest(cwd) {
|
|
@@ -69487,25 +69184,25 @@ function detectDotnetTest(cwd) {
|
|
|
69487
69184
|
}
|
|
69488
69185
|
}
|
|
69489
69186
|
function detectCTest(cwd) {
|
|
69490
|
-
const hasSource = fs29.existsSync(
|
|
69491
|
-
const hasBuildCache = fs29.existsSync(
|
|
69187
|
+
const hasSource = fs29.existsSync(path46.join(cwd, "CMakeLists.txt"));
|
|
69188
|
+
const hasBuildCache = fs29.existsSync(path46.join(cwd, "CMakeCache.txt")) || fs29.existsSync(path46.join(cwd, "build", "CMakeCache.txt"));
|
|
69492
69189
|
return (hasSource || hasBuildCache) && isCommandAvailable("ctest");
|
|
69493
69190
|
}
|
|
69494
69191
|
function detectSwiftTest(cwd) {
|
|
69495
|
-
return fs29.existsSync(
|
|
69192
|
+
return fs29.existsSync(path46.join(cwd, "Package.swift")) && isCommandAvailable("swift");
|
|
69496
69193
|
}
|
|
69497
69194
|
function detectDartTest(cwd) {
|
|
69498
|
-
return fs29.existsSync(
|
|
69195
|
+
return fs29.existsSync(path46.join(cwd, "pubspec.yaml")) && (isCommandAvailable("dart") || isCommandAvailable("flutter"));
|
|
69499
69196
|
}
|
|
69500
69197
|
function detectRSpec(cwd) {
|
|
69501
|
-
const hasRSpecFile = fs29.existsSync(
|
|
69502
|
-
const hasGemfile = fs29.existsSync(
|
|
69503
|
-
const hasSpecDir = fs29.existsSync(
|
|
69198
|
+
const hasRSpecFile = fs29.existsSync(path46.join(cwd, ".rspec"));
|
|
69199
|
+
const hasGemfile = fs29.existsSync(path46.join(cwd, "Gemfile"));
|
|
69200
|
+
const hasSpecDir = fs29.existsSync(path46.join(cwd, "spec"));
|
|
69504
69201
|
const hasRSpec = hasRSpecFile || hasGemfile && hasSpecDir;
|
|
69505
69202
|
return hasRSpec && (isCommandAvailable("bundle") || isCommandAvailable("rspec"));
|
|
69506
69203
|
}
|
|
69507
69204
|
function detectMinitest(cwd) {
|
|
69508
|
-
return fs29.existsSync(
|
|
69205
|
+
return fs29.existsSync(path46.join(cwd, "test")) && (fs29.existsSync(path46.join(cwd, "Gemfile")) || fs29.existsSync(path46.join(cwd, "Rakefile"))) && isCommandAvailable("ruby");
|
|
69509
69206
|
}
|
|
69510
69207
|
async function detectTestFrameworkViaDispatch(cwd) {
|
|
69511
69208
|
try {
|
|
@@ -69567,7 +69264,7 @@ async function parseTestOutputViaDispatch(framework, output, baseDir) {
|
|
|
69567
69264
|
async function detectTestFramework(cwd) {
|
|
69568
69265
|
const baseDir = cwd;
|
|
69569
69266
|
try {
|
|
69570
|
-
const packageJsonPath =
|
|
69267
|
+
const packageJsonPath = path46.join(baseDir, "package.json");
|
|
69571
69268
|
if (fs29.existsSync(packageJsonPath)) {
|
|
69572
69269
|
const content = fs29.readFileSync(packageJsonPath, "utf-8");
|
|
69573
69270
|
const pkg = JSON.parse(content);
|
|
@@ -69588,16 +69285,16 @@ async function detectTestFramework(cwd) {
|
|
|
69588
69285
|
return "jest";
|
|
69589
69286
|
if (hasDevDependency(devDeps, "mocha", "@types/mocha"))
|
|
69590
69287
|
return "mocha";
|
|
69591
|
-
if (fs29.existsSync(
|
|
69288
|
+
if (fs29.existsSync(path46.join(baseDir, "bun.lockb")) || fs29.existsSync(path46.join(baseDir, "bun.lock"))) {
|
|
69592
69289
|
if (scripts.test?.includes("bun"))
|
|
69593
69290
|
return "bun";
|
|
69594
69291
|
}
|
|
69595
69292
|
}
|
|
69596
69293
|
} catch {}
|
|
69597
69294
|
try {
|
|
69598
|
-
const pyprojectTomlPath =
|
|
69599
|
-
const setupCfgPath =
|
|
69600
|
-
const requirementsTxtPath =
|
|
69295
|
+
const pyprojectTomlPath = path46.join(baseDir, "pyproject.toml");
|
|
69296
|
+
const setupCfgPath = path46.join(baseDir, "setup.cfg");
|
|
69297
|
+
const requirementsTxtPath = path46.join(baseDir, "requirements.txt");
|
|
69601
69298
|
if (fs29.existsSync(pyprojectTomlPath)) {
|
|
69602
69299
|
const content = fs29.readFileSync(pyprojectTomlPath, "utf-8");
|
|
69603
69300
|
if (content.includes("[tool.pytest"))
|
|
@@ -69617,7 +69314,7 @@ async function detectTestFramework(cwd) {
|
|
|
69617
69314
|
}
|
|
69618
69315
|
} catch {}
|
|
69619
69316
|
try {
|
|
69620
|
-
const cargoTomlPath =
|
|
69317
|
+
const cargoTomlPath = path46.join(baseDir, "Cargo.toml");
|
|
69621
69318
|
if (fs29.existsSync(cargoTomlPath)) {
|
|
69622
69319
|
const content = fs29.readFileSync(cargoTomlPath, "utf-8");
|
|
69623
69320
|
if (content.includes("[dev-dependencies]")) {
|
|
@@ -69628,9 +69325,9 @@ async function detectTestFramework(cwd) {
|
|
|
69628
69325
|
}
|
|
69629
69326
|
} catch {}
|
|
69630
69327
|
try {
|
|
69631
|
-
const pesterConfigPath =
|
|
69632
|
-
const pesterConfigJsonPath =
|
|
69633
|
-
const pesterPs1Path =
|
|
69328
|
+
const pesterConfigPath = path46.join(baseDir, "pester.config.ps1");
|
|
69329
|
+
const pesterConfigJsonPath = path46.join(baseDir, "pester.config.ps1.json");
|
|
69330
|
+
const pesterPs1Path = path46.join(baseDir, "tests.ps1");
|
|
69634
69331
|
if (fs29.existsSync(pesterConfigPath) || fs29.existsSync(pesterConfigJsonPath) || fs29.existsSync(pesterPs1Path)) {
|
|
69635
69332
|
return "pester";
|
|
69636
69333
|
}
|
|
@@ -69659,12 +69356,12 @@ function isTestDirectoryPath(normalizedPath) {
|
|
|
69659
69356
|
return normalizedPath.split("/").some((segment) => TEST_DIRECTORY_NAMES.includes(segment));
|
|
69660
69357
|
}
|
|
69661
69358
|
function resolveWorkspacePath(file3, workingDir) {
|
|
69662
|
-
return
|
|
69359
|
+
return path46.isAbsolute(file3) ? path46.resolve(file3) : path46.resolve(workingDir, file3);
|
|
69663
69360
|
}
|
|
69664
69361
|
function toWorkspaceOutputPath(absolutePath, workingDir, preferRelative) {
|
|
69665
69362
|
if (!preferRelative)
|
|
69666
69363
|
return absolutePath;
|
|
69667
|
-
return
|
|
69364
|
+
return path46.relative(workingDir, absolutePath);
|
|
69668
69365
|
}
|
|
69669
69366
|
function dedupePush(target, value) {
|
|
69670
69367
|
if (!target.includes(value)) {
|
|
@@ -69701,18 +69398,18 @@ function buildLanguageSpecificTestNames(nameWithoutExt, ext) {
|
|
|
69701
69398
|
}
|
|
69702
69399
|
}
|
|
69703
69400
|
function getRepoLevelCandidateDirectories(workingDir, relativePath, ext) {
|
|
69704
|
-
const relativeDir =
|
|
69401
|
+
const relativeDir = path46.dirname(relativePath);
|
|
69705
69402
|
const nestedRelativeDir = relativeDir === "." ? "" : relativeDir;
|
|
69706
69403
|
const directories = TEST_DIRECTORY_NAMES.flatMap((dirName) => {
|
|
69707
|
-
const rootDir =
|
|
69708
|
-
return nestedRelativeDir ? [rootDir,
|
|
69404
|
+
const rootDir = path46.join(workingDir, dirName);
|
|
69405
|
+
return nestedRelativeDir ? [rootDir, path46.join(rootDir, nestedRelativeDir)] : [rootDir];
|
|
69709
69406
|
});
|
|
69710
69407
|
const normalizedRelativePath = relativePath.replace(/\\/g, "/");
|
|
69711
69408
|
if (ext === ".java" && normalizedRelativePath.startsWith("src/main/java/")) {
|
|
69712
|
-
directories.push(
|
|
69409
|
+
directories.push(path46.join(workingDir, "src/test/java", path46.dirname(normalizedRelativePath.slice("src/main/java/".length))));
|
|
69713
69410
|
}
|
|
69714
69411
|
if ((ext === ".kt" || ext === ".java") && normalizedRelativePath.startsWith("src/main/kotlin/")) {
|
|
69715
|
-
directories.push(
|
|
69412
|
+
directories.push(path46.join(workingDir, "src/test/kotlin", path46.dirname(normalizedRelativePath.slice("src/main/kotlin/".length))));
|
|
69716
69413
|
}
|
|
69717
69414
|
return [...new Set(directories)];
|
|
69718
69415
|
}
|
|
@@ -69740,23 +69437,23 @@ function isLanguageSpecificTestFile(basename8) {
|
|
|
69740
69437
|
}
|
|
69741
69438
|
function isConventionTestFilePath(filePath) {
|
|
69742
69439
|
const normalizedPath = filePath.replace(/\\/g, "/");
|
|
69743
|
-
const basename8 =
|
|
69440
|
+
const basename8 = path46.basename(filePath);
|
|
69744
69441
|
return hasCompoundTestExtension(basename8) || basename8.includes(".spec.") || basename8.includes(".test.") || isLanguageSpecificTestFile(basename8) || isTestDirectoryPath(normalizedPath);
|
|
69745
69442
|
}
|
|
69746
69443
|
function getTestFilesFromConvention(sourceFiles, workingDir = process.cwd()) {
|
|
69747
69444
|
const testFiles = [];
|
|
69748
69445
|
for (const file3 of sourceFiles) {
|
|
69749
69446
|
const absoluteFile = resolveWorkspacePath(file3, workingDir);
|
|
69750
|
-
const relativeFile =
|
|
69751
|
-
const basename8 =
|
|
69752
|
-
const
|
|
69753
|
-
const preferRelativeOutput = !
|
|
69447
|
+
const relativeFile = path46.relative(workingDir, absoluteFile);
|
|
69448
|
+
const basename8 = path46.basename(absoluteFile);
|
|
69449
|
+
const dirname19 = path46.dirname(absoluteFile);
|
|
69450
|
+
const preferRelativeOutput = !path46.isAbsolute(file3);
|
|
69754
69451
|
if (isConventionTestFilePath(relativeFile) || isConventionTestFilePath(file3)) {
|
|
69755
69452
|
dedupePush(testFiles, toWorkspaceOutputPath(absoluteFile, workingDir, preferRelativeOutput));
|
|
69756
69453
|
continue;
|
|
69757
69454
|
}
|
|
69758
69455
|
const nameWithoutExt = basename8.replace(/\.[^.]+$/, "");
|
|
69759
|
-
const ext =
|
|
69456
|
+
const ext = path46.extname(basename8);
|
|
69760
69457
|
const genericTestNames = [
|
|
69761
69458
|
`${nameWithoutExt}.spec${ext}`,
|
|
69762
69459
|
`${nameWithoutExt}.test${ext}`
|
|
@@ -69765,7 +69462,7 @@ function getTestFilesFromConvention(sourceFiles, workingDir = process.cwd()) {
|
|
|
69765
69462
|
const colocatedCandidates = [
|
|
69766
69463
|
...genericTestNames,
|
|
69767
69464
|
...languageSpecificTestNames
|
|
69768
|
-
].map((candidateName) =>
|
|
69465
|
+
].map((candidateName) => path46.join(dirname19, candidateName));
|
|
69769
69466
|
const testDirectoryNames = [
|
|
69770
69467
|
basename8,
|
|
69771
69468
|
...genericTestNames,
|
|
@@ -69774,8 +69471,8 @@ function getTestFilesFromConvention(sourceFiles, workingDir = process.cwd()) {
|
|
|
69774
69471
|
const repoLevelDirectories = getRepoLevelCandidateDirectories(workingDir, relativeFile, ext);
|
|
69775
69472
|
const possibleTestFiles = [
|
|
69776
69473
|
...colocatedCandidates,
|
|
69777
|
-
...TEST_DIRECTORY_NAMES.flatMap((dirName) => testDirectoryNames.map((candidateName) =>
|
|
69778
|
-
...repoLevelDirectories.flatMap((candidateDir) => testDirectoryNames.map((candidateName) =>
|
|
69474
|
+
...TEST_DIRECTORY_NAMES.flatMap((dirName) => testDirectoryNames.map((candidateName) => path46.join(dirname19, dirName, candidateName))),
|
|
69475
|
+
...repoLevelDirectories.flatMap((candidateDir) => testDirectoryNames.map((candidateName) => path46.join(candidateDir, candidateName)))
|
|
69779
69476
|
];
|
|
69780
69477
|
for (const testFile of possibleTestFiles) {
|
|
69781
69478
|
if (fs29.existsSync(testFile)) {
|
|
@@ -69796,7 +69493,7 @@ async function getTestFilesFromGraph(sourceFiles, workingDir) {
|
|
|
69796
69493
|
try {
|
|
69797
69494
|
const absoluteTestFile = resolveWorkspacePath(testFile, workingDir);
|
|
69798
69495
|
const content = fs29.readFileSync(absoluteTestFile, "utf-8");
|
|
69799
|
-
const testDir =
|
|
69496
|
+
const testDir = path46.dirname(absoluteTestFile);
|
|
69800
69497
|
const importRegex = /import\s+.*?\s+from\s+['"]([^'"]+)['"]/g;
|
|
69801
69498
|
let match;
|
|
69802
69499
|
match = importRegex.exec(content);
|
|
@@ -69804,8 +69501,8 @@ async function getTestFilesFromGraph(sourceFiles, workingDir) {
|
|
|
69804
69501
|
const importPath = match[1];
|
|
69805
69502
|
let resolvedImport;
|
|
69806
69503
|
if (importPath.startsWith(".")) {
|
|
69807
|
-
resolvedImport =
|
|
69808
|
-
const existingExt =
|
|
69504
|
+
resolvedImport = path46.resolve(testDir, importPath);
|
|
69505
|
+
const existingExt = path46.extname(resolvedImport);
|
|
69809
69506
|
if (!existingExt) {
|
|
69810
69507
|
for (const extToTry of [
|
|
69811
69508
|
".ts",
|
|
@@ -69825,12 +69522,12 @@ async function getTestFilesFromGraph(sourceFiles, workingDir) {
|
|
|
69825
69522
|
} else {
|
|
69826
69523
|
continue;
|
|
69827
69524
|
}
|
|
69828
|
-
const importBasename =
|
|
69829
|
-
const importDir =
|
|
69525
|
+
const importBasename = path46.basename(resolvedImport, path46.extname(resolvedImport));
|
|
69526
|
+
const importDir = path46.dirname(resolvedImport);
|
|
69830
69527
|
for (const sourceFile of absoluteSourceFiles) {
|
|
69831
|
-
const sourceDir =
|
|
69832
|
-
const sourceBasename =
|
|
69833
|
-
const isRelatedDir = importDir === sourceDir || importDir ===
|
|
69528
|
+
const sourceDir = path46.dirname(sourceFile);
|
|
69529
|
+
const sourceBasename = path46.basename(sourceFile, path46.extname(sourceFile));
|
|
69530
|
+
const isRelatedDir = importDir === sourceDir || importDir === path46.join(sourceDir, "__tests__") || importDir === path46.join(sourceDir, "tests") || importDir === path46.join(sourceDir, "test") || importDir === path46.join(sourceDir, "spec");
|
|
69834
69531
|
if (resolvedImport === sourceFile || importBasename === sourceBasename && isRelatedDir) {
|
|
69835
69532
|
dedupePush(testFiles, testFile);
|
|
69836
69533
|
break;
|
|
@@ -69843,8 +69540,8 @@ async function getTestFilesFromGraph(sourceFiles, workingDir) {
|
|
|
69843
69540
|
while (match !== null) {
|
|
69844
69541
|
const importPath = match[1];
|
|
69845
69542
|
if (importPath.startsWith(".")) {
|
|
69846
|
-
let resolvedImport =
|
|
69847
|
-
const existingExt =
|
|
69543
|
+
let resolvedImport = path46.resolve(testDir, importPath);
|
|
69544
|
+
const existingExt = path46.extname(resolvedImport);
|
|
69848
69545
|
if (!existingExt) {
|
|
69849
69546
|
for (const extToTry of [
|
|
69850
69547
|
".ts",
|
|
@@ -69861,12 +69558,12 @@ async function getTestFilesFromGraph(sourceFiles, workingDir) {
|
|
|
69861
69558
|
}
|
|
69862
69559
|
}
|
|
69863
69560
|
}
|
|
69864
|
-
const importDir =
|
|
69865
|
-
const importBasename =
|
|
69561
|
+
const importDir = path46.dirname(resolvedImport);
|
|
69562
|
+
const importBasename = path46.basename(resolvedImport, path46.extname(resolvedImport));
|
|
69866
69563
|
for (const sourceFile of absoluteSourceFiles) {
|
|
69867
|
-
const sourceDir =
|
|
69868
|
-
const sourceBasename =
|
|
69869
|
-
const isRelatedDir = importDir === sourceDir || importDir ===
|
|
69564
|
+
const sourceDir = path46.dirname(sourceFile);
|
|
69565
|
+
const sourceBasename = path46.basename(sourceFile, path46.extname(sourceFile));
|
|
69566
|
+
const isRelatedDir = importDir === sourceDir || importDir === path46.join(sourceDir, "__tests__") || importDir === path46.join(sourceDir, "tests") || importDir === path46.join(sourceDir, "test") || importDir === path46.join(sourceDir, "spec");
|
|
69870
69567
|
if (resolvedImport === sourceFile || importBasename === sourceBasename && isRelatedDir) {
|
|
69871
69568
|
dedupePush(testFiles, testFile);
|
|
69872
69569
|
break;
|
|
@@ -69976,8 +69673,8 @@ function buildTestCommand2(framework, scope, files, coverage, baseDir) {
|
|
|
69976
69673
|
return ["mvn", "test"];
|
|
69977
69674
|
case "gradle": {
|
|
69978
69675
|
const isWindows = process.platform === "win32";
|
|
69979
|
-
const hasGradlewBat = fs29.existsSync(
|
|
69980
|
-
const hasGradlew = fs29.existsSync(
|
|
69676
|
+
const hasGradlewBat = fs29.existsSync(path46.join(baseDir, "gradlew.bat"));
|
|
69677
|
+
const hasGradlew = fs29.existsSync(path46.join(baseDir, "gradlew"));
|
|
69981
69678
|
if (hasGradlewBat && isWindows)
|
|
69982
69679
|
return ["gradlew.bat", "test"];
|
|
69983
69680
|
if (hasGradlew)
|
|
@@ -69994,7 +69691,7 @@ function buildTestCommand2(framework, scope, files, coverage, baseDir) {
|
|
|
69994
69691
|
"cmake-build-release",
|
|
69995
69692
|
"out"
|
|
69996
69693
|
];
|
|
69997
|
-
const actualBuildDir = buildDirCandidates.find((d) => fs29.existsSync(
|
|
69694
|
+
const actualBuildDir = buildDirCandidates.find((d) => fs29.existsSync(path46.join(baseDir, d, "CMakeCache.txt"))) ?? "build";
|
|
69998
69695
|
return ["ctest", "--test-dir", actualBuildDir];
|
|
69999
69696
|
}
|
|
70000
69697
|
case "swift-test":
|
|
@@ -70426,11 +70123,11 @@ async function runTests(framework, scope, files, coverage, timeout_ms, cwd) {
|
|
|
70426
70123
|
};
|
|
70427
70124
|
}
|
|
70428
70125
|
const startTime = Date.now();
|
|
70429
|
-
const vitestJsonOutputPath = framework === "vitest" ?
|
|
70126
|
+
const vitestJsonOutputPath = framework === "vitest" ? path46.join(cwd, ".swarm", "cache", "test-runner-vitest.json") : undefined;
|
|
70430
70127
|
try {
|
|
70431
70128
|
if (vitestJsonOutputPath) {
|
|
70432
70129
|
try {
|
|
70433
|
-
fs29.mkdirSync(
|
|
70130
|
+
fs29.mkdirSync(path46.dirname(vitestJsonOutputPath), { recursive: true });
|
|
70434
70131
|
if (fs29.existsSync(vitestJsonOutputPath)) {
|
|
70435
70132
|
fs29.unlinkSync(vitestJsonOutputPath);
|
|
70436
70133
|
}
|
|
@@ -70546,10 +70243,10 @@ async function runTests(framework, scope, files, coverage, timeout_ms, cwd) {
|
|
|
70546
70243
|
}
|
|
70547
70244
|
function normalizeHistoryTestFile(testFile, workingDir) {
|
|
70548
70245
|
const normalized = testFile.replace(/\\/g, "/");
|
|
70549
|
-
if (!
|
|
70246
|
+
if (!path46.isAbsolute(testFile))
|
|
70550
70247
|
return normalized;
|
|
70551
|
-
const relative10 =
|
|
70552
|
-
if (relative10.startsWith("..") ||
|
|
70248
|
+
const relative10 = path46.relative(workingDir, testFile);
|
|
70249
|
+
if (relative10.startsWith("..") || path46.isAbsolute(relative10)) {
|
|
70553
70250
|
return normalized;
|
|
70554
70251
|
}
|
|
70555
70252
|
return relative10.replace(/\\/g, "/");
|
|
@@ -70887,7 +70584,7 @@ var init_test_runner = __esm(() => {
|
|
|
70887
70584
|
const sourceFiles = args2.files.filter((file3) => {
|
|
70888
70585
|
if (directTestFiles.includes(file3))
|
|
70889
70586
|
return false;
|
|
70890
|
-
const ext =
|
|
70587
|
+
const ext = path46.extname(file3).toLowerCase();
|
|
70891
70588
|
return SOURCE_EXTENSIONS.has(ext);
|
|
70892
70589
|
});
|
|
70893
70590
|
const invalidFiles = args2.files.filter((file3) => !directTestFiles.includes(file3) && !sourceFiles.includes(file3));
|
|
@@ -70933,7 +70630,7 @@ var init_test_runner = __esm(() => {
|
|
|
70933
70630
|
if (isConventionTestFilePath(f)) {
|
|
70934
70631
|
return false;
|
|
70935
70632
|
}
|
|
70936
|
-
const ext =
|
|
70633
|
+
const ext = path46.extname(f).toLowerCase();
|
|
70937
70634
|
return SOURCE_EXTENSIONS.has(ext);
|
|
70938
70635
|
});
|
|
70939
70636
|
if (sourceFiles.length === 0) {
|
|
@@ -70983,7 +70680,7 @@ var init_test_runner = __esm(() => {
|
|
|
70983
70680
|
if (isConventionTestFilePath(f)) {
|
|
70984
70681
|
return false;
|
|
70985
70682
|
}
|
|
70986
|
-
const ext =
|
|
70683
|
+
const ext = path46.extname(f).toLowerCase();
|
|
70987
70684
|
return SOURCE_EXTENSIONS.has(ext);
|
|
70988
70685
|
});
|
|
70989
70686
|
if (sourceFiles.length === 0) {
|
|
@@ -71035,8 +70732,8 @@ var init_test_runner = __esm(() => {
|
|
|
71035
70732
|
}
|
|
71036
70733
|
if (impactResult.impactedTests.length > 0) {
|
|
71037
70734
|
testFiles = impactResult.impactedTests.map((absPath) => {
|
|
71038
|
-
const relativePath =
|
|
71039
|
-
return
|
|
70735
|
+
const relativePath = path46.relative(workingDir, absPath);
|
|
70736
|
+
return path46.isAbsolute(relativePath) ? absPath : relativePath;
|
|
71040
70737
|
});
|
|
71041
70738
|
} else {
|
|
71042
70739
|
graphFallbackReason = "no impacted tests found via impact analysis, falling back to graph";
|
|
@@ -71112,7 +70809,7 @@ var init_test_runner = __esm(() => {
|
|
|
71112
70809
|
|
|
71113
70810
|
// src/services/preflight-service.ts
|
|
71114
70811
|
import * as fs30 from "node:fs";
|
|
71115
|
-
import * as
|
|
70812
|
+
import * as path47 from "node:path";
|
|
71116
70813
|
function validateDirectoryPath(dir) {
|
|
71117
70814
|
if (!dir || typeof dir !== "string") {
|
|
71118
70815
|
throw new Error("Directory path is required");
|
|
@@ -71120,8 +70817,8 @@ function validateDirectoryPath(dir) {
|
|
|
71120
70817
|
if (dir.includes("..")) {
|
|
71121
70818
|
throw new Error("Directory path must not contain path traversal sequences");
|
|
71122
70819
|
}
|
|
71123
|
-
const normalized =
|
|
71124
|
-
const absolutePath =
|
|
70820
|
+
const normalized = path47.normalize(dir);
|
|
70821
|
+
const absolutePath = path47.isAbsolute(normalized) ? normalized : path47.resolve(normalized);
|
|
71125
70822
|
return absolutePath;
|
|
71126
70823
|
}
|
|
71127
70824
|
function validateTimeout(timeoutMs, defaultValue) {
|
|
@@ -71144,7 +70841,7 @@ function validateTimeout(timeoutMs, defaultValue) {
|
|
|
71144
70841
|
}
|
|
71145
70842
|
function getPackageVersion(dir) {
|
|
71146
70843
|
try {
|
|
71147
|
-
const packagePath =
|
|
70844
|
+
const packagePath = path47.join(dir, "package.json");
|
|
71148
70845
|
if (fs30.existsSync(packagePath)) {
|
|
71149
70846
|
const content = fs30.readFileSync(packagePath, "utf-8");
|
|
71150
70847
|
const pkg = JSON.parse(content);
|
|
@@ -71155,7 +70852,7 @@ function getPackageVersion(dir) {
|
|
|
71155
70852
|
}
|
|
71156
70853
|
function getChangelogVersion(dir) {
|
|
71157
70854
|
try {
|
|
71158
|
-
const changelogPath =
|
|
70855
|
+
const changelogPath = path47.join(dir, "CHANGELOG.md");
|
|
71159
70856
|
if (fs30.existsSync(changelogPath)) {
|
|
71160
70857
|
const content = fs30.readFileSync(changelogPath, "utf-8");
|
|
71161
70858
|
const match = content.match(/^##\s*\[?(\d+\.\d+\.\d+)\]?/m);
|
|
@@ -71169,7 +70866,7 @@ function getChangelogVersion(dir) {
|
|
|
71169
70866
|
function getVersionFileVersion(dir) {
|
|
71170
70867
|
const possibleFiles = ["VERSION.txt", "version.txt", "VERSION", "version"];
|
|
71171
70868
|
for (const file3 of possibleFiles) {
|
|
71172
|
-
const filePath =
|
|
70869
|
+
const filePath = path47.join(dir, file3);
|
|
71173
70870
|
if (fs30.existsSync(filePath)) {
|
|
71174
70871
|
try {
|
|
71175
70872
|
const content = fs30.readFileSync(filePath, "utf-8").trim();
|
|
@@ -71496,7 +71193,7 @@ async function runEvidenceCheck(dir) {
|
|
|
71496
71193
|
async function runRequirementCoverageCheck(dir, currentPhase) {
|
|
71497
71194
|
const startTime = Date.now();
|
|
71498
71195
|
try {
|
|
71499
|
-
const specPath =
|
|
71196
|
+
const specPath = path47.join(dir, ".swarm", "spec.md");
|
|
71500
71197
|
if (!fs30.existsSync(specPath)) {
|
|
71501
71198
|
return {
|
|
71502
71199
|
type: "req_coverage",
|
|
@@ -72634,7 +72331,7 @@ var init_manager3 = __esm(() => {
|
|
|
72634
72331
|
|
|
72635
72332
|
// src/commands/reset.ts
|
|
72636
72333
|
import * as fs31 from "node:fs";
|
|
72637
|
-
import * as
|
|
72334
|
+
import * as path48 from "node:path";
|
|
72638
72335
|
async function handleResetCommand(directory, args2) {
|
|
72639
72336
|
const hasConfirm = args2.includes("--confirm");
|
|
72640
72337
|
if (!hasConfirm) {
|
|
@@ -72674,7 +72371,7 @@ async function handleResetCommand(directory, args2) {
|
|
|
72674
72371
|
}
|
|
72675
72372
|
for (const filename of ["SWARM_PLAN.md", "SWARM_PLAN.json"]) {
|
|
72676
72373
|
try {
|
|
72677
|
-
const rootPath =
|
|
72374
|
+
const rootPath = path48.join(directory, filename);
|
|
72678
72375
|
if (fs31.existsSync(rootPath)) {
|
|
72679
72376
|
fs31.unlinkSync(rootPath);
|
|
72680
72377
|
results.push(`- ✅ Deleted ${filename} (root)`);
|
|
@@ -72714,7 +72411,7 @@ var init_reset = __esm(() => {
|
|
|
72714
72411
|
|
|
72715
72412
|
// src/commands/reset-session.ts
|
|
72716
72413
|
import * as fs32 from "node:fs";
|
|
72717
|
-
import * as
|
|
72414
|
+
import * as path49 from "node:path";
|
|
72718
72415
|
async function handleResetSessionCommand(directory, _args) {
|
|
72719
72416
|
const results = [];
|
|
72720
72417
|
try {
|
|
@@ -72729,13 +72426,13 @@ async function handleResetSessionCommand(directory, _args) {
|
|
|
72729
72426
|
results.push("❌ Failed to delete state.json");
|
|
72730
72427
|
}
|
|
72731
72428
|
try {
|
|
72732
|
-
const sessionDir =
|
|
72429
|
+
const sessionDir = path49.dirname(validateSwarmPath(directory, "session/state.json"));
|
|
72733
72430
|
if (fs32.existsSync(sessionDir)) {
|
|
72734
72431
|
const files = fs32.readdirSync(sessionDir);
|
|
72735
72432
|
const otherFiles = files.filter((f) => f !== "state.json");
|
|
72736
72433
|
let deletedCount = 0;
|
|
72737
72434
|
for (const file3 of otherFiles) {
|
|
72738
|
-
const filePath =
|
|
72435
|
+
const filePath = path49.join(sessionDir, file3);
|
|
72739
72436
|
if (fs32.lstatSync(filePath).isFile()) {
|
|
72740
72437
|
fs32.unlinkSync(filePath);
|
|
72741
72438
|
deletedCount++;
|
|
@@ -72768,7 +72465,7 @@ var init_reset_session = __esm(() => {
|
|
|
72768
72465
|
|
|
72769
72466
|
// src/summaries/manager.ts
|
|
72770
72467
|
import { mkdirSync as mkdirSync15, readdirSync as readdirSync14, renameSync as renameSync11, rmSync as rmSync5, statSync as statSync13 } from "node:fs";
|
|
72771
|
-
import * as
|
|
72468
|
+
import * as path50 from "node:path";
|
|
72772
72469
|
function sanitizeSummaryId(id) {
|
|
72773
72470
|
if (!id || id.length === 0) {
|
|
72774
72471
|
throw new Error("Invalid summary ID: empty string");
|
|
@@ -72802,9 +72499,9 @@ async function storeSummary(directory, id, fullOutput, summaryText, maxStoredByt
|
|
|
72802
72499
|
if (serializedSize > maxStoredBytes) {
|
|
72803
72500
|
throw new Error(`Summary entry size (${serializedSize} bytes) exceeds maximum (${maxStoredBytes} bytes)`);
|
|
72804
72501
|
}
|
|
72805
|
-
const relativePath =
|
|
72502
|
+
const relativePath = path50.join("summaries", `${sanitizedId}.json`);
|
|
72806
72503
|
const summaryPath = validateSwarmPath(directory, relativePath);
|
|
72807
|
-
const summaryDir =
|
|
72504
|
+
const summaryDir = path50.dirname(summaryPath);
|
|
72808
72505
|
const entry = {
|
|
72809
72506
|
id: sanitizedId,
|
|
72810
72507
|
summaryText,
|
|
@@ -72814,7 +72511,7 @@ async function storeSummary(directory, id, fullOutput, summaryText, maxStoredByt
|
|
|
72814
72511
|
};
|
|
72815
72512
|
const entryJson = JSON.stringify(entry);
|
|
72816
72513
|
mkdirSync15(summaryDir, { recursive: true });
|
|
72817
|
-
const tempPath =
|
|
72514
|
+
const tempPath = path50.join(summaryDir, `${sanitizedId}.json.tmp.${Date.now()}.${process.pid}`);
|
|
72818
72515
|
try {
|
|
72819
72516
|
await bunWrite(tempPath, entryJson);
|
|
72820
72517
|
renameSync11(tempPath, summaryPath);
|
|
@@ -72827,7 +72524,7 @@ async function storeSummary(directory, id, fullOutput, summaryText, maxStoredByt
|
|
|
72827
72524
|
}
|
|
72828
72525
|
async function loadFullOutput(directory, id) {
|
|
72829
72526
|
const sanitizedId = sanitizeSummaryId(id);
|
|
72830
|
-
const relativePath =
|
|
72527
|
+
const relativePath = path50.join("summaries", `${sanitizedId}.json`);
|
|
72831
72528
|
validateSwarmPath(directory, relativePath);
|
|
72832
72529
|
const content = await readSwarmFileAsync(directory, relativePath);
|
|
72833
72530
|
if (content === null) {
|
|
@@ -72890,7 +72587,7 @@ var init_retrieve = __esm(() => {
|
|
|
72890
72587
|
|
|
72891
72588
|
// src/commands/rollback.ts
|
|
72892
72589
|
import * as fs33 from "node:fs";
|
|
72893
|
-
import * as
|
|
72590
|
+
import * as path51 from "node:path";
|
|
72894
72591
|
async function handleRollbackCommand(directory, args2) {
|
|
72895
72592
|
const phaseArg = args2[0];
|
|
72896
72593
|
if (!phaseArg) {
|
|
@@ -72955,8 +72652,8 @@ async function handleRollbackCommand(directory, args2) {
|
|
|
72955
72652
|
if (EXCLUDE_FILES.has(file3) || file3.startsWith("plan-ledger.archived-")) {
|
|
72956
72653
|
continue;
|
|
72957
72654
|
}
|
|
72958
|
-
const src =
|
|
72959
|
-
const dest =
|
|
72655
|
+
const src = path51.join(checkpointDir, file3);
|
|
72656
|
+
const dest = path51.join(swarmDir, file3);
|
|
72960
72657
|
try {
|
|
72961
72658
|
fs33.cpSync(src, dest, { recursive: true, force: true });
|
|
72962
72659
|
successes.push(file3);
|
|
@@ -72975,12 +72672,12 @@ async function handleRollbackCommand(directory, args2) {
|
|
|
72975
72672
|
].join(`
|
|
72976
72673
|
`);
|
|
72977
72674
|
}
|
|
72978
|
-
const existingLedgerPath =
|
|
72675
|
+
const existingLedgerPath = path51.join(swarmDir, "plan-ledger.jsonl");
|
|
72979
72676
|
if (fs33.existsSync(existingLedgerPath)) {
|
|
72980
72677
|
fs33.unlinkSync(existingLedgerPath);
|
|
72981
72678
|
}
|
|
72982
72679
|
try {
|
|
72983
|
-
const planJsonPath =
|
|
72680
|
+
const planJsonPath = path51.join(swarmDir, "plan.json");
|
|
72984
72681
|
if (fs33.existsSync(planJsonPath)) {
|
|
72985
72682
|
const planRaw = fs33.readFileSync(planJsonPath, "utf-8");
|
|
72986
72683
|
const plan = PlanSchema.parse(JSON.parse(planRaw));
|
|
@@ -73071,9 +72768,9 @@ Ensure this is a git repository with commit history.`;
|
|
|
73071
72768
|
`);
|
|
73072
72769
|
try {
|
|
73073
72770
|
const fs34 = await import("node:fs/promises");
|
|
73074
|
-
const
|
|
73075
|
-
const reportPath =
|
|
73076
|
-
await fs34.mkdir(
|
|
72771
|
+
const path52 = await import("node:path");
|
|
72772
|
+
const reportPath = path52.join(directory, ".swarm", "simulate-report.md");
|
|
72773
|
+
await fs34.mkdir(path52.dirname(reportPath), { recursive: true });
|
|
73077
72774
|
await fs34.writeFile(reportPath, report, "utf-8");
|
|
73078
72775
|
} catch (err2) {
|
|
73079
72776
|
const writeErr = err2 instanceof Error ? err2.message : String(err2);
|
|
@@ -73097,12 +72794,12 @@ async function handleSpecifyCommand(_directory, args2) {
|
|
|
73097
72794
|
|
|
73098
72795
|
// src/turbo/lean/state.ts
|
|
73099
72796
|
import * as fs34 from "node:fs";
|
|
73100
|
-
import * as
|
|
72797
|
+
import * as path52 from "node:path";
|
|
73101
72798
|
function nowISO2() {
|
|
73102
72799
|
return new Date().toISOString();
|
|
73103
72800
|
}
|
|
73104
72801
|
function ensureSwarmDir2(directory) {
|
|
73105
|
-
const swarmDir =
|
|
72802
|
+
const swarmDir = path52.resolve(directory, ".swarm");
|
|
73106
72803
|
if (!fs34.existsSync(swarmDir)) {
|
|
73107
72804
|
fs34.mkdirSync(swarmDir, { recursive: true });
|
|
73108
72805
|
}
|
|
@@ -73146,7 +72843,7 @@ function markStateUnreadable2(directory, reason) {
|
|
|
73146
72843
|
}
|
|
73147
72844
|
function readPersisted2(directory) {
|
|
73148
72845
|
try {
|
|
73149
|
-
const filePath =
|
|
72846
|
+
const filePath = path52.join(directory, ".swarm", STATE_FILE2);
|
|
73150
72847
|
if (!fs34.existsSync(filePath)) {
|
|
73151
72848
|
const seed = emptyPersisted2();
|
|
73152
72849
|
try {
|
|
@@ -73182,7 +72879,7 @@ function writePersisted2(directory, persisted) {
|
|
|
73182
72879
|
let payload;
|
|
73183
72880
|
try {
|
|
73184
72881
|
ensureSwarmDir2(directory);
|
|
73185
|
-
filePath =
|
|
72882
|
+
filePath = path52.join(directory, ".swarm", STATE_FILE2);
|
|
73186
72883
|
tmpPath = `${filePath}.tmp.${Date.now()}`;
|
|
73187
72884
|
persisted.updatedAt = nowISO2();
|
|
73188
72885
|
payload = `${JSON.stringify(persisted, null, 2)}
|
|
@@ -73249,7 +72946,7 @@ var init_state3 = __esm(() => {
|
|
|
73249
72946
|
|
|
73250
72947
|
// src/services/compaction-service.ts
|
|
73251
72948
|
import * as fs35 from "node:fs";
|
|
73252
|
-
import * as
|
|
72949
|
+
import * as path53 from "node:path";
|
|
73253
72950
|
function makeInitialState() {
|
|
73254
72951
|
return {
|
|
73255
72952
|
lastObservationAt: 0,
|
|
@@ -73271,7 +72968,7 @@ function getSessionState(sessionId) {
|
|
|
73271
72968
|
}
|
|
73272
72969
|
function appendSnapshot(directory, tier, budgetPct, message) {
|
|
73273
72970
|
try {
|
|
73274
|
-
const snapshotPath =
|
|
72971
|
+
const snapshotPath = path53.join(directory, ".swarm", "context-snapshot.md");
|
|
73275
72972
|
const timestamp = new Date().toISOString();
|
|
73276
72973
|
const entry = `
|
|
73277
72974
|
## [${tier.toUpperCase()}] ${timestamp} — ${budgetPct.toFixed(1)}% used
|
|
@@ -73524,10 +73221,10 @@ var init_context_budget_service = __esm(() => {
|
|
|
73524
73221
|
|
|
73525
73222
|
// src/services/status-service.ts
|
|
73526
73223
|
import * as fsSync3 from "node:fs";
|
|
73527
|
-
import * as
|
|
73224
|
+
import * as path54 from "node:path";
|
|
73528
73225
|
function readSpecStalenessSnapshot(directory) {
|
|
73529
73226
|
try {
|
|
73530
|
-
const p =
|
|
73227
|
+
const p = path54.join(directory, ".swarm", "spec-staleness.json");
|
|
73531
73228
|
if (!fsSync3.existsSync(p))
|
|
73532
73229
|
return { stale: false };
|
|
73533
73230
|
const raw = fsSync3.readFileSync(p, "utf-8");
|
|
@@ -74053,7 +73750,7 @@ var init_write_retro2 = __esm(() => {
|
|
|
74053
73750
|
|
|
74054
73751
|
// src/commands/command-dispatch.ts
|
|
74055
73752
|
import fs36 from "node:fs";
|
|
74056
|
-
import
|
|
73753
|
+
import path55 from "node:path";
|
|
74057
73754
|
function normalizeSwarmCommandInput(command, argumentText) {
|
|
74058
73755
|
if (command !== "swarm" && !command.startsWith("swarm-")) {
|
|
74059
73756
|
return { isSwarmCommand: false, tokens: [] };
|
|
@@ -74089,9 +73786,9 @@ ${similar.map((cmd) => ` - /swarm ${cmd}`).join(`
|
|
|
74089
73786
|
`);
|
|
74090
73787
|
}
|
|
74091
73788
|
function maybeMarkFirstRun(directory) {
|
|
74092
|
-
const sentinelPath =
|
|
73789
|
+
const sentinelPath = path55.join(directory, ".swarm", ".first-run-complete");
|
|
74093
73790
|
try {
|
|
74094
|
-
const swarmDir =
|
|
73791
|
+
const swarmDir = path55.join(directory, ".swarm");
|
|
74095
73792
|
fs36.mkdirSync(swarmDir, { recursive: true });
|
|
74096
73793
|
fs36.writeFileSync(sentinelPath, `first-run-complete: ${new Date().toISOString()}
|
|
74097
73794
|
`, { flag: "wx" });
|
|
@@ -74773,24 +74470,24 @@ function validateAliases() {
|
|
|
74773
74470
|
}
|
|
74774
74471
|
aliasTargets.get(target).push(name2);
|
|
74775
74472
|
const visited = new Set;
|
|
74776
|
-
const
|
|
74473
|
+
const path56 = [];
|
|
74777
74474
|
let current = target;
|
|
74778
74475
|
while (current) {
|
|
74779
74476
|
const currentEntry = COMMAND_REGISTRY[current];
|
|
74780
74477
|
if (!currentEntry)
|
|
74781
74478
|
break;
|
|
74782
74479
|
if (visited.has(current)) {
|
|
74783
|
-
const cycleStart =
|
|
74480
|
+
const cycleStart = path56.indexOf(current);
|
|
74784
74481
|
const fullChain = [
|
|
74785
74482
|
name2,
|
|
74786
|
-
...
|
|
74483
|
+
...path56.slice(0, cycleStart > 0 ? cycleStart : path56.length),
|
|
74787
74484
|
current
|
|
74788
74485
|
].join(" → ");
|
|
74789
74486
|
errors5.push(`Circular alias detected: ${fullChain}`);
|
|
74790
74487
|
break;
|
|
74791
74488
|
}
|
|
74792
74489
|
visited.add(current);
|
|
74793
|
-
|
|
74490
|
+
path56.push(current);
|
|
74794
74491
|
current = currentEntry.aliasOf || "";
|
|
74795
74492
|
}
|
|
74796
74493
|
}
|
|
@@ -79468,8 +79165,8 @@ COVERAGE REPORTING:
|
|
|
79468
79165
|
`;
|
|
79469
79166
|
|
|
79470
79167
|
// src/agents/index.ts
|
|
79471
|
-
import { mkdir as
|
|
79472
|
-
import * as
|
|
79168
|
+
import { mkdir as mkdir9, writeFile as writeFile9 } from "node:fs/promises";
|
|
79169
|
+
import * as path56 from "node:path";
|
|
79473
79170
|
function stripSwarmPrefix(agentName, swarmPrefix) {
|
|
79474
79171
|
if (!swarmPrefix || !agentName)
|
|
79475
79172
|
return agentName;
|
|
@@ -79872,14 +79569,14 @@ function getAgentConfigs(config3, directory, sessionId, projectContext) {
|
|
|
79872
79569
|
}));
|
|
79873
79570
|
if (directory) {
|
|
79874
79571
|
const sid = sessionId ?? `init-${Date.now()}`;
|
|
79875
|
-
const evidenceDir =
|
|
79572
|
+
const evidenceDir = path56.join(directory, ".swarm", "evidence");
|
|
79876
79573
|
const filename = `agent-tools-${sid}.json`;
|
|
79877
79574
|
const snapshotData = JSON.stringify({
|
|
79878
79575
|
sessionId: sid,
|
|
79879
79576
|
generatedAt: new Date().toISOString(),
|
|
79880
79577
|
agents: agentToolSnapshot
|
|
79881
79578
|
}, null, 2);
|
|
79882
|
-
|
|
79579
|
+
mkdir9(evidenceDir, { recursive: true }).then(() => writeFile9(path56.join(evidenceDir, filename), snapshotData)).catch(() => {});
|
|
79883
79580
|
}
|
|
79884
79581
|
return result;
|
|
79885
79582
|
}
|
|
@@ -79916,14 +79613,14 @@ __export(exports_evidence_summary_integration, {
|
|
|
79916
79613
|
createEvidenceSummaryIntegration: () => createEvidenceSummaryIntegration,
|
|
79917
79614
|
EvidenceSummaryIntegration: () => EvidenceSummaryIntegration
|
|
79918
79615
|
});
|
|
79919
|
-
import { existsSync as
|
|
79920
|
-
import * as
|
|
79616
|
+
import { existsSync as existsSync31, mkdirSync as mkdirSync17, writeFileSync as writeFileSync8 } from "node:fs";
|
|
79617
|
+
import * as path57 from "node:path";
|
|
79921
79618
|
function persistSummary(projectDir, artifact, filename) {
|
|
79922
|
-
const swarmPath =
|
|
79923
|
-
if (!
|
|
79619
|
+
const swarmPath = path57.join(projectDir, ".swarm");
|
|
79620
|
+
if (!existsSync31(swarmPath)) {
|
|
79924
79621
|
mkdirSync17(swarmPath, { recursive: true });
|
|
79925
79622
|
}
|
|
79926
|
-
const artifactPath =
|
|
79623
|
+
const artifactPath = path57.join(swarmPath, filename);
|
|
79927
79624
|
const content = JSON.stringify(artifact, null, 2);
|
|
79928
79625
|
writeFileSync8(artifactPath, content, "utf-8");
|
|
79929
79626
|
log("[EvidenceSummaryIntegration] Summary persisted", {
|
|
@@ -80042,7 +79739,7 @@ __export(exports_status_artifact, {
|
|
|
80042
79739
|
AutomationStatusArtifact: () => AutomationStatusArtifact
|
|
80043
79740
|
});
|
|
80044
79741
|
import * as fs38 from "node:fs";
|
|
80045
|
-
import * as
|
|
79742
|
+
import * as path59 from "node:path";
|
|
80046
79743
|
function createEmptySnapshot(mode, capabilities) {
|
|
80047
79744
|
return {
|
|
80048
79745
|
timestamp: Date.now(),
|
|
@@ -80101,7 +79798,7 @@ class AutomationStatusArtifact {
|
|
|
80101
79798
|
});
|
|
80102
79799
|
}
|
|
80103
79800
|
getFilePath() {
|
|
80104
|
-
return
|
|
79801
|
+
return path59.join(this.swarmDir, this.filename);
|
|
80105
79802
|
}
|
|
80106
79803
|
load() {
|
|
80107
79804
|
const filePath = this.getFilePath();
|
|
@@ -80514,12 +80211,12 @@ __export(exports_review_receipt, {
|
|
|
80514
80211
|
});
|
|
80515
80212
|
import * as crypto5 from "node:crypto";
|
|
80516
80213
|
import * as fs44 from "node:fs";
|
|
80517
|
-
import * as
|
|
80214
|
+
import * as path62 from "node:path";
|
|
80518
80215
|
function resolveReceiptsDir(directory) {
|
|
80519
|
-
return
|
|
80216
|
+
return path62.join(directory, ".swarm", "review-receipts");
|
|
80520
80217
|
}
|
|
80521
80218
|
function resolveReceiptIndexPath(directory) {
|
|
80522
|
-
return
|
|
80219
|
+
return path62.join(resolveReceiptsDir(directory), "index.json");
|
|
80523
80220
|
}
|
|
80524
80221
|
function buildReceiptFilename(id, date9) {
|
|
80525
80222
|
const dateStr = date9.toISOString().slice(0, 10);
|
|
@@ -80558,7 +80255,7 @@ async function readReceiptIndex(directory) {
|
|
|
80558
80255
|
}
|
|
80559
80256
|
async function writeReceiptIndex(directory, index) {
|
|
80560
80257
|
const indexPath = resolveReceiptIndexPath(directory);
|
|
80561
|
-
const dir =
|
|
80258
|
+
const dir = path62.dirname(indexPath);
|
|
80562
80259
|
await fs44.promises.mkdir(dir, { recursive: true });
|
|
80563
80260
|
const tmpPath = `${indexPath}.tmp.${Date.now()}.${Math.random().toString(36).slice(2)}`;
|
|
80564
80261
|
await fs44.promises.writeFile(tmpPath, JSON.stringify(index, null, 2), "utf-8");
|
|
@@ -80569,7 +80266,7 @@ async function persistReviewReceipt(directory, receipt) {
|
|
|
80569
80266
|
await fs44.promises.mkdir(receiptsDir, { recursive: true });
|
|
80570
80267
|
const now = new Date(receipt.reviewed_at);
|
|
80571
80268
|
const filename = buildReceiptFilename(receipt.id, now);
|
|
80572
|
-
const receiptPath =
|
|
80269
|
+
const receiptPath = path62.join(receiptsDir, filename);
|
|
80573
80270
|
const tmpPath = `${receiptPath}.tmp.${Date.now()}.${Math.random().toString(36).slice(2)}`;
|
|
80574
80271
|
await fs44.promises.writeFile(tmpPath, JSON.stringify(receipt, null, 2), "utf-8");
|
|
80575
80272
|
fs44.renameSync(tmpPath, receiptPath);
|
|
@@ -80591,7 +80288,7 @@ async function readReceiptById(directory, receiptId) {
|
|
|
80591
80288
|
const entry = index.entries.find((e) => e.id === receiptId);
|
|
80592
80289
|
if (!entry)
|
|
80593
80290
|
return null;
|
|
80594
|
-
const receiptPath =
|
|
80291
|
+
const receiptPath = path62.join(resolveReceiptsDir(directory), entry.filename);
|
|
80595
80292
|
try {
|
|
80596
80293
|
const content = await fs44.promises.readFile(receiptPath, "utf-8");
|
|
80597
80294
|
return JSON.parse(content);
|
|
@@ -80604,7 +80301,7 @@ async function readReceiptsByScopeHash(directory, scopeHash) {
|
|
|
80604
80301
|
const matching = index.entries.filter((e) => e.scope_hash === scopeHash).sort((a, b) => b.reviewed_at.localeCompare(a.reviewed_at));
|
|
80605
80302
|
const receipts = [];
|
|
80606
80303
|
for (const entry of matching) {
|
|
80607
|
-
const receiptPath =
|
|
80304
|
+
const receiptPath = path62.join(resolveReceiptsDir(directory), entry.filename);
|
|
80608
80305
|
try {
|
|
80609
80306
|
const content = await fs44.promises.readFile(receiptPath, "utf-8");
|
|
80610
80307
|
receipts.push(JSON.parse(content));
|
|
@@ -80617,7 +80314,7 @@ async function readAllReceipts(directory) {
|
|
|
80617
80314
|
const sorted = [...index.entries].sort((a, b) => b.reviewed_at.localeCompare(a.reviewed_at));
|
|
80618
80315
|
const receipts = [];
|
|
80619
80316
|
for (const entry of sorted) {
|
|
80620
|
-
const receiptPath =
|
|
80317
|
+
const receiptPath = path62.join(resolveReceiptsDir(directory), entry.filename);
|
|
80621
80318
|
try {
|
|
80622
80319
|
const content = await fs44.promises.readFile(receiptPath, "utf-8");
|
|
80623
80320
|
receipts.push(JSON.parse(content));
|
|
@@ -82205,11 +81902,11 @@ ${JSON.stringify(symbolNames, null, 2)}`);
|
|
|
82205
81902
|
throw toThrow;
|
|
82206
81903
|
}, "quit_");
|
|
82207
81904
|
var scriptDirectory = "";
|
|
82208
|
-
function locateFile(
|
|
81905
|
+
function locateFile(path77) {
|
|
82209
81906
|
if (Module["locateFile"]) {
|
|
82210
|
-
return Module["locateFile"](
|
|
81907
|
+
return Module["locateFile"](path77, scriptDirectory);
|
|
82211
81908
|
}
|
|
82212
|
-
return scriptDirectory +
|
|
81909
|
+
return scriptDirectory + path77;
|
|
82213
81910
|
}
|
|
82214
81911
|
__name(locateFile, "locateFile");
|
|
82215
81912
|
var readAsync, readBinary;
|
|
@@ -83959,12 +83656,12 @@ __export(exports_runtime, {
|
|
|
83959
83656
|
clearParserCache: () => clearParserCache,
|
|
83960
83657
|
_internals: () => _internals37
|
|
83961
83658
|
});
|
|
83962
|
-
import * as
|
|
83659
|
+
import * as path77 from "node:path";
|
|
83963
83660
|
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
83964
83661
|
async function initTreeSitter() {
|
|
83965
83662
|
if (!treeSitterInitPromise) {
|
|
83966
83663
|
treeSitterInitPromise = (async () => {
|
|
83967
|
-
const thisDir =
|
|
83664
|
+
const thisDir = path77.dirname(fileURLToPath2(import.meta.url));
|
|
83968
83665
|
const isSource = thisDir.replace(/\\/g, "/").endsWith("/src/lang");
|
|
83969
83666
|
if (isSource) {
|
|
83970
83667
|
await _internals37.parserInit();
|
|
@@ -83972,7 +83669,7 @@ async function initTreeSitter() {
|
|
|
83972
83669
|
const grammarsDir = getGrammarsDirAbsolute();
|
|
83973
83670
|
await _internals37.parserInit({
|
|
83974
83671
|
locateFile(scriptName) {
|
|
83975
|
-
return
|
|
83672
|
+
return path77.join(grammarsDir, scriptName);
|
|
83976
83673
|
}
|
|
83977
83674
|
});
|
|
83978
83675
|
}
|
|
@@ -83998,11 +83695,11 @@ function getWasmFileName(languageId) {
|
|
|
83998
83695
|
return `tree-sitter-${sanitized}.wasm`;
|
|
83999
83696
|
}
|
|
84000
83697
|
function getGrammarsDirAbsolute() {
|
|
84001
|
-
const thisDir =
|
|
83698
|
+
const thisDir = path77.dirname(fileURLToPath2(import.meta.url));
|
|
84002
83699
|
const normalized = thisDir.replace(/\\/g, "/");
|
|
84003
83700
|
const isSource = normalized.endsWith("/src/lang");
|
|
84004
83701
|
const isCliBundle = normalized.endsWith("/cli");
|
|
84005
|
-
return isSource ?
|
|
83702
|
+
return isSource ? path77.join(thisDir, "grammars") : isCliBundle ? path77.join(thisDir, "..", "lang", "grammars") : path77.join(thisDir, "lang", "grammars");
|
|
84006
83703
|
}
|
|
84007
83704
|
async function loadGrammar(languageId) {
|
|
84008
83705
|
if (typeof languageId !== "string" || languageId.length > 100) {
|
|
@@ -84018,9 +83715,9 @@ async function loadGrammar(languageId) {
|
|
|
84018
83715
|
await initTreeSitter();
|
|
84019
83716
|
const parser = new Parser;
|
|
84020
83717
|
const wasmFileName = getWasmFileName(normalizedId);
|
|
84021
|
-
const wasmPath =
|
|
84022
|
-
const { existsSync:
|
|
84023
|
-
if (!
|
|
83718
|
+
const wasmPath = path77.join(getGrammarsDirAbsolute(), wasmFileName);
|
|
83719
|
+
const { existsSync: existsSync41 } = await import("node:fs");
|
|
83720
|
+
if (!existsSync41(wasmPath)) {
|
|
84024
83721
|
throw new Error(`Grammar file not found for ${languageId}: ${wasmPath}
|
|
84025
83722
|
Make sure to run 'bun run build' to copy grammar files to dist/lang/grammars/`);
|
|
84026
83723
|
}
|
|
@@ -84053,7 +83750,7 @@ async function isGrammarAvailable(languageId) {
|
|
|
84053
83750
|
}
|
|
84054
83751
|
try {
|
|
84055
83752
|
const wasmFileName = getWasmFileName(normalizedId);
|
|
84056
|
-
const wasmPath =
|
|
83753
|
+
const wasmPath = path77.join(getGrammarsDirAbsolute(), wasmFileName);
|
|
84057
83754
|
const { statSync: statSync21 } = await import("node:fs");
|
|
84058
83755
|
statSync21(wasmPath);
|
|
84059
83756
|
return true;
|
|
@@ -84115,20 +83812,20 @@ __export(exports_doc_scan, {
|
|
|
84115
83812
|
import * as crypto7 from "node:crypto";
|
|
84116
83813
|
import * as fs53 from "node:fs";
|
|
84117
83814
|
import {
|
|
84118
|
-
mkdir as
|
|
83815
|
+
mkdir as mkdir12,
|
|
84119
83816
|
readdir as readdir5,
|
|
84120
|
-
readFile as
|
|
83817
|
+
readFile as readFile11,
|
|
84121
83818
|
realpath as realpath2,
|
|
84122
83819
|
stat as stat6,
|
|
84123
|
-
writeFile as
|
|
83820
|
+
writeFile as writeFile11
|
|
84124
83821
|
} from "node:fs/promises";
|
|
84125
|
-
import * as
|
|
83822
|
+
import * as path79 from "node:path";
|
|
84126
83823
|
function normalizeSeparators(filePath) {
|
|
84127
83824
|
return filePath.replace(/\\/g, "/");
|
|
84128
83825
|
}
|
|
84129
83826
|
function matchesDocPattern(filePath, patterns) {
|
|
84130
83827
|
const normalizedPath = normalizeSeparators(filePath);
|
|
84131
|
-
const basename10 =
|
|
83828
|
+
const basename10 = path79.basename(filePath);
|
|
84132
83829
|
for (const pattern of patterns) {
|
|
84133
83830
|
if (!pattern.includes("/") && !pattern.includes("\\")) {
|
|
84134
83831
|
if (basename10 === pattern) {
|
|
@@ -84184,7 +83881,7 @@ function stripMarkdown(text) {
|
|
|
84184
83881
|
return text.replace(/\[([^\]]+)\]\([^)]+\)/g, "$1").replace(/\*\*([^*]+)\*\*/g, "$1").replace(/`([^`]+)`/g, "$1").replace(/^\s*[-*•]\s+/gm, "").replace(/^\s*\d+\.\s+/gm, "").trim();
|
|
84185
83882
|
}
|
|
84186
83883
|
async function scanDocIndex(directory) {
|
|
84187
|
-
const manifestPath =
|
|
83884
|
+
const manifestPath = path79.join(directory, ".swarm", "doc-manifest.json");
|
|
84188
83885
|
const defaultPatterns = DocsConfigSchema.parse({}).doc_patterns;
|
|
84189
83886
|
const extraPatterns = [
|
|
84190
83887
|
"ARCHITECTURE.md",
|
|
@@ -84195,13 +83892,13 @@ async function scanDocIndex(directory) {
|
|
|
84195
83892
|
];
|
|
84196
83893
|
const allPatterns = [...defaultPatterns, ...extraPatterns];
|
|
84197
83894
|
try {
|
|
84198
|
-
const manifestContent = await
|
|
83895
|
+
const manifestContent = await readFile11(manifestPath, "utf-8");
|
|
84199
83896
|
const existingManifest = JSON.parse(manifestContent);
|
|
84200
83897
|
if (existingManifest.schema_version === 1 && existingManifest.files) {
|
|
84201
83898
|
let cacheValid = true;
|
|
84202
83899
|
for (const file3 of existingManifest.files) {
|
|
84203
83900
|
try {
|
|
84204
|
-
const fullPath =
|
|
83901
|
+
const fullPath = path79.join(directory, file3.path);
|
|
84205
83902
|
const stat7 = fs53.statSync(fullPath);
|
|
84206
83903
|
if (stat7.mtimeMs > file3.mtime) {
|
|
84207
83904
|
cacheValid = false;
|
|
@@ -84236,10 +83933,10 @@ async function scanDocIndex(directory) {
|
|
|
84236
83933
|
let isFile = entry.isFile();
|
|
84237
83934
|
if (entry.isSymbolicLink()) {
|
|
84238
83935
|
try {
|
|
84239
|
-
const symlinkPath =
|
|
83936
|
+
const symlinkPath = path79.join(dir, entry.name);
|
|
84240
83937
|
const resolved = await realpath2(symlinkPath);
|
|
84241
|
-
const rel =
|
|
84242
|
-
if (rel.startsWith("..") ||
|
|
83938
|
+
const rel = path79.relative(resolvedDirectory, resolved);
|
|
83939
|
+
if (rel.startsWith("..") || path79.isAbsolute(rel))
|
|
84243
83940
|
continue;
|
|
84244
83941
|
const targetStat = await stat6(symlinkPath);
|
|
84245
83942
|
isFile = targetStat.isFile();
|
|
@@ -84249,14 +83946,14 @@ async function scanDocIndex(directory) {
|
|
|
84249
83946
|
}
|
|
84250
83947
|
if (isDir) {
|
|
84251
83948
|
if (!SKIP_DIRECTORIES3.has(entry.name)) {
|
|
84252
|
-
await walkDir(
|
|
83949
|
+
await walkDir(path79.join(dir, entry.name));
|
|
84253
83950
|
}
|
|
84254
83951
|
continue;
|
|
84255
83952
|
}
|
|
84256
83953
|
if (!isFile)
|
|
84257
83954
|
continue;
|
|
84258
|
-
const fullPath =
|
|
84259
|
-
const relPath = normalizeSeparators(
|
|
83955
|
+
const fullPath = path79.join(dir, entry.name);
|
|
83956
|
+
const relPath = normalizeSeparators(path79.relative(directory, fullPath));
|
|
84260
83957
|
let skipThisFile = false;
|
|
84261
83958
|
for (const pattern of SKIP_PATTERNS) {
|
|
84262
83959
|
if (pattern.test(relPath)) {
|
|
@@ -84276,11 +83973,11 @@ async function scanDocIndex(directory) {
|
|
|
84276
83973
|
}
|
|
84277
83974
|
let content;
|
|
84278
83975
|
try {
|
|
84279
|
-
content = await
|
|
83976
|
+
content = await readFile11(fullPath, "utf-8");
|
|
84280
83977
|
} catch {
|
|
84281
83978
|
continue;
|
|
84282
83979
|
}
|
|
84283
|
-
const { title, summary } = extractTitleAndSummary(content,
|
|
83980
|
+
const { title, summary } = extractTitleAndSummary(content, path79.basename(relPath));
|
|
84284
83981
|
discoveredFiles.push({
|
|
84285
83982
|
path: relPath,
|
|
84286
83983
|
title,
|
|
@@ -84317,8 +84014,8 @@ async function scanDocIndex(directory) {
|
|
|
84317
84014
|
files: discoveredFiles
|
|
84318
84015
|
};
|
|
84319
84016
|
try {
|
|
84320
|
-
await
|
|
84321
|
-
await
|
|
84017
|
+
await mkdir12(path79.dirname(manifestPath), { recursive: true });
|
|
84018
|
+
await writeFile11(manifestPath, JSON.stringify(manifest, null, 2), "utf-8");
|
|
84322
84019
|
} catch {}
|
|
84323
84020
|
return { manifest, cached: false };
|
|
84324
84021
|
}
|
|
@@ -84356,10 +84053,10 @@ function extractConstraintsFromContent(content) {
|
|
|
84356
84053
|
return constraints;
|
|
84357
84054
|
}
|
|
84358
84055
|
async function extractDocConstraints(directory, taskFiles, taskDescription) {
|
|
84359
|
-
const manifestPath =
|
|
84056
|
+
const manifestPath = path79.join(directory, ".swarm", "doc-manifest.json");
|
|
84360
84057
|
let manifest;
|
|
84361
84058
|
try {
|
|
84362
|
-
const content = await
|
|
84059
|
+
const content = await readFile11(manifestPath, "utf-8");
|
|
84363
84060
|
manifest = JSON.parse(content);
|
|
84364
84061
|
} catch {
|
|
84365
84062
|
const result = await scanDocIndex(directory);
|
|
@@ -84382,7 +84079,7 @@ async function extractDocConstraints(directory, taskFiles, taskDescription) {
|
|
|
84382
84079
|
}
|
|
84383
84080
|
let fullContent;
|
|
84384
84081
|
try {
|
|
84385
|
-
fullContent = await
|
|
84082
|
+
fullContent = await readFile11(path79.join(directory, docFile.path), "utf-8");
|
|
84386
84083
|
} catch {
|
|
84387
84084
|
skippedCount++;
|
|
84388
84085
|
continue;
|
|
@@ -84405,7 +84102,7 @@ async function extractDocConstraints(directory, taskFiles, taskDescription) {
|
|
|
84405
84102
|
tier: "swarm",
|
|
84406
84103
|
lesson: constraint,
|
|
84407
84104
|
category: "architecture",
|
|
84408
|
-
tags: ["doc-scan",
|
|
84105
|
+
tags: ["doc-scan", path79.basename(docFile.path)],
|
|
84409
84106
|
scope: "global",
|
|
84410
84107
|
confidence: 0.5,
|
|
84411
84108
|
status: "candidate",
|
|
@@ -84484,7 +84181,7 @@ var init_doc_scan = __esm(() => {
|
|
|
84484
84181
|
}
|
|
84485
84182
|
} catch {}
|
|
84486
84183
|
if (force) {
|
|
84487
|
-
const manifestPath =
|
|
84184
|
+
const manifestPath = path79.join(directory, ".swarm", "doc-manifest.json");
|
|
84488
84185
|
try {
|
|
84489
84186
|
fs53.unlinkSync(manifestPath);
|
|
84490
84187
|
} catch {}
|
|
@@ -84536,11 +84233,12 @@ __export(exports_knowledge_recall, {
|
|
|
84536
84233
|
knowledge_recall: () => knowledge_recall,
|
|
84537
84234
|
_internals: () => _internals38
|
|
84538
84235
|
});
|
|
84539
|
-
var knowledge_recall, _internals38;
|
|
84236
|
+
var NORMAL_RETRIEVAL_STATUSES, knowledge_recall, _internals38;
|
|
84540
84237
|
var init_knowledge_recall = __esm(() => {
|
|
84541
84238
|
init_zod();
|
|
84542
84239
|
init_knowledge_store();
|
|
84543
84240
|
init_create_tool();
|
|
84241
|
+
NORMAL_RETRIEVAL_STATUSES = new Set(["established", "promoted"]);
|
|
84544
84242
|
knowledge_recall = createSwarmTool({
|
|
84545
84243
|
description: "Search the knowledge base for relevant past decisions, patterns, and lessons learned. Returns ranked results by semantic similarity.",
|
|
84546
84244
|
args: {
|
|
@@ -84592,7 +84290,9 @@ var init_knowledge_recall = __esm(() => {
|
|
|
84592
84290
|
if (tier === "all" || tier === "hive") {
|
|
84593
84291
|
entries = entries.concat(hiveEntries);
|
|
84594
84292
|
}
|
|
84595
|
-
|
|
84293
|
+
const retractions = await readRetractionRecords(directory);
|
|
84294
|
+
const suppressedLessons = new Set(retractions.map((record3) => record3.normalized_lesson).filter((value) => typeof value === "string" && value.length > 0));
|
|
84295
|
+
entries = entries.filter((entry) => NORMAL_RETRIEVAL_STATUSES.has(entry.status) && !suppressedLessons.has(normalize2(entry.lesson)));
|
|
84596
84296
|
if (entries.length === 0) {
|
|
84597
84297
|
const result2 = { results: [], total: 0 };
|
|
84598
84298
|
return JSON.stringify(result2);
|
|
@@ -84680,9 +84380,9 @@ __export(exports_curator_drift, {
|
|
|
84680
84380
|
_internals: () => _internals40
|
|
84681
84381
|
});
|
|
84682
84382
|
import * as fs60 from "node:fs";
|
|
84683
|
-
import * as
|
|
84383
|
+
import * as path85 from "node:path";
|
|
84684
84384
|
async function readPriorDriftReports(directory) {
|
|
84685
|
-
const swarmDir =
|
|
84385
|
+
const swarmDir = path85.join(directory, ".swarm");
|
|
84686
84386
|
const entries = await fs60.promises.readdir(swarmDir).catch(() => null);
|
|
84687
84387
|
if (entries === null)
|
|
84688
84388
|
return [];
|
|
@@ -84709,7 +84409,7 @@ async function readPriorDriftReports(directory) {
|
|
|
84709
84409
|
async function writeDriftReport(directory, report) {
|
|
84710
84410
|
const filename = `${DRIFT_REPORT_PREFIX}${report.phase}.json`;
|
|
84711
84411
|
const filePath = validateSwarmPath(directory, filename);
|
|
84712
|
-
const swarmDir =
|
|
84412
|
+
const swarmDir = path85.dirname(filePath);
|
|
84713
84413
|
await fs60.promises.mkdir(swarmDir, { recursive: true });
|
|
84714
84414
|
try {
|
|
84715
84415
|
await fs60.promises.writeFile(filePath, JSON.stringify(report, null, 2), "utf-8");
|
|
@@ -84996,7 +84696,7 @@ init_manager3();
|
|
|
84996
84696
|
init_manager();
|
|
84997
84697
|
init_utils();
|
|
84998
84698
|
import * as fs37 from "node:fs";
|
|
84999
|
-
import * as
|
|
84699
|
+
import * as path58 from "node:path";
|
|
85000
84700
|
|
|
85001
84701
|
class PlanSyncWorker {
|
|
85002
84702
|
directory;
|
|
@@ -85020,10 +84720,10 @@ class PlanSyncWorker {
|
|
|
85020
84720
|
this.onSyncComplete = options.onSyncComplete;
|
|
85021
84721
|
}
|
|
85022
84722
|
getSwarmDir() {
|
|
85023
|
-
return
|
|
84723
|
+
return path58.resolve(this.directory, ".swarm");
|
|
85024
84724
|
}
|
|
85025
84725
|
getPlanJsonPath() {
|
|
85026
|
-
return
|
|
84726
|
+
return path58.join(this.getSwarmDir(), "plan.json");
|
|
85027
84727
|
}
|
|
85028
84728
|
start() {
|
|
85029
84729
|
if (this.disposed) {
|
|
@@ -85242,8 +84942,8 @@ class PlanSyncWorker {
|
|
|
85242
84942
|
checkForUnauthorizedWrite() {
|
|
85243
84943
|
try {
|
|
85244
84944
|
const swarmDir = this.getSwarmDir();
|
|
85245
|
-
const planJsonPath =
|
|
85246
|
-
const markerPath =
|
|
84945
|
+
const planJsonPath = path58.join(swarmDir, "plan.json");
|
|
84946
|
+
const markerPath = path58.join(swarmDir, ".plan-write-marker");
|
|
85247
84947
|
const planStats = fs37.statSync(planJsonPath);
|
|
85248
84948
|
const planMtimeMs = Math.floor(planStats.mtimeMs);
|
|
85249
84949
|
const markerContent = fs37.readFileSync(markerPath, "utf8");
|
|
@@ -85284,13 +84984,13 @@ init_constants();
|
|
|
85284
84984
|
// src/config/project-init.ts
|
|
85285
84985
|
init_constants();
|
|
85286
84986
|
import * as fs39 from "node:fs";
|
|
85287
|
-
import * as
|
|
84987
|
+
import * as path60 from "node:path";
|
|
85288
84988
|
var STARTER_CONTENT = `{}
|
|
85289
84989
|
`;
|
|
85290
84990
|
function writeProjectConfigIfNew(directory, quiet = false) {
|
|
85291
84991
|
try {
|
|
85292
|
-
const opencodeDir =
|
|
85293
|
-
const dest =
|
|
84992
|
+
const opencodeDir = path60.join(directory, ".opencode");
|
|
84993
|
+
const dest = path60.join(opencodeDir, "opencode-swarm.json");
|
|
85294
84994
|
try {
|
|
85295
84995
|
const stat4 = fs39.lstatSync(opencodeDir);
|
|
85296
84996
|
if (stat4.isSymbolicLink())
|
|
@@ -85315,8 +85015,8 @@ function writeProjectConfigIfNew(directory, quiet = false) {
|
|
|
85315
85015
|
}
|
|
85316
85016
|
function writeSwarmConfigExampleIfNew(projectDirectory) {
|
|
85317
85017
|
try {
|
|
85318
|
-
const swarmDir =
|
|
85319
|
-
const dest =
|
|
85018
|
+
const swarmDir = path60.join(projectDirectory, ".swarm");
|
|
85019
|
+
const dest = path60.join(swarmDir, "config.example.json");
|
|
85320
85020
|
if (fs39.existsSync(dest))
|
|
85321
85021
|
return;
|
|
85322
85022
|
if (!fs39.existsSync(swarmDir)) {
|
|
@@ -85353,7 +85053,7 @@ init_state();
|
|
|
85353
85053
|
init_logger();
|
|
85354
85054
|
init_state2();
|
|
85355
85055
|
import * as fs40 from "node:fs";
|
|
85356
|
-
import * as
|
|
85056
|
+
import * as path61 from "node:path";
|
|
85357
85057
|
var oversightSequenceCounter = 0;
|
|
85358
85058
|
var VALID_VERDICTS = [
|
|
85359
85059
|
"APPROVED",
|
|
@@ -85527,10 +85227,10 @@ async function writeFullAutoOversightEvidence(directory, phase, event) {
|
|
|
85527
85227
|
if (phase === undefined)
|
|
85528
85228
|
return;
|
|
85529
85229
|
try {
|
|
85530
|
-
const evidenceDir = validateSwarmPath(directory,
|
|
85230
|
+
const evidenceDir = validateSwarmPath(directory, path61.posix.join("evidence", String(phase)));
|
|
85531
85231
|
fs40.mkdirSync(evidenceDir, { recursive: true });
|
|
85532
85232
|
const fileName = `full-auto-${event.oversight_sequence}.json`;
|
|
85533
|
-
const filePath = validateSwarmPath(directory,
|
|
85233
|
+
const filePath = validateSwarmPath(directory, path61.posix.join("evidence", String(phase), fileName));
|
|
85534
85234
|
fs40.writeFileSync(filePath, `${JSON.stringify(event, null, 2)}
|
|
85535
85235
|
`, "utf-8");
|
|
85536
85236
|
return filePath;
|
|
@@ -85939,11 +85639,11 @@ async function doFlush(directory) {
|
|
|
85939
85639
|
const activitySection = renderActivitySection();
|
|
85940
85640
|
const updated = replaceOrAppendSection(existing, "## Agent Activity", activitySection);
|
|
85941
85641
|
const flushedCount = swarmState.pendingEvents;
|
|
85942
|
-
const
|
|
85943
|
-
const tempPath = `${
|
|
85642
|
+
const path62 = nodePath2.join(directory, ".swarm", "context.md");
|
|
85643
|
+
const tempPath = `${path62}.tmp`;
|
|
85944
85644
|
try {
|
|
85945
85645
|
await bunWrite(tempPath, updated);
|
|
85946
|
-
renameSync13(tempPath,
|
|
85646
|
+
renameSync13(tempPath, path62);
|
|
85947
85647
|
} catch (writeError) {
|
|
85948
85648
|
try {
|
|
85949
85649
|
unlinkSync11(tempPath);
|
|
@@ -86186,7 +85886,7 @@ init_state();
|
|
|
86186
85886
|
init_extractors();
|
|
86187
85887
|
init_utils2();
|
|
86188
85888
|
import * as fs41 from "node:fs";
|
|
86189
|
-
import { join as
|
|
85889
|
+
import { join as join54 } from "node:path";
|
|
86190
85890
|
function createCompactionCustomizerHook(config3, directory) {
|
|
86191
85891
|
const enabled = config3.hooks?.compaction !== false;
|
|
86192
85892
|
if (!enabled) {
|
|
@@ -86231,7 +85931,7 @@ function createCompactionCustomizerHook(config3, directory) {
|
|
|
86231
85931
|
}
|
|
86232
85932
|
}
|
|
86233
85933
|
try {
|
|
86234
|
-
const summariesDir =
|
|
85934
|
+
const summariesDir = join54(directory, ".swarm", "summaries");
|
|
86235
85935
|
const files = await fs41.promises.readdir(summariesDir);
|
|
86236
85936
|
if (files.length > 0) {
|
|
86237
85937
|
const count = files.length;
|
|
@@ -87611,7 +87311,7 @@ init_schema();
|
|
|
87611
87311
|
init_manager();
|
|
87612
87312
|
init_curator();
|
|
87613
87313
|
init_utils2();
|
|
87614
|
-
import * as
|
|
87314
|
+
import * as path63 from "node:path";
|
|
87615
87315
|
function createPhaseMonitorHook(directory, preflightManager, curatorRunner, delegateFactory) {
|
|
87616
87316
|
let lastKnownPhase = null;
|
|
87617
87317
|
const handler = async (input, _output) => {
|
|
@@ -87631,10 +87331,10 @@ function createPhaseMonitorHook(directory, preflightManager, curatorRunner, dele
|
|
|
87631
87331
|
const llmDelegate = delegateFactory?.(sessionId);
|
|
87632
87332
|
const initResult = await runner(directory, curatorConfig, llmDelegate);
|
|
87633
87333
|
if (initResult.briefing) {
|
|
87634
|
-
const briefingPath =
|
|
87635
|
-
const { mkdir:
|
|
87636
|
-
await
|
|
87637
|
-
await
|
|
87334
|
+
const briefingPath = path63.join(directory, ".swarm", "curator-briefing.md");
|
|
87335
|
+
const { mkdir: mkdir10, writeFile: writeFile10 } = await import("node:fs/promises");
|
|
87336
|
+
await mkdir10(path63.dirname(briefingPath), { recursive: true });
|
|
87337
|
+
await writeFile10(briefingPath, initResult.briefing, "utf-8");
|
|
87638
87338
|
const { buildApprovedReceipt: buildApprovedReceipt2, persistReviewReceipt: persistReviewReceipt2 } = await Promise.resolve().then(() => (init_review_receipt(), exports_review_receipt));
|
|
87639
87339
|
const initReceipt = buildApprovedReceipt2({
|
|
87640
87340
|
agent: "curator",
|
|
@@ -87760,16 +87460,16 @@ ${originalText}`;
|
|
|
87760
87460
|
// src/hooks/repo-graph-builder.ts
|
|
87761
87461
|
init_constants();
|
|
87762
87462
|
import { realpathSync as realpathSync10 } from "node:fs";
|
|
87763
|
-
import * as
|
|
87463
|
+
import * as path70 from "node:path";
|
|
87764
87464
|
|
|
87765
87465
|
// src/tools/repo-graph/builder.ts
|
|
87766
87466
|
init_logger();
|
|
87767
87467
|
init_path_security();
|
|
87768
87468
|
import * as fsSync4 from "node:fs";
|
|
87769
|
-
import { existsSync as
|
|
87469
|
+
import { existsSync as existsSync37, realpathSync as realpathSync8 } from "node:fs";
|
|
87770
87470
|
import * as fsPromises5 from "node:fs/promises";
|
|
87771
87471
|
import * as os7 from "node:os";
|
|
87772
|
-
import * as
|
|
87472
|
+
import * as path66 from "node:path";
|
|
87773
87473
|
|
|
87774
87474
|
// src/utils/timeout.ts
|
|
87775
87475
|
async function withTimeout(promise3, ms, timeoutError) {
|
|
@@ -87801,7 +87501,7 @@ init_zod();
|
|
|
87801
87501
|
init_create_tool();
|
|
87802
87502
|
init_path_security();
|
|
87803
87503
|
import * as fs45 from "node:fs";
|
|
87804
|
-
import * as
|
|
87504
|
+
import * as path64 from "node:path";
|
|
87805
87505
|
var MAX_FILE_SIZE_BYTES2 = 1024 * 1024;
|
|
87806
87506
|
var WINDOWS_RESERVED_NAMES = /^(con|prn|aux|nul|com[1-9]|lpt[1-9])(\.|:|$)/i;
|
|
87807
87507
|
function containsWindowsAttacks(str) {
|
|
@@ -87818,11 +87518,11 @@ function containsWindowsAttacks(str) {
|
|
|
87818
87518
|
}
|
|
87819
87519
|
function isPathInWorkspace(filePath, workspace) {
|
|
87820
87520
|
try {
|
|
87821
|
-
const resolvedPath =
|
|
87521
|
+
const resolvedPath = path64.resolve(workspace, filePath);
|
|
87822
87522
|
const realWorkspace = fs45.realpathSync(workspace);
|
|
87823
87523
|
const realResolvedPath = fs45.realpathSync(resolvedPath);
|
|
87824
|
-
const relativePath =
|
|
87825
|
-
if (relativePath.startsWith("..") ||
|
|
87524
|
+
const relativePath = path64.relative(realWorkspace, realResolvedPath);
|
|
87525
|
+
if (relativePath.startsWith("..") || path64.isAbsolute(relativePath)) {
|
|
87826
87526
|
return false;
|
|
87827
87527
|
}
|
|
87828
87528
|
return true;
|
|
@@ -87834,7 +87534,7 @@ function validatePathForRead(filePath, workspace) {
|
|
|
87834
87534
|
return isPathInWorkspace(filePath, workspace);
|
|
87835
87535
|
}
|
|
87836
87536
|
function extractTSSymbols(filePath, cwd) {
|
|
87837
|
-
const fullPath =
|
|
87537
|
+
const fullPath = path64.join(cwd, filePath);
|
|
87838
87538
|
if (!validatePathForRead(fullPath, cwd)) {
|
|
87839
87539
|
return [];
|
|
87840
87540
|
}
|
|
@@ -87986,7 +87686,7 @@ function extractTSSymbols(filePath, cwd) {
|
|
|
87986
87686
|
});
|
|
87987
87687
|
}
|
|
87988
87688
|
function extractPythonSymbols(filePath, cwd) {
|
|
87989
|
-
const fullPath =
|
|
87689
|
+
const fullPath = path64.join(cwd, filePath);
|
|
87990
87690
|
if (!validatePathForRead(fullPath, cwd)) {
|
|
87991
87691
|
return [];
|
|
87992
87692
|
}
|
|
@@ -88069,7 +87769,7 @@ var symbols = createSwarmTool({
|
|
|
88069
87769
|
}, null, 2);
|
|
88070
87770
|
}
|
|
88071
87771
|
const cwd = directory;
|
|
88072
|
-
const ext =
|
|
87772
|
+
const ext = path64.extname(file3);
|
|
88073
87773
|
if (containsControlChars(file3)) {
|
|
88074
87774
|
return JSON.stringify({
|
|
88075
87775
|
file: file3,
|
|
@@ -88130,16 +87830,16 @@ var symbols = createSwarmTool({
|
|
|
88130
87830
|
});
|
|
88131
87831
|
|
|
88132
87832
|
// src/tools/repo-graph/types.ts
|
|
88133
|
-
import * as
|
|
87833
|
+
import * as path65 from "node:path";
|
|
88134
87834
|
var REPO_GRAPH_FILENAME = "repo-graph.json";
|
|
88135
87835
|
var GRAPH_SCHEMA_VERSION = "1.0.0";
|
|
88136
87836
|
function normalizeGraphPath(filePath) {
|
|
88137
|
-
return
|
|
87837
|
+
return path65.normalize(filePath).replace(/\\/g, "/");
|
|
88138
87838
|
}
|
|
88139
87839
|
function createEmptyGraph(workspaceRoot) {
|
|
88140
87840
|
return {
|
|
88141
87841
|
schema_version: GRAPH_SCHEMA_VERSION,
|
|
88142
|
-
workspaceRoot:
|
|
87842
|
+
workspaceRoot: path65.normalize(workspaceRoot),
|
|
88143
87843
|
nodes: {},
|
|
88144
87844
|
edges: [],
|
|
88145
87845
|
metadata: {
|
|
@@ -88314,8 +88014,8 @@ function resolveModuleSpecifier(workspaceRoot, sourceFile, specifier) {
|
|
|
88314
88014
|
}
|
|
88315
88015
|
try {
|
|
88316
88016
|
if (specifier.startsWith(".")) {
|
|
88317
|
-
const sourceDir =
|
|
88318
|
-
let resolved =
|
|
88017
|
+
const sourceDir = path66.dirname(sourceFile);
|
|
88018
|
+
let resolved = path66.resolve(sourceDir, specifier);
|
|
88319
88019
|
let realResolved;
|
|
88320
88020
|
try {
|
|
88321
88021
|
realResolved = realpathSync8(resolved);
|
|
@@ -88326,9 +88026,9 @@ function resolveModuleSpecifier(workspaceRoot, sourceFile, specifier) {
|
|
|
88326
88026
|
try {
|
|
88327
88027
|
realRoot = realpathSync8(workspaceRoot);
|
|
88328
88028
|
} catch {
|
|
88329
|
-
realRoot =
|
|
88029
|
+
realRoot = path66.normalize(workspaceRoot);
|
|
88330
88030
|
}
|
|
88331
|
-
if (!
|
|
88031
|
+
if (!existsSync37(resolved)) {
|
|
88332
88032
|
const EXTENSIONS = [
|
|
88333
88033
|
".ts",
|
|
88334
88034
|
".tsx",
|
|
@@ -88342,7 +88042,7 @@ function resolveModuleSpecifier(workspaceRoot, sourceFile, specifier) {
|
|
|
88342
88042
|
let found = null;
|
|
88343
88043
|
for (const ext of EXTENSIONS) {
|
|
88344
88044
|
const candidate = resolved + ext;
|
|
88345
|
-
if (
|
|
88045
|
+
if (existsSync37(candidate)) {
|
|
88346
88046
|
found = candidate;
|
|
88347
88047
|
break;
|
|
88348
88048
|
}
|
|
@@ -88358,9 +88058,9 @@ function resolveModuleSpecifier(workspaceRoot, sourceFile, specifier) {
|
|
|
88358
88058
|
return null;
|
|
88359
88059
|
}
|
|
88360
88060
|
}
|
|
88361
|
-
const normalizedResolved =
|
|
88362
|
-
const normalizedRoot =
|
|
88363
|
-
if (!normalizedResolved.startsWith(normalizedRoot +
|
|
88061
|
+
const normalizedResolved = path66.normalize(realResolved);
|
|
88062
|
+
const normalizedRoot = path66.normalize(realRoot);
|
|
88063
|
+
if (!normalizedResolved.startsWith(normalizedRoot + path66.sep) && normalizedResolved !== normalizedRoot) {
|
|
88364
88064
|
return null;
|
|
88365
88065
|
}
|
|
88366
88066
|
return resolved;
|
|
@@ -88375,12 +88075,12 @@ function isRefusedWorkspaceRoot(target) {
|
|
|
88375
88075
|
try {
|
|
88376
88076
|
resolved = realpathSync8(target);
|
|
88377
88077
|
} catch {
|
|
88378
|
-
resolved =
|
|
88078
|
+
resolved = path66.resolve(target);
|
|
88379
88079
|
}
|
|
88380
88080
|
const refused = new Set;
|
|
88381
88081
|
const add = (p) => {
|
|
88382
88082
|
if (typeof p === "string" && p.length > 0) {
|
|
88383
|
-
refused.add(
|
|
88083
|
+
refused.add(path66.resolve(p));
|
|
88384
88084
|
}
|
|
88385
88085
|
};
|
|
88386
88086
|
add(os7.homedir());
|
|
@@ -88490,7 +88190,7 @@ async function findSourceFilesAsync(dir, stats, options) {
|
|
|
88490
88190
|
ctx.stats.skippedDirs++;
|
|
88491
88191
|
continue;
|
|
88492
88192
|
}
|
|
88493
|
-
const fullPath =
|
|
88193
|
+
const fullPath = path66.join(current, entry.name);
|
|
88494
88194
|
if (entry.isSymbolicLink() && !ctx.followSymlinks) {
|
|
88495
88195
|
ctx.stats.skippedDirs++;
|
|
88496
88196
|
continue;
|
|
@@ -88498,7 +88198,7 @@ async function findSourceFilesAsync(dir, stats, options) {
|
|
|
88498
88198
|
if (entry.isDirectory()) {
|
|
88499
88199
|
queue.push(fullPath);
|
|
88500
88200
|
} else if (entry.isFile()) {
|
|
88501
|
-
const ext =
|
|
88201
|
+
const ext = path66.extname(fullPath).toLowerCase();
|
|
88502
88202
|
if (SUPPORTED_EXTENSIONS.includes(ext)) {
|
|
88503
88203
|
files.push(fullPath);
|
|
88504
88204
|
}
|
|
@@ -88515,11 +88215,11 @@ async function findSourceFilesAsync(dir, stats, options) {
|
|
|
88515
88215
|
return files;
|
|
88516
88216
|
}
|
|
88517
88217
|
function toModuleName(filePath, workspaceRoot) {
|
|
88518
|
-
const relative12 =
|
|
88519
|
-
return relative12.split(
|
|
88218
|
+
const relative12 = path66.relative(workspaceRoot, filePath);
|
|
88219
|
+
return relative12.split(path66.sep).join("/");
|
|
88520
88220
|
}
|
|
88521
88221
|
function getLanguage(filePath) {
|
|
88522
|
-
const ext =
|
|
88222
|
+
const ext = path66.extname(filePath).toLowerCase();
|
|
88523
88223
|
return EXTENSION_TO_LANGUAGE[ext] ?? "unknown";
|
|
88524
88224
|
}
|
|
88525
88225
|
function isBinaryContent(content) {
|
|
@@ -88543,15 +88243,15 @@ function scanFile(filePath, absoluteRoot, maxFileSize) {
|
|
|
88543
88243
|
if (isBinaryContent(content)) {
|
|
88544
88244
|
return { node: null, edges: [] };
|
|
88545
88245
|
}
|
|
88546
|
-
const ext =
|
|
88246
|
+
const ext = path66.extname(filePath).toLowerCase();
|
|
88547
88247
|
let exports = [];
|
|
88548
88248
|
try {
|
|
88549
88249
|
if ([".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs"].includes(ext)) {
|
|
88550
|
-
const relativePath =
|
|
88250
|
+
const relativePath = path66.relative(absoluteRoot, filePath);
|
|
88551
88251
|
const symbols2 = extractTSSymbols(relativePath, absoluteRoot);
|
|
88552
88252
|
exports = symbols2.filter((s) => s.exported).map((s) => s.name);
|
|
88553
88253
|
} else if (ext === ".py") {
|
|
88554
|
-
const relativePath =
|
|
88254
|
+
const relativePath = path66.relative(absoluteRoot, filePath);
|
|
88555
88255
|
const symbols2 = extractPythonSymbols(relativePath, absoluteRoot);
|
|
88556
88256
|
exports = symbols2.filter((s) => s.exported).map((s) => s.name);
|
|
88557
88257
|
}
|
|
@@ -88588,8 +88288,8 @@ async function buildWorkspaceGraphAsync(workspaceRoot, options) {
|
|
|
88588
88288
|
const maxFiles = options?.maxFiles ?? DEFAULT_WALK_FILE_CAP;
|
|
88589
88289
|
const walkBudgetMs = options?.walkBudgetMs ?? DEFAULT_WALK_BUDGET_MS;
|
|
88590
88290
|
const followSymlinks = options?.followSymlinks ?? false;
|
|
88591
|
-
const absoluteRoot =
|
|
88592
|
-
if (!
|
|
88291
|
+
const absoluteRoot = path66.resolve(workspaceRoot);
|
|
88292
|
+
if (!existsSync37(absoluteRoot)) {
|
|
88593
88293
|
throw new Error(`Workspace directory does not exist: ${workspaceRoot}`);
|
|
88594
88294
|
}
|
|
88595
88295
|
if (isRefusedWorkspaceRoot(absoluteRoot)) {
|
|
@@ -88644,15 +88344,15 @@ async function buildWorkspaceGraphAsync(workspaceRoot, options) {
|
|
|
88644
88344
|
return graph;
|
|
88645
88345
|
}
|
|
88646
88346
|
// src/tools/repo-graph/cache.ts
|
|
88647
|
-
import * as
|
|
88347
|
+
import * as path67 from "node:path";
|
|
88648
88348
|
var graphCache = new Map;
|
|
88649
88349
|
var dirtyFlags = new Map;
|
|
88650
88350
|
var mtimeCache = new Map;
|
|
88651
88351
|
function getCachedGraph(workspace) {
|
|
88652
|
-
return graphCache.get(
|
|
88352
|
+
return graphCache.get(path67.normalize(workspace));
|
|
88653
88353
|
}
|
|
88654
88354
|
function setCachedGraph(workspace, graph, mtime) {
|
|
88655
|
-
const normalized =
|
|
88355
|
+
const normalized = path67.normalize(workspace);
|
|
88656
88356
|
graphCache.set(normalized, graph);
|
|
88657
88357
|
dirtyFlags.set(normalized, false);
|
|
88658
88358
|
if (mtime !== undefined) {
|
|
@@ -88660,30 +88360,30 @@ function setCachedGraph(workspace, graph, mtime) {
|
|
|
88660
88360
|
}
|
|
88661
88361
|
}
|
|
88662
88362
|
function isDirty(workspace) {
|
|
88663
|
-
return dirtyFlags.get(
|
|
88363
|
+
return dirtyFlags.get(path67.normalize(workspace)) ?? false;
|
|
88664
88364
|
}
|
|
88665
88365
|
function clearCache(workspace) {
|
|
88666
|
-
const normalized =
|
|
88366
|
+
const normalized = path67.normalize(workspace);
|
|
88667
88367
|
graphCache.delete(normalized);
|
|
88668
88368
|
dirtyFlags.delete(normalized);
|
|
88669
88369
|
mtimeCache.delete(normalized);
|
|
88670
88370
|
}
|
|
88671
88371
|
function getCachedMtime(workspace) {
|
|
88672
|
-
return mtimeCache.get(
|
|
88372
|
+
return mtimeCache.get(path67.normalize(workspace));
|
|
88673
88373
|
}
|
|
88674
88374
|
// src/tools/repo-graph/incremental.ts
|
|
88675
88375
|
init_logger();
|
|
88676
|
-
import { existsSync as
|
|
88376
|
+
import { existsSync as existsSync39 } from "node:fs";
|
|
88677
88377
|
import * as fsPromises7 from "node:fs/promises";
|
|
88678
|
-
import * as
|
|
88378
|
+
import * as path69 from "node:path";
|
|
88679
88379
|
|
|
88680
88380
|
// src/tools/repo-graph/storage.ts
|
|
88681
88381
|
init_utils2();
|
|
88682
88382
|
init_logger();
|
|
88683
88383
|
init_path_security();
|
|
88684
|
-
import { constants as constants4, existsSync as
|
|
88384
|
+
import { constants as constants4, existsSync as existsSync38, realpathSync as realpathSync9 } from "node:fs";
|
|
88685
88385
|
import * as fsPromises6 from "node:fs/promises";
|
|
88686
|
-
import * as
|
|
88386
|
+
import * as path68 from "node:path";
|
|
88687
88387
|
var WINDOWS_RENAME_MAX_RETRIES2 = 3;
|
|
88688
88388
|
var WINDOWS_RENAME_RETRY_DELAY_MS2 = 50;
|
|
88689
88389
|
function getGraphPath(workspace) {
|
|
@@ -88694,12 +88394,12 @@ function getGraphPath(workspace) {
|
|
|
88694
88394
|
}
|
|
88695
88395
|
async function loadGraph(workspace) {
|
|
88696
88396
|
validateWorkspace(workspace);
|
|
88697
|
-
const normalized =
|
|
88397
|
+
const normalized = path68.normalize(workspace);
|
|
88698
88398
|
const cached3 = getCachedGraph(normalized);
|
|
88699
88399
|
if (cached3 && !isDirty(normalized)) {
|
|
88700
88400
|
try {
|
|
88701
88401
|
const graphPath = getGraphPath(workspace);
|
|
88702
|
-
if (
|
|
88402
|
+
if (existsSync38(graphPath)) {
|
|
88703
88403
|
const stats = await fsPromises6.stat(graphPath);
|
|
88704
88404
|
const cachedMtime = getCachedMtime(normalized);
|
|
88705
88405
|
if (cachedMtime !== undefined && stats.mtimeMs !== cachedMtime) {
|
|
@@ -88716,7 +88416,7 @@ async function loadGraph(workspace) {
|
|
|
88716
88416
|
}
|
|
88717
88417
|
try {
|
|
88718
88418
|
const graphPath = getGraphPath(workspace);
|
|
88719
|
-
if (!
|
|
88419
|
+
if (!existsSync38(graphPath)) {
|
|
88720
88420
|
return null;
|
|
88721
88421
|
}
|
|
88722
88422
|
const stats = await fsPromises6.stat(graphPath);
|
|
@@ -88788,28 +88488,28 @@ async function saveGraph(workspace, graph, options) {
|
|
|
88788
88488
|
if (!Array.isArray(graph.edges)) {
|
|
88789
88489
|
throw new Error("Graph must have edges array");
|
|
88790
88490
|
}
|
|
88791
|
-
const normalizedWorkspace =
|
|
88491
|
+
const normalizedWorkspace = path68.normalize(workspace);
|
|
88792
88492
|
let realWorkspace;
|
|
88793
88493
|
try {
|
|
88794
88494
|
realWorkspace = realpathSync9(workspace);
|
|
88795
88495
|
} catch {
|
|
88796
88496
|
realWorkspace = normalizedWorkspace;
|
|
88797
88497
|
}
|
|
88798
|
-
const normalizedGraphRoot =
|
|
88498
|
+
const normalizedGraphRoot = path68.normalize(graph.workspaceRoot);
|
|
88799
88499
|
let realGraphRoot;
|
|
88800
88500
|
try {
|
|
88801
88501
|
realGraphRoot = realpathSync9(graph.workspaceRoot);
|
|
88802
88502
|
} catch {
|
|
88803
88503
|
realGraphRoot = normalizedGraphRoot;
|
|
88804
88504
|
}
|
|
88805
|
-
if (
|
|
88505
|
+
if (path68.normalize(realWorkspace) !== path68.normalize(realGraphRoot)) {
|
|
88806
88506
|
throw new Error(`Graph workspaceRoot mismatch: graph was built for "${graph.workspaceRoot}" but save was called for "${workspace}"`);
|
|
88807
88507
|
}
|
|
88808
88508
|
const normalized = normalizedWorkspace;
|
|
88809
88509
|
const graphPath = getGraphPath(workspace);
|
|
88810
88510
|
updateGraphMetadata(graph);
|
|
88811
88511
|
const tempPath = `${graphPath}.tmp.${Date.now()}.${Math.floor(Math.random() * 1e9)}`;
|
|
88812
|
-
await fsPromises6.mkdir(
|
|
88512
|
+
await fsPromises6.mkdir(path68.dirname(tempPath), { recursive: true });
|
|
88813
88513
|
let lastError = null;
|
|
88814
88514
|
try {
|
|
88815
88515
|
if (options?.createAtomic) {
|
|
@@ -88877,12 +88577,12 @@ async function updateGraphForFiles(workspaceRoot, filePaths, options) {
|
|
|
88877
88577
|
return graph2;
|
|
88878
88578
|
}
|
|
88879
88579
|
const graph = existingGraph;
|
|
88880
|
-
const absoluteRoot =
|
|
88580
|
+
const absoluteRoot = path69.resolve(workspaceRoot);
|
|
88881
88581
|
const maxFileSize = 1024 * 1024;
|
|
88882
88582
|
const updatedPaths = new Set;
|
|
88883
88583
|
for (const rawFilePath of filePaths) {
|
|
88884
88584
|
const normalizedPath = normalizeGraphPath(rawFilePath);
|
|
88885
|
-
const fileExists =
|
|
88585
|
+
const fileExists = existsSync39(rawFilePath);
|
|
88886
88586
|
if (fileExists) {
|
|
88887
88587
|
graph.edges = graph.edges.filter((e) => normalizeGraphPath(e.source) !== normalizedPath);
|
|
88888
88588
|
const result = scanFile(rawFilePath, absoluteRoot, maxFileSize);
|
|
@@ -88917,12 +88617,12 @@ async function updateGraphForFiles(workspaceRoot, filePaths, options) {
|
|
|
88917
88617
|
await saveGraph(workspaceRoot, rebuiltGraph);
|
|
88918
88618
|
return rebuiltGraph;
|
|
88919
88619
|
}
|
|
88920
|
-
const normalizedWorkspace =
|
|
88620
|
+
const normalizedWorkspace = path69.normalize(workspaceRoot);
|
|
88921
88621
|
const loadedMtime = getCachedMtime(normalizedWorkspace);
|
|
88922
88622
|
if (loadedMtime !== undefined) {
|
|
88923
88623
|
try {
|
|
88924
88624
|
const graphPath = getGraphPath(workspaceRoot);
|
|
88925
|
-
if (
|
|
88625
|
+
if (existsSync39(graphPath)) {
|
|
88926
88626
|
const currentStats = await fsPromises7.stat(graphPath);
|
|
88927
88627
|
if (currentStats.mtimeMs !== loadedMtime) {
|
|
88928
88628
|
warn(`[repo-graph] Concurrent modification detected — falling back to full rebuild`);
|
|
@@ -89015,7 +88715,7 @@ function createRepoGraphBuilderHook(workspaceRoot, deps) {
|
|
|
89015
88715
|
return;
|
|
89016
88716
|
if (!isSupportedSourceFile(filePath))
|
|
89017
88717
|
return;
|
|
89018
|
-
const absoluteFilePath =
|
|
88718
|
+
const absoluteFilePath = path70.isAbsolute(filePath) ? filePath : path70.resolve(workspaceRoot, filePath);
|
|
89019
88719
|
let realFilePath;
|
|
89020
88720
|
try {
|
|
89021
88721
|
realFilePath = realpathSync10(absoluteFilePath);
|
|
@@ -89042,7 +88742,7 @@ function createRepoGraphBuilderHook(workspaceRoot, deps) {
|
|
|
89042
88742
|
try {
|
|
89043
88743
|
await _updateGraphForFiles(workspaceRoot, [absoluteFilePath]);
|
|
89044
88744
|
consecutiveFailures = 0;
|
|
89045
|
-
log(`[repo-graph] Incremental update for ${
|
|
88745
|
+
log(`[repo-graph] Incremental update for ${path70.basename(filePath)}`);
|
|
89046
88746
|
} catch (error93) {
|
|
89047
88747
|
const message = error93 instanceof Error ? error93.message : String(error93);
|
|
89048
88748
|
consecutiveFailures++;
|
|
@@ -89065,14 +88765,14 @@ init_manager2();
|
|
|
89065
88765
|
init_detector();
|
|
89066
88766
|
init_manager();
|
|
89067
88767
|
import * as fs54 from "node:fs";
|
|
89068
|
-
import * as
|
|
88768
|
+
import * as path80 from "node:path";
|
|
89069
88769
|
|
|
89070
88770
|
// src/services/decision-drift-analyzer.ts
|
|
89071
88771
|
init_utils2();
|
|
89072
88772
|
init_manager();
|
|
89073
88773
|
init_utils();
|
|
89074
88774
|
import * as fs46 from "node:fs";
|
|
89075
|
-
import * as
|
|
88775
|
+
import * as path71 from "node:path";
|
|
89076
88776
|
var DEFAULT_DRIFT_CONFIG = {
|
|
89077
88777
|
staleThresholdPhases: 1,
|
|
89078
88778
|
detectContradictions: true,
|
|
@@ -89226,7 +88926,7 @@ async function analyzeDecisionDrift(directory, config3 = {}) {
|
|
|
89226
88926
|
currentPhase = legacyPhase;
|
|
89227
88927
|
}
|
|
89228
88928
|
}
|
|
89229
|
-
const contextPath =
|
|
88929
|
+
const contextPath = path71.join(directory, ".swarm", "context.md");
|
|
89230
88930
|
let contextContent = "";
|
|
89231
88931
|
try {
|
|
89232
88932
|
if (fs46.existsSync(contextPath)) {
|
|
@@ -89365,7 +89065,7 @@ init_utils();
|
|
|
89365
89065
|
init_constants();
|
|
89366
89066
|
init_schema();
|
|
89367
89067
|
import * as fs47 from "node:fs/promises";
|
|
89368
|
-
import * as
|
|
89068
|
+
import * as path72 from "node:path";
|
|
89369
89069
|
function safeGet(obj, key) {
|
|
89370
89070
|
if (!obj || !Object.hasOwn(obj, key))
|
|
89371
89071
|
return;
|
|
@@ -89597,9 +89297,9 @@ async function handleDebuggingSpiral(match, taskId, directory) {
|
|
|
89597
89297
|
let eventLogged = false;
|
|
89598
89298
|
let checkpointCreated = false;
|
|
89599
89299
|
try {
|
|
89600
|
-
const swarmDir =
|
|
89300
|
+
const swarmDir = path72.join(directory, ".swarm");
|
|
89601
89301
|
await fs47.mkdir(swarmDir, { recursive: true });
|
|
89602
|
-
const eventsPath =
|
|
89302
|
+
const eventsPath = path72.join(swarmDir, "events.jsonl");
|
|
89603
89303
|
await fs47.appendFile(eventsPath, `${formatDebuggingSpiralEvent(match, taskId)}
|
|
89604
89304
|
`);
|
|
89605
89305
|
eventLogged = true;
|
|
@@ -89735,7 +89435,7 @@ import * as fs51 from "node:fs";
|
|
|
89735
89435
|
|
|
89736
89436
|
// src/graph/graph-builder.ts
|
|
89737
89437
|
import * as fs49 from "node:fs";
|
|
89738
|
-
import * as
|
|
89438
|
+
import * as path75 from "node:path";
|
|
89739
89439
|
|
|
89740
89440
|
// node_modules/yocto-queue/index.js
|
|
89741
89441
|
class Node {
|
|
@@ -89896,7 +89596,7 @@ function validateConcurrency(concurrency) {
|
|
|
89896
89596
|
// src/graph/import-extractor.ts
|
|
89897
89597
|
init_path_security();
|
|
89898
89598
|
import * as fs48 from "node:fs";
|
|
89899
|
-
import * as
|
|
89599
|
+
import * as path73 from "node:path";
|
|
89900
89600
|
var SOURCE_EXTENSIONS2 = [
|
|
89901
89601
|
".ts",
|
|
89902
89602
|
".tsx",
|
|
@@ -89941,14 +89641,14 @@ function getLanguageFromExtension(ext) {
|
|
|
89941
89641
|
return null;
|
|
89942
89642
|
}
|
|
89943
89643
|
function toRelForwardSlash(absPath, root) {
|
|
89944
|
-
return
|
|
89644
|
+
return path73.relative(root, absPath).replace(/\\/g, "/");
|
|
89945
89645
|
}
|
|
89946
89646
|
function tryResolveTSJS(rawModule, sourceFileAbs) {
|
|
89947
89647
|
if (!rawModule.startsWith(".") && !rawModule.startsWith("/")) {
|
|
89948
89648
|
return null;
|
|
89949
89649
|
}
|
|
89950
|
-
const sourceDir =
|
|
89951
|
-
const baseAbs =
|
|
89650
|
+
const sourceDir = path73.dirname(sourceFileAbs);
|
|
89651
|
+
const baseAbs = path73.resolve(sourceDir, rawModule);
|
|
89952
89652
|
const probe = (basePath) => {
|
|
89953
89653
|
for (const ext of RESOLVE_EXTENSION_CANDIDATES) {
|
|
89954
89654
|
const test = basePath + ext;
|
|
@@ -89959,7 +89659,7 @@ function tryResolveTSJS(rawModule, sourceFileAbs) {
|
|
|
89959
89659
|
} catch {}
|
|
89960
89660
|
}
|
|
89961
89661
|
for (const indexFile of RESOLVE_INDEX_CANDIDATES) {
|
|
89962
|
-
const test =
|
|
89662
|
+
const test = path73.join(basePath, indexFile);
|
|
89963
89663
|
try {
|
|
89964
89664
|
const stat6 = fs48.statSync(test);
|
|
89965
89665
|
if (stat6.isFile())
|
|
@@ -89989,13 +89689,13 @@ function tryResolvePython(rawModule, sourceFileAbs, workspaceRoot) {
|
|
|
89989
89689
|
}
|
|
89990
89690
|
const remainder = rawModule.slice(leadingDots).replace(/\./g, "/");
|
|
89991
89691
|
const upDirs = "../".repeat(Math.max(0, leadingDots - 1));
|
|
89992
|
-
const sourceDir =
|
|
89993
|
-
const baseAbs =
|
|
89692
|
+
const sourceDir = path73.dirname(sourceFileAbs);
|
|
89693
|
+
const baseAbs = path73.resolve(sourceDir, upDirs + remainder);
|
|
89994
89694
|
const accept = (test) => {
|
|
89995
89695
|
try {
|
|
89996
89696
|
const stat6 = fs48.statSync(test);
|
|
89997
89697
|
if (stat6.isFile()) {
|
|
89998
|
-
const rel =
|
|
89698
|
+
const rel = path73.relative(workspaceRoot, test).replace(/\\/g, "/");
|
|
89999
89699
|
if (rel.startsWith(".."))
|
|
90000
89700
|
return null;
|
|
90001
89701
|
return test;
|
|
@@ -90009,7 +89709,7 @@ function tryResolvePython(rawModule, sourceFileAbs, workspaceRoot) {
|
|
|
90009
89709
|
return hit;
|
|
90010
89710
|
}
|
|
90011
89711
|
for (const indexFile of PY_INDEX_CANDIDATES) {
|
|
90012
|
-
const hit = accept(
|
|
89712
|
+
const hit = accept(path73.join(baseAbs, indexFile));
|
|
90013
89713
|
if (hit)
|
|
90014
89714
|
return hit;
|
|
90015
89715
|
}
|
|
@@ -90380,7 +90080,7 @@ function parseRustUses(content) {
|
|
|
90380
90080
|
}
|
|
90381
90081
|
function extractImports5(opts) {
|
|
90382
90082
|
const { absoluteFilePath, workspaceRoot } = opts;
|
|
90383
|
-
const ext =
|
|
90083
|
+
const ext = path73.extname(absoluteFilePath).toLowerCase();
|
|
90384
90084
|
const language = getLanguageFromExtension(ext);
|
|
90385
90085
|
if (!language)
|
|
90386
90086
|
return [];
|
|
@@ -90431,9 +90131,9 @@ function extractImports5(opts) {
|
|
|
90431
90131
|
}
|
|
90432
90132
|
|
|
90433
90133
|
// src/graph/symbol-extractor.ts
|
|
90434
|
-
import * as
|
|
90134
|
+
import * as path74 from "node:path";
|
|
90435
90135
|
function extractExportedSymbols(relativeFilePath, workspaceRoot) {
|
|
90436
|
-
const ext =
|
|
90136
|
+
const ext = path74.extname(relativeFilePath).toLowerCase();
|
|
90437
90137
|
const language = getLanguageFromExtension(ext);
|
|
90438
90138
|
if (!language)
|
|
90439
90139
|
return [];
|
|
@@ -90522,15 +90222,15 @@ function findSourceFiles(workspaceRoot, skipDirs = DEFAULT_SKIP_DIRS) {
|
|
|
90522
90222
|
if (entry.isDirectory()) {
|
|
90523
90223
|
if (skipDirs.has(entry.name))
|
|
90524
90224
|
continue;
|
|
90525
|
-
stack.push(
|
|
90225
|
+
stack.push(path75.join(dir, entry.name));
|
|
90526
90226
|
continue;
|
|
90527
90227
|
}
|
|
90528
90228
|
if (!entry.isFile())
|
|
90529
90229
|
continue;
|
|
90530
|
-
const ext =
|
|
90230
|
+
const ext = path75.extname(entry.name).toLowerCase();
|
|
90531
90231
|
if (!SOURCE_EXT_SET.has(ext))
|
|
90532
90232
|
continue;
|
|
90533
|
-
out2.push(
|
|
90233
|
+
out2.push(path75.join(dir, entry.name));
|
|
90534
90234
|
}
|
|
90535
90235
|
}
|
|
90536
90236
|
return out2;
|
|
@@ -90558,7 +90258,7 @@ async function buildRepoGraph(workspaceRoot, options = {}) {
|
|
|
90558
90258
|
};
|
|
90559
90259
|
}
|
|
90560
90260
|
async function processFile(absoluteFilePath, workspaceRoot) {
|
|
90561
|
-
const ext =
|
|
90261
|
+
const ext = path75.extname(absoluteFilePath).toLowerCase();
|
|
90562
90262
|
const language = getLanguageFromExtension(ext);
|
|
90563
90263
|
if (!language)
|
|
90564
90264
|
return null;
|
|
@@ -90578,7 +90278,7 @@ async function processFile(absoluteFilePath, workspaceRoot) {
|
|
|
90578
90278
|
} catch {
|
|
90579
90279
|
return null;
|
|
90580
90280
|
}
|
|
90581
|
-
const relPath =
|
|
90281
|
+
const relPath = path75.relative(workspaceRoot, absoluteFilePath).replace(/\\/g, "/");
|
|
90582
90282
|
const imports = extractImports5({
|
|
90583
90283
|
absoluteFilePath,
|
|
90584
90284
|
workspaceRoot,
|
|
@@ -90820,10 +90520,10 @@ function formatSummary(opts) {
|
|
|
90820
90520
|
// src/graph/graph-store.ts
|
|
90821
90521
|
import * as crypto6 from "node:crypto";
|
|
90822
90522
|
import * as fs50 from "node:fs";
|
|
90823
|
-
import * as
|
|
90523
|
+
import * as path76 from "node:path";
|
|
90824
90524
|
var SWARM_DIR = ".swarm";
|
|
90825
90525
|
function getGraphPath2(workspaceRoot) {
|
|
90826
|
-
return
|
|
90526
|
+
return path76.join(workspaceRoot, SWARM_DIR, REPO_GRAPH_FILENAME2);
|
|
90827
90527
|
}
|
|
90828
90528
|
function loadGraph2(workspaceRoot) {
|
|
90829
90529
|
const file3 = getGraphPath2(workspaceRoot);
|
|
@@ -90845,7 +90545,7 @@ function loadGraph2(workspaceRoot) {
|
|
|
90845
90545
|
}
|
|
90846
90546
|
function saveGraph2(workspaceRoot, graph) {
|
|
90847
90547
|
const file3 = getGraphPath2(workspaceRoot);
|
|
90848
|
-
const dir =
|
|
90548
|
+
const dir = path76.dirname(file3);
|
|
90849
90549
|
try {
|
|
90850
90550
|
const stat6 = fs50.lstatSync(dir);
|
|
90851
90551
|
if (stat6.isSymbolicLink()) {
|
|
@@ -90951,7 +90651,7 @@ function buildReviewerBlastRadiusBlock(directory, changedFiles) {
|
|
|
90951
90651
|
// src/hooks/semantic-diff-injection.ts
|
|
90952
90652
|
import * as child_process5 from "node:child_process";
|
|
90953
90653
|
import * as fs52 from "node:fs";
|
|
90954
|
-
import * as
|
|
90654
|
+
import * as path78 from "node:path";
|
|
90955
90655
|
|
|
90956
90656
|
// src/diff/ast-diff.ts
|
|
90957
90657
|
init_tree_sitter();
|
|
@@ -91698,17 +91398,17 @@ async function buildSemanticDiffBlock(directory, changedFiles, maxFiles = 10) {
|
|
|
91698
91398
|
const fileConsumers = {};
|
|
91699
91399
|
if (graph) {
|
|
91700
91400
|
for (const f of filesToProcess) {
|
|
91701
|
-
const relativePath =
|
|
91401
|
+
const relativePath = path78.isAbsolute(f) ? path78.relative(directory, f) : f;
|
|
91702
91402
|
const normalized = normalizeGraphPath2(relativePath);
|
|
91703
91403
|
fileConsumers[normalized] = getImporters(graph, normalized).length;
|
|
91704
91404
|
fileConsumers[f] = fileConsumers[normalized];
|
|
91705
91405
|
}
|
|
91706
91406
|
}
|
|
91707
91407
|
for (const filePath of filesToProcess) {
|
|
91708
|
-
const normalizedPath =
|
|
91709
|
-
const resolvedPath =
|
|
91710
|
-
const relativeToDir =
|
|
91711
|
-
if (relativeToDir.startsWith("..") ||
|
|
91408
|
+
const normalizedPath = path78.normalize(filePath);
|
|
91409
|
+
const resolvedPath = path78.resolve(directory, normalizedPath);
|
|
91410
|
+
const relativeToDir = path78.relative(directory, resolvedPath);
|
|
91411
|
+
if (relativeToDir.startsWith("..") || path78.isAbsolute(relativeToDir)) {
|
|
91712
91412
|
continue;
|
|
91713
91413
|
}
|
|
91714
91414
|
try {
|
|
@@ -91735,7 +91435,7 @@ async function buildSemanticDiffBlock(directory, changedFiles, maxFiles = 10) {
|
|
|
91735
91435
|
stdio: "pipe",
|
|
91736
91436
|
maxBuffer: 5 * 1024 * 1024
|
|
91737
91437
|
}) : "";
|
|
91738
|
-
const newContent = fs52.readFileSync(
|
|
91438
|
+
const newContent = fs52.readFileSync(path78.join(directory, filePath), "utf-8");
|
|
91739
91439
|
const astResult = await computeASTDiff(filePath, oldContent, newContent);
|
|
91740
91440
|
if (astResult && (astResult.changes.length > 0 || astResult.error !== undefined)) {
|
|
91741
91441
|
astDiffs.push(astResult);
|
|
@@ -91778,7 +91478,7 @@ function buildSpecDriftAdvisory(args2) {
|
|
|
91778
91478
|
}
|
|
91779
91479
|
function readSpecStalenessSnapshot2(directory) {
|
|
91780
91480
|
try {
|
|
91781
|
-
const p =
|
|
91481
|
+
const p = path80.join(directory, ".swarm", "spec-staleness.json");
|
|
91782
91482
|
if (!fs54.existsSync(p))
|
|
91783
91483
|
return null;
|
|
91784
91484
|
const raw = fs54.readFileSync(p, "utf-8");
|
|
@@ -92126,7 +91826,7 @@ function createSystemEnhancerHook(config3, directory) {
|
|
|
92126
91826
|
await fs54.promises.writeFile(darkMatterPath, darkMatterReport, "utf-8");
|
|
92127
91827
|
warn(`[system-enhancer] Dark matter scan complete: ${darkMatter.length} co-change patterns found`);
|
|
92128
91828
|
try {
|
|
92129
|
-
const projectName =
|
|
91829
|
+
const projectName = path80.basename(path80.resolve(directory));
|
|
92130
91830
|
const knowledgeEntries = darkMatterToKnowledgeEntries2(darkMatter, projectName);
|
|
92131
91831
|
const knowledgePath = resolveSwarmKnowledgePath(directory);
|
|
92132
91832
|
const existingEntries = await readKnowledge(knowledgePath);
|
|
@@ -92326,7 +92026,7 @@ ${lines.join(`
|
|
|
92326
92026
|
try {
|
|
92327
92027
|
const taskId_ccp = ccpSession?.currentTaskId;
|
|
92328
92028
|
if (taskId_ccp && !taskId_ccp.includes("..") && !taskId_ccp.includes("/") && !taskId_ccp.includes("\\") && !taskId_ccp.includes("\x00")) {
|
|
92329
|
-
const evidencePath =
|
|
92029
|
+
const evidencePath = path80.join(directory, ".swarm", "evidence", `${taskId_ccp}.json`);
|
|
92330
92030
|
if (fs54.existsSync(evidencePath)) {
|
|
92331
92031
|
const evidenceContent = fs54.readFileSync(evidencePath, "utf-8");
|
|
92332
92032
|
const evidenceData = JSON.parse(evidenceContent);
|
|
@@ -93490,7 +93190,7 @@ import * as fs56 from "node:fs";
|
|
|
93490
93190
|
// src/full-auto/policy.ts
|
|
93491
93191
|
init_constants();
|
|
93492
93192
|
import * as fs55 from "node:fs";
|
|
93493
|
-
import * as
|
|
93193
|
+
import * as path81 from "node:path";
|
|
93494
93194
|
var READ_ONLY_TOOLS = new Set([
|
|
93495
93195
|
"check_gate_status",
|
|
93496
93196
|
"completion_verify",
|
|
@@ -93689,11 +93389,11 @@ function normalizePath3(p) {
|
|
|
93689
93389
|
function isWithinDirectory(target, root) {
|
|
93690
93390
|
if (!target || !root)
|
|
93691
93391
|
return false;
|
|
93692
|
-
const resolvedTarget =
|
|
93693
|
-
const resolvedRoot =
|
|
93392
|
+
const resolvedTarget = path81.resolve(target);
|
|
93393
|
+
const resolvedRoot = path81.resolve(root);
|
|
93694
93394
|
if (resolvedTarget === resolvedRoot)
|
|
93695
93395
|
return true;
|
|
93696
|
-
const withSep = resolvedRoot.endsWith(
|
|
93396
|
+
const withSep = resolvedRoot.endsWith(path81.sep) ? resolvedRoot : resolvedRoot + path81.sep;
|
|
93697
93397
|
if (process.platform === "win32") {
|
|
93698
93398
|
return resolvedTarget.toLowerCase().startsWith(withSep.toLowerCase());
|
|
93699
93399
|
}
|
|
@@ -93752,7 +93452,7 @@ function classifyPathRisk(filePath, context) {
|
|
|
93752
93452
|
highRiskBuild: false
|
|
93753
93453
|
};
|
|
93754
93454
|
}
|
|
93755
|
-
const absolute =
|
|
93455
|
+
const absolute = path81.isAbsolute(filePath) ? filePath : path81.resolve(context.directory, filePath);
|
|
93756
93456
|
const resolvedAbsolute = (() => {
|
|
93757
93457
|
try {
|
|
93758
93458
|
let candidate = absolute;
|
|
@@ -93768,7 +93468,7 @@ function classifyPathRisk(filePath, context) {
|
|
|
93768
93468
|
}
|
|
93769
93469
|
return absolute;
|
|
93770
93470
|
}
|
|
93771
|
-
const parent =
|
|
93471
|
+
const parent = path81.dirname(candidate);
|
|
93772
93472
|
if (parent === candidate)
|
|
93773
93473
|
break;
|
|
93774
93474
|
candidate = parent;
|
|
@@ -93780,7 +93480,7 @@ function classifyPathRisk(filePath, context) {
|
|
|
93780
93480
|
}
|
|
93781
93481
|
})();
|
|
93782
93482
|
const withinProjectRoot = isWithinDirectory(absolute, context.directory) && isWithinDirectory(resolvedAbsolute, context.directory);
|
|
93783
|
-
const relative18 =
|
|
93483
|
+
const relative18 = path81.relative(context.directory, absolute).replace(/\\/g, "/");
|
|
93784
93484
|
let withinDeclaredScope = null;
|
|
93785
93485
|
if (Array.isArray(context.declaredScope)) {
|
|
93786
93486
|
withinDeclaredScope = context.declaredScope.length === 0 ? false : context.declaredScope.some((scope) => {
|
|
@@ -94090,7 +93790,7 @@ function classifyFullAutoToolAction(input) {
|
|
|
94090
93790
|
recoverable: true
|
|
94091
93791
|
};
|
|
94092
93792
|
}
|
|
94093
|
-
if (isProtectedPath(
|
|
93793
|
+
if (isProtectedPath(path81.relative(input.directory, path81.resolve(input.directory, p)), config3)) {
|
|
94094
93794
|
return {
|
|
94095
93795
|
action: "escalate_critic",
|
|
94096
93796
|
reason: `write to protected path requires critic approval: ${p}`,
|
|
@@ -94864,7 +94564,7 @@ init_hive_promoter();
|
|
|
94864
94564
|
|
|
94865
94565
|
// src/hooks/incremental-verify.ts
|
|
94866
94566
|
import * as fs58 from "node:fs";
|
|
94867
|
-
import * as
|
|
94567
|
+
import * as path82 from "node:path";
|
|
94868
94568
|
|
|
94869
94569
|
// src/hooks/spawn-helper.ts
|
|
94870
94570
|
import * as child_process6 from "node:child_process";
|
|
@@ -94942,18 +94642,18 @@ function spawnAsync(command, cwd, timeoutMs) {
|
|
|
94942
94642
|
// src/hooks/incremental-verify.ts
|
|
94943
94643
|
var emittedSkipAdvisories = new Set;
|
|
94944
94644
|
function detectPackageManager(projectDir) {
|
|
94945
|
-
if (fs58.existsSync(
|
|
94645
|
+
if (fs58.existsSync(path82.join(projectDir, "bun.lockb")))
|
|
94946
94646
|
return "bun";
|
|
94947
|
-
if (fs58.existsSync(
|
|
94647
|
+
if (fs58.existsSync(path82.join(projectDir, "pnpm-lock.yaml")))
|
|
94948
94648
|
return "pnpm";
|
|
94949
|
-
if (fs58.existsSync(
|
|
94649
|
+
if (fs58.existsSync(path82.join(projectDir, "yarn.lock")))
|
|
94950
94650
|
return "yarn";
|
|
94951
|
-
if (fs58.existsSync(
|
|
94651
|
+
if (fs58.existsSync(path82.join(projectDir, "package-lock.json")))
|
|
94952
94652
|
return "npm";
|
|
94953
94653
|
return "bun";
|
|
94954
94654
|
}
|
|
94955
94655
|
function detectTypecheckCommand(projectDir) {
|
|
94956
|
-
const pkgPath =
|
|
94656
|
+
const pkgPath = path82.join(projectDir, "package.json");
|
|
94957
94657
|
if (fs58.existsSync(pkgPath)) {
|
|
94958
94658
|
try {
|
|
94959
94659
|
const pkg = JSON.parse(fs58.readFileSync(pkgPath, "utf8"));
|
|
@@ -94970,8 +94670,8 @@ function detectTypecheckCommand(projectDir) {
|
|
|
94970
94670
|
...pkg.dependencies,
|
|
94971
94671
|
...pkg.devDependencies
|
|
94972
94672
|
};
|
|
94973
|
-
if (!deps?.typescript && !fs58.existsSync(
|
|
94974
|
-
const hasTSMarkers = deps?.typescript || fs58.existsSync(
|
|
94673
|
+
if (!deps?.typescript && !fs58.existsSync(path82.join(projectDir, "tsconfig.json"))) {}
|
|
94674
|
+
const hasTSMarkers = deps?.typescript || fs58.existsSync(path82.join(projectDir, "tsconfig.json"));
|
|
94975
94675
|
if (hasTSMarkers) {
|
|
94976
94676
|
return { command: ["npx", "tsc", "--noEmit"], language: "typescript" };
|
|
94977
94677
|
}
|
|
@@ -94979,13 +94679,13 @@ function detectTypecheckCommand(projectDir) {
|
|
|
94979
94679
|
return null;
|
|
94980
94680
|
}
|
|
94981
94681
|
}
|
|
94982
|
-
if (fs58.existsSync(
|
|
94682
|
+
if (fs58.existsSync(path82.join(projectDir, "go.mod"))) {
|
|
94983
94683
|
return { command: ["go", "vet", "./..."], language: "go" };
|
|
94984
94684
|
}
|
|
94985
|
-
if (fs58.existsSync(
|
|
94685
|
+
if (fs58.existsSync(path82.join(projectDir, "Cargo.toml"))) {
|
|
94986
94686
|
return { command: ["cargo", "check"], language: "rust" };
|
|
94987
94687
|
}
|
|
94988
|
-
if (fs58.existsSync(
|
|
94688
|
+
if (fs58.existsSync(path82.join(projectDir, "pyproject.toml")) || fs58.existsSync(path82.join(projectDir, "requirements.txt")) || fs58.existsSync(path82.join(projectDir, "setup.py"))) {
|
|
94989
94689
|
return { command: null, language: "python" };
|
|
94990
94690
|
}
|
|
94991
94691
|
try {
|
|
@@ -95061,18 +94761,18 @@ ${errorSummary}`);
|
|
|
95061
94761
|
init_schema();
|
|
95062
94762
|
init_state();
|
|
95063
94763
|
init_logger();
|
|
95064
|
-
import { appendFile as appendFile7, mkdir as
|
|
95065
|
-
import * as
|
|
94764
|
+
import { appendFile as appendFile7, mkdir as mkdir14 } from "node:fs/promises";
|
|
94765
|
+
import * as path84 from "node:path";
|
|
95066
94766
|
|
|
95067
94767
|
// src/hooks/knowledge-application.ts
|
|
95068
94768
|
init_logger();
|
|
95069
94769
|
init_knowledge_store();
|
|
95070
94770
|
var import_proper_lockfile7 = __toESM(require_proper_lockfile(), 1);
|
|
95071
|
-
import { existsSync as
|
|
95072
|
-
import { appendFile as appendFile6, mkdir as
|
|
95073
|
-
import * as
|
|
94771
|
+
import { existsSync as existsSync44 } from "node:fs";
|
|
94772
|
+
import { appendFile as appendFile6, mkdir as mkdir13, readFile as readFile12 } from "node:fs/promises";
|
|
94773
|
+
import * as path83 from "node:path";
|
|
95074
94774
|
function resolveApplicationLogPath(directory) {
|
|
95075
|
-
return
|
|
94775
|
+
return path83.join(directory, ".swarm", "knowledge-application.jsonl");
|
|
95076
94776
|
}
|
|
95077
94777
|
var ACK_PATTERN = /KNOWLEDGE_(APPLIED|IGNORED|VIOLATED)\s*:\s*([0-9a-fA-F-]{8,64})(?:\s+reason\s*=\s*([^\n\r]+?))?(?=$|[\n\r]|\s+KNOWLEDGE_)/g;
|
|
95078
94778
|
function parseAcknowledgments(text) {
|
|
@@ -95090,7 +94790,7 @@ function parseAcknowledgments(text) {
|
|
|
95090
94790
|
}
|
|
95091
94791
|
async function appendAudit(directory, record3) {
|
|
95092
94792
|
const filePath = resolveApplicationLogPath(directory);
|
|
95093
|
-
await
|
|
94793
|
+
await mkdir13(path83.dirname(filePath), { recursive: true });
|
|
95094
94794
|
await appendFile6(filePath, `${JSON.stringify(record3)}
|
|
95095
94795
|
`, "utf-8");
|
|
95096
94796
|
}
|
|
@@ -95134,7 +94834,7 @@ async function bumpCountersBatch(directory, bumps) {
|
|
|
95134
94834
|
if (applyOne(swarm))
|
|
95135
94835
|
await rewriteKnowledge(swarmPath, swarm);
|
|
95136
94836
|
const hivePath = resolveHiveKnowledgePath();
|
|
95137
|
-
if (
|
|
94837
|
+
if (existsSync44(hivePath)) {
|
|
95138
94838
|
const hive = await readKnowledge(hivePath);
|
|
95139
94839
|
if (applyOne(hive))
|
|
95140
94840
|
await rewriteKnowledge(hivePath, hive);
|
|
@@ -95259,8 +94959,8 @@ async function knowledgeApplicationGateBefore(directory, input, config3) {
|
|
|
95259
94959
|
}).catch(() => {});
|
|
95260
94960
|
}
|
|
95261
94961
|
async function writeWarnEvent(directory, record3) {
|
|
95262
|
-
const filePath =
|
|
95263
|
-
await
|
|
94962
|
+
const filePath = path84.join(directory, ".swarm", "events.jsonl");
|
|
94963
|
+
await mkdir14(path84.dirname(filePath), { recursive: true });
|
|
95264
94964
|
await appendFile7(filePath, `${JSON.stringify(record3)}
|
|
95265
94965
|
`, "utf-8");
|
|
95266
94966
|
}
|
|
@@ -95469,7 +95169,343 @@ init_state();
|
|
|
95469
95169
|
init_logger();
|
|
95470
95170
|
init_curator_drift();
|
|
95471
95171
|
init_extractors();
|
|
95472
|
-
|
|
95172
|
+
|
|
95173
|
+
// src/hooks/knowledge-reader.ts
|
|
95174
|
+
init_logger();
|
|
95175
|
+
init_knowledge_store();
|
|
95176
|
+
import { existsSync as existsSync45 } from "node:fs";
|
|
95177
|
+
import { mkdir as mkdir15, readFile as readFile13, writeFile as writeFile12 } from "node:fs/promises";
|
|
95178
|
+
import * as path86 from "node:path";
|
|
95179
|
+
var JACCARD_THRESHOLD = 0.6;
|
|
95180
|
+
var HIVE_TIER_BOOST = 0.05;
|
|
95181
|
+
var SAME_PROJECT_PENALTY = -0.05;
|
|
95182
|
+
var NORMAL_RETRIEVAL_STATUSES2 = new Set(["established", "promoted"]);
|
|
95183
|
+
function inferCategoriesFromPhase(phaseDescription) {
|
|
95184
|
+
const lower = phaseDescription.toLowerCase();
|
|
95185
|
+
const patterns = [
|
|
95186
|
+
{
|
|
95187
|
+
pattern: /\b(?:test|qa|quality|verification|validation)\b/,
|
|
95188
|
+
categories: ["testing", "debugging"]
|
|
95189
|
+
},
|
|
95190
|
+
{
|
|
95191
|
+
pattern: /\b(?:implement|build|develop|coding|code)\b/,
|
|
95192
|
+
categories: ["tooling", "architecture", "debugging"]
|
|
95193
|
+
},
|
|
95194
|
+
{
|
|
95195
|
+
pattern: /\b(?:integrat|deploy|ci|cd|release|publish)\b/,
|
|
95196
|
+
categories: ["integration", "tooling", "performance"]
|
|
95197
|
+
},
|
|
95198
|
+
{
|
|
95199
|
+
pattern: /\b(?:plan|design|architect|spec|requirement)\b/,
|
|
95200
|
+
categories: ["architecture", "process"]
|
|
95201
|
+
},
|
|
95202
|
+
{
|
|
95203
|
+
pattern: /\b(?:review|refactor|cleanup|polish|optimi)\b/,
|
|
95204
|
+
categories: ["performance", "architecture", "process"]
|
|
95205
|
+
},
|
|
95206
|
+
{
|
|
95207
|
+
pattern: /\b(?:secur|audit|harden|compliance)\b/,
|
|
95208
|
+
categories: ["security", "testing"]
|
|
95209
|
+
},
|
|
95210
|
+
{
|
|
95211
|
+
pattern: /\b(?:setup|config|scaffold|init|bootstrap)\b/,
|
|
95212
|
+
categories: ["tooling", "other"]
|
|
95213
|
+
},
|
|
95214
|
+
{
|
|
95215
|
+
pattern: /\b(?:doc|readme|changelog)\b/,
|
|
95216
|
+
categories: ["process", "tooling"]
|
|
95217
|
+
}
|
|
95218
|
+
];
|
|
95219
|
+
for (const { pattern, categories } of patterns) {
|
|
95220
|
+
if (pattern.test(lower)) {
|
|
95221
|
+
return categories;
|
|
95222
|
+
}
|
|
95223
|
+
}
|
|
95224
|
+
return ["process", "tooling"];
|
|
95225
|
+
}
|
|
95226
|
+
async function recordLessonsShown(directory, lessonIds, currentPhase) {
|
|
95227
|
+
const shownFile = path86.join(directory, ".swarm", ".knowledge-shown.json");
|
|
95228
|
+
try {
|
|
95229
|
+
let shownData = {};
|
|
95230
|
+
if (existsSync45(shownFile)) {
|
|
95231
|
+
const content = await readFile13(shownFile, "utf-8");
|
|
95232
|
+
shownData = JSON.parse(content);
|
|
95233
|
+
}
|
|
95234
|
+
const phaseMatch = /^Phase\s+(\d+)/i.exec(currentPhase);
|
|
95235
|
+
const canonicalKey = phaseMatch ? `Phase ${phaseMatch[1]}` : currentPhase;
|
|
95236
|
+
shownData[canonicalKey] = lessonIds;
|
|
95237
|
+
await mkdir15(path86.dirname(shownFile), { recursive: true });
|
|
95238
|
+
await writeFile12(shownFile, JSON.stringify(shownData, null, 2), "utf-8");
|
|
95239
|
+
} catch {
|
|
95240
|
+
warn("[swarm] Knowledge: failed to record shown lessons");
|
|
95241
|
+
}
|
|
95242
|
+
}
|
|
95243
|
+
async function readMergedKnowledge(directory, config3, context) {
|
|
95244
|
+
const swarmPath = resolveSwarmKnowledgePath(directory);
|
|
95245
|
+
const swarmEntries = await readKnowledge(swarmPath);
|
|
95246
|
+
let hiveEntries = [];
|
|
95247
|
+
if (config3.hive_enabled !== false) {
|
|
95248
|
+
const hivePath = resolveHiveKnowledgePath();
|
|
95249
|
+
hiveEntries = await readKnowledge(hivePath);
|
|
95250
|
+
}
|
|
95251
|
+
const seenLessons = new Set;
|
|
95252
|
+
const merged = [];
|
|
95253
|
+
for (const entry of hiveEntries) {
|
|
95254
|
+
const normalized = normalize2(entry.lesson);
|
|
95255
|
+
seenLessons.add(normalized);
|
|
95256
|
+
merged.push({
|
|
95257
|
+
...entry,
|
|
95258
|
+
relevanceScore: { category: 0, confidence: 0, keywords: 0 },
|
|
95259
|
+
finalScore: 0
|
|
95260
|
+
});
|
|
95261
|
+
}
|
|
95262
|
+
for (const entry of swarmEntries) {
|
|
95263
|
+
const normalized = normalize2(entry.lesson);
|
|
95264
|
+
if (seenLessons.has(normalized)) {
|
|
95265
|
+
continue;
|
|
95266
|
+
}
|
|
95267
|
+
const swarmBigrams = wordBigrams(normalized);
|
|
95268
|
+
const isHiveNearDup = hiveEntries.some((hiveEntry) => jaccardBigram(swarmBigrams, wordBigrams(normalize2(hiveEntry.lesson))) >= JACCARD_THRESHOLD);
|
|
95269
|
+
if (isHiveNearDup)
|
|
95270
|
+
continue;
|
|
95271
|
+
const isSwarmNearDup = merged.some((m) => m.tier === "swarm" && jaccardBigram(swarmBigrams, wordBigrams(normalize2(m.lesson))) >= JACCARD_THRESHOLD);
|
|
95272
|
+
if (isSwarmNearDup)
|
|
95273
|
+
continue;
|
|
95274
|
+
seenLessons.add(normalized);
|
|
95275
|
+
merged.push({
|
|
95276
|
+
...entry,
|
|
95277
|
+
relevanceScore: { category: 0, confidence: 0, keywords: 0 },
|
|
95278
|
+
finalScore: 0
|
|
95279
|
+
});
|
|
95280
|
+
}
|
|
95281
|
+
const retractionRecords = await readRetractionRecords(directory);
|
|
95282
|
+
const suppressedLessons = new Set(retractionRecords.map((record3) => record3.normalized_lesson).filter((value) => typeof value === "string" && value.length > 0));
|
|
95283
|
+
const scopeFilter = config3.scope_filter ?? ["global"];
|
|
95284
|
+
const filtered = merged.filter((entry) => scopeFilter.some((pattern) => (entry.scope ?? "global") === pattern) && NORMAL_RETRIEVAL_STATUSES2.has(entry.status) && !suppressedLessons.has(normalize2(entry.lesson)));
|
|
95285
|
+
const ranked = filtered.map((entry) => {
|
|
95286
|
+
let categoryScore = 0;
|
|
95287
|
+
if (context?.currentPhase) {
|
|
95288
|
+
const phaseCategories = inferCategoriesFromPhase(context.currentPhase);
|
|
95289
|
+
if (phaseCategories.includes(entry.category)) {
|
|
95290
|
+
categoryScore = 1;
|
|
95291
|
+
} else if (entry.category === "process") {
|
|
95292
|
+
categoryScore = 0.5;
|
|
95293
|
+
}
|
|
95294
|
+
} else {
|
|
95295
|
+
categoryScore = 0.5;
|
|
95296
|
+
}
|
|
95297
|
+
const confidenceScore = entry.confidence;
|
|
95298
|
+
let keywordsScore = 0;
|
|
95299
|
+
if (context?.techStack && entry.tags.length > 0) {
|
|
95300
|
+
const matchingTags = entry.tags.filter((t) => context.techStack.some((s) => t.toLowerCase().includes(s.toLowerCase()) || s.toLowerCase().includes(t.toLowerCase()))).length;
|
|
95301
|
+
keywordsScore = Math.min(matchingTags / Math.max(entry.tags.length, 1), 1);
|
|
95302
|
+
} else if (entry.tags.length === 0) {
|
|
95303
|
+
keywordsScore = 0.5;
|
|
95304
|
+
}
|
|
95305
|
+
const tierBoost = entry.tier === "hive" ? HIVE_TIER_BOOST : 0;
|
|
95306
|
+
const isSameProjectSource = context?.projectName && entry.tier === "hive" && "source_project" in entry && entry.source_project === context.projectName;
|
|
95307
|
+
const sameProjectPenalty = isSameProjectSource ? SAME_PROJECT_PENALTY : 0;
|
|
95308
|
+
const finalScore = categoryScore * 0.4 + confidenceScore * 0.35 + keywordsScore * 0.25 + tierBoost + sameProjectPenalty;
|
|
95309
|
+
const relevanceScore = {
|
|
95310
|
+
category: categoryScore,
|
|
95311
|
+
confidence: confidenceScore,
|
|
95312
|
+
keywords: keywordsScore
|
|
95313
|
+
};
|
|
95314
|
+
return {
|
|
95315
|
+
...entry,
|
|
95316
|
+
relevanceScore,
|
|
95317
|
+
finalScore: Math.min(Math.max(finalScore, 0), 1)
|
|
95318
|
+
};
|
|
95319
|
+
});
|
|
95320
|
+
ranked.sort((a, b) => {
|
|
95321
|
+
const scoreDiff = b.finalScore - a.finalScore;
|
|
95322
|
+
if (Math.abs(scoreDiff) > 0.001)
|
|
95323
|
+
return scoreDiff;
|
|
95324
|
+
const dateA = new Date(a.created_at).getTime();
|
|
95325
|
+
const dateB = new Date(b.created_at).getTime();
|
|
95326
|
+
return dateB - dateA;
|
|
95327
|
+
});
|
|
95328
|
+
const maxInject = config3.max_inject_count ?? 5;
|
|
95329
|
+
const topN = ranked.slice(0, maxInject);
|
|
95330
|
+
if (topN.length > 0 && context?.currentPhase) {
|
|
95331
|
+
recordLessonsShown(directory, topN.map((e) => e.id), context.currentPhase).catch((err2) => {
|
|
95332
|
+
warn("[knowledge-reader] recordLessonsShown unexpected rejection:", err2);
|
|
95333
|
+
});
|
|
95334
|
+
}
|
|
95335
|
+
return topN;
|
|
95336
|
+
}
|
|
95337
|
+
async function updateRetrievalOutcome(directory, phaseInfo, phaseSucceeded) {
|
|
95338
|
+
const shownFile = path86.join(directory, ".swarm", ".knowledge-shown.json");
|
|
95339
|
+
try {
|
|
95340
|
+
if (!existsSync45(shownFile)) {
|
|
95341
|
+
return;
|
|
95342
|
+
}
|
|
95343
|
+
const content = await readFile13(shownFile, "utf-8");
|
|
95344
|
+
const shownData = JSON.parse(content);
|
|
95345
|
+
const shownIds = shownData[phaseInfo];
|
|
95346
|
+
if (!shownIds || shownIds.length === 0) {
|
|
95347
|
+
return;
|
|
95348
|
+
}
|
|
95349
|
+
const swarmPath = resolveSwarmKnowledgePath(directory);
|
|
95350
|
+
const entries = await readKnowledge(swarmPath);
|
|
95351
|
+
let updated = false;
|
|
95352
|
+
const foundInSwarm = new Set;
|
|
95353
|
+
for (const entry of entries) {
|
|
95354
|
+
if (shownIds.includes(entry.id)) {
|
|
95355
|
+
const ro = entry.retrieval_outcomes;
|
|
95356
|
+
if (phaseSucceeded) {
|
|
95357
|
+
ro.succeeded_after_shown_count = (ro.succeeded_after_shown_count ?? 0) + 1;
|
|
95358
|
+
} else {
|
|
95359
|
+
ro.failed_after_shown_count = (ro.failed_after_shown_count ?? 0) + 1;
|
|
95360
|
+
}
|
|
95361
|
+
updated = true;
|
|
95362
|
+
foundInSwarm.add(entry.id);
|
|
95363
|
+
}
|
|
95364
|
+
}
|
|
95365
|
+
if (updated) {
|
|
95366
|
+
await rewriteKnowledge(swarmPath, entries);
|
|
95367
|
+
}
|
|
95368
|
+
const remainingIds = shownIds.filter((id) => !foundInSwarm.has(id));
|
|
95369
|
+
if (remainingIds.length === 0) {
|
|
95370
|
+
delete shownData[phaseInfo];
|
|
95371
|
+
await writeFile12(shownFile, JSON.stringify(shownData, null, 2), "utf-8");
|
|
95372
|
+
return;
|
|
95373
|
+
}
|
|
95374
|
+
const hivePath = resolveHiveKnowledgePath();
|
|
95375
|
+
const hiveEntries = await readKnowledge(hivePath);
|
|
95376
|
+
let hiveUpdated = false;
|
|
95377
|
+
for (const entry of hiveEntries) {
|
|
95378
|
+
if (remainingIds.includes(entry.id)) {
|
|
95379
|
+
const ro = entry.retrieval_outcomes;
|
|
95380
|
+
if (phaseSucceeded) {
|
|
95381
|
+
ro.succeeded_after_shown_count = (ro.succeeded_after_shown_count ?? 0) + 1;
|
|
95382
|
+
} else {
|
|
95383
|
+
ro.failed_after_shown_count = (ro.failed_after_shown_count ?? 0) + 1;
|
|
95384
|
+
}
|
|
95385
|
+
hiveUpdated = true;
|
|
95386
|
+
}
|
|
95387
|
+
}
|
|
95388
|
+
if (hiveUpdated) {
|
|
95389
|
+
await rewriteKnowledge(hivePath, hiveEntries);
|
|
95390
|
+
}
|
|
95391
|
+
delete shownData[phaseInfo];
|
|
95392
|
+
await writeFile12(shownFile, JSON.stringify(shownData, null, 2), "utf-8");
|
|
95393
|
+
} catch {
|
|
95394
|
+
warn("[swarm] Knowledge: failed to update retrieval outcomes");
|
|
95395
|
+
}
|
|
95396
|
+
}
|
|
95397
|
+
var DIRECTIVE_BOOST_MIN_CONFIDENCE = 0.75;
|
|
95398
|
+
function lc(s) {
|
|
95399
|
+
return (s ?? "").toLowerCase();
|
|
95400
|
+
}
|
|
95401
|
+
function anyMatch(haystack, needles) {
|
|
95402
|
+
if (needles.length === 0)
|
|
95403
|
+
return false;
|
|
95404
|
+
const hay = haystack.map(lc);
|
|
95405
|
+
return needles.some((n) => hay.some((h) => h.includes(lc(n))));
|
|
95406
|
+
}
|
|
95407
|
+
function tokenizeContext(ctx) {
|
|
95408
|
+
const parts2 = [];
|
|
95409
|
+
if (ctx.taskTitle)
|
|
95410
|
+
parts2.push(ctx.taskTitle);
|
|
95411
|
+
if (ctx.taskDescription)
|
|
95412
|
+
parts2.push(ctx.taskDescription);
|
|
95413
|
+
if (ctx.lastUserMessage)
|
|
95414
|
+
parts2.push(ctx.lastUserMessage);
|
|
95415
|
+
if (ctx.currentAction)
|
|
95416
|
+
parts2.push(ctx.currentAction);
|
|
95417
|
+
if (ctx.currentTool)
|
|
95418
|
+
parts2.push(ctx.currentTool);
|
|
95419
|
+
if (ctx.targetAgent)
|
|
95420
|
+
parts2.push(ctx.targetAgent);
|
|
95421
|
+
if (ctx.declaredScope)
|
|
95422
|
+
parts2.push(ctx.declaredScope);
|
|
95423
|
+
if (ctx.recentReviewerFailures)
|
|
95424
|
+
parts2.push(...ctx.recentReviewerFailures);
|
|
95425
|
+
if (ctx.recentTestFailures)
|
|
95426
|
+
parts2.push(...ctx.recentTestFailures);
|
|
95427
|
+
if (ctx.recentToolErrors)
|
|
95428
|
+
parts2.push(...ctx.recentToolErrors);
|
|
95429
|
+
if (ctx.planConstraints)
|
|
95430
|
+
parts2.push(...ctx.planConstraints);
|
|
95431
|
+
if (ctx.filePaths)
|
|
95432
|
+
parts2.push(...ctx.filePaths);
|
|
95433
|
+
return parts2.map(lc);
|
|
95434
|
+
}
|
|
95435
|
+
function scoreDirectiveAgainstContext(entry, ctx) {
|
|
95436
|
+
const haystack = tokenizeContext(ctx);
|
|
95437
|
+
const triggerHit = entry.triggers && entry.triggers.length > 0 ? anyMatch(haystack, entry.triggers) : false;
|
|
95438
|
+
const actionHit = entry.applies_to_tools && entry.applies_to_tools.length > 0 ? entry.applies_to_tools.map(lc).some((t) => t === lc(ctx.currentTool) || t === lc(ctx.currentAction)) : false;
|
|
95439
|
+
const agentHit = entry.applies_to_agents && entry.applies_to_agents.length > 0 ? entry.applies_to_agents.map(lc).some((a) => a === lc(ctx.targetAgent)) : false;
|
|
95440
|
+
let score = 0;
|
|
95441
|
+
if (triggerHit)
|
|
95442
|
+
score += 0.5;
|
|
95443
|
+
if (actionHit)
|
|
95444
|
+
score += 0.35;
|
|
95445
|
+
if (agentHit)
|
|
95446
|
+
score += 0.25;
|
|
95447
|
+
if (entry.directive_priority === "critical")
|
|
95448
|
+
score += 0.4;
|
|
95449
|
+
else if (entry.directive_priority === "high")
|
|
95450
|
+
score += 0.2;
|
|
95451
|
+
else if (entry.directive_priority === "medium")
|
|
95452
|
+
score += 0.1;
|
|
95453
|
+
return { triggerHit, actionHit, agentHit, score: Math.min(1, score) };
|
|
95454
|
+
}
|
|
95455
|
+
async function readContextualKnowledge(directory, config3, ctx) {
|
|
95456
|
+
const projected = {
|
|
95457
|
+
projectName: ctx.projectName ?? "unknown",
|
|
95458
|
+
currentPhase: ctx.currentPhase ?? "Phase 0",
|
|
95459
|
+
techStack: ctx.techStack,
|
|
95460
|
+
recentErrors: [
|
|
95461
|
+
...ctx.recentReviewerFailures ?? [],
|
|
95462
|
+
...ctx.recentTestFailures ?? [],
|
|
95463
|
+
...ctx.recentToolErrors ?? []
|
|
95464
|
+
]
|
|
95465
|
+
};
|
|
95466
|
+
const wideCfg = {
|
|
95467
|
+
...config3,
|
|
95468
|
+
max_inject_count: Math.max(20, config3.max_inject_count ?? 5)
|
|
95469
|
+
};
|
|
95470
|
+
const candidates = await readMergedKnowledge(directory, wideCfg, projected) ?? [];
|
|
95471
|
+
const minConf = typeof config3.directive_min_confidence === "number" ? config3.directive_min_confidence : DIRECTIVE_BOOST_MIN_CONFIDENCE;
|
|
95472
|
+
const rescored = candidates.map((entry) => {
|
|
95473
|
+
const ds = scoreDirectiveAgainstContext(entry, ctx);
|
|
95474
|
+
const confBoost = entry.confidence >= minConf && (ds.actionHit || ds.agentHit) ? 0.25 : 0;
|
|
95475
|
+
const generatedSkillBoost = entry.generated_skill_path && entry.status !== "archived" ? 0.05 : 0;
|
|
95476
|
+
const finalScore = Math.min(1, entry.finalScore + ds.score + confBoost + generatedSkillBoost);
|
|
95477
|
+
return {
|
|
95478
|
+
...entry,
|
|
95479
|
+
finalScore,
|
|
95480
|
+
__directive: ds
|
|
95481
|
+
};
|
|
95482
|
+
});
|
|
95483
|
+
rescored.sort((a, b) => b.finalScore - a.finalScore);
|
|
95484
|
+
const max = config3.max_inject_count ?? 5;
|
|
95485
|
+
const top = [];
|
|
95486
|
+
const seen = new Set;
|
|
95487
|
+
for (const e of rescored) {
|
|
95488
|
+
if (top.length >= max)
|
|
95489
|
+
break;
|
|
95490
|
+
const ds = e.__directive;
|
|
95491
|
+
const isCritical = e.directive_priority === "critical" && (ds.triggerHit || ds.actionHit || ds.agentHit);
|
|
95492
|
+
if (isCritical && !seen.has(e.id)) {
|
|
95493
|
+
top.push(e);
|
|
95494
|
+
seen.add(e.id);
|
|
95495
|
+
}
|
|
95496
|
+
}
|
|
95497
|
+
for (const e of rescored) {
|
|
95498
|
+
if (top.length >= max)
|
|
95499
|
+
break;
|
|
95500
|
+
if (!seen.has(e.id)) {
|
|
95501
|
+
top.push(e);
|
|
95502
|
+
seen.add(e.id);
|
|
95503
|
+
}
|
|
95504
|
+
}
|
|
95505
|
+
return top.map(({ __directive: _d, ...rest }) => rest);
|
|
95506
|
+
}
|
|
95507
|
+
|
|
95508
|
+
// src/hooks/knowledge-injector.ts
|
|
95473
95509
|
init_knowledge_store();
|
|
95474
95510
|
init_utils2();
|
|
95475
95511
|
var INJECTION_SENTINEL = "[[KNOWLEDGE-INJECTED]]";
|
|
@@ -103383,7 +103419,13 @@ var VALID_CATEGORIES3 = [
|
|
|
103383
103419
|
"todo",
|
|
103384
103420
|
"other"
|
|
103385
103421
|
];
|
|
103386
|
-
var VALID_STATUSES = [
|
|
103422
|
+
var VALID_STATUSES = [
|
|
103423
|
+
"candidate",
|
|
103424
|
+
"established",
|
|
103425
|
+
"promoted",
|
|
103426
|
+
"archived"
|
|
103427
|
+
];
|
|
103428
|
+
var DEFAULT_QUERY_STATUSES = new Set(["established", "promoted"]);
|
|
103387
103429
|
var VALID_TIERS = ["swarm", "hive", "all"];
|
|
103388
103430
|
function validateTierInput(tier) {
|
|
103389
103431
|
if (typeof tier !== "string")
|
|
@@ -103450,9 +103492,13 @@ async function readHiveKnowledge() {
|
|
|
103450
103492
|
}
|
|
103451
103493
|
return readKnowledge(hivePath);
|
|
103452
103494
|
}
|
|
103453
|
-
function filterSwarmEntries(entries, filters, scopeFilter) {
|
|
103495
|
+
function filterSwarmEntries(entries, filters, suppressedLessons, scopeFilter) {
|
|
103454
103496
|
return entries.filter((entry) => {
|
|
103455
|
-
if (filters.status
|
|
103497
|
+
if (filters.status) {
|
|
103498
|
+
if (entry.status !== filters.status) {
|
|
103499
|
+
return false;
|
|
103500
|
+
}
|
|
103501
|
+
} else if (!DEFAULT_QUERY_STATUSES.has(entry.status)) {
|
|
103456
103502
|
return false;
|
|
103457
103503
|
}
|
|
103458
103504
|
if (filters.category && entry.category !== filters.category) {
|
|
@@ -103467,12 +103513,19 @@ function filterSwarmEntries(entries, filters, scopeFilter) {
|
|
|
103467
103513
|
return false;
|
|
103468
103514
|
}
|
|
103469
103515
|
}
|
|
103516
|
+
if (suppressedLessons.has(normalize2(entry.lesson))) {
|
|
103517
|
+
return false;
|
|
103518
|
+
}
|
|
103470
103519
|
return true;
|
|
103471
103520
|
});
|
|
103472
103521
|
}
|
|
103473
|
-
function filterHiveEntries(entries, filters) {
|
|
103522
|
+
function filterHiveEntries(entries, filters, suppressedLessons) {
|
|
103474
103523
|
return entries.filter((entry) => {
|
|
103475
|
-
if (filters.status
|
|
103524
|
+
if (filters.status) {
|
|
103525
|
+
if (entry.status !== filters.status) {
|
|
103526
|
+
return false;
|
|
103527
|
+
}
|
|
103528
|
+
} else if (!DEFAULT_QUERY_STATUSES.has(entry.status)) {
|
|
103476
103529
|
return false;
|
|
103477
103530
|
}
|
|
103478
103531
|
if (filters.category && entry.category !== filters.category) {
|
|
@@ -103481,6 +103534,9 @@ function filterHiveEntries(entries, filters) {
|
|
|
103481
103534
|
if (filters.minScore !== undefined && entry.confidence < filters.minScore) {
|
|
103482
103535
|
return false;
|
|
103483
103536
|
}
|
|
103537
|
+
if (suppressedLessons.has(normalize2(entry.lesson))) {
|
|
103538
|
+
return false;
|
|
103539
|
+
}
|
|
103484
103540
|
return true;
|
|
103485
103541
|
});
|
|
103486
103542
|
}
|
|
@@ -103519,7 +103575,7 @@ var knowledge_query = createSwarmTool({
|
|
|
103519
103575
|
description: 'Query swarm knowledge (project-level) or hive knowledge (cross-project) with optional filters. Returns human-readable formatted text output. Use tier "all" to query both swarm and hive knowledge.',
|
|
103520
103576
|
args: {
|
|
103521
103577
|
tier: exports_external.string().optional().describe("Knowledge tier to query: 'swarm', 'hive', or 'all' (default: 'all')"),
|
|
103522
|
-
status: exports_external.string().optional().describe("Filter by status: 'candidate', 'established', or '
|
|
103578
|
+
status: exports_external.string().optional().describe("Filter by status: 'candidate', 'established', 'promoted', or 'archived'"),
|
|
103523
103579
|
category: exports_external.string().optional().describe("Filter by category: 'process', 'architecture', 'tooling', 'security', 'testing', 'debugging', 'performance', 'integration', 'todo', or 'other'"),
|
|
103524
103580
|
min_score: exports_external.number().optional().describe("Minimum confidence score filter (0.0-1.0)"),
|
|
103525
103581
|
limit: exports_external.number().optional().describe(`Maximum number of results to return (default: ${DEFAULT_LIMIT}, max: 100)`)
|
|
@@ -103550,6 +103606,8 @@ var knowledge_query = createSwarmTool({
|
|
|
103550
103606
|
category: category ?? undefined,
|
|
103551
103607
|
minScore: minScore ?? undefined
|
|
103552
103608
|
};
|
|
103609
|
+
const retractionRecords = await readRetractionRecords(directory);
|
|
103610
|
+
const suppressedLessons = new Set(retractionRecords.map((record3) => record3.normalized_lesson).filter((value) => typeof value === "string" && value.length > 0));
|
|
103553
103611
|
const results = [];
|
|
103554
103612
|
let scopeFilter;
|
|
103555
103613
|
try {
|
|
@@ -103558,14 +103616,14 @@ var knowledge_query = createSwarmTool({
|
|
|
103558
103616
|
} catch {}
|
|
103559
103617
|
if (tier === "swarm" || tier === "all") {
|
|
103560
103618
|
const swarmEntries = await readSwarmKnowledge(directory);
|
|
103561
|
-
const filtered = filterSwarmEntries(swarmEntries, filters, scopeFilter);
|
|
103619
|
+
const filtered = filterSwarmEntries(swarmEntries, filters, suppressedLessons, scopeFilter);
|
|
103562
103620
|
for (const entry of filtered) {
|
|
103563
103621
|
results.push({ entry, tier: "swarm" });
|
|
103564
103622
|
}
|
|
103565
103623
|
}
|
|
103566
103624
|
if (tier === "hive" || tier === "all") {
|
|
103567
103625
|
const hiveEntries = await readHiveKnowledge();
|
|
103568
|
-
const filtered = filterHiveEntries(hiveEntries, filters);
|
|
103626
|
+
const filtered = filterHiveEntries(hiveEntries, filters, suppressedLessons);
|
|
103569
103627
|
for (const entry of filtered) {
|
|
103570
103628
|
results.push({ entry, tier: "hive" });
|
|
103571
103629
|
}
|
|
@@ -103824,7 +103882,6 @@ function phaseIsExplicitlyNonCode(directory, phase) {
|
|
|
103824
103882
|
init_gate_evidence();
|
|
103825
103883
|
init_curator();
|
|
103826
103884
|
init_knowledge_curator();
|
|
103827
|
-
init_knowledge_reader();
|
|
103828
103885
|
init_knowledge_store();
|
|
103829
103886
|
init_review_receipt();
|
|
103830
103887
|
init_utils2();
|