opencode-swarm 7.29.4 → 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/agents/architect.d.ts +1 -1
- package/dist/cli/index.js +471 -490
- package/dist/config/constants.d.ts +2 -0
- package/dist/config/index.d.ts +2 -2
- package/dist/config/schema.d.ts +35 -0
- package/dist/hooks/knowledge-store.d.ts +12 -0
- package/dist/index.js +2240 -1056
- package/dist/memory/config.d.ts +22 -0
- package/dist/memory/errors.d.ts +7 -0
- package/dist/memory/gateway.d.ts +51 -0
- package/dist/memory/index.d.ts +11 -0
- package/dist/memory/local-jsonl-provider.d.ts +26 -0
- package/dist/memory/prompt-block.d.ts +13 -0
- package/dist/memory/provider.d.ts +17 -0
- package/dist/memory/redaction.d.ts +7 -0
- package/dist/memory/schema.d.ts +256 -0
- package/dist/memory/scoring.d.ts +5 -0
- package/dist/memory/types.d.ts +96 -0
- package/dist/tools/index.d.ts +3 -1
- package/dist/tools/swarm-command.d.ts +1 -0
- package/dist/tools/swarm-memory-propose.d.ts +8 -0
- package/dist/tools/swarm-memory-recall.d.ts +8 -0
- package/dist/tools/tool-names.d.ts +1 -1
- package/package.json +1 -1
package/dist/cli/index.js
CHANGED
|
@@ -34,7 +34,7 @@ var package_default;
|
|
|
34
34
|
var init_package = __esm(() => {
|
|
35
35
|
package_default = {
|
|
36
36
|
name: "opencode-swarm",
|
|
37
|
-
version: "7.
|
|
37
|
+
version: "7.31.0",
|
|
38
38
|
description: "Architect-centric agentic swarm plugin for OpenCode - hub-and-spoke orchestration with SME consultation, code generation, and QA review",
|
|
39
39
|
main: "dist/index.js",
|
|
40
40
|
types: "dist/index.d.ts",
|
|
@@ -16225,6 +16225,8 @@ var init_tool_names = __esm(() => {
|
|
|
16225
16225
|
"skill_improve",
|
|
16226
16226
|
"spec_write",
|
|
16227
16227
|
"knowledge_ack",
|
|
16228
|
+
"swarm_memory_recall",
|
|
16229
|
+
"swarm_memory_propose",
|
|
16228
16230
|
"swarm_command",
|
|
16229
16231
|
"lean_turbo_plan_lanes",
|
|
16230
16232
|
"lean_turbo_acquire_locks",
|
|
@@ -16757,6 +16759,8 @@ var init_constants = __esm(() => {
|
|
|
16757
16759
|
skill_improve: "run the skill_improver agent to review and refine skills",
|
|
16758
16760
|
spec_write: "author or update .swarm/spec.md for the current project",
|
|
16759
16761
|
knowledge_ack: "record an explicit KNOWLEDGE_APPLIED/IGNORED/VIOLATED acknowledgment",
|
|
16762
|
+
swarm_memory_recall: "recall scoped Swarm memory for the current repository as untrusted background",
|
|
16763
|
+
swarm_memory_propose: "create a pending Swarm memory proposal; does not write durable memory directly",
|
|
16760
16764
|
swarm_command: "run supported /swarm commands through the canonical command registry",
|
|
16761
16765
|
lean_turbo_plan_lanes: "partition phase tasks into parallel lanes based on file-scope conflicts for Lean Turbo execution",
|
|
16762
16766
|
lean_turbo_acquire_locks: "acquire file locks for all files in a lane (all-or-nothing) before lane execution",
|
|
@@ -16868,7 +16872,7 @@ function getCanonicalAgentRole(agentName, generatedAgentNames) {
|
|
|
16868
16872
|
function stripKnownSwarmPrefix(agentName) {
|
|
16869
16873
|
return getCanonicalAgentRole(agentName);
|
|
16870
16874
|
}
|
|
16871
|
-
var SEPARATORS, CANONICAL_ROLES_LONGEST_FIRST, CANONICAL_ROLES_SET, AgentOverrideConfigSchema, SwarmConfigSchema, HooksConfigSchema, ScoringWeightsSchema, DecisionDecaySchema, TokenRatiosSchema, ScoringConfigSchema, ContextBudgetConfigSchema, EvidenceConfigSchema, GateFeatureSchema, PlaceholderScanConfigSchema, QualityBudgetConfigSchema, GateConfigSchema, PipelineConfigSchema, PhaseCompleteConfigSchema, SummaryConfigSchema, ReviewPassesConfigSchema, AdversarialDetectionConfigSchema, AdversarialTestingConfigSchemaBase, AdversarialTestingConfigSchema, IntegrationAnalysisConfigSchema, DocsConfigSchema, UIReviewConfigSchema, CompactionAdvisoryConfigSchema, LintConfigSchema, SecretscanConfigSchema, GuardrailsProfileSchema, DEFAULT_AGENT_PROFILES, DEFAULT_ARCHITECT_PROFILE, GuardrailsConfigSchema, WatchdogConfigSchema, SelfReviewConfigSchema, ToolFilterConfigSchema, PlanCursorConfigSchema, CheckpointConfigSchema, AutomationModeSchema, AutomationCapabilitiesSchema, AutomationConfigSchemaBase, AutomationConfigSchema, KnowledgeConfigSchema, CuratorConfigSchema, KnowledgeApplicationConfigSchema, SkillImproverConfigSchema, SpecWriterConfigSchema, SlopDetectorConfigSchema, IncrementalVerifyConfigSchema, CompactionConfigSchema, PrmConfigSchema, AgentAuthorityRuleSchema, AuthorityConfigSchema, GeneralCouncilMemberConfigSchema, GeneralCouncilConfigSchema, CouncilConfigSchema, ParallelizationConfigSchema, LeanTurboConfigSchema, StandardTurboConfigSchema, LeanTurboStrategyConfigSchema, TurboConfigSchema, PluginConfigSchema;
|
|
16875
|
+
var SEPARATORS, CANONICAL_ROLES_LONGEST_FIRST, CANONICAL_ROLES_SET, AgentOverrideConfigSchema, SwarmConfigSchema, HooksConfigSchema, ScoringWeightsSchema, DecisionDecaySchema, TokenRatiosSchema, ScoringConfigSchema, ContextBudgetConfigSchema, EvidenceConfigSchema, GateFeatureSchema, PlaceholderScanConfigSchema, QualityBudgetConfigSchema, GateConfigSchema, PipelineConfigSchema, PhaseCompleteConfigSchema, SummaryConfigSchema, ReviewPassesConfigSchema, AdversarialDetectionConfigSchema, AdversarialTestingConfigSchemaBase, AdversarialTestingConfigSchema, IntegrationAnalysisConfigSchema, DocsConfigSchema, UIReviewConfigSchema, CompactionAdvisoryConfigSchema, LintConfigSchema, SecretscanConfigSchema, GuardrailsProfileSchema, DEFAULT_AGENT_PROFILES, DEFAULT_ARCHITECT_PROFILE, GuardrailsConfigSchema, WatchdogConfigSchema, SelfReviewConfigSchema, ToolFilterConfigSchema, PlanCursorConfigSchema, CheckpointConfigSchema, AutomationModeSchema, AutomationCapabilitiesSchema, AutomationConfigSchemaBase, AutomationConfigSchema, KnowledgeConfigSchema, MemoryConfigSchema, CuratorConfigSchema, KnowledgeApplicationConfigSchema, SkillImproverConfigSchema, SpecWriterConfigSchema, SlopDetectorConfigSchema, IncrementalVerifyConfigSchema, CompactionConfigSchema, PrmConfigSchema, AgentAuthorityRuleSchema, AuthorityConfigSchema, GeneralCouncilMemberConfigSchema, GeneralCouncilConfigSchema, CouncilConfigSchema, ParallelizationConfigSchema, LeanTurboConfigSchema, StandardTurboConfigSchema, LeanTurboStrategyConfigSchema, TurboConfigSchema, PluginConfigSchema;
|
|
16872
16876
|
var init_schema = __esm(() => {
|
|
16873
16877
|
init_zod();
|
|
16874
16878
|
init_constants();
|
|
@@ -17320,6 +17324,23 @@ var init_schema = __esm(() => {
|
|
|
17320
17324
|
todo_max_phases: exports_external.number().int().positive().default(3),
|
|
17321
17325
|
sweep_enabled: exports_external.boolean().default(true)
|
|
17322
17326
|
});
|
|
17327
|
+
MemoryConfigSchema = exports_external.object({
|
|
17328
|
+
enabled: exports_external.boolean().default(false),
|
|
17329
|
+
provider: exports_external.literal("local-jsonl").default("local-jsonl"),
|
|
17330
|
+
storageDir: exports_external.string().default(".swarm/memory"),
|
|
17331
|
+
recall: exports_external.object({
|
|
17332
|
+
defaultMaxItems: exports_external.number().int().min(1).max(20).default(8),
|
|
17333
|
+
defaultTokenBudget: exports_external.number().int().min(100).max(5000).default(1200),
|
|
17334
|
+
minScore: exports_external.number().min(0).max(1).default(0.05)
|
|
17335
|
+
}).default({ defaultMaxItems: 8, defaultTokenBudget: 1200, minScore: 0.05 }),
|
|
17336
|
+
writes: exports_external.object({
|
|
17337
|
+
mode: exports_external.literal("propose").default("propose")
|
|
17338
|
+
}).default({ mode: "propose" }),
|
|
17339
|
+
redaction: exports_external.object({
|
|
17340
|
+
rejectDurableSecrets: exports_external.boolean().default(true)
|
|
17341
|
+
}).default({ rejectDurableSecrets: true }),
|
|
17342
|
+
hardDelete: exports_external.boolean().default(false)
|
|
17343
|
+
});
|
|
17323
17344
|
CuratorConfigSchema = exports_external.object({
|
|
17324
17345
|
enabled: exports_external.boolean().default(true),
|
|
17325
17346
|
init_enabled: exports_external.boolean().default(true),
|
|
@@ -17527,6 +17548,7 @@ var init_schema = __esm(() => {
|
|
|
17527
17548
|
checkpoint: CheckpointConfigSchema.optional(),
|
|
17528
17549
|
automation: AutomationConfigSchema.optional(),
|
|
17529
17550
|
knowledge: KnowledgeConfigSchema.optional(),
|
|
17551
|
+
memory: MemoryConfigSchema.optional(),
|
|
17530
17552
|
curator: CuratorConfigSchema.optional(),
|
|
17531
17553
|
knowledge_application: KnowledgeApplicationConfigSchema.optional(),
|
|
17532
17554
|
skill_improver: SkillImproverConfigSchema.optional(),
|
|
@@ -35375,6 +35397,9 @@ function resolveSwarmKnowledgePath(directory) {
|
|
|
35375
35397
|
function resolveSwarmRejectedPath(directory) {
|
|
35376
35398
|
return path10.join(directory, ".swarm", "knowledge-rejected.jsonl");
|
|
35377
35399
|
}
|
|
35400
|
+
function resolveSwarmRetractionsPath(directory) {
|
|
35401
|
+
return path10.join(directory, ".swarm", "knowledge-retractions.jsonl");
|
|
35402
|
+
}
|
|
35378
35403
|
function resolveHiveKnowledgePath() {
|
|
35379
35404
|
const platform = process.platform;
|
|
35380
35405
|
const home = process.env.HOME || os3.homedir();
|
|
@@ -35473,6 +35498,12 @@ function normalizeEntry(raw) {
|
|
|
35473
35498
|
async function readRejectedLessons(directory) {
|
|
35474
35499
|
return readKnowledge(resolveSwarmRejectedPath(directory));
|
|
35475
35500
|
}
|
|
35501
|
+
async function readRetractionRecords(directory) {
|
|
35502
|
+
return readKnowledge(resolveSwarmRetractionsPath(directory));
|
|
35503
|
+
}
|
|
35504
|
+
async function appendRetractionRecord(directory, record3) {
|
|
35505
|
+
await appendKnowledge(resolveSwarmRetractionsPath(directory), record3);
|
|
35506
|
+
}
|
|
35476
35507
|
async function appendKnowledge(filePath, entry) {
|
|
35477
35508
|
await mkdir2(path10.dirname(filePath), { recursive: true });
|
|
35478
35509
|
await appendFile2(filePath, `${JSON.stringify(entry)}
|
|
@@ -36237,75 +36268,6 @@ var init_hive_promoter = __esm(() => {
|
|
|
36237
36268
|
init_utils2();
|
|
36238
36269
|
});
|
|
36239
36270
|
|
|
36240
|
-
// src/hooks/knowledge-reader.ts
|
|
36241
|
-
import { existsSync as existsSync8 } from "fs";
|
|
36242
|
-
import { mkdir as mkdir4, readFile as readFile4, writeFile as writeFile5 } from "fs/promises";
|
|
36243
|
-
import * as path13 from "path";
|
|
36244
|
-
async function updateRetrievalOutcome(directory, phaseInfo, phaseSucceeded) {
|
|
36245
|
-
const shownFile = path13.join(directory, ".swarm", ".knowledge-shown.json");
|
|
36246
|
-
try {
|
|
36247
|
-
if (!existsSync8(shownFile)) {
|
|
36248
|
-
return;
|
|
36249
|
-
}
|
|
36250
|
-
const content = await readFile4(shownFile, "utf-8");
|
|
36251
|
-
const shownData = JSON.parse(content);
|
|
36252
|
-
const shownIds = shownData[phaseInfo];
|
|
36253
|
-
if (!shownIds || shownIds.length === 0) {
|
|
36254
|
-
return;
|
|
36255
|
-
}
|
|
36256
|
-
const swarmPath = resolveSwarmKnowledgePath(directory);
|
|
36257
|
-
const entries = await readKnowledge(swarmPath);
|
|
36258
|
-
let updated = false;
|
|
36259
|
-
const foundInSwarm = new Set;
|
|
36260
|
-
for (const entry of entries) {
|
|
36261
|
-
if (shownIds.includes(entry.id)) {
|
|
36262
|
-
const ro = entry.retrieval_outcomes;
|
|
36263
|
-
if (phaseSucceeded) {
|
|
36264
|
-
ro.succeeded_after_shown_count = (ro.succeeded_after_shown_count ?? 0) + 1;
|
|
36265
|
-
} else {
|
|
36266
|
-
ro.failed_after_shown_count = (ro.failed_after_shown_count ?? 0) + 1;
|
|
36267
|
-
}
|
|
36268
|
-
updated = true;
|
|
36269
|
-
foundInSwarm.add(entry.id);
|
|
36270
|
-
}
|
|
36271
|
-
}
|
|
36272
|
-
if (updated) {
|
|
36273
|
-
await rewriteKnowledge(swarmPath, entries);
|
|
36274
|
-
}
|
|
36275
|
-
const remainingIds = shownIds.filter((id) => !foundInSwarm.has(id));
|
|
36276
|
-
if (remainingIds.length === 0) {
|
|
36277
|
-
delete shownData[phaseInfo];
|
|
36278
|
-
await writeFile5(shownFile, JSON.stringify(shownData, null, 2), "utf-8");
|
|
36279
|
-
return;
|
|
36280
|
-
}
|
|
36281
|
-
const hivePath = resolveHiveKnowledgePath();
|
|
36282
|
-
const hiveEntries = await readKnowledge(hivePath);
|
|
36283
|
-
let hiveUpdated = false;
|
|
36284
|
-
for (const entry of hiveEntries) {
|
|
36285
|
-
if (remainingIds.includes(entry.id)) {
|
|
36286
|
-
const ro = entry.retrieval_outcomes;
|
|
36287
|
-
if (phaseSucceeded) {
|
|
36288
|
-
ro.succeeded_after_shown_count = (ro.succeeded_after_shown_count ?? 0) + 1;
|
|
36289
|
-
} else {
|
|
36290
|
-
ro.failed_after_shown_count = (ro.failed_after_shown_count ?? 0) + 1;
|
|
36291
|
-
}
|
|
36292
|
-
hiveUpdated = true;
|
|
36293
|
-
}
|
|
36294
|
-
}
|
|
36295
|
-
if (hiveUpdated) {
|
|
36296
|
-
await rewriteKnowledge(hivePath, hiveEntries);
|
|
36297
|
-
}
|
|
36298
|
-
delete shownData[phaseInfo];
|
|
36299
|
-
await writeFile5(shownFile, JSON.stringify(shownData, null, 2), "utf-8");
|
|
36300
|
-
} catch {
|
|
36301
|
-
warn("[swarm] Knowledge: failed to update retrieval outcomes");
|
|
36302
|
-
}
|
|
36303
|
-
}
|
|
36304
|
-
var init_knowledge_reader = __esm(() => {
|
|
36305
|
-
init_logger();
|
|
36306
|
-
init_knowledge_store();
|
|
36307
|
-
});
|
|
36308
|
-
|
|
36309
36271
|
// src/hooks/knowledge-curator.ts
|
|
36310
36272
|
function pruneSeenRetroSections() {
|
|
36311
36273
|
const cutoff = Date.now() - 86400000;
|
|
@@ -36422,17 +36384,39 @@ function extractRetractionsAndLessons(allLessons) {
|
|
|
36422
36384
|
async function processRetractions(retractions, directory) {
|
|
36423
36385
|
if (retractions.length === 0)
|
|
36424
36386
|
return;
|
|
36425
|
-
const
|
|
36426
|
-
const
|
|
36387
|
+
const swarmEntries = await readKnowledge(resolveSwarmKnowledgePath(directory)) ?? [];
|
|
36388
|
+
const hiveEntries = await readKnowledge(resolveHiveKnowledgePath()) ?? [];
|
|
36389
|
+
const existingRetractions = await readRetractionRecords(directory);
|
|
36390
|
+
const existingSuppressedLessons = new Set(existingRetractions.map((record3) => record3.normalized_lesson).filter((value) => typeof value === "string" && value.length > 0));
|
|
36427
36391
|
for (const retractionText of retractions) {
|
|
36428
36392
|
const normalizedRetraction = normalize2(retractionText);
|
|
36429
|
-
|
|
36393
|
+
const matchedSwarmIds = [];
|
|
36394
|
+
const matchedHiveIds = [];
|
|
36395
|
+
for (const entry of swarmEntries) {
|
|
36430
36396
|
const normalizedLesson = normalize2(entry.lesson);
|
|
36431
36397
|
if (normalizedLesson === normalizedRetraction) {
|
|
36398
|
+
matchedSwarmIds.push(entry.id);
|
|
36432
36399
|
await quarantineEntry(directory, entry.id, `Retracted by architect: ${retractionText}`, "architect");
|
|
36433
36400
|
console.info(`[knowledge-curator] Quarantined entry ${entry.id}: "${entry.lesson}"`);
|
|
36434
36401
|
}
|
|
36435
36402
|
}
|
|
36403
|
+
for (const entry of hiveEntries) {
|
|
36404
|
+
if (normalize2(entry.lesson) === normalizedRetraction) {
|
|
36405
|
+
matchedHiveIds.push(entry.id);
|
|
36406
|
+
}
|
|
36407
|
+
}
|
|
36408
|
+
if (!existingSuppressedLessons.has(normalizedRetraction)) {
|
|
36409
|
+
await appendRetractionRecord(directory, {
|
|
36410
|
+
id: crypto.randomUUID(),
|
|
36411
|
+
retracted_lesson: retractionText,
|
|
36412
|
+
normalized_lesson: normalizedRetraction,
|
|
36413
|
+
recorded_at: new Date().toISOString(),
|
|
36414
|
+
reported_by: "architect",
|
|
36415
|
+
matched_swarm_ids: matchedSwarmIds,
|
|
36416
|
+
matched_hive_ids: matchedHiveIds
|
|
36417
|
+
});
|
|
36418
|
+
existingSuppressedLessons.add(normalizedRetraction);
|
|
36419
|
+
}
|
|
36436
36420
|
}
|
|
36437
36421
|
}
|
|
36438
36422
|
async function curateAndStoreSwarm(lessons, projectName, phaseInfo, directory, config3) {
|
|
@@ -36599,7 +36583,6 @@ function createKnowledgeCuratorHook(directory, config3) {
|
|
|
36599
36583
|
const projectName2 = evidenceData.project_name ?? "unknown";
|
|
36600
36584
|
const phaseNumber2 = typeof evidenceData.phase_number === "number" ? evidenceData.phase_number : 1;
|
|
36601
36585
|
await _internals8.curateAndStoreSwarm(lessons, projectName2, { phase_number: phaseNumber2 }, directory, config3);
|
|
36602
|
-
await updateRetrievalOutcome(directory, `Phase ${phaseNumber2}`, true);
|
|
36603
36586
|
return;
|
|
36604
36587
|
}
|
|
36605
36588
|
const planContent = await readSwarmFileAsync(directory, "plan.md");
|
|
@@ -36622,13 +36605,11 @@ function createKnowledgeCuratorHook(directory, config3) {
|
|
|
36622
36605
|
const phaseMatch = /^Phase:\s*(\d+)/m.exec(planContent);
|
|
36623
36606
|
const phaseNumber = phaseMatch ? parseInt(phaseMatch[1], 10) : 1;
|
|
36624
36607
|
await _internals8.curateAndStoreSwarm(normalLessons, projectName, { phase_number: phaseNumber }, directory, config3);
|
|
36625
|
-
await updateRetrievalOutcome(directory, `Phase ${phaseNumber}`, true);
|
|
36626
36608
|
};
|
|
36627
36609
|
return safeHook(handler);
|
|
36628
36610
|
}
|
|
36629
36611
|
var seenRetroSections, _internals8;
|
|
36630
36612
|
var init_knowledge_curator = __esm(() => {
|
|
36631
|
-
init_knowledge_reader();
|
|
36632
36613
|
init_knowledge_store();
|
|
36633
36614
|
init_knowledge_validator();
|
|
36634
36615
|
init_utils2();
|
|
@@ -36751,9 +36732,9 @@ var init_skill_improver_llm_factory = __esm(() => {
|
|
|
36751
36732
|
});
|
|
36752
36733
|
|
|
36753
36734
|
// src/services/skill-generator.ts
|
|
36754
|
-
import { existsSync as
|
|
36755
|
-
import { mkdir as
|
|
36756
|
-
import * as
|
|
36735
|
+
import { existsSync as existsSync8 } from "fs";
|
|
36736
|
+
import { mkdir as mkdir4, readFile as readFile4, rename as rename3, writeFile as writeFile5 } from "fs/promises";
|
|
36737
|
+
import * as path13 from "path";
|
|
36757
36738
|
function sanitizeSlug(input) {
|
|
36758
36739
|
const lc = input.toLowerCase().trim();
|
|
36759
36740
|
const mapped = lc.replace(/[^a-z0-9-]+/g, "-").replace(/-+/g, "-");
|
|
@@ -36764,10 +36745,10 @@ function isValidSlug(slug) {
|
|
|
36764
36745
|
return SLUG_PATTERN.test(slug);
|
|
36765
36746
|
}
|
|
36766
36747
|
function proposalPath(directory, slug) {
|
|
36767
|
-
return
|
|
36748
|
+
return path13.join(directory, ".swarm", "skills", "proposals", `${slug}.md`);
|
|
36768
36749
|
}
|
|
36769
36750
|
function activePath(directory, slug) {
|
|
36770
|
-
return
|
|
36751
|
+
return path13.join(directory, ".opencode", "skills", "generated", slug, "SKILL.md");
|
|
36771
36752
|
}
|
|
36772
36753
|
function activeRepoRelativePath(slug) {
|
|
36773
36754
|
return `.opencode/skills/generated/${slug}/SKILL.md`;
|
|
@@ -36775,7 +36756,7 @@ function activeRepoRelativePath(slug) {
|
|
|
36775
36756
|
async function selectCandidateEntries(directory, opts) {
|
|
36776
36757
|
const swarm = await readKnowledge(resolveSwarmKnowledgePath(directory));
|
|
36777
36758
|
const hivePath = resolveHiveKnowledgePath();
|
|
36778
|
-
const hive =
|
|
36759
|
+
const hive = existsSync8(hivePath) ? await readKnowledge(hivePath) : [];
|
|
36779
36760
|
const all = [...swarm, ...hive];
|
|
36780
36761
|
return all.filter((e) => {
|
|
36781
36762
|
if (e.status === "archived")
|
|
@@ -36923,9 +36904,9 @@ function escapeMarkdown(s) {
|
|
|
36923
36904
|
return s.replace(/[\r\n]+/g, " ").slice(0, 280);
|
|
36924
36905
|
}
|
|
36925
36906
|
async function atomicWrite(p, content) {
|
|
36926
|
-
await
|
|
36907
|
+
await mkdir4(path13.dirname(p), { recursive: true });
|
|
36927
36908
|
const tmp = `${p}.tmp-${process.pid}-${Date.now()}`;
|
|
36928
|
-
await
|
|
36909
|
+
await writeFile5(tmp, content, "utf-8");
|
|
36929
36910
|
await rename3(tmp, p);
|
|
36930
36911
|
}
|
|
36931
36912
|
async function generateSkills(req) {
|
|
@@ -36940,7 +36921,7 @@ async function generateSkills(req) {
|
|
|
36940
36921
|
const idSet = new Set(req.sourceKnowledgeIds);
|
|
36941
36922
|
const swarm = await readKnowledge(resolveSwarmKnowledgePath(req.directory));
|
|
36942
36923
|
const hivePath = resolveHiveKnowledgePath();
|
|
36943
|
-
const hive =
|
|
36924
|
+
const hive = existsSync8(hivePath) ? await readKnowledge(hivePath) : [];
|
|
36944
36925
|
pool = [...swarm, ...hive].filter((e) => idSet.has(e.id) && e.status !== "archived");
|
|
36945
36926
|
} else {
|
|
36946
36927
|
pool = candidates;
|
|
@@ -36968,7 +36949,7 @@ async function generateSkills(req) {
|
|
|
36968
36949
|
continue;
|
|
36969
36950
|
}
|
|
36970
36951
|
const targetPath = req.mode === "active" ? activePath(req.directory, cluster.slug) : proposalPath(req.directory, cluster.slug);
|
|
36971
|
-
const repoRel =
|
|
36952
|
+
const repoRel = path13.relative(req.directory, targetPath).replace(/\\/g, "/");
|
|
36972
36953
|
if (!validateSkillPath(repoRel)) {
|
|
36973
36954
|
result.skipped.push({
|
|
36974
36955
|
slug: cluster.slug,
|
|
@@ -36977,8 +36958,8 @@ async function generateSkills(req) {
|
|
|
36977
36958
|
continue;
|
|
36978
36959
|
}
|
|
36979
36960
|
let preserved = false;
|
|
36980
|
-
if (req.mode === "active" &&
|
|
36981
|
-
const existing = await
|
|
36961
|
+
if (req.mode === "active" && existsSync8(targetPath) && !req.force) {
|
|
36962
|
+
const existing = await readFile4(targetPath, "utf-8");
|
|
36982
36963
|
if (!existing.includes("generated by opencode-swarm skill-generator")) {
|
|
36983
36964
|
preserved = true;
|
|
36984
36965
|
result.skipped.push({
|
|
@@ -37022,7 +37003,7 @@ async function stampSourceEntries(directory, slug, ids) {
|
|
|
37022
37003
|
if (touched)
|
|
37023
37004
|
await rewriteKnowledge(swarmPath, swarm);
|
|
37024
37005
|
const hivePath = resolveHiveKnowledgePath();
|
|
37025
|
-
if (!
|
|
37006
|
+
if (!existsSync8(hivePath))
|
|
37026
37007
|
return;
|
|
37027
37008
|
const hive = await readKnowledge(hivePath);
|
|
37028
37009
|
let touchedHive = false;
|
|
@@ -37042,10 +37023,10 @@ async function listSkills(directory) {
|
|
|
37042
37023
|
proposals: [],
|
|
37043
37024
|
active: []
|
|
37044
37025
|
};
|
|
37045
|
-
const proposalsDir =
|
|
37046
|
-
const activeDir =
|
|
37026
|
+
const proposalsDir = path13.join(directory, ".swarm", "skills", "proposals");
|
|
37027
|
+
const activeDir = path13.join(directory, ".opencode", "skills", "generated");
|
|
37047
37028
|
const fs7 = await import("fs/promises");
|
|
37048
|
-
if (
|
|
37029
|
+
if (existsSync8(proposalsDir)) {
|
|
37049
37030
|
const entries = await fs7.readdir(proposalsDir);
|
|
37050
37031
|
for (const f of entries) {
|
|
37051
37032
|
if (!f.endsWith(".md"))
|
|
@@ -37053,17 +37034,17 @@ async function listSkills(directory) {
|
|
|
37053
37034
|
const slug = f.replace(/\.md$/, "");
|
|
37054
37035
|
result.proposals.push({
|
|
37055
37036
|
slug,
|
|
37056
|
-
path:
|
|
37037
|
+
path: path13.join(proposalsDir, f)
|
|
37057
37038
|
});
|
|
37058
37039
|
}
|
|
37059
37040
|
}
|
|
37060
|
-
if (
|
|
37041
|
+
if (existsSync8(activeDir)) {
|
|
37061
37042
|
const entries = await fs7.readdir(activeDir, { withFileTypes: true });
|
|
37062
37043
|
for (const e of entries) {
|
|
37063
37044
|
if (!e.isDirectory())
|
|
37064
37045
|
continue;
|
|
37065
|
-
const skillPath =
|
|
37066
|
-
if (
|
|
37046
|
+
const skillPath = path13.join(activeDir, e.name, "SKILL.md");
|
|
37047
|
+
if (existsSync8(skillPath)) {
|
|
37067
37048
|
result.active.push({
|
|
37068
37049
|
slug: e.name,
|
|
37069
37050
|
path: skillPath
|
|
@@ -37082,9 +37063,9 @@ var init_skill_generator = __esm(() => {
|
|
|
37082
37063
|
});
|
|
37083
37064
|
|
|
37084
37065
|
// src/services/skill-improver-quota.ts
|
|
37085
|
-
import { existsSync as
|
|
37086
|
-
import { mkdir as
|
|
37087
|
-
import * as
|
|
37066
|
+
import { existsSync as existsSync9 } from "fs";
|
|
37067
|
+
import { mkdir as mkdir5, readFile as readFile5, rename as rename4, writeFile as writeFile6 } from "fs/promises";
|
|
37068
|
+
import * as path14 from "path";
|
|
37088
37069
|
async function acquireLock(dir) {
|
|
37089
37070
|
const acquire = import_proper_lockfile5.default.lock(dir, LOCK_RETRY_OPTS);
|
|
37090
37071
|
let timer;
|
|
@@ -37102,7 +37083,7 @@ async function acquireLock(dir) {
|
|
|
37102
37083
|
}
|
|
37103
37084
|
}
|
|
37104
37085
|
function resolveQuotaPath(directory) {
|
|
37105
|
-
return
|
|
37086
|
+
return path14.join(directory, ".swarm", "skill-improver-quota.json");
|
|
37106
37087
|
}
|
|
37107
37088
|
function todayKey(window, now = new Date) {
|
|
37108
37089
|
if (window === "utc") {
|
|
@@ -37114,10 +37095,10 @@ function todayKey(window, now = new Date) {
|
|
|
37114
37095
|
return `${yr}-${m}-${d}`;
|
|
37115
37096
|
}
|
|
37116
37097
|
async function readState(filePath) {
|
|
37117
|
-
if (!
|
|
37098
|
+
if (!existsSync9(filePath))
|
|
37118
37099
|
return null;
|
|
37119
37100
|
try {
|
|
37120
|
-
const raw = await
|
|
37101
|
+
const raw = await readFile5(filePath, "utf-8");
|
|
37121
37102
|
const parsed = JSON.parse(raw);
|
|
37122
37103
|
if (typeof parsed.date !== "string" || typeof parsed.calls_used !== "number" || typeof parsed.max_calls !== "number" || parsed.window !== "utc" && parsed.window !== "local") {
|
|
37123
37104
|
return null;
|
|
@@ -37128,9 +37109,9 @@ async function readState(filePath) {
|
|
|
37128
37109
|
}
|
|
37129
37110
|
}
|
|
37130
37111
|
async function writeState(filePath, state) {
|
|
37131
|
-
await
|
|
37112
|
+
await mkdir5(path14.dirname(filePath), { recursive: true });
|
|
37132
37113
|
const tmp = `${filePath}.tmp-${process.pid}`;
|
|
37133
|
-
await
|
|
37114
|
+
await writeFile6(tmp, JSON.stringify(state, null, 2), "utf-8");
|
|
37134
37115
|
await rename4(tmp, filePath);
|
|
37135
37116
|
}
|
|
37136
37117
|
async function getQuotaState(directory, opts) {
|
|
@@ -37151,10 +37132,10 @@ async function getQuotaState(directory, opts) {
|
|
|
37151
37132
|
}
|
|
37152
37133
|
async function reserveQuota(directory, opts) {
|
|
37153
37134
|
const filePath = resolveQuotaPath(directory);
|
|
37154
|
-
await
|
|
37135
|
+
await mkdir5(path14.dirname(filePath), { recursive: true });
|
|
37155
37136
|
let release = null;
|
|
37156
37137
|
try {
|
|
37157
|
-
release = await acquireLock(
|
|
37138
|
+
release = await acquireLock(path14.dirname(filePath));
|
|
37158
37139
|
const state = await getQuotaState(directory, opts);
|
|
37159
37140
|
if (state.calls_used + opts.nCalls > opts.maxCalls) {
|
|
37160
37141
|
return {
|
|
@@ -37181,10 +37162,10 @@ async function reserveQuota(directory, opts) {
|
|
|
37181
37162
|
}
|
|
37182
37163
|
async function releaseQuota(directory, opts) {
|
|
37183
37164
|
const filePath = resolveQuotaPath(directory);
|
|
37184
|
-
await
|
|
37165
|
+
await mkdir5(path14.dirname(filePath), { recursive: true });
|
|
37185
37166
|
let release = null;
|
|
37186
37167
|
try {
|
|
37187
|
-
release = await acquireLock(
|
|
37168
|
+
release = await acquireLock(path14.dirname(filePath));
|
|
37188
37169
|
const state = await getQuotaState(directory, opts);
|
|
37189
37170
|
const next = {
|
|
37190
37171
|
...state,
|
|
@@ -37216,22 +37197,22 @@ var init_skill_improver_quota = __esm(() => {
|
|
|
37216
37197
|
});
|
|
37217
37198
|
|
|
37218
37199
|
// src/services/skill-improver.ts
|
|
37219
|
-
import { existsSync as
|
|
37220
|
-
import { mkdir as
|
|
37221
|
-
import * as
|
|
37200
|
+
import { existsSync as existsSync10 } from "fs";
|
|
37201
|
+
import { mkdir as mkdir6, rename as rename5, writeFile as writeFile7 } from "fs/promises";
|
|
37202
|
+
import * as path15 from "path";
|
|
37222
37203
|
function timestampSlug(d) {
|
|
37223
37204
|
return d.toISOString().replace(/[:.]/g, "-");
|
|
37224
37205
|
}
|
|
37225
37206
|
async function atomicWrite2(p, content) {
|
|
37226
|
-
await
|
|
37207
|
+
await mkdir6(path15.dirname(p), { recursive: true });
|
|
37227
37208
|
const tmp = `${p}.tmp-${process.pid}-${Date.now()}`;
|
|
37228
|
-
await
|
|
37209
|
+
await writeFile7(tmp, content, "utf-8");
|
|
37229
37210
|
await rename5(tmp, p);
|
|
37230
37211
|
}
|
|
37231
37212
|
async function gatherInventory(directory) {
|
|
37232
37213
|
const swarm = await readKnowledge(resolveSwarmKnowledgePath(directory));
|
|
37233
37214
|
const hivePath = resolveHiveKnowledgePath();
|
|
37234
|
-
const hive =
|
|
37215
|
+
const hive = existsSync10(hivePath) ? await readKnowledge(hivePath) : [];
|
|
37235
37216
|
const archived = [...swarm, ...hive].filter((e) => e.status === "archived").length;
|
|
37236
37217
|
const skills = await listSkills(directory);
|
|
37237
37218
|
const matureCandidates = swarm.concat(hive).filter((e) => e.status !== "archived" && e.confidence >= 0.85 && !e.generated_skill_slug && (e.confirmed_by ?? []).length >= 2);
|
|
@@ -37504,8 +37485,8 @@ async function runSkillImprover(req) {
|
|
|
37504
37485
|
}
|
|
37505
37486
|
throw err;
|
|
37506
37487
|
}
|
|
37507
|
-
const proposalDir =
|
|
37508
|
-
const proposalFile =
|
|
37488
|
+
const proposalDir = path15.join(req.directory, ".swarm", "skill-improver", "proposals");
|
|
37489
|
+
const proposalFile = path15.join(proposalDir, `${timestampSlug(now)}.md`);
|
|
37509
37490
|
const finalBody = source === "llm" ? buildLLMProposalFrame({
|
|
37510
37491
|
body,
|
|
37511
37492
|
targets,
|
|
@@ -37901,7 +37882,7 @@ var init_write_retro = __esm(() => {
|
|
|
37901
37882
|
|
|
37902
37883
|
// src/commands/close.ts
|
|
37903
37884
|
import { promises as fs7 } from "fs";
|
|
37904
|
-
import
|
|
37885
|
+
import path16 from "path";
|
|
37905
37886
|
async function runAbortableSkillReview(req, timeoutMs) {
|
|
37906
37887
|
const controller = new AbortController;
|
|
37907
37888
|
let timeout;
|
|
@@ -37957,10 +37938,10 @@ function guaranteeAllPlansComplete(planData) {
|
|
|
37957
37938
|
}
|
|
37958
37939
|
async function handleCloseCommand(directory, args, options = {}) {
|
|
37959
37940
|
const planPath = validateSwarmPath(directory, "plan.json");
|
|
37960
|
-
const swarmDir =
|
|
37941
|
+
const swarmDir = path16.join(directory, ".swarm");
|
|
37961
37942
|
let planExists = false;
|
|
37962
37943
|
let planData = {
|
|
37963
|
-
title:
|
|
37944
|
+
title: path16.basename(directory) || "Ad-hoc session",
|
|
37964
37945
|
phases: []
|
|
37965
37946
|
};
|
|
37966
37947
|
try {
|
|
@@ -38069,7 +38050,7 @@ async function handleCloseCommand(directory, args, options = {}) {
|
|
|
38069
38050
|
warnings.push(`Session retrospective write threw: ${retroError instanceof Error ? retroError.message : String(retroError)}`);
|
|
38070
38051
|
}
|
|
38071
38052
|
}
|
|
38072
|
-
const lessonsFilePath =
|
|
38053
|
+
const lessonsFilePath = path16.join(swarmDir, "close-lessons.md");
|
|
38073
38054
|
let explicitLessons = [];
|
|
38074
38055
|
try {
|
|
38075
38056
|
const lessonsText = await fs7.readFile(lessonsFilePath, "utf-8");
|
|
@@ -38078,11 +38059,11 @@ async function handleCloseCommand(directory, args, options = {}) {
|
|
|
38078
38059
|
} catch {}
|
|
38079
38060
|
const retroLessons = [];
|
|
38080
38061
|
try {
|
|
38081
|
-
const evidenceDir =
|
|
38062
|
+
const evidenceDir = path16.join(swarmDir, "evidence");
|
|
38082
38063
|
const evidenceEntries = await fs7.readdir(evidenceDir);
|
|
38083
38064
|
const retroDirs = evidenceEntries.filter((e) => e.startsWith("retro-")).sort((a, b) => a.localeCompare(b, undefined, { numeric: true }));
|
|
38084
38065
|
for (const retroDir of retroDirs) {
|
|
38085
|
-
const evidencePath =
|
|
38066
|
+
const evidencePath = path16.join(evidenceDir, retroDir, "evidence.json");
|
|
38086
38067
|
try {
|
|
38087
38068
|
const content = await fs7.readFile(evidencePath, "utf-8");
|
|
38088
38069
|
const parsed = JSON.parse(content);
|
|
@@ -38207,7 +38188,7 @@ async function handleCloseCommand(directory, args, options = {}) {
|
|
|
38207
38188
|
}
|
|
38208
38189
|
const timestamp = new Date().toISOString().replace(/[:.]/g, "-");
|
|
38209
38190
|
const suffix = Math.random().toString(36).slice(2, 8);
|
|
38210
|
-
const archiveDir =
|
|
38191
|
+
const archiveDir = path16.join(swarmDir, "archive", `swarm-${timestamp}-${suffix}`);
|
|
38211
38192
|
let archiveResult = "";
|
|
38212
38193
|
let archivedFileCount = 0;
|
|
38213
38194
|
const archivedActiveStateFiles = new Set;
|
|
@@ -38215,8 +38196,8 @@ async function handleCloseCommand(directory, args, options = {}) {
|
|
|
38215
38196
|
try {
|
|
38216
38197
|
await fs7.mkdir(archiveDir, { recursive: true });
|
|
38217
38198
|
for (const artifact of ARCHIVE_ARTIFACTS) {
|
|
38218
|
-
const srcPath =
|
|
38219
|
-
const destPath =
|
|
38199
|
+
const srcPath = path16.join(swarmDir, artifact);
|
|
38200
|
+
const destPath = path16.join(archiveDir, artifact);
|
|
38220
38201
|
try {
|
|
38221
38202
|
await fs7.copyFile(srcPath, destPath);
|
|
38222
38203
|
archivedFileCount++;
|
|
@@ -38226,22 +38207,22 @@ async function handleCloseCommand(directory, args, options = {}) {
|
|
|
38226
38207
|
} catch {}
|
|
38227
38208
|
}
|
|
38228
38209
|
for (const dirName of ACTIVE_STATE_DIRS_TO_CLEAN) {
|
|
38229
|
-
const srcDir =
|
|
38230
|
-
const destDir =
|
|
38210
|
+
const srcDir = path16.join(swarmDir, dirName);
|
|
38211
|
+
const destDir = path16.join(archiveDir, dirName);
|
|
38231
38212
|
try {
|
|
38232
38213
|
const entries = await fs7.readdir(srcDir);
|
|
38233
38214
|
if (entries.length > 0) {
|
|
38234
38215
|
await fs7.mkdir(destDir, { recursive: true });
|
|
38235
38216
|
for (const entry of entries) {
|
|
38236
|
-
const srcEntry =
|
|
38237
|
-
const destEntry =
|
|
38217
|
+
const srcEntry = path16.join(srcDir, entry);
|
|
38218
|
+
const destEntry = path16.join(destDir, entry);
|
|
38238
38219
|
try {
|
|
38239
38220
|
const stat2 = await fs7.stat(srcEntry);
|
|
38240
38221
|
if (stat2.isDirectory()) {
|
|
38241
38222
|
await fs7.mkdir(destEntry, { recursive: true });
|
|
38242
38223
|
const subEntries = await fs7.readdir(srcEntry);
|
|
38243
38224
|
for (const sub of subEntries) {
|
|
38244
|
-
await fs7.copyFile(
|
|
38225
|
+
await fs7.copyFile(path16.join(srcEntry, sub), path16.join(destEntry, sub)).catch(() => {});
|
|
38245
38226
|
}
|
|
38246
38227
|
} else {
|
|
38247
38228
|
await fs7.copyFile(srcEntry, destEntry);
|
|
@@ -38273,7 +38254,7 @@ async function handleCloseCommand(directory, args, options = {}) {
|
|
|
38273
38254
|
warnings.push(`Preserved ${artifact} because it was not successfully archived.`);
|
|
38274
38255
|
continue;
|
|
38275
38256
|
}
|
|
38276
|
-
const filePath =
|
|
38257
|
+
const filePath = path16.join(swarmDir, artifact);
|
|
38277
38258
|
try {
|
|
38278
38259
|
await fs7.unlink(filePath);
|
|
38279
38260
|
cleanedFiles.push(artifact);
|
|
@@ -38286,7 +38267,7 @@ async function handleCloseCommand(directory, args, options = {}) {
|
|
|
38286
38267
|
if (!archivedActiveStateDirs.has(dirName)) {
|
|
38287
38268
|
continue;
|
|
38288
38269
|
}
|
|
38289
|
-
const dirPath =
|
|
38270
|
+
const dirPath = path16.join(swarmDir, dirName);
|
|
38290
38271
|
try {
|
|
38291
38272
|
await fs7.rm(dirPath, { recursive: true, force: true });
|
|
38292
38273
|
cleanedFiles.push(`${dirName}/`);
|
|
@@ -38297,23 +38278,23 @@ async function handleCloseCommand(directory, args, options = {}) {
|
|
|
38297
38278
|
const configBackups = swarmFiles.filter((f) => f.startsWith("config-backup-") && f.endsWith(".json"));
|
|
38298
38279
|
for (const backup of configBackups) {
|
|
38299
38280
|
try {
|
|
38300
|
-
await fs7.unlink(
|
|
38281
|
+
await fs7.unlink(path16.join(swarmDir, backup));
|
|
38301
38282
|
configBackupsRemoved++;
|
|
38302
38283
|
} catch {}
|
|
38303
38284
|
}
|
|
38304
38285
|
const ledgerSiblings = swarmFiles.filter((f) => (f.startsWith("plan-ledger.archived-") || f.startsWith("plan-ledger.backup-")) && f.endsWith(".jsonl"));
|
|
38305
38286
|
for (const sibling of ledgerSiblings) {
|
|
38306
38287
|
try {
|
|
38307
|
-
await fs7.unlink(
|
|
38288
|
+
await fs7.unlink(path16.join(swarmDir, sibling));
|
|
38308
38289
|
} catch {}
|
|
38309
38290
|
}
|
|
38310
38291
|
} catch {}
|
|
38311
38292
|
let swarmPlanFilesRemoved = 0;
|
|
38312
38293
|
const candidates = [
|
|
38313
|
-
|
|
38314
|
-
|
|
38315
|
-
|
|
38316
|
-
|
|
38294
|
+
path16.join(directory, ".swarm", "SWARM_PLAN.json"),
|
|
38295
|
+
path16.join(directory, ".swarm", "SWARM_PLAN.md"),
|
|
38296
|
+
path16.join(directory, "SWARM_PLAN.json"),
|
|
38297
|
+
path16.join(directory, "SWARM_PLAN.md")
|
|
38317
38298
|
];
|
|
38318
38299
|
for (const candidate of candidates) {
|
|
38319
38300
|
try {
|
|
@@ -38321,12 +38302,12 @@ async function handleCloseCommand(directory, args, options = {}) {
|
|
|
38321
38302
|
swarmPlanFilesRemoved++;
|
|
38322
38303
|
} catch (err) {
|
|
38323
38304
|
if (err?.code !== "ENOENT") {
|
|
38324
|
-
warnings.push(`Failed to remove ${
|
|
38305
|
+
warnings.push(`Failed to remove ${path16.basename(candidate)}: ${err instanceof Error ? err.message : String(err)}`);
|
|
38325
38306
|
}
|
|
38326
38307
|
}
|
|
38327
38308
|
}
|
|
38328
38309
|
clearAllScopes(directory);
|
|
38329
|
-
const contextPath =
|
|
38310
|
+
const contextPath = path16.join(swarmDir, "context.md");
|
|
38330
38311
|
const contextContent = [
|
|
38331
38312
|
"# Context",
|
|
38332
38313
|
"",
|
|
@@ -38545,14 +38526,14 @@ var init_close = __esm(() => {
|
|
|
38545
38526
|
|
|
38546
38527
|
// src/commands/config.ts
|
|
38547
38528
|
import * as os4 from "os";
|
|
38548
|
-
import * as
|
|
38529
|
+
import * as path17 from "path";
|
|
38549
38530
|
function getUserConfigDir2() {
|
|
38550
|
-
return process.env.XDG_CONFIG_HOME ||
|
|
38531
|
+
return process.env.XDG_CONFIG_HOME || path17.join(os4.homedir(), ".config");
|
|
38551
38532
|
}
|
|
38552
38533
|
async function handleConfigCommand(directory, _args) {
|
|
38553
38534
|
const config3 = loadPluginConfig(directory);
|
|
38554
|
-
const userConfigPath =
|
|
38555
|
-
const projectConfigPath =
|
|
38535
|
+
const userConfigPath = path17.join(getUserConfigDir2(), "opencode", "opencode-swarm.json");
|
|
38536
|
+
const projectConfigPath = path17.join(directory, ".opencode", "opencode-swarm.json");
|
|
38556
38537
|
const lines = [
|
|
38557
38538
|
"## Swarm Configuration",
|
|
38558
38539
|
"",
|
|
@@ -38678,8 +38659,8 @@ var init_curate = __esm(() => {
|
|
|
38678
38659
|
// src/tools/co-change-analyzer.ts
|
|
38679
38660
|
import * as child_process3 from "child_process";
|
|
38680
38661
|
import { randomUUID } from "crypto";
|
|
38681
|
-
import { readdir, readFile as
|
|
38682
|
-
import * as
|
|
38662
|
+
import { readdir, readFile as readFile6, stat as stat2 } from "fs/promises";
|
|
38663
|
+
import * as path18 from "path";
|
|
38683
38664
|
import { promisify } from "util";
|
|
38684
38665
|
function getExecFileAsync() {
|
|
38685
38666
|
return promisify(child_process3.execFile);
|
|
@@ -38781,7 +38762,7 @@ async function scanSourceFiles(dir) {
|
|
|
38781
38762
|
try {
|
|
38782
38763
|
const entries = await readdir(dir, { withFileTypes: true });
|
|
38783
38764
|
for (const entry of entries) {
|
|
38784
|
-
const fullPath =
|
|
38765
|
+
const fullPath = path18.join(dir, entry.name);
|
|
38785
38766
|
if (entry.isDirectory()) {
|
|
38786
38767
|
if (skipDirs.has(entry.name)) {
|
|
38787
38768
|
continue;
|
|
@@ -38789,7 +38770,7 @@ async function scanSourceFiles(dir) {
|
|
|
38789
38770
|
const subFiles = await scanSourceFiles(fullPath);
|
|
38790
38771
|
results.push(...subFiles);
|
|
38791
38772
|
} else if (entry.isFile()) {
|
|
38792
|
-
const ext =
|
|
38773
|
+
const ext = path18.extname(entry.name);
|
|
38793
38774
|
if ([".ts", ".tsx", ".js", ".jsx", ".mjs"].includes(ext)) {
|
|
38794
38775
|
results.push(fullPath);
|
|
38795
38776
|
}
|
|
@@ -38803,7 +38784,7 @@ async function getStaticEdges(directory) {
|
|
|
38803
38784
|
const sourceFiles = await scanSourceFiles(directory);
|
|
38804
38785
|
for (const sourceFile of sourceFiles) {
|
|
38805
38786
|
try {
|
|
38806
|
-
const content = await
|
|
38787
|
+
const content = await readFile6(sourceFile, "utf-8");
|
|
38807
38788
|
const importRegex = /(?:import|require)\s*(?:\(?\s*['"`]|.*?from\s+['"`])([^'"`]+)['"`]/g;
|
|
38808
38789
|
for (let match = importRegex.exec(content);match !== null; match = importRegex.exec(content)) {
|
|
38809
38790
|
const importPath = match[1].trim();
|
|
@@ -38811,8 +38792,8 @@ async function getStaticEdges(directory) {
|
|
|
38811
38792
|
continue;
|
|
38812
38793
|
}
|
|
38813
38794
|
try {
|
|
38814
|
-
const sourceDir =
|
|
38815
|
-
const resolvedPath =
|
|
38795
|
+
const sourceDir = path18.dirname(sourceFile);
|
|
38796
|
+
const resolvedPath = path18.resolve(sourceDir, importPath);
|
|
38816
38797
|
const extensions = [
|
|
38817
38798
|
"",
|
|
38818
38799
|
".ts",
|
|
@@ -38837,8 +38818,8 @@ async function getStaticEdges(directory) {
|
|
|
38837
38818
|
if (!targetFile) {
|
|
38838
38819
|
continue;
|
|
38839
38820
|
}
|
|
38840
|
-
const relSource =
|
|
38841
|
-
const relTarget =
|
|
38821
|
+
const relSource = path18.relative(directory, sourceFile).replace(/\\/g, "/");
|
|
38822
|
+
const relTarget = path18.relative(directory, targetFile).replace(/\\/g, "/");
|
|
38842
38823
|
const [key] = relSource < relTarget ? [`${relSource}::${relTarget}`, relSource, relTarget] : [`${relTarget}::${relSource}`, relTarget, relSource];
|
|
38843
38824
|
edges.add(key);
|
|
38844
38825
|
} catch {}
|
|
@@ -38850,7 +38831,7 @@ async function getStaticEdges(directory) {
|
|
|
38850
38831
|
function isTestImplementationPair(fileA, fileB) {
|
|
38851
38832
|
const testPatterns = [".test.ts", ".test.js", ".spec.ts", ".spec.js"];
|
|
38852
38833
|
const getBaseName = (filePath) => {
|
|
38853
|
-
const base =
|
|
38834
|
+
const base = path18.basename(filePath);
|
|
38854
38835
|
for (const pattern of testPatterns) {
|
|
38855
38836
|
if (base.endsWith(pattern)) {
|
|
38856
38837
|
return base.slice(0, -pattern.length);
|
|
@@ -38860,16 +38841,16 @@ function isTestImplementationPair(fileA, fileB) {
|
|
|
38860
38841
|
};
|
|
38861
38842
|
const baseA = getBaseName(fileA);
|
|
38862
38843
|
const baseB = getBaseName(fileB);
|
|
38863
|
-
return baseA === baseB && baseA !==
|
|
38844
|
+
return baseA === baseB && baseA !== path18.basename(fileA) && baseA !== path18.basename(fileB);
|
|
38864
38845
|
}
|
|
38865
38846
|
function hasSharedPrefix(fileA, fileB) {
|
|
38866
|
-
const dirA =
|
|
38867
|
-
const dirB =
|
|
38847
|
+
const dirA = path18.dirname(fileA);
|
|
38848
|
+
const dirB = path18.dirname(fileB);
|
|
38868
38849
|
if (dirA !== dirB) {
|
|
38869
38850
|
return false;
|
|
38870
38851
|
}
|
|
38871
|
-
const baseA =
|
|
38872
|
-
const baseB =
|
|
38852
|
+
const baseA = path18.basename(fileA).replace(/\.(ts|js|tsx|jsx|mjs)$/, "");
|
|
38853
|
+
const baseB = path18.basename(fileB).replace(/\.(ts|js|tsx|jsx|mjs)$/, "");
|
|
38873
38854
|
if (baseA.startsWith(baseB) || baseB.startsWith(baseA)) {
|
|
38874
38855
|
return true;
|
|
38875
38856
|
}
|
|
@@ -38923,8 +38904,8 @@ function darkMatterToKnowledgeEntries(pairs, projectName) {
|
|
|
38923
38904
|
const entries = [];
|
|
38924
38905
|
const now = new Date().toISOString();
|
|
38925
38906
|
for (const pair of pairs.slice(0, 10)) {
|
|
38926
|
-
const baseA =
|
|
38927
|
-
const baseB =
|
|
38907
|
+
const baseA = path18.basename(pair.fileA);
|
|
38908
|
+
const baseB = path18.basename(pair.fileB);
|
|
38928
38909
|
let lesson = `Files ${pair.fileA} and ${pair.fileB} co-change with NPMI=${pair.npmi.toFixed(3)} but have no import relationship. This hidden coupling suggests a shared architectural concern \u2014 changes to one likely require changes to the other.`;
|
|
38929
38910
|
if (lesson.length > 280) {
|
|
38930
38911
|
lesson = `Files ${baseA} and ${baseB} co-change with NPMI=${pair.npmi.toFixed(3)} but have no import relationship. This hidden coupling suggests a shared architectural concern \u2014 changes to one likely require changes to the other.`;
|
|
@@ -39026,7 +39007,7 @@ var init_co_change_analyzer = __esm(() => {
|
|
|
39026
39007
|
});
|
|
39027
39008
|
|
|
39028
39009
|
// src/commands/dark-matter.ts
|
|
39029
|
-
import
|
|
39010
|
+
import path19 from "path";
|
|
39030
39011
|
async function handleDarkMatterCommand(directory, args) {
|
|
39031
39012
|
const options = {};
|
|
39032
39013
|
for (let i = 0;i < args.length; i++) {
|
|
@@ -39058,7 +39039,7 @@ Ensure this is a git repository with commit history.`;
|
|
|
39058
39039
|
const output = formatDarkMatterOutput(pairs);
|
|
39059
39040
|
if (pairs.length > 0) {
|
|
39060
39041
|
try {
|
|
39061
|
-
const projectName =
|
|
39042
|
+
const projectName = path19.basename(path19.resolve(directory));
|
|
39062
39043
|
const entries = darkMatterToKnowledgeEntries(pairs, projectName);
|
|
39063
39044
|
if (entries.length > 0) {
|
|
39064
39045
|
const knowledgePath = resolveSwarmKnowledgePath(directory);
|
|
@@ -39195,67 +39176,67 @@ var init_deep_dive = __esm(() => {
|
|
|
39195
39176
|
|
|
39196
39177
|
// src/config/cache-paths.ts
|
|
39197
39178
|
import * as os5 from "os";
|
|
39198
|
-
import * as
|
|
39179
|
+
import * as path20 from "path";
|
|
39199
39180
|
function getPluginConfigDir() {
|
|
39200
|
-
return
|
|
39181
|
+
return path20.join(process.env.XDG_CONFIG_HOME || path20.join(os5.homedir(), ".config"), "opencode");
|
|
39201
39182
|
}
|
|
39202
39183
|
function getPluginCachePaths() {
|
|
39203
|
-
const cacheBase = process.env.XDG_CACHE_HOME ||
|
|
39184
|
+
const cacheBase = process.env.XDG_CACHE_HOME || path20.join(os5.homedir(), ".cache");
|
|
39204
39185
|
const configDir = getPluginConfigDir();
|
|
39205
39186
|
const paths = [
|
|
39206
|
-
|
|
39207
|
-
|
|
39208
|
-
|
|
39187
|
+
path20.join(cacheBase, "opencode", "node_modules", "opencode-swarm"),
|
|
39188
|
+
path20.join(cacheBase, "opencode", "packages", "opencode-swarm@latest"),
|
|
39189
|
+
path20.join(configDir, "node_modules", "opencode-swarm")
|
|
39209
39190
|
];
|
|
39210
39191
|
if (process.platform === "darwin") {
|
|
39211
|
-
const libCaches =
|
|
39212
|
-
paths.push(
|
|
39192
|
+
const libCaches = path20.join(os5.homedir(), "Library", "Caches");
|
|
39193
|
+
paths.push(path20.join(libCaches, "opencode", "node_modules", "opencode-swarm"), path20.join(libCaches, "opencode", "packages", "opencode-swarm@latest"));
|
|
39213
39194
|
}
|
|
39214
39195
|
if (process.platform === "win32") {
|
|
39215
|
-
const localAppData = process.env.LOCALAPPDATA ||
|
|
39216
|
-
const appData = process.env.APPDATA ||
|
|
39217
|
-
paths.push(
|
|
39196
|
+
const localAppData = process.env.LOCALAPPDATA || path20.join(os5.homedir(), "AppData", "Local");
|
|
39197
|
+
const appData = process.env.APPDATA || path20.join(os5.homedir(), "AppData", "Roaming");
|
|
39198
|
+
paths.push(path20.join(localAppData, "opencode", "node_modules", "opencode-swarm"), path20.join(localAppData, "opencode", "packages", "opencode-swarm@latest"), path20.join(appData, "opencode", "node_modules", "opencode-swarm"));
|
|
39218
39199
|
}
|
|
39219
39200
|
return paths;
|
|
39220
39201
|
}
|
|
39221
39202
|
function getPluginLockFilePaths() {
|
|
39222
|
-
const cacheBase = process.env.XDG_CACHE_HOME ||
|
|
39203
|
+
const cacheBase = process.env.XDG_CACHE_HOME || path20.join(os5.homedir(), ".cache");
|
|
39223
39204
|
const configDir = getPluginConfigDir();
|
|
39224
39205
|
const paths = [
|
|
39225
|
-
|
|
39226
|
-
|
|
39227
|
-
|
|
39206
|
+
path20.join(cacheBase, "opencode", "bun.lock"),
|
|
39207
|
+
path20.join(cacheBase, "opencode", "bun.lockb"),
|
|
39208
|
+
path20.join(configDir, "package-lock.json")
|
|
39228
39209
|
];
|
|
39229
39210
|
if (process.platform === "darwin") {
|
|
39230
|
-
const libCaches =
|
|
39231
|
-
paths.push(
|
|
39211
|
+
const libCaches = path20.join(os5.homedir(), "Library", "Caches");
|
|
39212
|
+
paths.push(path20.join(libCaches, "opencode", "bun.lock"), path20.join(libCaches, "opencode", "bun.lockb"));
|
|
39232
39213
|
}
|
|
39233
39214
|
if (process.platform === "win32") {
|
|
39234
|
-
const localAppData = process.env.LOCALAPPDATA ||
|
|
39235
|
-
paths.push(
|
|
39215
|
+
const localAppData = process.env.LOCALAPPDATA || path20.join(os5.homedir(), "AppData", "Local");
|
|
39216
|
+
paths.push(path20.join(localAppData, "opencode", "bun.lock"), path20.join(localAppData, "opencode", "bun.lockb"));
|
|
39236
39217
|
}
|
|
39237
39218
|
return paths;
|
|
39238
39219
|
}
|
|
39239
39220
|
var init_cache_paths = () => {};
|
|
39240
39221
|
|
|
39241
39222
|
// src/services/version-check.ts
|
|
39242
|
-
import { existsSync as
|
|
39223
|
+
import { existsSync as existsSync11, mkdirSync as mkdirSync7, readFileSync as readFileSync6, writeFileSync as writeFileSync4 } from "fs";
|
|
39243
39224
|
import { homedir as homedir5 } from "os";
|
|
39244
|
-
import { join as
|
|
39225
|
+
import { join as join19 } from "path";
|
|
39245
39226
|
function cacheDir() {
|
|
39246
39227
|
const xdg = process.env.XDG_CACHE_HOME;
|
|
39247
|
-
const base = xdg && xdg.length > 0 ? xdg :
|
|
39248
|
-
return
|
|
39228
|
+
const base = xdg && xdg.length > 0 ? xdg : join19(homedir5(), ".cache");
|
|
39229
|
+
return join19(base, "opencode-swarm");
|
|
39249
39230
|
}
|
|
39250
39231
|
function cacheFile() {
|
|
39251
|
-
return
|
|
39232
|
+
return join19(cacheDir(), "version-check.json");
|
|
39252
39233
|
}
|
|
39253
39234
|
function readVersionCache() {
|
|
39254
39235
|
try {
|
|
39255
|
-
const
|
|
39256
|
-
if (!
|
|
39236
|
+
const path21 = cacheFile();
|
|
39237
|
+
if (!existsSync11(path21))
|
|
39257
39238
|
return null;
|
|
39258
|
-
const raw = readFileSync6(
|
|
39239
|
+
const raw = readFileSync6(path21, "utf-8");
|
|
39259
39240
|
const parsed = JSON.parse(raw);
|
|
39260
39241
|
if (typeof parsed?.checkedAt !== "number")
|
|
39261
39242
|
return null;
|
|
@@ -39294,8 +39275,8 @@ var init_version_check = __esm(() => {
|
|
|
39294
39275
|
|
|
39295
39276
|
// src/services/diagnose-service.ts
|
|
39296
39277
|
import * as child_process4 from "child_process";
|
|
39297
|
-
import { existsSync as
|
|
39298
|
-
import
|
|
39278
|
+
import { existsSync as existsSync12, readdirSync as readdirSync4, readFileSync as readFileSync7, statSync as statSync6 } from "fs";
|
|
39279
|
+
import path21 from "path";
|
|
39299
39280
|
import { fileURLToPath } from "url";
|
|
39300
39281
|
function validateTaskDag(plan) {
|
|
39301
39282
|
const allTaskIds = new Set;
|
|
@@ -39528,7 +39509,7 @@ async function checkConfigBackups(directory) {
|
|
|
39528
39509
|
}
|
|
39529
39510
|
async function checkGitRepository(directory) {
|
|
39530
39511
|
try {
|
|
39531
|
-
if (!
|
|
39512
|
+
if (!existsSync12(directory) || !statSync6(directory).isDirectory()) {
|
|
39532
39513
|
return {
|
|
39533
39514
|
name: "Git Repository",
|
|
39534
39515
|
status: "\u274C",
|
|
@@ -39592,8 +39573,8 @@ async function checkSpecStaleness(directory, plan) {
|
|
|
39592
39573
|
};
|
|
39593
39574
|
}
|
|
39594
39575
|
async function checkConfigParseability(directory) {
|
|
39595
|
-
const configPath =
|
|
39596
|
-
if (!
|
|
39576
|
+
const configPath = path21.join(directory, ".opencode/opencode-swarm.json");
|
|
39577
|
+
if (!existsSync12(configPath)) {
|
|
39597
39578
|
return {
|
|
39598
39579
|
name: "Config Parseability",
|
|
39599
39580
|
status: "\u2705",
|
|
@@ -39621,7 +39602,7 @@ function resolveGrammarDir(thisDir) {
|
|
|
39621
39602
|
const normalized = thisDir.replace(/\\/g, "/");
|
|
39622
39603
|
const isSource = normalized.endsWith("/src/services");
|
|
39623
39604
|
const isCliBundle = normalized.endsWith("/cli");
|
|
39624
|
-
return isSource || isCliBundle ?
|
|
39605
|
+
return isSource || isCliBundle ? path21.join(thisDir, "..", "lang", "grammars") : path21.join(thisDir, "lang", "grammars");
|
|
39625
39606
|
}
|
|
39626
39607
|
async function checkGrammarWasmFiles() {
|
|
39627
39608
|
const grammarFiles = [
|
|
@@ -39645,14 +39626,14 @@ async function checkGrammarWasmFiles() {
|
|
|
39645
39626
|
"tree-sitter-ini.wasm",
|
|
39646
39627
|
"tree-sitter-regex.wasm"
|
|
39647
39628
|
];
|
|
39648
|
-
const thisDir =
|
|
39629
|
+
const thisDir = path21.dirname(fileURLToPath(import.meta.url));
|
|
39649
39630
|
const grammarDir = resolveGrammarDir(thisDir);
|
|
39650
39631
|
const missing = [];
|
|
39651
|
-
if (!
|
|
39632
|
+
if (!existsSync12(path21.join(grammarDir, "tree-sitter.wasm"))) {
|
|
39652
39633
|
missing.push("tree-sitter.wasm (core runtime)");
|
|
39653
39634
|
}
|
|
39654
39635
|
for (const file3 of grammarFiles) {
|
|
39655
|
-
if (!
|
|
39636
|
+
if (!existsSync12(path21.join(grammarDir, file3))) {
|
|
39656
39637
|
missing.push(file3);
|
|
39657
39638
|
}
|
|
39658
39639
|
}
|
|
@@ -39670,8 +39651,8 @@ async function checkGrammarWasmFiles() {
|
|
|
39670
39651
|
};
|
|
39671
39652
|
}
|
|
39672
39653
|
async function checkCheckpointManifest(directory) {
|
|
39673
|
-
const manifestPath =
|
|
39674
|
-
if (!
|
|
39654
|
+
const manifestPath = path21.join(directory, ".swarm/checkpoints.json");
|
|
39655
|
+
if (!existsSync12(manifestPath)) {
|
|
39675
39656
|
return {
|
|
39676
39657
|
name: "Checkpoint Manifest",
|
|
39677
39658
|
status: "\u2705",
|
|
@@ -39722,8 +39703,8 @@ async function checkCheckpointManifest(directory) {
|
|
|
39722
39703
|
}
|
|
39723
39704
|
}
|
|
39724
39705
|
async function checkEventStreamIntegrity(directory) {
|
|
39725
|
-
const eventsPath =
|
|
39726
|
-
if (!
|
|
39706
|
+
const eventsPath = path21.join(directory, ".swarm/events.jsonl");
|
|
39707
|
+
if (!existsSync12(eventsPath)) {
|
|
39727
39708
|
return {
|
|
39728
39709
|
name: "Event Stream",
|
|
39729
39710
|
status: "\u2705",
|
|
@@ -39763,8 +39744,8 @@ async function checkEventStreamIntegrity(directory) {
|
|
|
39763
39744
|
}
|
|
39764
39745
|
}
|
|
39765
39746
|
async function checkSteeringDirectives(directory) {
|
|
39766
|
-
const eventsPath =
|
|
39767
|
-
if (!
|
|
39747
|
+
const eventsPath = path21.join(directory, ".swarm/events.jsonl");
|
|
39748
|
+
if (!existsSync12(eventsPath)) {
|
|
39768
39749
|
return {
|
|
39769
39750
|
name: "Steering Directives",
|
|
39770
39751
|
status: "\u2705",
|
|
@@ -39819,8 +39800,8 @@ async function checkCurator(directory) {
|
|
|
39819
39800
|
detail: "Disabled (enable via curator.enabled)"
|
|
39820
39801
|
};
|
|
39821
39802
|
}
|
|
39822
|
-
const summaryPath =
|
|
39823
|
-
if (!
|
|
39803
|
+
const summaryPath = path21.join(directory, ".swarm/curator-summary.json");
|
|
39804
|
+
if (!existsSync12(summaryPath)) {
|
|
39824
39805
|
return {
|
|
39825
39806
|
name: "Curator",
|
|
39826
39807
|
status: "\u2705",
|
|
@@ -39985,8 +39966,8 @@ async function getDiagnoseData(directory) {
|
|
|
39985
39966
|
checks5.push(await checkSteeringDirectives(directory));
|
|
39986
39967
|
checks5.push(await checkCurator(directory));
|
|
39987
39968
|
try {
|
|
39988
|
-
const evidenceDir =
|
|
39989
|
-
const snapshotFiles =
|
|
39969
|
+
const evidenceDir = path21.join(directory, ".swarm", "evidence");
|
|
39970
|
+
const snapshotFiles = existsSync12(evidenceDir) ? readdirSync4(evidenceDir).filter((f) => f.startsWith("agent-tools-") && f.endsWith(".json")) : [];
|
|
39990
39971
|
if (snapshotFiles.length > 0) {
|
|
39991
39972
|
const latest = snapshotFiles.sort().pop();
|
|
39992
39973
|
checks5.push({
|
|
@@ -40019,11 +40000,11 @@ async function getDiagnoseData(directory) {
|
|
|
40019
40000
|
const cacheRows = [];
|
|
40020
40001
|
for (const cachePath of cachePaths) {
|
|
40021
40002
|
try {
|
|
40022
|
-
if (!
|
|
40003
|
+
if (!existsSync12(cachePath)) {
|
|
40023
40004
|
cacheRows.push(`\u2B1C ${cachePath} \u2014 absent`);
|
|
40024
40005
|
continue;
|
|
40025
40006
|
}
|
|
40026
|
-
const pkgJsonPath =
|
|
40007
|
+
const pkgJsonPath = path21.join(cachePath, "package.json");
|
|
40027
40008
|
try {
|
|
40028
40009
|
const raw = readFileSync7(pkgJsonPath, "utf-8");
|
|
40029
40010
|
const parsed = JSON.parse(raw);
|
|
@@ -40113,13 +40094,13 @@ __export(exports_config_doctor, {
|
|
|
40113
40094
|
import * as crypto3 from "crypto";
|
|
40114
40095
|
import * as fs8 from "fs";
|
|
40115
40096
|
import * as os6 from "os";
|
|
40116
|
-
import * as
|
|
40097
|
+
import * as path22 from "path";
|
|
40117
40098
|
function getUserConfigDir3() {
|
|
40118
|
-
return process.env.XDG_CONFIG_HOME ||
|
|
40099
|
+
return process.env.XDG_CONFIG_HOME || path22.join(os6.homedir(), ".config");
|
|
40119
40100
|
}
|
|
40120
40101
|
function getConfigPaths(directory) {
|
|
40121
|
-
const userConfigPath =
|
|
40122
|
-
const projectConfigPath =
|
|
40102
|
+
const userConfigPath = path22.join(getUserConfigDir3(), "opencode", "opencode-swarm.json");
|
|
40103
|
+
const projectConfigPath = path22.join(directory, ".opencode", "opencode-swarm.json");
|
|
40123
40104
|
return { userConfigPath, projectConfigPath };
|
|
40124
40105
|
}
|
|
40125
40106
|
function computeHash(content) {
|
|
@@ -40144,9 +40125,9 @@ function isValidConfigPath(configPath, directory) {
|
|
|
40144
40125
|
const normalizedUser = userConfigPath.replace(/\\/g, "/");
|
|
40145
40126
|
const normalizedProject = projectConfigPath.replace(/\\/g, "/");
|
|
40146
40127
|
try {
|
|
40147
|
-
const resolvedConfig =
|
|
40148
|
-
const resolvedUser =
|
|
40149
|
-
const resolvedProject =
|
|
40128
|
+
const resolvedConfig = path22.resolve(configPath);
|
|
40129
|
+
const resolvedUser = path22.resolve(normalizedUser);
|
|
40130
|
+
const resolvedProject = path22.resolve(normalizedProject);
|
|
40150
40131
|
return resolvedConfig === resolvedUser || resolvedConfig === resolvedProject;
|
|
40151
40132
|
} catch {
|
|
40152
40133
|
return false;
|
|
@@ -40186,12 +40167,12 @@ function createConfigBackup(directory) {
|
|
|
40186
40167
|
};
|
|
40187
40168
|
}
|
|
40188
40169
|
function writeBackupArtifact(directory, backup) {
|
|
40189
|
-
const swarmDir =
|
|
40170
|
+
const swarmDir = path22.join(directory, ".swarm");
|
|
40190
40171
|
if (!fs8.existsSync(swarmDir)) {
|
|
40191
40172
|
fs8.mkdirSync(swarmDir, { recursive: true });
|
|
40192
40173
|
}
|
|
40193
40174
|
const backupFilename = `config-backup-${backup.createdAt}.json`;
|
|
40194
|
-
const backupPath =
|
|
40175
|
+
const backupPath = path22.join(swarmDir, backupFilename);
|
|
40195
40176
|
const artifact = {
|
|
40196
40177
|
createdAt: backup.createdAt,
|
|
40197
40178
|
configPath: backup.configPath,
|
|
@@ -40221,7 +40202,7 @@ function restoreFromBackup(backupPath, directory) {
|
|
|
40221
40202
|
return null;
|
|
40222
40203
|
}
|
|
40223
40204
|
const targetPath = artifact.configPath;
|
|
40224
|
-
const targetDir =
|
|
40205
|
+
const targetDir = path22.dirname(targetPath);
|
|
40225
40206
|
if (!fs8.existsSync(targetDir)) {
|
|
40226
40207
|
fs8.mkdirSync(targetDir, { recursive: true });
|
|
40227
40208
|
}
|
|
@@ -40252,9 +40233,9 @@ function readConfigFromFile(directory) {
|
|
|
40252
40233
|
return null;
|
|
40253
40234
|
}
|
|
40254
40235
|
}
|
|
40255
|
-
function validateConfigKey(
|
|
40236
|
+
function validateConfigKey(path23, value, _config) {
|
|
40256
40237
|
const findings = [];
|
|
40257
|
-
switch (
|
|
40238
|
+
switch (path23) {
|
|
40258
40239
|
case "agents": {
|
|
40259
40240
|
if (value !== undefined) {
|
|
40260
40241
|
findings.push({
|
|
@@ -40491,27 +40472,27 @@ function validateConfigKey(path24, value, _config) {
|
|
|
40491
40472
|
}
|
|
40492
40473
|
return findings;
|
|
40493
40474
|
}
|
|
40494
|
-
function walkConfigAndValidate(obj,
|
|
40475
|
+
function walkConfigAndValidate(obj, path23, config3, findings) {
|
|
40495
40476
|
if (obj === null || obj === undefined) {
|
|
40496
40477
|
return;
|
|
40497
40478
|
}
|
|
40498
|
-
if (
|
|
40499
|
-
const keyFindings = validateConfigKey(
|
|
40479
|
+
if (path23 && typeof obj === "object" && !Array.isArray(obj)) {
|
|
40480
|
+
const keyFindings = validateConfigKey(path23, obj, config3);
|
|
40500
40481
|
findings.push(...keyFindings);
|
|
40501
40482
|
}
|
|
40502
40483
|
if (typeof obj !== "object") {
|
|
40503
|
-
const keyFindings = validateConfigKey(
|
|
40484
|
+
const keyFindings = validateConfigKey(path23, obj, config3);
|
|
40504
40485
|
findings.push(...keyFindings);
|
|
40505
40486
|
return;
|
|
40506
40487
|
}
|
|
40507
40488
|
if (Array.isArray(obj)) {
|
|
40508
40489
|
obj.forEach((item, index) => {
|
|
40509
|
-
walkConfigAndValidate(item, `${
|
|
40490
|
+
walkConfigAndValidate(item, `${path23}[${index}]`, config3, findings);
|
|
40510
40491
|
});
|
|
40511
40492
|
return;
|
|
40512
40493
|
}
|
|
40513
40494
|
for (const [key, value] of Object.entries(obj)) {
|
|
40514
|
-
const newPath =
|
|
40495
|
+
const newPath = path23 ? `${path23}.${key}` : key;
|
|
40515
40496
|
walkConfigAndValidate(value, newPath, config3, findings);
|
|
40516
40497
|
}
|
|
40517
40498
|
}
|
|
@@ -40631,7 +40612,7 @@ function applySafeAutoFixes(directory, result) {
|
|
|
40631
40612
|
}
|
|
40632
40613
|
}
|
|
40633
40614
|
if (appliedFixes.length > 0) {
|
|
40634
|
-
const configDir =
|
|
40615
|
+
const configDir = path22.dirname(configPath);
|
|
40635
40616
|
if (!fs8.existsSync(configDir)) {
|
|
40636
40617
|
fs8.mkdirSync(configDir, { recursive: true });
|
|
40637
40618
|
}
|
|
@@ -40641,12 +40622,12 @@ function applySafeAutoFixes(directory, result) {
|
|
|
40641
40622
|
return { appliedFixes, updatedConfigPath };
|
|
40642
40623
|
}
|
|
40643
40624
|
function writeDoctorArtifact(directory, result) {
|
|
40644
|
-
const swarmDir =
|
|
40625
|
+
const swarmDir = path22.join(directory, ".swarm");
|
|
40645
40626
|
if (!fs8.existsSync(swarmDir)) {
|
|
40646
40627
|
fs8.mkdirSync(swarmDir, { recursive: true });
|
|
40647
40628
|
}
|
|
40648
40629
|
const artifactFilename = "config-doctor.json";
|
|
40649
|
-
const artifactPath =
|
|
40630
|
+
const artifactPath = path22.join(swarmDir, artifactFilename);
|
|
40650
40631
|
const guiOutput = {
|
|
40651
40632
|
timestamp: result.timestamp,
|
|
40652
40633
|
summary: result.summary,
|
|
@@ -40742,17 +40723,17 @@ function detectStraySwarmDirs(projectRoot) {
|
|
|
40742
40723
|
if (!entry.isDirectory())
|
|
40743
40724
|
continue;
|
|
40744
40725
|
const name = entry.name;
|
|
40745
|
-
const fullPath =
|
|
40726
|
+
const fullPath = path22.join(dir, name);
|
|
40746
40727
|
if (SKIP_DIRS.has(name))
|
|
40747
40728
|
continue;
|
|
40748
|
-
const gitPath =
|
|
40729
|
+
const gitPath = path22.join(fullPath, ".git");
|
|
40749
40730
|
try {
|
|
40750
40731
|
const gitStat = fs8.statSync(gitPath);
|
|
40751
40732
|
if (gitStat.isFile() || gitStat.isDirectory())
|
|
40752
40733
|
continue;
|
|
40753
40734
|
} catch {}
|
|
40754
40735
|
if (name === ".swarm") {
|
|
40755
|
-
const parentDir =
|
|
40736
|
+
const parentDir = path22.dirname(fullPath);
|
|
40756
40737
|
if (parentDir === projectRoot)
|
|
40757
40738
|
continue;
|
|
40758
40739
|
let contents = [];
|
|
@@ -40762,7 +40743,7 @@ function detectStraySwarmDirs(projectRoot) {
|
|
|
40762
40743
|
contents = ["<unreadable>"];
|
|
40763
40744
|
}
|
|
40764
40745
|
findings.push({
|
|
40765
|
-
path:
|
|
40746
|
+
path: path22.relative(projectRoot, fullPath).replace(/\\/g, "/"),
|
|
40766
40747
|
absolutePath: fullPath,
|
|
40767
40748
|
contents: contents.slice(0, MAX_CONTENTS_ENTRIES),
|
|
40768
40749
|
totalEntries: contents.length
|
|
@@ -40780,21 +40761,21 @@ function removeStraySwarmDir(projectRoot, strayPath) {
|
|
|
40780
40761
|
let canonicalStray;
|
|
40781
40762
|
try {
|
|
40782
40763
|
canonicalRoot = fs8.realpathSync(projectRoot);
|
|
40783
|
-
canonicalStray = fs8.realpathSync(
|
|
40764
|
+
canonicalStray = fs8.realpathSync(path22.isAbsolute(strayPath) ? strayPath : path22.resolve(projectRoot, strayPath));
|
|
40784
40765
|
} catch (err) {
|
|
40785
40766
|
return {
|
|
40786
40767
|
success: false,
|
|
40787
40768
|
message: `Failed to resolve paths: ${err instanceof Error ? err.message : String(err)}`
|
|
40788
40769
|
};
|
|
40789
40770
|
}
|
|
40790
|
-
const rootSwarm =
|
|
40771
|
+
const rootSwarm = path22.join(canonicalRoot, ".swarm");
|
|
40791
40772
|
if (canonicalStray === rootSwarm || canonicalStray === canonicalRoot) {
|
|
40792
40773
|
return {
|
|
40793
40774
|
success: false,
|
|
40794
40775
|
message: "Refusing to remove root .swarm/ directory"
|
|
40795
40776
|
};
|
|
40796
40777
|
}
|
|
40797
|
-
if (!canonicalStray.startsWith(canonicalRoot +
|
|
40778
|
+
if (!canonicalStray.startsWith(canonicalRoot + path22.sep)) {
|
|
40798
40779
|
return {
|
|
40799
40780
|
success: false,
|
|
40800
40781
|
message: "Path is outside project root \u2014 refusing to remove"
|
|
@@ -41883,7 +41864,7 @@ var init_profiles = __esm(() => {
|
|
|
41883
41864
|
|
|
41884
41865
|
// src/lang/detector.ts
|
|
41885
41866
|
import { access as access3, readdir as readdir2 } from "fs/promises";
|
|
41886
|
-
import { extname as extname2, join as
|
|
41867
|
+
import { extname as extname2, join as join21 } from "path";
|
|
41887
41868
|
async function detectProjectLanguages(projectDir) {
|
|
41888
41869
|
const detected = new Set;
|
|
41889
41870
|
async function scanDir(dir) {
|
|
@@ -41899,7 +41880,7 @@ async function detectProjectLanguages(projectDir) {
|
|
|
41899
41880
|
if (detectFile.includes("*") || detectFile.includes("?"))
|
|
41900
41881
|
continue;
|
|
41901
41882
|
try {
|
|
41902
|
-
await access3(
|
|
41883
|
+
await access3(join21(dir, detectFile));
|
|
41903
41884
|
detected.add(profile.id);
|
|
41904
41885
|
break;
|
|
41905
41886
|
} catch {}
|
|
@@ -41920,7 +41901,7 @@ async function detectProjectLanguages(projectDir) {
|
|
|
41920
41901
|
const topEntries = await readdir2(projectDir, { withFileTypes: true });
|
|
41921
41902
|
for (const entry of topEntries) {
|
|
41922
41903
|
if (entry.isDirectory() && !entry.name.startsWith(".") && entry.name !== "node_modules") {
|
|
41923
|
-
await scanDir(
|
|
41904
|
+
await scanDir(join21(projectDir, entry.name));
|
|
41924
41905
|
}
|
|
41925
41906
|
}
|
|
41926
41907
|
} catch {}
|
|
@@ -41939,7 +41920,7 @@ var init_detector = __esm(() => {
|
|
|
41939
41920
|
|
|
41940
41921
|
// src/build/discovery.ts
|
|
41941
41922
|
import * as fs9 from "fs";
|
|
41942
|
-
import * as
|
|
41923
|
+
import * as path23 from "path";
|
|
41943
41924
|
function isCommandAvailable(command) {
|
|
41944
41925
|
if (toolchainCache.has(command)) {
|
|
41945
41926
|
return toolchainCache.get(command);
|
|
@@ -41974,11 +41955,11 @@ function findBuildFiles(workingDir, patterns) {
|
|
|
41974
41955
|
const regex = simpleGlobToRegex(pattern);
|
|
41975
41956
|
const matches = files.filter((f) => regex.test(f));
|
|
41976
41957
|
if (matches.length > 0) {
|
|
41977
|
-
return
|
|
41958
|
+
return path23.join(dir, matches[0]);
|
|
41978
41959
|
}
|
|
41979
41960
|
} catch {}
|
|
41980
41961
|
} else {
|
|
41981
|
-
const filePath =
|
|
41962
|
+
const filePath = path23.join(workingDir, pattern);
|
|
41982
41963
|
if (fs9.existsSync(filePath)) {
|
|
41983
41964
|
return filePath;
|
|
41984
41965
|
}
|
|
@@ -41987,7 +41968,7 @@ function findBuildFiles(workingDir, patterns) {
|
|
|
41987
41968
|
return null;
|
|
41988
41969
|
}
|
|
41989
41970
|
function getRepoDefinedScripts(workingDir, scripts) {
|
|
41990
|
-
const packageJsonPath =
|
|
41971
|
+
const packageJsonPath = path23.join(workingDir, "package.json");
|
|
41991
41972
|
if (!fs9.existsSync(packageJsonPath)) {
|
|
41992
41973
|
return [];
|
|
41993
41974
|
}
|
|
@@ -42028,7 +42009,7 @@ function findAllBuildFiles(workingDir) {
|
|
|
42028
42009
|
const regex = simpleGlobToRegex(pattern);
|
|
42029
42010
|
findFilesRecursive(workingDir, regex, allBuildFiles);
|
|
42030
42011
|
} else {
|
|
42031
|
-
const filePath =
|
|
42012
|
+
const filePath = path23.join(workingDir, pattern);
|
|
42032
42013
|
if (fs9.existsSync(filePath)) {
|
|
42033
42014
|
allBuildFiles.add(filePath);
|
|
42034
42015
|
}
|
|
@@ -42041,7 +42022,7 @@ function findFilesRecursive(dir, regex, results) {
|
|
|
42041
42022
|
try {
|
|
42042
42023
|
const entries = fs9.readdirSync(dir, { withFileTypes: true });
|
|
42043
42024
|
for (const entry of entries) {
|
|
42044
|
-
const fullPath =
|
|
42025
|
+
const fullPath = path23.join(dir, entry.name);
|
|
42045
42026
|
if (entry.isDirectory() && !["node_modules", ".git", "dist", "build", "target"].includes(entry.name)) {
|
|
42046
42027
|
findFilesRecursive(fullPath, regex, results);
|
|
42047
42028
|
} else if (entry.isFile() && regex.test(entry.name)) {
|
|
@@ -42064,7 +42045,7 @@ async function discoverBuildCommandsFromProfiles(workingDir) {
|
|
|
42064
42045
|
let foundCommand = false;
|
|
42065
42046
|
for (const cmd of sortedCommands) {
|
|
42066
42047
|
if (cmd.detectFile) {
|
|
42067
|
-
const detectFilePath =
|
|
42048
|
+
const detectFilePath = path23.join(workingDir, cmd.detectFile);
|
|
42068
42049
|
if (!fs9.existsSync(detectFilePath)) {
|
|
42069
42050
|
continue;
|
|
42070
42051
|
}
|
|
@@ -42305,7 +42286,7 @@ var init_discovery = __esm(() => {
|
|
|
42305
42286
|
|
|
42306
42287
|
// src/services/tool-doctor.ts
|
|
42307
42288
|
import * as fs10 from "fs";
|
|
42308
|
-
import * as
|
|
42289
|
+
import * as path24 from "path";
|
|
42309
42290
|
function extractRegisteredToolKeys(indexPath) {
|
|
42310
42291
|
const registeredKeys = new Set;
|
|
42311
42292
|
try {
|
|
@@ -42360,8 +42341,8 @@ function checkBinaryReadiness() {
|
|
|
42360
42341
|
}
|
|
42361
42342
|
function runToolDoctor(_directory, pluginRoot) {
|
|
42362
42343
|
const findings = [];
|
|
42363
|
-
const resolvedPluginRoot = pluginRoot ??
|
|
42364
|
-
const indexPath =
|
|
42344
|
+
const resolvedPluginRoot = pluginRoot ?? path24.resolve(import.meta.dir, "..", "..");
|
|
42345
|
+
const indexPath = path24.join(resolvedPluginRoot, "src", "index.ts");
|
|
42365
42346
|
if (!fs10.existsSync(indexPath)) {
|
|
42366
42347
|
return {
|
|
42367
42348
|
findings: [
|
|
@@ -43107,12 +43088,12 @@ var init_export = __esm(() => {
|
|
|
43107
43088
|
|
|
43108
43089
|
// src/full-auto/state.ts
|
|
43109
43090
|
import * as fs11 from "fs";
|
|
43110
|
-
import * as
|
|
43091
|
+
import * as path25 from "path";
|
|
43111
43092
|
function nowISO() {
|
|
43112
43093
|
return new Date().toISOString();
|
|
43113
43094
|
}
|
|
43114
43095
|
function ensureSwarmDir(directory) {
|
|
43115
|
-
const swarmDir =
|
|
43096
|
+
const swarmDir = path25.resolve(directory, ".swarm");
|
|
43116
43097
|
if (!fs11.existsSync(swarmDir)) {
|
|
43117
43098
|
fs11.mkdirSync(swarmDir, { recursive: true });
|
|
43118
43099
|
}
|
|
@@ -43813,7 +43794,7 @@ var init_handoff_service = __esm(() => {
|
|
|
43813
43794
|
|
|
43814
43795
|
// src/session/snapshot-writer.ts
|
|
43815
43796
|
import { closeSync as closeSync3, fsyncSync as fsyncSync2, mkdirSync as mkdirSync10, openSync as openSync3, renameSync as renameSync6 } from "fs";
|
|
43816
|
-
import * as
|
|
43797
|
+
import * as path26 from "path";
|
|
43817
43798
|
function serializeAgentSession(s) {
|
|
43818
43799
|
const gateLog = {};
|
|
43819
43800
|
const rawGateLog = s.gateLog ?? new Map;
|
|
@@ -43910,7 +43891,7 @@ async function writeSnapshot(directory, state) {
|
|
|
43910
43891
|
}
|
|
43911
43892
|
const content = JSON.stringify(snapshot, null, 2);
|
|
43912
43893
|
const resolvedPath = validateSwarmPath(directory, "session/state.json");
|
|
43913
|
-
const dir =
|
|
43894
|
+
const dir = path26.dirname(resolvedPath);
|
|
43914
43895
|
mkdirSync10(dir, { recursive: true });
|
|
43915
43896
|
const tempPath = `${resolvedPath}.tmp.${Date.now()}.${Math.random().toString(36).slice(2)}`;
|
|
43916
43897
|
await bunWrite(tempPath, content);
|
|
@@ -44367,9 +44348,9 @@ var init_issue = __esm(() => {
|
|
|
44367
44348
|
|
|
44368
44349
|
// src/hooks/knowledge-migrator.ts
|
|
44369
44350
|
import { randomUUID as randomUUID2 } from "crypto";
|
|
44370
|
-
import { existsSync as
|
|
44371
|
-
import { mkdir as
|
|
44372
|
-
import * as
|
|
44351
|
+
import { existsSync as existsSync17, readFileSync as readFileSync12 } from "fs";
|
|
44352
|
+
import { mkdir as mkdir7, readFile as readFile7, writeFile as writeFile8 } from "fs/promises";
|
|
44353
|
+
import * as path27 from "path";
|
|
44373
44354
|
async function migrateKnowledgeToExternal(_directory, _config) {
|
|
44374
44355
|
return {
|
|
44375
44356
|
migrated: false,
|
|
@@ -44380,10 +44361,10 @@ async function migrateKnowledgeToExternal(_directory, _config) {
|
|
|
44380
44361
|
};
|
|
44381
44362
|
}
|
|
44382
44363
|
async function migrateContextToKnowledge(directory, config3) {
|
|
44383
|
-
const sentinelPath =
|
|
44384
|
-
const contextPath =
|
|
44364
|
+
const sentinelPath = path27.join(directory, ".swarm", ".knowledge-migrated");
|
|
44365
|
+
const contextPath = path27.join(directory, ".swarm", "context.md");
|
|
44385
44366
|
const knowledgePath = resolveSwarmKnowledgePath(directory);
|
|
44386
|
-
if (
|
|
44367
|
+
if (existsSync17(sentinelPath)) {
|
|
44387
44368
|
return {
|
|
44388
44369
|
migrated: false,
|
|
44389
44370
|
entriesMigrated: 0,
|
|
@@ -44392,7 +44373,7 @@ async function migrateContextToKnowledge(directory, config3) {
|
|
|
44392
44373
|
skippedReason: "sentinel-exists"
|
|
44393
44374
|
};
|
|
44394
44375
|
}
|
|
44395
|
-
if (!
|
|
44376
|
+
if (!existsSync17(contextPath)) {
|
|
44396
44377
|
return {
|
|
44397
44378
|
migrated: false,
|
|
44398
44379
|
entriesMigrated: 0,
|
|
@@ -44401,7 +44382,7 @@ async function migrateContextToKnowledge(directory, config3) {
|
|
|
44401
44382
|
skippedReason: "no-context-file"
|
|
44402
44383
|
};
|
|
44403
44384
|
}
|
|
44404
|
-
const contextContent = await
|
|
44385
|
+
const contextContent = await readFile7(contextPath, "utf-8");
|
|
44405
44386
|
if (contextContent.trim().length === 0) {
|
|
44406
44387
|
return {
|
|
44407
44388
|
migrated: false,
|
|
@@ -44577,8 +44558,8 @@ function truncateLesson(text) {
|
|
|
44577
44558
|
return `${text.slice(0, 277)}...`;
|
|
44578
44559
|
}
|
|
44579
44560
|
function inferProjectName(directory) {
|
|
44580
|
-
const packageJsonPath =
|
|
44581
|
-
if (
|
|
44561
|
+
const packageJsonPath = path27.join(directory, "package.json");
|
|
44562
|
+
if (existsSync17(packageJsonPath)) {
|
|
44582
44563
|
try {
|
|
44583
44564
|
const pkg = JSON.parse(readFileSync12(packageJsonPath, "utf-8"));
|
|
44584
44565
|
if (pkg.name && typeof pkg.name === "string") {
|
|
@@ -44586,7 +44567,7 @@ function inferProjectName(directory) {
|
|
|
44586
44567
|
}
|
|
44587
44568
|
} catch {}
|
|
44588
44569
|
}
|
|
44589
|
-
return
|
|
44570
|
+
return path27.basename(directory);
|
|
44590
44571
|
}
|
|
44591
44572
|
async function writeSentinel(sentinelPath, migrated, dropped) {
|
|
44592
44573
|
const sentinel = {
|
|
@@ -44598,8 +44579,8 @@ async function writeSentinel(sentinelPath, migrated, dropped) {
|
|
|
44598
44579
|
schema_version: 1,
|
|
44599
44580
|
migration_tool: "knowledge-migrator.ts"
|
|
44600
44581
|
};
|
|
44601
|
-
await
|
|
44602
|
-
await
|
|
44582
|
+
await mkdir7(path27.dirname(sentinelPath), { recursive: true });
|
|
44583
|
+
await writeFile8(sentinelPath, JSON.stringify(sentinel, null, 2), "utf-8");
|
|
44603
44584
|
}
|
|
44604
44585
|
var _internals16;
|
|
44605
44586
|
var init_knowledge_migrator = __esm(() => {
|
|
@@ -44620,7 +44601,7 @@ var init_knowledge_migrator = __esm(() => {
|
|
|
44620
44601
|
});
|
|
44621
44602
|
|
|
44622
44603
|
// src/commands/knowledge.ts
|
|
44623
|
-
import { join as
|
|
44604
|
+
import { join as join25 } from "path";
|
|
44624
44605
|
function resolveEntryByPrefix(entries, inputId) {
|
|
44625
44606
|
const exact = entries.find((e) => e.id === inputId);
|
|
44626
44607
|
if (exact)
|
|
@@ -44671,7 +44652,7 @@ async function handleKnowledgeRestoreCommand(directory, args) {
|
|
|
44671
44652
|
return "Invalid entry ID. IDs must be 1-64 characters: letters, digits, hyphens, underscores only.";
|
|
44672
44653
|
}
|
|
44673
44654
|
try {
|
|
44674
|
-
const quarantinePath =
|
|
44655
|
+
const quarantinePath = join25(directory, ".swarm", "knowledge-quarantined.jsonl");
|
|
44675
44656
|
const entries = await readKnowledge(quarantinePath);
|
|
44676
44657
|
const resolved = resolveEntryByPrefix(entries, inputId);
|
|
44677
44658
|
if ("error" in resolved) {
|
|
@@ -45126,7 +45107,7 @@ var init_path_security = () => {};
|
|
|
45126
45107
|
|
|
45127
45108
|
// src/tools/lint.ts
|
|
45128
45109
|
import * as fs12 from "fs";
|
|
45129
|
-
import * as
|
|
45110
|
+
import * as path28 from "path";
|
|
45130
45111
|
function validateArgs(args) {
|
|
45131
45112
|
if (typeof args !== "object" || args === null)
|
|
45132
45113
|
return false;
|
|
@@ -45137,9 +45118,9 @@ function validateArgs(args) {
|
|
|
45137
45118
|
}
|
|
45138
45119
|
function getLinterCommand(linter, mode, projectDir) {
|
|
45139
45120
|
const isWindows = process.platform === "win32";
|
|
45140
|
-
const binDir =
|
|
45141
|
-
const biomeBin = isWindows ?
|
|
45142
|
-
const eslintBin = isWindows ?
|
|
45121
|
+
const binDir = path28.join(projectDir, "node_modules", ".bin");
|
|
45122
|
+
const biomeBin = isWindows ? path28.join(binDir, "biome.EXE") : path28.join(binDir, "biome");
|
|
45123
|
+
const eslintBin = isWindows ? path28.join(binDir, "eslint.cmd") : path28.join(binDir, "eslint");
|
|
45143
45124
|
switch (linter) {
|
|
45144
45125
|
case "biome":
|
|
45145
45126
|
if (mode === "fix") {
|
|
@@ -45155,7 +45136,7 @@ function getLinterCommand(linter, mode, projectDir) {
|
|
|
45155
45136
|
}
|
|
45156
45137
|
function getAdditionalLinterCommand(linter, mode, cwd) {
|
|
45157
45138
|
const gradlewName = process.platform === "win32" ? "gradlew.bat" : "gradlew";
|
|
45158
|
-
const gradlew = fs12.existsSync(
|
|
45139
|
+
const gradlew = fs12.existsSync(path28.join(cwd, gradlewName)) ? path28.join(cwd, gradlewName) : null;
|
|
45159
45140
|
switch (linter) {
|
|
45160
45141
|
case "ruff":
|
|
45161
45142
|
return mode === "fix" ? ["ruff", "check", "--fix", "."] : ["ruff", "check", "."];
|
|
@@ -45189,10 +45170,10 @@ function getAdditionalLinterCommand(linter, mode, cwd) {
|
|
|
45189
45170
|
}
|
|
45190
45171
|
}
|
|
45191
45172
|
function detectRuff(cwd) {
|
|
45192
|
-
if (fs12.existsSync(
|
|
45173
|
+
if (fs12.existsSync(path28.join(cwd, "ruff.toml")))
|
|
45193
45174
|
return isCommandAvailable("ruff");
|
|
45194
45175
|
try {
|
|
45195
|
-
const pyproject =
|
|
45176
|
+
const pyproject = path28.join(cwd, "pyproject.toml");
|
|
45196
45177
|
if (fs12.existsSync(pyproject)) {
|
|
45197
45178
|
const content = fs12.readFileSync(pyproject, "utf-8");
|
|
45198
45179
|
if (content.includes("[tool.ruff]"))
|
|
@@ -45202,19 +45183,19 @@ function detectRuff(cwd) {
|
|
|
45202
45183
|
return false;
|
|
45203
45184
|
}
|
|
45204
45185
|
function detectClippy(cwd) {
|
|
45205
|
-
return fs12.existsSync(
|
|
45186
|
+
return fs12.existsSync(path28.join(cwd, "Cargo.toml")) && isCommandAvailable("cargo");
|
|
45206
45187
|
}
|
|
45207
45188
|
function detectGolangciLint(cwd) {
|
|
45208
|
-
return fs12.existsSync(
|
|
45189
|
+
return fs12.existsSync(path28.join(cwd, "go.mod")) && isCommandAvailable("golangci-lint");
|
|
45209
45190
|
}
|
|
45210
45191
|
function detectCheckstyle(cwd) {
|
|
45211
|
-
const hasMaven = fs12.existsSync(
|
|
45212
|
-
const hasGradle = fs12.existsSync(
|
|
45213
|
-
const hasBinary = hasMaven && isCommandAvailable("mvn") || hasGradle && (fs12.existsSync(
|
|
45192
|
+
const hasMaven = fs12.existsSync(path28.join(cwd, "pom.xml"));
|
|
45193
|
+
const hasGradle = fs12.existsSync(path28.join(cwd, "build.gradle")) || fs12.existsSync(path28.join(cwd, "build.gradle.kts"));
|
|
45194
|
+
const hasBinary = hasMaven && isCommandAvailable("mvn") || hasGradle && (fs12.existsSync(path28.join(cwd, "gradlew")) || isCommandAvailable("gradle"));
|
|
45214
45195
|
return (hasMaven || hasGradle) && hasBinary;
|
|
45215
45196
|
}
|
|
45216
45197
|
function detectKtlint(cwd) {
|
|
45217
|
-
const hasKotlin = fs12.existsSync(
|
|
45198
|
+
const hasKotlin = fs12.existsSync(path28.join(cwd, "build.gradle.kts")) || fs12.existsSync(path28.join(cwd, "build.gradle")) || (() => {
|
|
45218
45199
|
try {
|
|
45219
45200
|
return fs12.readdirSync(cwd).some((f) => f.endsWith(".kt") || f.endsWith(".kts"));
|
|
45220
45201
|
} catch {
|
|
@@ -45233,11 +45214,11 @@ function detectDotnetFormat(cwd) {
|
|
|
45233
45214
|
}
|
|
45234
45215
|
}
|
|
45235
45216
|
function detectCppcheck(cwd) {
|
|
45236
|
-
if (fs12.existsSync(
|
|
45217
|
+
if (fs12.existsSync(path28.join(cwd, "CMakeLists.txt"))) {
|
|
45237
45218
|
return isCommandAvailable("cppcheck");
|
|
45238
45219
|
}
|
|
45239
45220
|
try {
|
|
45240
|
-
const dirsToCheck = [cwd,
|
|
45221
|
+
const dirsToCheck = [cwd, path28.join(cwd, "src")];
|
|
45241
45222
|
const hasCpp = dirsToCheck.some((dir) => {
|
|
45242
45223
|
try {
|
|
45243
45224
|
return fs12.readdirSync(dir).some((f) => /\.(c|cpp|cc|cxx|h|hpp)$/.test(f));
|
|
@@ -45251,13 +45232,13 @@ function detectCppcheck(cwd) {
|
|
|
45251
45232
|
}
|
|
45252
45233
|
}
|
|
45253
45234
|
function detectSwiftlint(cwd) {
|
|
45254
|
-
return fs12.existsSync(
|
|
45235
|
+
return fs12.existsSync(path28.join(cwd, "Package.swift")) && isCommandAvailable("swiftlint");
|
|
45255
45236
|
}
|
|
45256
45237
|
function detectDartAnalyze(cwd) {
|
|
45257
|
-
return fs12.existsSync(
|
|
45238
|
+
return fs12.existsSync(path28.join(cwd, "pubspec.yaml")) && (isCommandAvailable("dart") || isCommandAvailable("flutter"));
|
|
45258
45239
|
}
|
|
45259
45240
|
function detectRubocop(cwd) {
|
|
45260
|
-
return (fs12.existsSync(
|
|
45241
|
+
return (fs12.existsSync(path28.join(cwd, "Gemfile")) || fs12.existsSync(path28.join(cwd, "gems.rb")) || fs12.existsSync(path28.join(cwd, ".rubocop.yml"))) && (isCommandAvailable("rubocop") || isCommandAvailable("bundle"));
|
|
45261
45242
|
}
|
|
45262
45243
|
function detectAdditionalLinter(cwd) {
|
|
45263
45244
|
if (detectRuff(cwd))
|
|
@@ -45285,10 +45266,10 @@ function detectAdditionalLinter(cwd) {
|
|
|
45285
45266
|
function findBinInAncestors(startDir, binName) {
|
|
45286
45267
|
let dir = startDir;
|
|
45287
45268
|
while (true) {
|
|
45288
|
-
const candidate =
|
|
45269
|
+
const candidate = path28.join(dir, "node_modules", ".bin", binName);
|
|
45289
45270
|
if (fs12.existsSync(candidate))
|
|
45290
45271
|
return candidate;
|
|
45291
|
-
const parent =
|
|
45272
|
+
const parent = path28.dirname(dir);
|
|
45292
45273
|
if (parent === dir)
|
|
45293
45274
|
break;
|
|
45294
45275
|
dir = parent;
|
|
@@ -45297,10 +45278,10 @@ function findBinInAncestors(startDir, binName) {
|
|
|
45297
45278
|
}
|
|
45298
45279
|
function findBinInEnvPath(binName) {
|
|
45299
45280
|
const searchPath = process.env.PATH ?? "";
|
|
45300
|
-
for (const dir of searchPath.split(
|
|
45281
|
+
for (const dir of searchPath.split(path28.delimiter)) {
|
|
45301
45282
|
if (!dir)
|
|
45302
45283
|
continue;
|
|
45303
|
-
const candidate =
|
|
45284
|
+
const candidate = path28.join(dir, binName);
|
|
45304
45285
|
if (fs12.existsSync(candidate))
|
|
45305
45286
|
return candidate;
|
|
45306
45287
|
}
|
|
@@ -45313,13 +45294,13 @@ async function detectAvailableLinter(directory) {
|
|
|
45313
45294
|
return null;
|
|
45314
45295
|
const projectDir = directory;
|
|
45315
45296
|
const isWindows = process.platform === "win32";
|
|
45316
|
-
const biomeBin = isWindows ?
|
|
45317
|
-
const eslintBin = isWindows ?
|
|
45297
|
+
const biomeBin = isWindows ? path28.join(projectDir, "node_modules", ".bin", "biome.EXE") : path28.join(projectDir, "node_modules", ".bin", "biome");
|
|
45298
|
+
const eslintBin = isWindows ? path28.join(projectDir, "node_modules", ".bin", "eslint.cmd") : path28.join(projectDir, "node_modules", ".bin", "eslint");
|
|
45318
45299
|
const localResult = await _detectAvailableLinter(projectDir, biomeBin, eslintBin);
|
|
45319
45300
|
if (localResult)
|
|
45320
45301
|
return localResult;
|
|
45321
|
-
const biomeAncestor = findBinInAncestors(
|
|
45322
|
-
const eslintAncestor = findBinInAncestors(
|
|
45302
|
+
const biomeAncestor = findBinInAncestors(path28.dirname(projectDir), isWindows ? "biome.EXE" : "biome");
|
|
45303
|
+
const eslintAncestor = findBinInAncestors(path28.dirname(projectDir), isWindows ? "eslint.cmd" : "eslint");
|
|
45323
45304
|
if (biomeAncestor || eslintAncestor) {
|
|
45324
45305
|
return _detectAvailableLinter(projectDir, biomeAncestor ?? biomeBin, eslintAncestor ?? eslintBin);
|
|
45325
45306
|
}
|
|
@@ -45542,7 +45523,7 @@ For Rust: rustup component add clippy`
|
|
|
45542
45523
|
|
|
45543
45524
|
// src/tools/secretscan.ts
|
|
45544
45525
|
import * as fs13 from "fs";
|
|
45545
|
-
import * as
|
|
45526
|
+
import * as path29 from "path";
|
|
45546
45527
|
function calculateShannonEntropy(str) {
|
|
45547
45528
|
if (str.length === 0)
|
|
45548
45529
|
return 0;
|
|
@@ -45590,7 +45571,7 @@ function isGlobOrPathPattern(pattern) {
|
|
|
45590
45571
|
return pattern.includes("/") || pattern.includes("\\") || /[*?[\]{}]/.test(pattern);
|
|
45591
45572
|
}
|
|
45592
45573
|
function loadSecretScanIgnore(scanDir) {
|
|
45593
|
-
const ignorePath =
|
|
45574
|
+
const ignorePath = path29.join(scanDir, ".secretscanignore");
|
|
45594
45575
|
try {
|
|
45595
45576
|
if (!fs13.existsSync(ignorePath))
|
|
45596
45577
|
return [];
|
|
@@ -45613,7 +45594,7 @@ function isExcluded(entry, relPath, exactNames, globPatterns) {
|
|
|
45613
45594
|
if (exactNames.has(entry))
|
|
45614
45595
|
return true;
|
|
45615
45596
|
for (const pattern of globPatterns) {
|
|
45616
|
-
if (
|
|
45597
|
+
if (path29.matchesGlob(relPath, pattern))
|
|
45617
45598
|
return true;
|
|
45618
45599
|
}
|
|
45619
45600
|
return false;
|
|
@@ -45634,7 +45615,7 @@ function validateDirectoryInput(dir) {
|
|
|
45634
45615
|
return null;
|
|
45635
45616
|
}
|
|
45636
45617
|
function isBinaryFile(filePath, buffer) {
|
|
45637
|
-
const ext =
|
|
45618
|
+
const ext = path29.extname(filePath).toLowerCase();
|
|
45638
45619
|
if (DEFAULT_EXCLUDE_EXTENSIONS.has(ext)) {
|
|
45639
45620
|
return true;
|
|
45640
45621
|
}
|
|
@@ -45770,9 +45751,9 @@ function isSymlinkLoop(realPath, visited) {
|
|
|
45770
45751
|
return false;
|
|
45771
45752
|
}
|
|
45772
45753
|
function isPathWithinScope(realPath, scanDir) {
|
|
45773
|
-
const resolvedScanDir =
|
|
45774
|
-
const resolvedRealPath =
|
|
45775
|
-
return resolvedRealPath === resolvedScanDir || resolvedRealPath.startsWith(resolvedScanDir +
|
|
45754
|
+
const resolvedScanDir = path29.resolve(scanDir);
|
|
45755
|
+
const resolvedRealPath = path29.resolve(realPath);
|
|
45756
|
+
return resolvedRealPath === resolvedScanDir || resolvedRealPath.startsWith(resolvedScanDir + path29.sep) || resolvedRealPath.startsWith(`${resolvedScanDir}/`) || resolvedRealPath.startsWith(`${resolvedScanDir}\\`);
|
|
45776
45757
|
}
|
|
45777
45758
|
function findScannableFiles(dir, excludeExact, excludeGlobs, scanDir, visited, stats = {
|
|
45778
45759
|
skippedDirs: 0,
|
|
@@ -45798,8 +45779,8 @@ function findScannableFiles(dir, excludeExact, excludeGlobs, scanDir, visited, s
|
|
|
45798
45779
|
return a.localeCompare(b);
|
|
45799
45780
|
});
|
|
45800
45781
|
for (const entry of entries) {
|
|
45801
|
-
const fullPath =
|
|
45802
|
-
const relPath =
|
|
45782
|
+
const fullPath = path29.join(dir, entry);
|
|
45783
|
+
const relPath = path29.relative(scanDir, fullPath).replace(/\\/g, "/");
|
|
45803
45784
|
if (isExcluded(entry, relPath, excludeExact, excludeGlobs)) {
|
|
45804
45785
|
stats.skippedDirs++;
|
|
45805
45786
|
continue;
|
|
@@ -45834,7 +45815,7 @@ function findScannableFiles(dir, excludeExact, excludeGlobs, scanDir, visited, s
|
|
|
45834
45815
|
const subFiles = findScannableFiles(fullPath, excludeExact, excludeGlobs, scanDir, visited, stats);
|
|
45835
45816
|
files.push(...subFiles);
|
|
45836
45817
|
} else if (lstat.isFile()) {
|
|
45837
|
-
const ext =
|
|
45818
|
+
const ext = path29.extname(fullPath).toLowerCase();
|
|
45838
45819
|
if (!DEFAULT_EXCLUDE_EXTENSIONS.has(ext)) {
|
|
45839
45820
|
files.push(fullPath);
|
|
45840
45821
|
} else {
|
|
@@ -46094,7 +46075,7 @@ var init_secretscan = __esm(() => {
|
|
|
46094
46075
|
}
|
|
46095
46076
|
}
|
|
46096
46077
|
try {
|
|
46097
|
-
const _scanDirRaw =
|
|
46078
|
+
const _scanDirRaw = path29.resolve(directory);
|
|
46098
46079
|
const scanDir = (() => {
|
|
46099
46080
|
try {
|
|
46100
46081
|
return fs13.realpathSync(_scanDirRaw);
|
|
@@ -46241,7 +46222,7 @@ var init_secretscan = __esm(() => {
|
|
|
46241
46222
|
|
|
46242
46223
|
// src/lang/default-backend.ts
|
|
46243
46224
|
import * as fs14 from "fs";
|
|
46244
|
-
import * as
|
|
46225
|
+
import * as path30 from "path";
|
|
46245
46226
|
function detectFileExists(dir, pattern) {
|
|
46246
46227
|
if (pattern.includes("*") || pattern.includes("?")) {
|
|
46247
46228
|
try {
|
|
@@ -46253,7 +46234,7 @@ function detectFileExists(dir, pattern) {
|
|
|
46253
46234
|
}
|
|
46254
46235
|
}
|
|
46255
46236
|
try {
|
|
46256
|
-
fs14.accessSync(
|
|
46237
|
+
fs14.accessSync(path30.join(dir, pattern));
|
|
46257
46238
|
return true;
|
|
46258
46239
|
} catch {
|
|
46259
46240
|
return false;
|
|
@@ -46381,8 +46362,8 @@ function defaultBuildTestCommand(profile, framework, files, dir = ".", opts = {}
|
|
|
46381
46362
|
return ["mvn", "test"];
|
|
46382
46363
|
case "gradle": {
|
|
46383
46364
|
const isWindows = process.platform === "win32";
|
|
46384
|
-
const hasGradlewBat = fs14.existsSync(
|
|
46385
|
-
const hasGradlew = fs14.existsSync(
|
|
46365
|
+
const hasGradlewBat = fs14.existsSync(path30.join(dir, "gradlew.bat"));
|
|
46366
|
+
const hasGradlew = fs14.existsSync(path30.join(dir, "gradlew"));
|
|
46386
46367
|
if (hasGradlewBat && isWindows)
|
|
46387
46368
|
return ["gradlew.bat", "test"];
|
|
46388
46369
|
if (hasGradlew)
|
|
@@ -46399,7 +46380,7 @@ function defaultBuildTestCommand(profile, framework, files, dir = ".", opts = {}
|
|
|
46399
46380
|
"cmake-build-release",
|
|
46400
46381
|
"out"
|
|
46401
46382
|
];
|
|
46402
|
-
const actualBuildDir = buildDirCandidates.find((d) => fs14.existsSync(
|
|
46383
|
+
const actualBuildDir = buildDirCandidates.find((d) => fs14.existsSync(path30.join(dir, d, "CMakeCache.txt"))) ?? "build";
|
|
46403
46384
|
return ["ctest", "--test-dir", actualBuildDir];
|
|
46404
46385
|
}
|
|
46405
46386
|
case "swift-test":
|
|
@@ -46686,17 +46667,17 @@ async function defaultSelectBuildCommand(profile, dir) {
|
|
|
46686
46667
|
return null;
|
|
46687
46668
|
}
|
|
46688
46669
|
async function defaultTestFilesFor(profile, sourceFile, dir) {
|
|
46689
|
-
const ext =
|
|
46670
|
+
const ext = path30.extname(sourceFile);
|
|
46690
46671
|
if (!profile.extensions.includes(ext))
|
|
46691
46672
|
return [];
|
|
46692
|
-
const base =
|
|
46693
|
-
const rel =
|
|
46694
|
-
const relDir =
|
|
46673
|
+
const base = path30.basename(sourceFile, ext);
|
|
46674
|
+
const rel = path30.relative(dir, sourceFile);
|
|
46675
|
+
const relDir = path30.dirname(rel);
|
|
46695
46676
|
const stripSrc = relDir.replace(/^src(\/|\\)/, "");
|
|
46696
46677
|
const candidates = new Set;
|
|
46697
46678
|
for (const tDir of ["tests", "test", "__tests__", "spec"]) {
|
|
46698
46679
|
for (const suffix of ["", "_test", ".test", "_spec", ".spec"]) {
|
|
46699
|
-
candidates.add(
|
|
46680
|
+
candidates.add(path30.join(dir, tDir, stripSrc, `${base}${suffix}${ext}`));
|
|
46700
46681
|
}
|
|
46701
46682
|
}
|
|
46702
46683
|
const existing = [];
|
|
@@ -46737,7 +46718,7 @@ var init_default_backend = __esm(() => {
|
|
|
46737
46718
|
|
|
46738
46719
|
// src/lang/backends/go.ts
|
|
46739
46720
|
import * as fs15 from "fs";
|
|
46740
|
-
import * as
|
|
46721
|
+
import * as path31 from "path";
|
|
46741
46722
|
function extractImports(_sourceFile, source) {
|
|
46742
46723
|
const out = new Set;
|
|
46743
46724
|
IMPORT_REGEX_SINGLE.lastIndex = 0;
|
|
@@ -46763,7 +46744,7 @@ function extractImports(_sourceFile, source) {
|
|
|
46763
46744
|
async function selectFramework(dir) {
|
|
46764
46745
|
let content;
|
|
46765
46746
|
try {
|
|
46766
|
-
content = fs15.readFileSync(
|
|
46747
|
+
content = fs15.readFileSync(path31.join(dir, "go.mod"), "utf-8");
|
|
46767
46748
|
} catch {
|
|
46768
46749
|
return null;
|
|
46769
46750
|
}
|
|
@@ -46784,16 +46765,16 @@ async function selectFramework(dir) {
|
|
|
46784
46765
|
async function selectEntryPoints(dir) {
|
|
46785
46766
|
const points = [];
|
|
46786
46767
|
try {
|
|
46787
|
-
fs15.accessSync(
|
|
46768
|
+
fs15.accessSync(path31.join(dir, "main.go"));
|
|
46788
46769
|
points.push("main.go");
|
|
46789
46770
|
} catch {}
|
|
46790
46771
|
try {
|
|
46791
|
-
const cmdDir =
|
|
46772
|
+
const cmdDir = path31.join(dir, "cmd");
|
|
46792
46773
|
const subdirs = fs15.readdirSync(cmdDir, { withFileTypes: true }).filter((d) => d.isDirectory());
|
|
46793
46774
|
for (const sub of subdirs) {
|
|
46794
|
-
const main =
|
|
46775
|
+
const main = path31.join("cmd", sub.name, "main.go");
|
|
46795
46776
|
try {
|
|
46796
|
-
fs15.accessSync(
|
|
46777
|
+
fs15.accessSync(path31.join(dir, main));
|
|
46797
46778
|
points.push(main);
|
|
46798
46779
|
} catch {}
|
|
46799
46780
|
}
|
|
@@ -46824,7 +46805,7 @@ var init_go = __esm(() => {
|
|
|
46824
46805
|
|
|
46825
46806
|
// src/lang/backends/python.ts
|
|
46826
46807
|
import * as fs16 from "fs";
|
|
46827
|
-
import * as
|
|
46808
|
+
import * as path32 from "path";
|
|
46828
46809
|
function parseImportTargets(rawTargets) {
|
|
46829
46810
|
const cleaned = rawTargets.replace(/[()]/g, "").split(`
|
|
46830
46811
|
`).map((line) => line.replace(/#.*$/, "").replace(/\\\s*$/, "")).join(" ");
|
|
@@ -46884,7 +46865,7 @@ async function selectFramework2(dir) {
|
|
|
46884
46865
|
];
|
|
46885
46866
|
for (const candidate of ["pyproject.toml", "requirements.txt", "setup.py"]) {
|
|
46886
46867
|
try {
|
|
46887
|
-
const content = fs16.readFileSync(
|
|
46868
|
+
const content = fs16.readFileSync(path32.join(dir, candidate), "utf-8");
|
|
46888
46869
|
const lower = content.toLowerCase();
|
|
46889
46870
|
for (const [pkg, name] of candidates) {
|
|
46890
46871
|
if (lower.includes(pkg)) {
|
|
@@ -46898,7 +46879,7 @@ async function selectFramework2(dir) {
|
|
|
46898
46879
|
async function selectEntryPoints2(dir) {
|
|
46899
46880
|
const points = new Set;
|
|
46900
46881
|
try {
|
|
46901
|
-
const content = fs16.readFileSync(
|
|
46882
|
+
const content = fs16.readFileSync(path32.join(dir, "pyproject.toml"), "utf-8");
|
|
46902
46883
|
const scriptsBlock = content.match(/\[project\.scripts\][\s\S]*?(?=\n\[|$)/);
|
|
46903
46884
|
if (scriptsBlock) {
|
|
46904
46885
|
for (const line of scriptsBlock[0].split(`
|
|
@@ -46913,7 +46894,7 @@ async function selectEntryPoints2(dir) {
|
|
|
46913
46894
|
} catch {}
|
|
46914
46895
|
for (const name of ["manage.py", "main.py", "app.py", "__main__.py"]) {
|
|
46915
46896
|
try {
|
|
46916
|
-
fs16.accessSync(
|
|
46897
|
+
fs16.accessSync(path32.join(dir, name));
|
|
46917
46898
|
points.add(name);
|
|
46918
46899
|
} catch {}
|
|
46919
46900
|
}
|
|
@@ -46942,7 +46923,7 @@ var init_python = __esm(() => {
|
|
|
46942
46923
|
|
|
46943
46924
|
// src/test-impact/analyzer.ts
|
|
46944
46925
|
import fs17 from "fs";
|
|
46945
|
-
import
|
|
46926
|
+
import path33 from "path";
|
|
46946
46927
|
function normalizePath(p) {
|
|
46947
46928
|
return p.replace(/\\/g, "/");
|
|
46948
46929
|
}
|
|
@@ -46963,8 +46944,8 @@ function resolveRelativeImport(fromDir, importPath) {
|
|
|
46963
46944
|
if (!importPath.startsWith(".")) {
|
|
46964
46945
|
return null;
|
|
46965
46946
|
}
|
|
46966
|
-
const resolved =
|
|
46967
|
-
if (
|
|
46947
|
+
const resolved = path33.resolve(fromDir, importPath);
|
|
46948
|
+
if (path33.extname(resolved)) {
|
|
46968
46949
|
if (fs17.existsSync(resolved) && fs17.statSync(resolved).isFile()) {
|
|
46969
46950
|
return normalizePath(resolved);
|
|
46970
46951
|
}
|
|
@@ -46984,20 +46965,20 @@ function resolvePythonImport(fromDir, module) {
|
|
|
46984
46965
|
const leadingDots = module.match(/^\.+/)?.[0].length ?? 0;
|
|
46985
46966
|
let baseDir = fromDir;
|
|
46986
46967
|
for (let i = 1;i < leadingDots; i++) {
|
|
46987
|
-
baseDir =
|
|
46968
|
+
baseDir = path33.dirname(baseDir);
|
|
46988
46969
|
}
|
|
46989
46970
|
const rest = module.slice(leadingDots);
|
|
46990
46971
|
if (rest.length === 0) {
|
|
46991
|
-
const initPath =
|
|
46972
|
+
const initPath = path33.join(baseDir, "__init__.py");
|
|
46992
46973
|
if (fs17.existsSync(initPath) && fs17.statSync(initPath).isFile()) {
|
|
46993
46974
|
return normalizePath(initPath);
|
|
46994
46975
|
}
|
|
46995
46976
|
return null;
|
|
46996
46977
|
}
|
|
46997
|
-
const subpath = rest.replace(/\./g,
|
|
46978
|
+
const subpath = rest.replace(/\./g, path33.sep);
|
|
46998
46979
|
const candidates = [
|
|
46999
|
-
`${
|
|
47000
|
-
|
|
46980
|
+
`${path33.join(baseDir, subpath)}.py`,
|
|
46981
|
+
path33.join(baseDir, subpath, "__init__.py")
|
|
47001
46982
|
];
|
|
47002
46983
|
for (const c of candidates) {
|
|
47003
46984
|
if (fs17.existsSync(c) && fs17.statSync(c).isFile())
|
|
@@ -47006,7 +46987,7 @@ function resolvePythonImport(fromDir, module) {
|
|
|
47006
46987
|
return null;
|
|
47007
46988
|
}
|
|
47008
46989
|
function findGoModule(fromDir) {
|
|
47009
|
-
const resolved =
|
|
46990
|
+
const resolved = path33.resolve(fromDir);
|
|
47010
46991
|
let cur = resolved;
|
|
47011
46992
|
const walked = [];
|
|
47012
46993
|
for (let i = 0;i < 16; i++) {
|
|
@@ -47018,7 +46999,7 @@ function findGoModule(fromDir) {
|
|
|
47018
46999
|
}
|
|
47019
47000
|
walked.push(cur);
|
|
47020
47001
|
try {
|
|
47021
|
-
const goMod =
|
|
47002
|
+
const goMod = path33.join(cur, "go.mod");
|
|
47022
47003
|
const content = fs17.readFileSync(goMod, "utf-8");
|
|
47023
47004
|
const moduleMatch = content.match(/^\s*module\s+"?([^"\s/]+(?:\/[^"\s]+)*)"?/m);
|
|
47024
47005
|
if (moduleMatch) {
|
|
@@ -47029,10 +47010,10 @@ function findGoModule(fromDir) {
|
|
|
47029
47010
|
}
|
|
47030
47011
|
} catch {}
|
|
47031
47012
|
try {
|
|
47032
|
-
fs17.accessSync(
|
|
47013
|
+
fs17.accessSync(path33.join(cur, ".git"));
|
|
47033
47014
|
break;
|
|
47034
47015
|
} catch {}
|
|
47035
|
-
const parent =
|
|
47016
|
+
const parent = path33.dirname(cur);
|
|
47036
47017
|
if (parent === cur)
|
|
47037
47018
|
break;
|
|
47038
47019
|
cur = parent;
|
|
@@ -47044,12 +47025,12 @@ function findGoModule(fromDir) {
|
|
|
47044
47025
|
function resolveGoImport(fromDir, importPath) {
|
|
47045
47026
|
let dir = null;
|
|
47046
47027
|
if (importPath.startsWith(".")) {
|
|
47047
|
-
dir =
|
|
47028
|
+
dir = path33.resolve(fromDir, importPath);
|
|
47048
47029
|
} else {
|
|
47049
47030
|
const mod = findGoModule(fromDir);
|
|
47050
47031
|
if (mod && (importPath === mod.modulePath || importPath.startsWith(`${mod.modulePath}/`))) {
|
|
47051
47032
|
const subpath = importPath.slice(mod.modulePath.length);
|
|
47052
|
-
dir =
|
|
47033
|
+
dir = path33.join(mod.moduleRoot, subpath);
|
|
47053
47034
|
}
|
|
47054
47035
|
}
|
|
47055
47036
|
if (dir === null)
|
|
@@ -47057,7 +47038,7 @@ function resolveGoImport(fromDir, importPath) {
|
|
|
47057
47038
|
if (!fs17.existsSync(dir) || !fs17.statSync(dir).isDirectory())
|
|
47058
47039
|
return [];
|
|
47059
47040
|
try {
|
|
47060
|
-
return fs17.readdirSync(dir).filter((f) => f.endsWith(".go") && !f.endsWith("_test.go")).map((f) => normalizePath(
|
|
47041
|
+
return fs17.readdirSync(dir).filter((f) => f.endsWith(".go") && !f.endsWith("_test.go")).map((f) => normalizePath(path33.join(dir, f)));
|
|
47061
47042
|
} catch {
|
|
47062
47043
|
return [];
|
|
47063
47044
|
}
|
|
@@ -47096,15 +47077,15 @@ function findTestFilesSync(cwd) {
|
|
|
47096
47077
|
for (const entry of entries) {
|
|
47097
47078
|
if (entry.isDirectory()) {
|
|
47098
47079
|
if (!skipDirs.has(entry.name)) {
|
|
47099
|
-
walk(
|
|
47080
|
+
walk(path33.join(dir, entry.name), visitedInodes);
|
|
47100
47081
|
}
|
|
47101
47082
|
} else if (entry.isFile()) {
|
|
47102
47083
|
const name = entry.name;
|
|
47103
47084
|
const isTsTest = /\.(test|spec)\.(ts|tsx|js|jsx)$/.test(name) || dir.includes("__tests__") && /\.(ts|tsx|js|jsx)$/.test(name);
|
|
47104
|
-
const isPyTest = /^test_.+\.py$/.test(name) || /.+_test\.py$/.test(name) || dir.includes(`${
|
|
47085
|
+
const isPyTest = /^test_.+\.py$/.test(name) || /.+_test\.py$/.test(name) || dir.includes(`${path33.sep}tests${path33.sep}`) && name.endsWith(".py");
|
|
47105
47086
|
const isGoTest = /.+_test\.go$/.test(name);
|
|
47106
47087
|
if (isTsTest || isPyTest || isGoTest) {
|
|
47107
|
-
testFiles.push(normalizePath(
|
|
47088
|
+
testFiles.push(normalizePath(path33.join(dir, entry.name)));
|
|
47108
47089
|
}
|
|
47109
47090
|
}
|
|
47110
47091
|
}
|
|
@@ -47129,8 +47110,8 @@ function extractImports3(content) {
|
|
|
47129
47110
|
];
|
|
47130
47111
|
}
|
|
47131
47112
|
function addImpactEdgesForTestFile(testFile, content, impactMap) {
|
|
47132
|
-
const ext =
|
|
47133
|
-
const testDir =
|
|
47113
|
+
const ext = path33.extname(testFile).toLowerCase();
|
|
47114
|
+
const testDir = path33.dirname(testFile);
|
|
47134
47115
|
function addEdge(source) {
|
|
47135
47116
|
if (!impactMap[source])
|
|
47136
47117
|
impactMap[source] = [];
|
|
@@ -47189,7 +47170,7 @@ async function buildImpactMap(cwd) {
|
|
|
47189
47170
|
return impactMap;
|
|
47190
47171
|
}
|
|
47191
47172
|
async function loadImpactMap(cwd, options) {
|
|
47192
|
-
const cachePath =
|
|
47173
|
+
const cachePath = path33.join(cwd, ".swarm", "cache", "impact-map.json");
|
|
47193
47174
|
if (fs17.existsSync(cachePath)) {
|
|
47194
47175
|
try {
|
|
47195
47176
|
const content = fs17.readFileSync(cachePath, "utf-8");
|
|
@@ -47222,12 +47203,12 @@ async function loadImpactMap(cwd, options) {
|
|
|
47222
47203
|
return _internals22.buildImpactMap(cwd);
|
|
47223
47204
|
}
|
|
47224
47205
|
async function saveImpactMap(cwd, impactMap) {
|
|
47225
|
-
if (!
|
|
47206
|
+
if (!path33.isAbsolute(cwd)) {
|
|
47226
47207
|
throw new Error(`saveImpactMap requires an absolute project root path, got: "${cwd}"`);
|
|
47227
47208
|
}
|
|
47228
47209
|
_internals22.validateProjectRoot(cwd);
|
|
47229
|
-
const cacheDir2 =
|
|
47230
|
-
const cachePath =
|
|
47210
|
+
const cacheDir2 = path33.join(cwd, ".swarm", "cache");
|
|
47211
|
+
const cachePath = path33.join(cacheDir2, "impact-map.json");
|
|
47231
47212
|
if (!fs17.existsSync(cacheDir2)) {
|
|
47232
47213
|
fs17.mkdirSync(cacheDir2, { recursive: true });
|
|
47233
47214
|
}
|
|
@@ -47259,7 +47240,7 @@ async function analyzeImpact(changedFiles, cwd, budget) {
|
|
|
47259
47240
|
budgetExceeded = true;
|
|
47260
47241
|
break;
|
|
47261
47242
|
}
|
|
47262
|
-
const normalizedChanged = normalizePath(
|
|
47243
|
+
const normalizedChanged = normalizePath(path33.resolve(changedFile));
|
|
47263
47244
|
const tests = impactMap[normalizedChanged];
|
|
47264
47245
|
if (tests && tests.length > 0) {
|
|
47265
47246
|
for (const test of tests) {
|
|
@@ -47552,15 +47533,15 @@ var FLAKY_THRESHOLD = 0.3, MIN_RUNS_FOR_QUARANTINE = 5, MAX_HISTORY_RUNS = 20;
|
|
|
47552
47533
|
|
|
47553
47534
|
// src/test-impact/history-store.ts
|
|
47554
47535
|
import fs18 from "fs";
|
|
47555
|
-
import
|
|
47536
|
+
import path34 from "path";
|
|
47556
47537
|
function getHistoryPath(workingDir) {
|
|
47557
47538
|
if (!workingDir) {
|
|
47558
47539
|
throw new Error("getHistoryPath requires a working directory \u2014 project root must be provided by the caller");
|
|
47559
47540
|
}
|
|
47560
|
-
if (!
|
|
47541
|
+
if (!path34.isAbsolute(workingDir)) {
|
|
47561
47542
|
throw new Error(`getHistoryPath requires an absolute project root path, got: "${workingDir}"`);
|
|
47562
47543
|
}
|
|
47563
|
-
return
|
|
47544
|
+
return path34.join(workingDir, ".swarm", "cache", "test-history.jsonl");
|
|
47564
47545
|
}
|
|
47565
47546
|
function sanitizeErrorMessage(errorMessage) {
|
|
47566
47547
|
if (errorMessage === undefined) {
|
|
@@ -47647,7 +47628,7 @@ function batchAppendTestRuns(records, workingDir) {
|
|
|
47647
47628
|
}
|
|
47648
47629
|
}
|
|
47649
47630
|
const historyPath = getHistoryPath(workingDir);
|
|
47650
|
-
const historyDir =
|
|
47631
|
+
const historyDir = path34.dirname(historyPath);
|
|
47651
47632
|
_internals23.validateProjectRoot(workingDir);
|
|
47652
47633
|
if (!fs18.existsSync(historyDir)) {
|
|
47653
47634
|
fs18.mkdirSync(historyDir, { recursive: true });
|
|
@@ -47743,7 +47724,7 @@ var init_history_store = __esm(() => {
|
|
|
47743
47724
|
|
|
47744
47725
|
// src/tools/resolve-working-directory.ts
|
|
47745
47726
|
import * as fs19 from "fs";
|
|
47746
|
-
import * as
|
|
47727
|
+
import * as path35 from "path";
|
|
47747
47728
|
function resolveWorkingDirectory(workingDirectory, fallbackDirectory) {
|
|
47748
47729
|
if (workingDirectory == null || workingDirectory === "") {
|
|
47749
47730
|
return { success: true, directory: fallbackDirectory };
|
|
@@ -47763,15 +47744,15 @@ function resolveWorkingDirectory(workingDirectory, fallbackDirectory) {
|
|
|
47763
47744
|
};
|
|
47764
47745
|
}
|
|
47765
47746
|
}
|
|
47766
|
-
const normalizedDir =
|
|
47767
|
-
const pathParts = normalizedDir.split(
|
|
47747
|
+
const normalizedDir = path35.normalize(workingDirectory);
|
|
47748
|
+
const pathParts = normalizedDir.split(path35.sep);
|
|
47768
47749
|
if (pathParts.includes("..")) {
|
|
47769
47750
|
return {
|
|
47770
47751
|
success: false,
|
|
47771
47752
|
message: "Invalid working_directory: path traversal sequences (..) are not allowed"
|
|
47772
47753
|
};
|
|
47773
47754
|
}
|
|
47774
|
-
const resolvedDir =
|
|
47755
|
+
const resolvedDir = path35.resolve(normalizedDir);
|
|
47775
47756
|
let statResult;
|
|
47776
47757
|
try {
|
|
47777
47758
|
statResult = fs19.statSync(resolvedDir);
|
|
@@ -47787,7 +47768,7 @@ function resolveWorkingDirectory(workingDirectory, fallbackDirectory) {
|
|
|
47787
47768
|
message: `Invalid working_directory: path "${resolvedDir}" is not a directory`
|
|
47788
47769
|
};
|
|
47789
47770
|
}
|
|
47790
|
-
const resolvedFallback =
|
|
47771
|
+
const resolvedFallback = path35.resolve(fallbackDirectory);
|
|
47791
47772
|
let fallbackExists = false;
|
|
47792
47773
|
try {
|
|
47793
47774
|
fs19.statSync(resolvedFallback);
|
|
@@ -47797,7 +47778,7 @@ function resolveWorkingDirectory(workingDirectory, fallbackDirectory) {
|
|
|
47797
47778
|
}
|
|
47798
47779
|
if (workingDirectory != null && workingDirectory !== "") {
|
|
47799
47780
|
if (fallbackExists) {
|
|
47800
|
-
const isSubdirectory = resolvedDir.startsWith(resolvedFallback +
|
|
47781
|
+
const isSubdirectory = resolvedDir.startsWith(resolvedFallback + path35.sep);
|
|
47801
47782
|
if (isSubdirectory) {
|
|
47802
47783
|
return {
|
|
47803
47784
|
success: false,
|
|
@@ -47852,10 +47833,10 @@ var init_registry_backend = __esm(() => {
|
|
|
47852
47833
|
|
|
47853
47834
|
// src/lang/backends/typescript.ts
|
|
47854
47835
|
import * as fs20 from "fs";
|
|
47855
|
-
import * as
|
|
47836
|
+
import * as path36 from "path";
|
|
47856
47837
|
function readPackageJsonRaw(dir) {
|
|
47857
47838
|
try {
|
|
47858
|
-
const content = fs20.readFileSync(
|
|
47839
|
+
const content = fs20.readFileSync(path36.join(dir, "package.json"), "utf-8");
|
|
47859
47840
|
return JSON.parse(content);
|
|
47860
47841
|
} catch {
|
|
47861
47842
|
return null;
|
|
@@ -48075,7 +48056,7 @@ __export(exports_dispatch, {
|
|
|
48075
48056
|
_internals: () => _internals25
|
|
48076
48057
|
});
|
|
48077
48058
|
import * as fs21 from "fs";
|
|
48078
|
-
import * as
|
|
48059
|
+
import * as path37 from "path";
|
|
48079
48060
|
function safeReaddirSet(dir) {
|
|
48080
48061
|
try {
|
|
48081
48062
|
return new Set(fs21.readdirSync(dir));
|
|
@@ -48092,14 +48073,14 @@ function manifestHash(dir) {
|
|
|
48092
48073
|
if (!entries.has(name))
|
|
48093
48074
|
continue;
|
|
48094
48075
|
try {
|
|
48095
|
-
const stat3 = fs21.statSync(
|
|
48076
|
+
const stat3 = fs21.statSync(path37.join(dir, name));
|
|
48096
48077
|
parts.push(`${name}:${stat3.size}:${stat3.mtimeMs}:${stat3.ino}`);
|
|
48097
48078
|
} catch {}
|
|
48098
48079
|
}
|
|
48099
48080
|
return parts.join("|");
|
|
48100
48081
|
}
|
|
48101
48082
|
function findManifestRoot(start) {
|
|
48102
|
-
const resolved =
|
|
48083
|
+
const resolved = path37.resolve(start);
|
|
48103
48084
|
const cached3 = manifestRootCache.get(resolved);
|
|
48104
48085
|
if (cached3 !== undefined)
|
|
48105
48086
|
return cached3;
|
|
@@ -48118,7 +48099,7 @@ function findManifestRoot(start) {
|
|
|
48118
48099
|
return cur;
|
|
48119
48100
|
}
|
|
48120
48101
|
}
|
|
48121
|
-
const parent =
|
|
48102
|
+
const parent = path37.dirname(cur);
|
|
48122
48103
|
if (parent === cur)
|
|
48123
48104
|
break;
|
|
48124
48105
|
cur = parent;
|
|
@@ -48228,13 +48209,13 @@ var init_dispatch = __esm(() => {
|
|
|
48228
48209
|
|
|
48229
48210
|
// src/tools/test-runner.ts
|
|
48230
48211
|
import * as fs22 from "fs";
|
|
48231
|
-
import * as
|
|
48212
|
+
import * as path38 from "path";
|
|
48232
48213
|
async function estimateFanOut(sourceFiles, cwd) {
|
|
48233
48214
|
try {
|
|
48234
48215
|
const impactMap = await loadImpactMap(cwd, { skipRebuild: true });
|
|
48235
48216
|
const uniqueTestFiles = new Set;
|
|
48236
48217
|
for (const sourceFile of sourceFiles) {
|
|
48237
|
-
const resolvedPath =
|
|
48218
|
+
const resolvedPath = path38.resolve(cwd, sourceFile);
|
|
48238
48219
|
const normalizedPath = resolvedPath.replace(/\\/g, "/");
|
|
48239
48220
|
const testFiles = impactMap[normalizedPath];
|
|
48240
48221
|
if (testFiles) {
|
|
@@ -48312,14 +48293,14 @@ function hasDevDependency(devDeps, ...patterns) {
|
|
|
48312
48293
|
return hasPackageJsonDependency(devDeps, ...patterns);
|
|
48313
48294
|
}
|
|
48314
48295
|
function detectGoTest(cwd) {
|
|
48315
|
-
return fs22.existsSync(
|
|
48296
|
+
return fs22.existsSync(path38.join(cwd, "go.mod")) && isCommandAvailable("go");
|
|
48316
48297
|
}
|
|
48317
48298
|
function detectJavaMaven(cwd) {
|
|
48318
|
-
return fs22.existsSync(
|
|
48299
|
+
return fs22.existsSync(path38.join(cwd, "pom.xml")) && isCommandAvailable("mvn");
|
|
48319
48300
|
}
|
|
48320
48301
|
function detectGradle(cwd) {
|
|
48321
|
-
const hasBuildFile = fs22.existsSync(
|
|
48322
|
-
const hasGradlew = fs22.existsSync(
|
|
48302
|
+
const hasBuildFile = fs22.existsSync(path38.join(cwd, "build.gradle")) || fs22.existsSync(path38.join(cwd, "build.gradle.kts"));
|
|
48303
|
+
const hasGradlew = fs22.existsSync(path38.join(cwd, "gradlew")) || fs22.existsSync(path38.join(cwd, "gradlew.bat"));
|
|
48323
48304
|
return hasBuildFile && (hasGradlew || isCommandAvailable("gradle"));
|
|
48324
48305
|
}
|
|
48325
48306
|
function detectDotnetTest(cwd) {
|
|
@@ -48332,25 +48313,25 @@ function detectDotnetTest(cwd) {
|
|
|
48332
48313
|
}
|
|
48333
48314
|
}
|
|
48334
48315
|
function detectCTest(cwd) {
|
|
48335
|
-
const hasSource = fs22.existsSync(
|
|
48336
|
-
const hasBuildCache = fs22.existsSync(
|
|
48316
|
+
const hasSource = fs22.existsSync(path38.join(cwd, "CMakeLists.txt"));
|
|
48317
|
+
const hasBuildCache = fs22.existsSync(path38.join(cwd, "CMakeCache.txt")) || fs22.existsSync(path38.join(cwd, "build", "CMakeCache.txt"));
|
|
48337
48318
|
return (hasSource || hasBuildCache) && isCommandAvailable("ctest");
|
|
48338
48319
|
}
|
|
48339
48320
|
function detectSwiftTest(cwd) {
|
|
48340
|
-
return fs22.existsSync(
|
|
48321
|
+
return fs22.existsSync(path38.join(cwd, "Package.swift")) && isCommandAvailable("swift");
|
|
48341
48322
|
}
|
|
48342
48323
|
function detectDartTest(cwd) {
|
|
48343
|
-
return fs22.existsSync(
|
|
48324
|
+
return fs22.existsSync(path38.join(cwd, "pubspec.yaml")) && (isCommandAvailable("dart") || isCommandAvailable("flutter"));
|
|
48344
48325
|
}
|
|
48345
48326
|
function detectRSpec(cwd) {
|
|
48346
|
-
const hasRSpecFile = fs22.existsSync(
|
|
48347
|
-
const hasGemfile = fs22.existsSync(
|
|
48348
|
-
const hasSpecDir = fs22.existsSync(
|
|
48327
|
+
const hasRSpecFile = fs22.existsSync(path38.join(cwd, ".rspec"));
|
|
48328
|
+
const hasGemfile = fs22.existsSync(path38.join(cwd, "Gemfile"));
|
|
48329
|
+
const hasSpecDir = fs22.existsSync(path38.join(cwd, "spec"));
|
|
48349
48330
|
const hasRSpec = hasRSpecFile || hasGemfile && hasSpecDir;
|
|
48350
48331
|
return hasRSpec && (isCommandAvailable("bundle") || isCommandAvailable("rspec"));
|
|
48351
48332
|
}
|
|
48352
48333
|
function detectMinitest(cwd) {
|
|
48353
|
-
return fs22.existsSync(
|
|
48334
|
+
return fs22.existsSync(path38.join(cwd, "test")) && (fs22.existsSync(path38.join(cwd, "Gemfile")) || fs22.existsSync(path38.join(cwd, "Rakefile"))) && isCommandAvailable("ruby");
|
|
48354
48335
|
}
|
|
48355
48336
|
async function detectTestFrameworkViaDispatch(cwd) {
|
|
48356
48337
|
try {
|
|
@@ -48412,7 +48393,7 @@ async function parseTestOutputViaDispatch(framework, output, baseDir) {
|
|
|
48412
48393
|
async function detectTestFramework(cwd) {
|
|
48413
48394
|
const baseDir = cwd;
|
|
48414
48395
|
try {
|
|
48415
|
-
const packageJsonPath =
|
|
48396
|
+
const packageJsonPath = path38.join(baseDir, "package.json");
|
|
48416
48397
|
if (fs22.existsSync(packageJsonPath)) {
|
|
48417
48398
|
const content = fs22.readFileSync(packageJsonPath, "utf-8");
|
|
48418
48399
|
const pkg = JSON.parse(content);
|
|
@@ -48433,16 +48414,16 @@ async function detectTestFramework(cwd) {
|
|
|
48433
48414
|
return "jest";
|
|
48434
48415
|
if (hasDevDependency(devDeps, "mocha", "@types/mocha"))
|
|
48435
48416
|
return "mocha";
|
|
48436
|
-
if (fs22.existsSync(
|
|
48417
|
+
if (fs22.existsSync(path38.join(baseDir, "bun.lockb")) || fs22.existsSync(path38.join(baseDir, "bun.lock"))) {
|
|
48437
48418
|
if (scripts.test?.includes("bun"))
|
|
48438
48419
|
return "bun";
|
|
48439
48420
|
}
|
|
48440
48421
|
}
|
|
48441
48422
|
} catch {}
|
|
48442
48423
|
try {
|
|
48443
|
-
const pyprojectTomlPath =
|
|
48444
|
-
const setupCfgPath =
|
|
48445
|
-
const requirementsTxtPath =
|
|
48424
|
+
const pyprojectTomlPath = path38.join(baseDir, "pyproject.toml");
|
|
48425
|
+
const setupCfgPath = path38.join(baseDir, "setup.cfg");
|
|
48426
|
+
const requirementsTxtPath = path38.join(baseDir, "requirements.txt");
|
|
48446
48427
|
if (fs22.existsSync(pyprojectTomlPath)) {
|
|
48447
48428
|
const content = fs22.readFileSync(pyprojectTomlPath, "utf-8");
|
|
48448
48429
|
if (content.includes("[tool.pytest"))
|
|
@@ -48462,7 +48443,7 @@ async function detectTestFramework(cwd) {
|
|
|
48462
48443
|
}
|
|
48463
48444
|
} catch {}
|
|
48464
48445
|
try {
|
|
48465
|
-
const cargoTomlPath =
|
|
48446
|
+
const cargoTomlPath = path38.join(baseDir, "Cargo.toml");
|
|
48466
48447
|
if (fs22.existsSync(cargoTomlPath)) {
|
|
48467
48448
|
const content = fs22.readFileSync(cargoTomlPath, "utf-8");
|
|
48468
48449
|
if (content.includes("[dev-dependencies]")) {
|
|
@@ -48473,9 +48454,9 @@ async function detectTestFramework(cwd) {
|
|
|
48473
48454
|
}
|
|
48474
48455
|
} catch {}
|
|
48475
48456
|
try {
|
|
48476
|
-
const pesterConfigPath =
|
|
48477
|
-
const pesterConfigJsonPath =
|
|
48478
|
-
const pesterPs1Path =
|
|
48457
|
+
const pesterConfigPath = path38.join(baseDir, "pester.config.ps1");
|
|
48458
|
+
const pesterConfigJsonPath = path38.join(baseDir, "pester.config.ps1.json");
|
|
48459
|
+
const pesterPs1Path = path38.join(baseDir, "tests.ps1");
|
|
48479
48460
|
if (fs22.existsSync(pesterConfigPath) || fs22.existsSync(pesterConfigJsonPath) || fs22.existsSync(pesterPs1Path)) {
|
|
48480
48461
|
return "pester";
|
|
48481
48462
|
}
|
|
@@ -48504,12 +48485,12 @@ function isTestDirectoryPath(normalizedPath) {
|
|
|
48504
48485
|
return normalizedPath.split("/").some((segment) => TEST_DIRECTORY_NAMES.includes(segment));
|
|
48505
48486
|
}
|
|
48506
48487
|
function resolveWorkspacePath(file3, workingDir) {
|
|
48507
|
-
return
|
|
48488
|
+
return path38.isAbsolute(file3) ? path38.resolve(file3) : path38.resolve(workingDir, file3);
|
|
48508
48489
|
}
|
|
48509
48490
|
function toWorkspaceOutputPath(absolutePath, workingDir, preferRelative) {
|
|
48510
48491
|
if (!preferRelative)
|
|
48511
48492
|
return absolutePath;
|
|
48512
|
-
return
|
|
48493
|
+
return path38.relative(workingDir, absolutePath);
|
|
48513
48494
|
}
|
|
48514
48495
|
function dedupePush(target, value) {
|
|
48515
48496
|
if (!target.includes(value)) {
|
|
@@ -48546,18 +48527,18 @@ function buildLanguageSpecificTestNames(nameWithoutExt, ext) {
|
|
|
48546
48527
|
}
|
|
48547
48528
|
}
|
|
48548
48529
|
function getRepoLevelCandidateDirectories(workingDir, relativePath, ext) {
|
|
48549
|
-
const relativeDir =
|
|
48530
|
+
const relativeDir = path38.dirname(relativePath);
|
|
48550
48531
|
const nestedRelativeDir = relativeDir === "." ? "" : relativeDir;
|
|
48551
48532
|
const directories = TEST_DIRECTORY_NAMES.flatMap((dirName) => {
|
|
48552
|
-
const rootDir =
|
|
48553
|
-
return nestedRelativeDir ? [rootDir,
|
|
48533
|
+
const rootDir = path38.join(workingDir, dirName);
|
|
48534
|
+
return nestedRelativeDir ? [rootDir, path38.join(rootDir, nestedRelativeDir)] : [rootDir];
|
|
48554
48535
|
});
|
|
48555
48536
|
const normalizedRelativePath = relativePath.replace(/\\/g, "/");
|
|
48556
48537
|
if (ext === ".java" && normalizedRelativePath.startsWith("src/main/java/")) {
|
|
48557
|
-
directories.push(
|
|
48538
|
+
directories.push(path38.join(workingDir, "src/test/java", path38.dirname(normalizedRelativePath.slice("src/main/java/".length))));
|
|
48558
48539
|
}
|
|
48559
48540
|
if ((ext === ".kt" || ext === ".java") && normalizedRelativePath.startsWith("src/main/kotlin/")) {
|
|
48560
|
-
directories.push(
|
|
48541
|
+
directories.push(path38.join(workingDir, "src/test/kotlin", path38.dirname(normalizedRelativePath.slice("src/main/kotlin/".length))));
|
|
48561
48542
|
}
|
|
48562
48543
|
return [...new Set(directories)];
|
|
48563
48544
|
}
|
|
@@ -48585,23 +48566,23 @@ function isLanguageSpecificTestFile(basename6) {
|
|
|
48585
48566
|
}
|
|
48586
48567
|
function isConventionTestFilePath(filePath) {
|
|
48587
48568
|
const normalizedPath = filePath.replace(/\\/g, "/");
|
|
48588
|
-
const basename6 =
|
|
48569
|
+
const basename6 = path38.basename(filePath);
|
|
48589
48570
|
return hasCompoundTestExtension(basename6) || basename6.includes(".spec.") || basename6.includes(".test.") || isLanguageSpecificTestFile(basename6) || isTestDirectoryPath(normalizedPath);
|
|
48590
48571
|
}
|
|
48591
48572
|
function getTestFilesFromConvention(sourceFiles, workingDir = process.cwd()) {
|
|
48592
48573
|
const testFiles = [];
|
|
48593
48574
|
for (const file3 of sourceFiles) {
|
|
48594
48575
|
const absoluteFile = resolveWorkspacePath(file3, workingDir);
|
|
48595
|
-
const relativeFile =
|
|
48596
|
-
const basename6 =
|
|
48597
|
-
const
|
|
48598
|
-
const preferRelativeOutput = !
|
|
48576
|
+
const relativeFile = path38.relative(workingDir, absoluteFile);
|
|
48577
|
+
const basename6 = path38.basename(absoluteFile);
|
|
48578
|
+
const dirname17 = path38.dirname(absoluteFile);
|
|
48579
|
+
const preferRelativeOutput = !path38.isAbsolute(file3);
|
|
48599
48580
|
if (isConventionTestFilePath(relativeFile) || isConventionTestFilePath(file3)) {
|
|
48600
48581
|
dedupePush(testFiles, toWorkspaceOutputPath(absoluteFile, workingDir, preferRelativeOutput));
|
|
48601
48582
|
continue;
|
|
48602
48583
|
}
|
|
48603
48584
|
const nameWithoutExt = basename6.replace(/\.[^.]+$/, "");
|
|
48604
|
-
const ext =
|
|
48585
|
+
const ext = path38.extname(basename6);
|
|
48605
48586
|
const genericTestNames = [
|
|
48606
48587
|
`${nameWithoutExt}.spec${ext}`,
|
|
48607
48588
|
`${nameWithoutExt}.test${ext}`
|
|
@@ -48610,7 +48591,7 @@ function getTestFilesFromConvention(sourceFiles, workingDir = process.cwd()) {
|
|
|
48610
48591
|
const colocatedCandidates = [
|
|
48611
48592
|
...genericTestNames,
|
|
48612
48593
|
...languageSpecificTestNames
|
|
48613
|
-
].map((candidateName) =>
|
|
48594
|
+
].map((candidateName) => path38.join(dirname17, candidateName));
|
|
48614
48595
|
const testDirectoryNames = [
|
|
48615
48596
|
basename6,
|
|
48616
48597
|
...genericTestNames,
|
|
@@ -48619,8 +48600,8 @@ function getTestFilesFromConvention(sourceFiles, workingDir = process.cwd()) {
|
|
|
48619
48600
|
const repoLevelDirectories = getRepoLevelCandidateDirectories(workingDir, relativeFile, ext);
|
|
48620
48601
|
const possibleTestFiles = [
|
|
48621
48602
|
...colocatedCandidates,
|
|
48622
|
-
...TEST_DIRECTORY_NAMES.flatMap((dirName) => testDirectoryNames.map((candidateName) =>
|
|
48623
|
-
...repoLevelDirectories.flatMap((candidateDir) => testDirectoryNames.map((candidateName) =>
|
|
48603
|
+
...TEST_DIRECTORY_NAMES.flatMap((dirName) => testDirectoryNames.map((candidateName) => path38.join(dirname17, dirName, candidateName))),
|
|
48604
|
+
...repoLevelDirectories.flatMap((candidateDir) => testDirectoryNames.map((candidateName) => path38.join(candidateDir, candidateName)))
|
|
48624
48605
|
];
|
|
48625
48606
|
for (const testFile of possibleTestFiles) {
|
|
48626
48607
|
if (fs22.existsSync(testFile)) {
|
|
@@ -48641,7 +48622,7 @@ async function getTestFilesFromGraph(sourceFiles, workingDir) {
|
|
|
48641
48622
|
try {
|
|
48642
48623
|
const absoluteTestFile = resolveWorkspacePath(testFile, workingDir);
|
|
48643
48624
|
const content = fs22.readFileSync(absoluteTestFile, "utf-8");
|
|
48644
|
-
const testDir =
|
|
48625
|
+
const testDir = path38.dirname(absoluteTestFile);
|
|
48645
48626
|
const importRegex = /import\s+.*?\s+from\s+['"]([^'"]+)['"]/g;
|
|
48646
48627
|
let match;
|
|
48647
48628
|
match = importRegex.exec(content);
|
|
@@ -48649,8 +48630,8 @@ async function getTestFilesFromGraph(sourceFiles, workingDir) {
|
|
|
48649
48630
|
const importPath = match[1];
|
|
48650
48631
|
let resolvedImport;
|
|
48651
48632
|
if (importPath.startsWith(".")) {
|
|
48652
|
-
resolvedImport =
|
|
48653
|
-
const existingExt =
|
|
48633
|
+
resolvedImport = path38.resolve(testDir, importPath);
|
|
48634
|
+
const existingExt = path38.extname(resolvedImport);
|
|
48654
48635
|
if (!existingExt) {
|
|
48655
48636
|
for (const extToTry of [
|
|
48656
48637
|
".ts",
|
|
@@ -48670,12 +48651,12 @@ async function getTestFilesFromGraph(sourceFiles, workingDir) {
|
|
|
48670
48651
|
} else {
|
|
48671
48652
|
continue;
|
|
48672
48653
|
}
|
|
48673
|
-
const importBasename =
|
|
48674
|
-
const importDir =
|
|
48654
|
+
const importBasename = path38.basename(resolvedImport, path38.extname(resolvedImport));
|
|
48655
|
+
const importDir = path38.dirname(resolvedImport);
|
|
48675
48656
|
for (const sourceFile of absoluteSourceFiles) {
|
|
48676
|
-
const sourceDir =
|
|
48677
|
-
const sourceBasename =
|
|
48678
|
-
const isRelatedDir = importDir === sourceDir || importDir ===
|
|
48657
|
+
const sourceDir = path38.dirname(sourceFile);
|
|
48658
|
+
const sourceBasename = path38.basename(sourceFile, path38.extname(sourceFile));
|
|
48659
|
+
const isRelatedDir = importDir === sourceDir || importDir === path38.join(sourceDir, "__tests__") || importDir === path38.join(sourceDir, "tests") || importDir === path38.join(sourceDir, "test") || importDir === path38.join(sourceDir, "spec");
|
|
48679
48660
|
if (resolvedImport === sourceFile || importBasename === sourceBasename && isRelatedDir) {
|
|
48680
48661
|
dedupePush(testFiles, testFile);
|
|
48681
48662
|
break;
|
|
@@ -48688,8 +48669,8 @@ async function getTestFilesFromGraph(sourceFiles, workingDir) {
|
|
|
48688
48669
|
while (match !== null) {
|
|
48689
48670
|
const importPath = match[1];
|
|
48690
48671
|
if (importPath.startsWith(".")) {
|
|
48691
|
-
let resolvedImport =
|
|
48692
|
-
const existingExt =
|
|
48672
|
+
let resolvedImport = path38.resolve(testDir, importPath);
|
|
48673
|
+
const existingExt = path38.extname(resolvedImport);
|
|
48693
48674
|
if (!existingExt) {
|
|
48694
48675
|
for (const extToTry of [
|
|
48695
48676
|
".ts",
|
|
@@ -48706,12 +48687,12 @@ async function getTestFilesFromGraph(sourceFiles, workingDir) {
|
|
|
48706
48687
|
}
|
|
48707
48688
|
}
|
|
48708
48689
|
}
|
|
48709
|
-
const importDir =
|
|
48710
|
-
const importBasename =
|
|
48690
|
+
const importDir = path38.dirname(resolvedImport);
|
|
48691
|
+
const importBasename = path38.basename(resolvedImport, path38.extname(resolvedImport));
|
|
48711
48692
|
for (const sourceFile of absoluteSourceFiles) {
|
|
48712
|
-
const sourceDir =
|
|
48713
|
-
const sourceBasename =
|
|
48714
|
-
const isRelatedDir = importDir === sourceDir || importDir ===
|
|
48693
|
+
const sourceDir = path38.dirname(sourceFile);
|
|
48694
|
+
const sourceBasename = path38.basename(sourceFile, path38.extname(sourceFile));
|
|
48695
|
+
const isRelatedDir = importDir === sourceDir || importDir === path38.join(sourceDir, "__tests__") || importDir === path38.join(sourceDir, "tests") || importDir === path38.join(sourceDir, "test") || importDir === path38.join(sourceDir, "spec");
|
|
48715
48696
|
if (resolvedImport === sourceFile || importBasename === sourceBasename && isRelatedDir) {
|
|
48716
48697
|
dedupePush(testFiles, testFile);
|
|
48717
48698
|
break;
|
|
@@ -48821,8 +48802,8 @@ function buildTestCommand2(framework, scope, files, coverage, baseDir) {
|
|
|
48821
48802
|
return ["mvn", "test"];
|
|
48822
48803
|
case "gradle": {
|
|
48823
48804
|
const isWindows = process.platform === "win32";
|
|
48824
|
-
const hasGradlewBat = fs22.existsSync(
|
|
48825
|
-
const hasGradlew = fs22.existsSync(
|
|
48805
|
+
const hasGradlewBat = fs22.existsSync(path38.join(baseDir, "gradlew.bat"));
|
|
48806
|
+
const hasGradlew = fs22.existsSync(path38.join(baseDir, "gradlew"));
|
|
48826
48807
|
if (hasGradlewBat && isWindows)
|
|
48827
48808
|
return ["gradlew.bat", "test"];
|
|
48828
48809
|
if (hasGradlew)
|
|
@@ -48839,7 +48820,7 @@ function buildTestCommand2(framework, scope, files, coverage, baseDir) {
|
|
|
48839
48820
|
"cmake-build-release",
|
|
48840
48821
|
"out"
|
|
48841
48822
|
];
|
|
48842
|
-
const actualBuildDir = buildDirCandidates.find((d) => fs22.existsSync(
|
|
48823
|
+
const actualBuildDir = buildDirCandidates.find((d) => fs22.existsSync(path38.join(baseDir, d, "CMakeCache.txt"))) ?? "build";
|
|
48843
48824
|
return ["ctest", "--test-dir", actualBuildDir];
|
|
48844
48825
|
}
|
|
48845
48826
|
case "swift-test":
|
|
@@ -49271,11 +49252,11 @@ async function runTests(framework, scope, files, coverage, timeout_ms, cwd) {
|
|
|
49271
49252
|
};
|
|
49272
49253
|
}
|
|
49273
49254
|
const startTime = Date.now();
|
|
49274
|
-
const vitestJsonOutputPath = framework === "vitest" ?
|
|
49255
|
+
const vitestJsonOutputPath = framework === "vitest" ? path38.join(cwd, ".swarm", "cache", "test-runner-vitest.json") : undefined;
|
|
49275
49256
|
try {
|
|
49276
49257
|
if (vitestJsonOutputPath) {
|
|
49277
49258
|
try {
|
|
49278
|
-
fs22.mkdirSync(
|
|
49259
|
+
fs22.mkdirSync(path38.dirname(vitestJsonOutputPath), { recursive: true });
|
|
49279
49260
|
if (fs22.existsSync(vitestJsonOutputPath)) {
|
|
49280
49261
|
fs22.unlinkSync(vitestJsonOutputPath);
|
|
49281
49262
|
}
|
|
@@ -49391,10 +49372,10 @@ async function runTests(framework, scope, files, coverage, timeout_ms, cwd) {
|
|
|
49391
49372
|
}
|
|
49392
49373
|
function normalizeHistoryTestFile(testFile, workingDir) {
|
|
49393
49374
|
const normalized = testFile.replace(/\\/g, "/");
|
|
49394
|
-
if (!
|
|
49375
|
+
if (!path38.isAbsolute(testFile))
|
|
49395
49376
|
return normalized;
|
|
49396
|
-
const relative9 =
|
|
49397
|
-
if (relative9.startsWith("..") ||
|
|
49377
|
+
const relative9 = path38.relative(workingDir, testFile);
|
|
49378
|
+
if (relative9.startsWith("..") || path38.isAbsolute(relative9)) {
|
|
49398
49379
|
return normalized;
|
|
49399
49380
|
}
|
|
49400
49381
|
return relative9.replace(/\\/g, "/");
|
|
@@ -49732,7 +49713,7 @@ var init_test_runner = __esm(() => {
|
|
|
49732
49713
|
const sourceFiles = args.files.filter((file3) => {
|
|
49733
49714
|
if (directTestFiles.includes(file3))
|
|
49734
49715
|
return false;
|
|
49735
|
-
const ext =
|
|
49716
|
+
const ext = path38.extname(file3).toLowerCase();
|
|
49736
49717
|
return SOURCE_EXTENSIONS.has(ext);
|
|
49737
49718
|
});
|
|
49738
49719
|
const invalidFiles = args.files.filter((file3) => !directTestFiles.includes(file3) && !sourceFiles.includes(file3));
|
|
@@ -49778,7 +49759,7 @@ var init_test_runner = __esm(() => {
|
|
|
49778
49759
|
if (isConventionTestFilePath(f)) {
|
|
49779
49760
|
return false;
|
|
49780
49761
|
}
|
|
49781
|
-
const ext =
|
|
49762
|
+
const ext = path38.extname(f).toLowerCase();
|
|
49782
49763
|
return SOURCE_EXTENSIONS.has(ext);
|
|
49783
49764
|
});
|
|
49784
49765
|
if (sourceFiles.length === 0) {
|
|
@@ -49828,7 +49809,7 @@ var init_test_runner = __esm(() => {
|
|
|
49828
49809
|
if (isConventionTestFilePath(f)) {
|
|
49829
49810
|
return false;
|
|
49830
49811
|
}
|
|
49831
|
-
const ext =
|
|
49812
|
+
const ext = path38.extname(f).toLowerCase();
|
|
49832
49813
|
return SOURCE_EXTENSIONS.has(ext);
|
|
49833
49814
|
});
|
|
49834
49815
|
if (sourceFiles.length === 0) {
|
|
@@ -49880,8 +49861,8 @@ var init_test_runner = __esm(() => {
|
|
|
49880
49861
|
}
|
|
49881
49862
|
if (impactResult.impactedTests.length > 0) {
|
|
49882
49863
|
testFiles = impactResult.impactedTests.map((absPath) => {
|
|
49883
|
-
const relativePath =
|
|
49884
|
-
return
|
|
49864
|
+
const relativePath = path38.relative(workingDir, absPath);
|
|
49865
|
+
return path38.isAbsolute(relativePath) ? absPath : relativePath;
|
|
49885
49866
|
});
|
|
49886
49867
|
} else {
|
|
49887
49868
|
graphFallbackReason = "no impacted tests found via impact analysis, falling back to graph";
|
|
@@ -49957,7 +49938,7 @@ var init_test_runner = __esm(() => {
|
|
|
49957
49938
|
|
|
49958
49939
|
// src/services/preflight-service.ts
|
|
49959
49940
|
import * as fs23 from "fs";
|
|
49960
|
-
import * as
|
|
49941
|
+
import * as path39 from "path";
|
|
49961
49942
|
function validateDirectoryPath(dir) {
|
|
49962
49943
|
if (!dir || typeof dir !== "string") {
|
|
49963
49944
|
throw new Error("Directory path is required");
|
|
@@ -49965,8 +49946,8 @@ function validateDirectoryPath(dir) {
|
|
|
49965
49946
|
if (dir.includes("..")) {
|
|
49966
49947
|
throw new Error("Directory path must not contain path traversal sequences");
|
|
49967
49948
|
}
|
|
49968
|
-
const normalized =
|
|
49969
|
-
const absolutePath =
|
|
49949
|
+
const normalized = path39.normalize(dir);
|
|
49950
|
+
const absolutePath = path39.isAbsolute(normalized) ? normalized : path39.resolve(normalized);
|
|
49970
49951
|
return absolutePath;
|
|
49971
49952
|
}
|
|
49972
49953
|
function validateTimeout(timeoutMs, defaultValue) {
|
|
@@ -49989,7 +49970,7 @@ function validateTimeout(timeoutMs, defaultValue) {
|
|
|
49989
49970
|
}
|
|
49990
49971
|
function getPackageVersion(dir) {
|
|
49991
49972
|
try {
|
|
49992
|
-
const packagePath =
|
|
49973
|
+
const packagePath = path39.join(dir, "package.json");
|
|
49993
49974
|
if (fs23.existsSync(packagePath)) {
|
|
49994
49975
|
const content = fs23.readFileSync(packagePath, "utf-8");
|
|
49995
49976
|
const pkg = JSON.parse(content);
|
|
@@ -50000,7 +49981,7 @@ function getPackageVersion(dir) {
|
|
|
50000
49981
|
}
|
|
50001
49982
|
function getChangelogVersion(dir) {
|
|
50002
49983
|
try {
|
|
50003
|
-
const changelogPath =
|
|
49984
|
+
const changelogPath = path39.join(dir, "CHANGELOG.md");
|
|
50004
49985
|
if (fs23.existsSync(changelogPath)) {
|
|
50005
49986
|
const content = fs23.readFileSync(changelogPath, "utf-8");
|
|
50006
49987
|
const match = content.match(/^##\s*\[?(\d+\.\d+\.\d+)\]?/m);
|
|
@@ -50014,7 +49995,7 @@ function getChangelogVersion(dir) {
|
|
|
50014
49995
|
function getVersionFileVersion(dir) {
|
|
50015
49996
|
const possibleFiles = ["VERSION.txt", "version.txt", "VERSION", "version"];
|
|
50016
49997
|
for (const file3 of possibleFiles) {
|
|
50017
|
-
const filePath =
|
|
49998
|
+
const filePath = path39.join(dir, file3);
|
|
50018
49999
|
if (fs23.existsSync(filePath)) {
|
|
50019
50000
|
try {
|
|
50020
50001
|
const content = fs23.readFileSync(filePath, "utf-8").trim();
|
|
@@ -50341,7 +50322,7 @@ async function runEvidenceCheck(dir) {
|
|
|
50341
50322
|
async function runRequirementCoverageCheck(dir, currentPhase) {
|
|
50342
50323
|
const startTime = Date.now();
|
|
50343
50324
|
try {
|
|
50344
|
-
const specPath =
|
|
50325
|
+
const specPath = path39.join(dir, ".swarm", "spec.md");
|
|
50345
50326
|
if (!fs23.existsSync(specPath)) {
|
|
50346
50327
|
return {
|
|
50347
50328
|
type: "req_coverage",
|
|
@@ -51458,7 +51439,7 @@ var init_manager3 = __esm(() => {
|
|
|
51458
51439
|
|
|
51459
51440
|
// src/commands/reset.ts
|
|
51460
51441
|
import * as fs24 from "fs";
|
|
51461
|
-
import * as
|
|
51442
|
+
import * as path40 from "path";
|
|
51462
51443
|
async function handleResetCommand(directory, args) {
|
|
51463
51444
|
const hasConfirm = args.includes("--confirm");
|
|
51464
51445
|
if (!hasConfirm) {
|
|
@@ -51498,7 +51479,7 @@ async function handleResetCommand(directory, args) {
|
|
|
51498
51479
|
}
|
|
51499
51480
|
for (const filename of ["SWARM_PLAN.md", "SWARM_PLAN.json"]) {
|
|
51500
51481
|
try {
|
|
51501
|
-
const rootPath =
|
|
51482
|
+
const rootPath = path40.join(directory, filename);
|
|
51502
51483
|
if (fs24.existsSync(rootPath)) {
|
|
51503
51484
|
fs24.unlinkSync(rootPath);
|
|
51504
51485
|
results.push(`- \u2705 Deleted ${filename} (root)`);
|
|
@@ -51538,7 +51519,7 @@ var init_reset = __esm(() => {
|
|
|
51538
51519
|
|
|
51539
51520
|
// src/commands/reset-session.ts
|
|
51540
51521
|
import * as fs25 from "fs";
|
|
51541
|
-
import * as
|
|
51522
|
+
import * as path41 from "path";
|
|
51542
51523
|
async function handleResetSessionCommand(directory, _args) {
|
|
51543
51524
|
const results = [];
|
|
51544
51525
|
try {
|
|
@@ -51553,13 +51534,13 @@ async function handleResetSessionCommand(directory, _args) {
|
|
|
51553
51534
|
results.push("\u274C Failed to delete state.json");
|
|
51554
51535
|
}
|
|
51555
51536
|
try {
|
|
51556
|
-
const sessionDir =
|
|
51537
|
+
const sessionDir = path41.dirname(validateSwarmPath(directory, "session/state.json"));
|
|
51557
51538
|
if (fs25.existsSync(sessionDir)) {
|
|
51558
51539
|
const files = fs25.readdirSync(sessionDir);
|
|
51559
51540
|
const otherFiles = files.filter((f) => f !== "state.json");
|
|
51560
51541
|
let deletedCount = 0;
|
|
51561
51542
|
for (const file3 of otherFiles) {
|
|
51562
|
-
const filePath =
|
|
51543
|
+
const filePath = path41.join(sessionDir, file3);
|
|
51563
51544
|
if (fs25.lstatSync(filePath).isFile()) {
|
|
51564
51545
|
fs25.unlinkSync(filePath);
|
|
51565
51546
|
deletedCount++;
|
|
@@ -51591,7 +51572,7 @@ var init_reset_session = __esm(() => {
|
|
|
51591
51572
|
});
|
|
51592
51573
|
|
|
51593
51574
|
// src/summaries/manager.ts
|
|
51594
|
-
import * as
|
|
51575
|
+
import * as path42 from "path";
|
|
51595
51576
|
function sanitizeSummaryId(id) {
|
|
51596
51577
|
if (!id || id.length === 0) {
|
|
51597
51578
|
throw new Error("Invalid summary ID: empty string");
|
|
@@ -51614,7 +51595,7 @@ function sanitizeSummaryId(id) {
|
|
|
51614
51595
|
}
|
|
51615
51596
|
async function loadFullOutput(directory, id) {
|
|
51616
51597
|
const sanitizedId = sanitizeSummaryId(id);
|
|
51617
|
-
const relativePath =
|
|
51598
|
+
const relativePath = path42.join("summaries", `${sanitizedId}.json`);
|
|
51618
51599
|
validateSwarmPath(directory, relativePath);
|
|
51619
51600
|
const content = await readSwarmFileAsync(directory, relativePath);
|
|
51620
51601
|
if (content === null) {
|
|
@@ -51677,7 +51658,7 @@ var init_retrieve = __esm(() => {
|
|
|
51677
51658
|
|
|
51678
51659
|
// src/commands/rollback.ts
|
|
51679
51660
|
import * as fs26 from "fs";
|
|
51680
|
-
import * as
|
|
51661
|
+
import * as path43 from "path";
|
|
51681
51662
|
async function handleRollbackCommand(directory, args) {
|
|
51682
51663
|
const phaseArg = args[0];
|
|
51683
51664
|
if (!phaseArg) {
|
|
@@ -51742,8 +51723,8 @@ async function handleRollbackCommand(directory, args) {
|
|
|
51742
51723
|
if (EXCLUDE_FILES.has(file3) || file3.startsWith("plan-ledger.archived-")) {
|
|
51743
51724
|
continue;
|
|
51744
51725
|
}
|
|
51745
|
-
const src =
|
|
51746
|
-
const dest =
|
|
51726
|
+
const src = path43.join(checkpointDir, file3);
|
|
51727
|
+
const dest = path43.join(swarmDir, file3);
|
|
51747
51728
|
try {
|
|
51748
51729
|
fs26.cpSync(src, dest, { recursive: true, force: true });
|
|
51749
51730
|
successes.push(file3);
|
|
@@ -51762,12 +51743,12 @@ async function handleRollbackCommand(directory, args) {
|
|
|
51762
51743
|
].join(`
|
|
51763
51744
|
`);
|
|
51764
51745
|
}
|
|
51765
|
-
const existingLedgerPath =
|
|
51746
|
+
const existingLedgerPath = path43.join(swarmDir, "plan-ledger.jsonl");
|
|
51766
51747
|
if (fs26.existsSync(existingLedgerPath)) {
|
|
51767
51748
|
fs26.unlinkSync(existingLedgerPath);
|
|
51768
51749
|
}
|
|
51769
51750
|
try {
|
|
51770
|
-
const planJsonPath =
|
|
51751
|
+
const planJsonPath = path43.join(swarmDir, "plan.json");
|
|
51771
51752
|
if (fs26.existsSync(planJsonPath)) {
|
|
51772
51753
|
const planRaw = fs26.readFileSync(planJsonPath, "utf-8");
|
|
51773
51754
|
const plan = PlanSchema.parse(JSON.parse(planRaw));
|
|
@@ -51858,9 +51839,9 @@ Ensure this is a git repository with commit history.`;
|
|
|
51858
51839
|
`);
|
|
51859
51840
|
try {
|
|
51860
51841
|
const fs27 = await import("fs/promises");
|
|
51861
|
-
const
|
|
51862
|
-
const reportPath =
|
|
51863
|
-
await fs27.mkdir(
|
|
51842
|
+
const path44 = await import("path");
|
|
51843
|
+
const reportPath = path44.join(directory, ".swarm", "simulate-report.md");
|
|
51844
|
+
await fs27.mkdir(path44.dirname(reportPath), { recursive: true });
|
|
51864
51845
|
await fs27.writeFile(reportPath, report, "utf-8");
|
|
51865
51846
|
} catch (err) {
|
|
51866
51847
|
const writeErr = err instanceof Error ? err.message : String(err);
|
|
@@ -51884,12 +51865,12 @@ async function handleSpecifyCommand(_directory, args) {
|
|
|
51884
51865
|
|
|
51885
51866
|
// src/turbo/lean/state.ts
|
|
51886
51867
|
import * as fs27 from "fs";
|
|
51887
|
-
import * as
|
|
51868
|
+
import * as path44 from "path";
|
|
51888
51869
|
function nowISO2() {
|
|
51889
51870
|
return new Date().toISOString();
|
|
51890
51871
|
}
|
|
51891
51872
|
function ensureSwarmDir2(directory) {
|
|
51892
|
-
const swarmDir =
|
|
51873
|
+
const swarmDir = path44.resolve(directory, ".swarm");
|
|
51893
51874
|
if (!fs27.existsSync(swarmDir)) {
|
|
51894
51875
|
fs27.mkdirSync(swarmDir, { recursive: true });
|
|
51895
51876
|
}
|
|
@@ -51933,7 +51914,7 @@ function markStateUnreadable2(directory, reason) {
|
|
|
51933
51914
|
}
|
|
51934
51915
|
function readPersisted2(directory) {
|
|
51935
51916
|
try {
|
|
51936
|
-
const filePath =
|
|
51917
|
+
const filePath = path44.join(directory, ".swarm", STATE_FILE2);
|
|
51937
51918
|
if (!fs27.existsSync(filePath)) {
|
|
51938
51919
|
const seed = emptyPersisted2();
|
|
51939
51920
|
try {
|
|
@@ -51969,7 +51950,7 @@ function writePersisted2(directory, persisted) {
|
|
|
51969
51950
|
let payload;
|
|
51970
51951
|
try {
|
|
51971
51952
|
ensureSwarmDir2(directory);
|
|
51972
|
-
filePath =
|
|
51953
|
+
filePath = path44.join(directory, ".swarm", STATE_FILE2);
|
|
51973
51954
|
tmpPath = `${filePath}.tmp.${Date.now()}`;
|
|
51974
51955
|
persisted.updatedAt = nowISO2();
|
|
51975
51956
|
payload = `${JSON.stringify(persisted, null, 2)}
|
|
@@ -52096,10 +52077,10 @@ var init_context_budget_service = __esm(() => {
|
|
|
52096
52077
|
|
|
52097
52078
|
// src/services/status-service.ts
|
|
52098
52079
|
import * as fsSync2 from "fs";
|
|
52099
|
-
import * as
|
|
52080
|
+
import * as path45 from "path";
|
|
52100
52081
|
function readSpecStalenessSnapshot(directory) {
|
|
52101
52082
|
try {
|
|
52102
|
-
const p =
|
|
52083
|
+
const p = path45.join(directory, ".swarm", "spec-staleness.json");
|
|
52103
52084
|
if (!fsSync2.existsSync(p))
|
|
52104
52085
|
return { stale: false };
|
|
52105
52086
|
const raw = fsSync2.readFileSync(p, "utf-8");
|
|
@@ -52625,7 +52606,7 @@ var init_write_retro2 = __esm(() => {
|
|
|
52625
52606
|
|
|
52626
52607
|
// src/commands/command-dispatch.ts
|
|
52627
52608
|
import fs28 from "fs";
|
|
52628
|
-
import
|
|
52609
|
+
import path46 from "path";
|
|
52629
52610
|
function normalizeSwarmCommandInput(command, argumentText) {
|
|
52630
52611
|
if (command !== "swarm" && !command.startsWith("swarm-")) {
|
|
52631
52612
|
return { isSwarmCommand: false, tokens: [] };
|
|
@@ -52661,9 +52642,9 @@ ${similar.map((cmd) => ` - /swarm ${cmd}`).join(`
|
|
|
52661
52642
|
`);
|
|
52662
52643
|
}
|
|
52663
52644
|
function maybeMarkFirstRun(directory) {
|
|
52664
|
-
const sentinelPath =
|
|
52645
|
+
const sentinelPath = path46.join(directory, ".swarm", ".first-run-complete");
|
|
52665
52646
|
try {
|
|
52666
|
-
const swarmDir =
|
|
52647
|
+
const swarmDir = path46.join(directory, ".swarm");
|
|
52667
52648
|
fs28.mkdirSync(swarmDir, { recursive: true });
|
|
52668
52649
|
fs28.writeFileSync(sentinelPath, `first-run-complete: ${new Date().toISOString()}
|
|
52669
52650
|
`, { flag: "wx" });
|
|
@@ -53345,24 +53326,24 @@ function validateAliases() {
|
|
|
53345
53326
|
}
|
|
53346
53327
|
aliasTargets.get(target).push(name);
|
|
53347
53328
|
const visited = new Set;
|
|
53348
|
-
const
|
|
53329
|
+
const path47 = [];
|
|
53349
53330
|
let current = target;
|
|
53350
53331
|
while (current) {
|
|
53351
53332
|
const currentEntry = COMMAND_REGISTRY[current];
|
|
53352
53333
|
if (!currentEntry)
|
|
53353
53334
|
break;
|
|
53354
53335
|
if (visited.has(current)) {
|
|
53355
|
-
const cycleStart =
|
|
53336
|
+
const cycleStart = path47.indexOf(current);
|
|
53356
53337
|
const fullChain = [
|
|
53357
53338
|
name,
|
|
53358
|
-
...
|
|
53339
|
+
...path47.slice(0, cycleStart > 0 ? cycleStart : path47.length),
|
|
53359
53340
|
current
|
|
53360
53341
|
].join(" \u2192 ");
|
|
53361
53342
|
errors5.push(`Circular alias detected: ${fullChain}`);
|
|
53362
53343
|
break;
|
|
53363
53344
|
}
|
|
53364
53345
|
visited.add(current);
|
|
53365
|
-
|
|
53346
|
+
path47.push(current);
|
|
53366
53347
|
current = currentEntry.aliasOf || "";
|
|
53367
53348
|
}
|
|
53368
53349
|
}
|
|
@@ -53873,53 +53854,53 @@ init_cache_paths();
|
|
|
53873
53854
|
init_constants();
|
|
53874
53855
|
import * as fs29 from "fs";
|
|
53875
53856
|
import * as os7 from "os";
|
|
53876
|
-
import * as
|
|
53857
|
+
import * as path47 from "path";
|
|
53877
53858
|
var { version: version4 } = package_default;
|
|
53878
53859
|
var CONFIG_DIR = getPluginConfigDir();
|
|
53879
|
-
var OPENCODE_CONFIG_PATH =
|
|
53880
|
-
var PLUGIN_CONFIG_PATH =
|
|
53881
|
-
var PROMPTS_DIR =
|
|
53860
|
+
var OPENCODE_CONFIG_PATH = path47.join(CONFIG_DIR, "opencode.json");
|
|
53861
|
+
var PLUGIN_CONFIG_PATH = path47.join(CONFIG_DIR, "opencode-swarm.json");
|
|
53862
|
+
var PROMPTS_DIR = path47.join(CONFIG_DIR, "opencode-swarm");
|
|
53882
53863
|
var OPENCODE_PLUGIN_CACHE_PATHS = getPluginCachePaths();
|
|
53883
53864
|
var OPENCODE_PLUGIN_LOCK_FILE_PATHS = getPluginLockFilePaths();
|
|
53884
53865
|
function isSafeCachePath(p) {
|
|
53885
|
-
const resolved =
|
|
53886
|
-
const home =
|
|
53866
|
+
const resolved = path47.resolve(p);
|
|
53867
|
+
const home = path47.resolve(os7.homedir());
|
|
53887
53868
|
if (resolved === "/" || resolved === home || resolved.length <= home.length) {
|
|
53888
53869
|
return false;
|
|
53889
53870
|
}
|
|
53890
|
-
const segments = resolved.split(
|
|
53871
|
+
const segments = resolved.split(path47.sep).filter((s) => s.length > 0);
|
|
53891
53872
|
if (segments.length < 4) {
|
|
53892
53873
|
return false;
|
|
53893
53874
|
}
|
|
53894
|
-
const leaf =
|
|
53875
|
+
const leaf = path47.basename(resolved);
|
|
53895
53876
|
if (leaf !== "opencode-swarm@latest" && leaf !== "opencode-swarm") {
|
|
53896
53877
|
return false;
|
|
53897
53878
|
}
|
|
53898
|
-
const parent =
|
|
53879
|
+
const parent = path47.basename(path47.dirname(resolved));
|
|
53899
53880
|
if (parent !== "packages" && parent !== "node_modules") {
|
|
53900
53881
|
return false;
|
|
53901
53882
|
}
|
|
53902
|
-
const grandparent =
|
|
53883
|
+
const grandparent = path47.basename(path47.dirname(path47.dirname(resolved)));
|
|
53903
53884
|
if (grandparent !== "opencode") {
|
|
53904
53885
|
return false;
|
|
53905
53886
|
}
|
|
53906
53887
|
return true;
|
|
53907
53888
|
}
|
|
53908
53889
|
function isSafeLockFilePath(p) {
|
|
53909
|
-
const resolved =
|
|
53910
|
-
const home =
|
|
53890
|
+
const resolved = path47.resolve(p);
|
|
53891
|
+
const home = path47.resolve(os7.homedir());
|
|
53911
53892
|
if (resolved === "/" || resolved === home || resolved.length <= home.length) {
|
|
53912
53893
|
return false;
|
|
53913
53894
|
}
|
|
53914
|
-
const segments = resolved.split(
|
|
53895
|
+
const segments = resolved.split(path47.sep).filter((s) => s.length > 0);
|
|
53915
53896
|
if (segments.length < 4) {
|
|
53916
53897
|
return false;
|
|
53917
53898
|
}
|
|
53918
|
-
const leaf =
|
|
53899
|
+
const leaf = path47.basename(resolved);
|
|
53919
53900
|
if (leaf !== "bun.lock" && leaf !== "bun.lockb" && leaf !== "package-lock.json") {
|
|
53920
53901
|
return false;
|
|
53921
53902
|
}
|
|
53922
|
-
const parent =
|
|
53903
|
+
const parent = path47.basename(path47.dirname(resolved));
|
|
53923
53904
|
if (parent !== "opencode") {
|
|
53924
53905
|
return false;
|
|
53925
53906
|
}
|
|
@@ -53945,8 +53926,8 @@ function saveJson(filepath, data) {
|
|
|
53945
53926
|
}
|
|
53946
53927
|
function writeProjectConfigIfMissing(cwd) {
|
|
53947
53928
|
try {
|
|
53948
|
-
const opencodeDir =
|
|
53949
|
-
const projectConfigPath =
|
|
53929
|
+
const opencodeDir = path47.join(cwd, ".opencode");
|
|
53930
|
+
const projectConfigPath = path47.join(opencodeDir, "opencode-swarm.json");
|
|
53950
53931
|
if (fs29.existsSync(projectConfigPath)) {
|
|
53951
53932
|
return;
|
|
53952
53933
|
}
|
|
@@ -53963,7 +53944,7 @@ async function install() {
|
|
|
53963
53944
|
`);
|
|
53964
53945
|
ensureDir(CONFIG_DIR);
|
|
53965
53946
|
ensureDir(PROMPTS_DIR);
|
|
53966
|
-
const LEGACY_CONFIG_PATH =
|
|
53947
|
+
const LEGACY_CONFIG_PATH = path47.join(CONFIG_DIR, "config.json");
|
|
53967
53948
|
let opencodeConfig = loadJson(OPENCODE_CONFIG_PATH);
|
|
53968
53949
|
if (!opencodeConfig) {
|
|
53969
53950
|
const legacyConfig = loadJson(LEGACY_CONFIG_PATH);
|