opencode-swarm 7.5.1 → 7.5.3
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/critic.d.ts +13 -0
- package/dist/background/event-bus.d.ts +8 -0
- package/dist/background/manager.d.ts +9 -0
- package/dist/build/discovery.d.ts +7 -0
- package/dist/cli/index.js +940 -431
- package/dist/commands/registry.d.ts +16 -0
- package/dist/config/index.d.ts +13 -0
- package/dist/config/schema.d.ts +10 -0
- package/dist/db/qa-gate-profile.d.ts +13 -0
- package/dist/evidence/manager.d.ts +14 -0
- package/dist/git/branch.d.ts +19 -0
- package/dist/hooks/curator-drift.d.ts +6 -0
- package/dist/hooks/curator.d.ts +13 -0
- package/dist/hooks/extractors.d.ts +11 -0
- package/dist/hooks/knowledge-curator.d.ts +6 -0
- package/dist/hooks/knowledge-migrator.d.ts +52 -1
- package/dist/hooks/knowledge-reader.d.ts +4 -0
- package/dist/hooks/knowledge-store.d.ts +21 -0
- package/dist/hooks/knowledge-validator.d.ts +6 -0
- package/dist/hooks/utils.d.ts +14 -0
- package/dist/index.js +971 -570
- package/dist/lang/detector.d.ts +4 -0
- package/dist/lang/index.d.ts +3 -2
- package/dist/lang/registry.d.ts +6 -0
- package/dist/mutation/engine.d.ts +5 -0
- package/dist/mutation/equivalence.d.ts +5 -0
- package/dist/mutation/gate.d.ts +8 -0
- package/dist/parallel/file-locks.d.ts +15 -0
- package/dist/plan/checkpoint.d.ts +4 -0
- package/dist/plan/ledger.d.ts +36 -0
- package/dist/plan/manager.d.ts +13 -0
- package/dist/sast/rules/index.d.ts +14 -0
- package/dist/sast/semgrep.d.ts +8 -0
- package/dist/services/evidence-summary-service.d.ts +51 -1
- package/dist/services/handoff-service.d.ts +68 -0
- package/dist/services/preflight-service.d.ts +67 -0
- package/dist/services/run-memory.d.ts +22 -0
- package/dist/session/snapshot-writer.d.ts +9 -0
- package/dist/state.d.ts +26 -0
- package/dist/telemetry.d.ts +12 -0
- package/dist/test-impact/analyzer.d.ts +20 -0
- package/dist/tools/co-change-analyzer.d.ts +12 -0
- package/dist/tools/knowledge-recall.d.ts +7 -0
- package/dist/tools/lint.d.ts +10 -0
- package/dist/tools/quality-budget.d.ts +7 -0
- package/dist/tools/sast-baseline.d.ts +10 -0
- package/dist/tools/sast-scan.d.ts +8 -0
- package/dist/tools/secretscan.d.ts +8 -0
- package/dist/tools/write-retro.d.ts +9 -0
- package/dist/utils/logger.d.ts +12 -0
- package/dist/utils/path-security.d.ts +10 -0
- package/dist/utils/spec-hash.d.ts +8 -0
- package/package.json +2 -2
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.5.
|
|
37
|
+
version: "7.5.3",
|
|
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",
|
|
@@ -43,7 +43,7 @@ var init_package = __esm(() => {
|
|
|
43
43
|
},
|
|
44
44
|
type: "module",
|
|
45
45
|
engines: {
|
|
46
|
-
bun: ">=1.
|
|
46
|
+
bun: ">=1.3.13"
|
|
47
47
|
},
|
|
48
48
|
license: "MIT",
|
|
49
49
|
repository: {
|
|
@@ -104,7 +104,19 @@ var init_package = __esm(() => {
|
|
|
104
104
|
});
|
|
105
105
|
|
|
106
106
|
// src/utils/errors.ts
|
|
107
|
-
var
|
|
107
|
+
var SwarmError;
|
|
108
|
+
var init_errors = __esm(() => {
|
|
109
|
+
SwarmError = class SwarmError extends Error {
|
|
110
|
+
code;
|
|
111
|
+
guidance;
|
|
112
|
+
constructor(message, code, guidance) {
|
|
113
|
+
super(message);
|
|
114
|
+
this.name = "SwarmError";
|
|
115
|
+
this.code = code;
|
|
116
|
+
this.guidance = guidance;
|
|
117
|
+
}
|
|
118
|
+
};
|
|
119
|
+
});
|
|
108
120
|
|
|
109
121
|
// src/utils/logger.ts
|
|
110
122
|
function isDebug() {
|
|
@@ -130,6 +142,7 @@ function warn(message, data) {
|
|
|
130
142
|
console.warn(`[opencode-swarm ${timestamp}] WARN: ${message}`);
|
|
131
143
|
}
|
|
132
144
|
}
|
|
145
|
+
var init_logger = () => {};
|
|
133
146
|
|
|
134
147
|
// src/utils/merge.ts
|
|
135
148
|
function deepMergeInternal(base, override, depth) {
|
|
@@ -169,6 +182,7 @@ function simpleGlobToRegex(pattern, flags = "i") {
|
|
|
169
182
|
// src/utils/index.ts
|
|
170
183
|
var init_utils = __esm(() => {
|
|
171
184
|
init_errors();
|
|
185
|
+
init_logger();
|
|
172
186
|
});
|
|
173
187
|
|
|
174
188
|
// src/utils/bun-compat.ts
|
|
@@ -500,6 +514,32 @@ var init_bun_compat = () => {};
|
|
|
500
514
|
|
|
501
515
|
// src/hooks/utils.ts
|
|
502
516
|
import * as path2 from "path";
|
|
517
|
+
function safeHook(fn) {
|
|
518
|
+
return async (input, output) => {
|
|
519
|
+
try {
|
|
520
|
+
await fn(input, output);
|
|
521
|
+
} catch (_error) {
|
|
522
|
+
const functionName = fn.name || "unknown";
|
|
523
|
+
if (_error instanceof SwarmError) {
|
|
524
|
+
warn(`Hook '${functionName}' failed: ${_error.message}
|
|
525
|
+
\u2192 ${_error.guidance}`);
|
|
526
|
+
} else {
|
|
527
|
+
warn(`Hook function '${functionName}' failed:`, _error);
|
|
528
|
+
}
|
|
529
|
+
}
|
|
530
|
+
};
|
|
531
|
+
}
|
|
532
|
+
function composeHandlers(...fns) {
|
|
533
|
+
if (fns.length === 0) {
|
|
534
|
+
return async () => {};
|
|
535
|
+
}
|
|
536
|
+
return async (input, output) => {
|
|
537
|
+
for (const fn of fns) {
|
|
538
|
+
const safeFn = _internals.safeHook(fn);
|
|
539
|
+
await safeFn(input, output);
|
|
540
|
+
}
|
|
541
|
+
};
|
|
542
|
+
}
|
|
503
543
|
function validateSwarmPath(directory, filename) {
|
|
504
544
|
if (/[\0]/.test(filename)) {
|
|
505
545
|
throw new Error("Invalid filename: contains null bytes");
|
|
@@ -528,7 +568,7 @@ function validateSwarmPath(directory, filename) {
|
|
|
528
568
|
}
|
|
529
569
|
async function readSwarmFileAsync(directory, filename) {
|
|
530
570
|
try {
|
|
531
|
-
const resolvedPath = validateSwarmPath(directory, filename);
|
|
571
|
+
const resolvedPath = _internals.validateSwarmPath(directory, filename);
|
|
532
572
|
const file = bunFile(resolvedPath);
|
|
533
573
|
const content = await file.text();
|
|
534
574
|
return content;
|
|
@@ -536,9 +576,11 @@ async function readSwarmFileAsync(directory, filename) {
|
|
|
536
576
|
return null;
|
|
537
577
|
}
|
|
538
578
|
}
|
|
579
|
+
var _internals;
|
|
539
580
|
var init_utils2 = __esm(() => {
|
|
540
581
|
init_utils();
|
|
541
582
|
init_bun_compat();
|
|
583
|
+
_internals = { safeHook, composeHandlers, validateSwarmPath, readSwarmFileAsync };
|
|
542
584
|
});
|
|
543
585
|
|
|
544
586
|
// node_modules/zod/v4/core/core.js
|
|
@@ -14519,7 +14561,7 @@ async function computeSpecHash(directory) {
|
|
|
14519
14561
|
return hash2;
|
|
14520
14562
|
}
|
|
14521
14563
|
async function isSpecStale(directory, plan) {
|
|
14522
|
-
const currentHash = await computeSpecHash(directory);
|
|
14564
|
+
const currentHash = await _internals2.computeSpecHash(directory);
|
|
14523
14565
|
if (!plan.specHash) {
|
|
14524
14566
|
return { stale: false };
|
|
14525
14567
|
}
|
|
@@ -14539,7 +14581,13 @@ async function isSpecStale(directory, plan) {
|
|
|
14539
14581
|
}
|
|
14540
14582
|
return { stale: false };
|
|
14541
14583
|
}
|
|
14542
|
-
var
|
|
14584
|
+
var _internals2;
|
|
14585
|
+
var init_spec_hash = __esm(() => {
|
|
14586
|
+
_internals2 = {
|
|
14587
|
+
computeSpecHash,
|
|
14588
|
+
isSpecStale
|
|
14589
|
+
};
|
|
14590
|
+
});
|
|
14543
14591
|
|
|
14544
14592
|
// src/plan/ledger.ts
|
|
14545
14593
|
import * as crypto2 from "crypto";
|
|
@@ -15113,7 +15161,7 @@ async function loadPlan(directory) {
|
|
|
15113
15161
|
const inSync = await isPlanMdInSync(directory, validated);
|
|
15114
15162
|
if (!inSync) {
|
|
15115
15163
|
try {
|
|
15116
|
-
await regeneratePlanMarkdown(directory, validated);
|
|
15164
|
+
await _internals3.regeneratePlanMarkdown(directory, validated);
|
|
15117
15165
|
} catch (regenError) {
|
|
15118
15166
|
warn(`Failed to regenerate plan.md: ${regenError instanceof Error ? regenError.message : String(regenError)}. Proceeding with plan.json only.`);
|
|
15119
15167
|
}
|
|
@@ -15246,7 +15294,7 @@ async function loadPlan(directory) {
|
|
|
15246
15294
|
const existingMutex = recoveryMutexes.get(resolvedDir);
|
|
15247
15295
|
if (existingMutex) {
|
|
15248
15296
|
await existingMutex;
|
|
15249
|
-
const postRecoveryPlan = await loadPlanJsonOnly(directory);
|
|
15297
|
+
const postRecoveryPlan = await _internals3.loadPlanJsonOnly(directory);
|
|
15250
15298
|
if (postRecoveryPlan)
|
|
15251
15299
|
return postRecoveryPlan;
|
|
15252
15300
|
}
|
|
@@ -15300,7 +15348,7 @@ async function savePlan(directory, plan, options) {
|
|
|
15300
15348
|
const validated = PlanSchema.parse(plan);
|
|
15301
15349
|
if (options?.preserveCompletedStatuses !== false) {
|
|
15302
15350
|
try {
|
|
15303
|
-
const currentPlan2 = await loadPlanJsonOnly(directory);
|
|
15351
|
+
const currentPlan2 = await _internals3.loadPlanJsonOnly(directory);
|
|
15304
15352
|
if (currentPlan2) {
|
|
15305
15353
|
const completedTaskIds = new Set;
|
|
15306
15354
|
for (const phase of currentPlan2.phases) {
|
|
@@ -15333,7 +15381,7 @@ async function savePlan(directory, plan, options) {
|
|
|
15333
15381
|
phase.status = "pending";
|
|
15334
15382
|
}
|
|
15335
15383
|
}
|
|
15336
|
-
const currentPlan = await loadPlanJsonOnly(directory);
|
|
15384
|
+
const currentPlan = await _internals3.loadPlanJsonOnly(directory);
|
|
15337
15385
|
const planId = `${validated.swarm}-${validated.title}`.replace(/[^a-zA-Z0-9-_]/g, "_");
|
|
15338
15386
|
const planHashForInit = computePlanHash(validated);
|
|
15339
15387
|
if (!await ledgerExists(directory)) {
|
|
@@ -15449,7 +15497,7 @@ async function savePlan(directory, plan, options) {
|
|
|
15449
15497
|
expectedHash: currentHash,
|
|
15450
15498
|
planHashAfter: hashAfter,
|
|
15451
15499
|
verifyValid: async () => {
|
|
15452
|
-
const onDisk = await loadPlanJsonOnly(directory);
|
|
15500
|
+
const onDisk = await _internals3.loadPlanJsonOnly(directory);
|
|
15453
15501
|
if (!onDisk)
|
|
15454
15502
|
return true;
|
|
15455
15503
|
for (const p of onDisk.phases) {
|
|
@@ -15829,7 +15877,7 @@ function migrateLegacyPlan(planContent, swarmId) {
|
|
|
15829
15877
|
};
|
|
15830
15878
|
return plan;
|
|
15831
15879
|
}
|
|
15832
|
-
var PlanConcurrentModificationError, startupLedgerCheckedWorkspaces, recoveryMutexes, CAS_BACKOFF_START_MS = 5, CAS_BACKOFF_CAP_MS = 250, CAS_BACKOFF_JITTER = 0.25, CAS_MAX_RETRIES = 3;
|
|
15880
|
+
var PlanConcurrentModificationError, startupLedgerCheckedWorkspaces, recoveryMutexes, _internals3, CAS_BACKOFF_START_MS = 5, CAS_BACKOFF_CAP_MS = 250, CAS_BACKOFF_JITTER = 0.25, CAS_MAX_RETRIES = 3;
|
|
15833
15881
|
var init_manager = __esm(() => {
|
|
15834
15882
|
init_plan_schema();
|
|
15835
15883
|
init_utils2();
|
|
@@ -15846,6 +15894,11 @@ var init_manager = __esm(() => {
|
|
|
15846
15894
|
};
|
|
15847
15895
|
startupLedgerCheckedWorkspaces = new Set;
|
|
15848
15896
|
recoveryMutexes = new Map;
|
|
15897
|
+
_internals3 = {
|
|
15898
|
+
loadPlan,
|
|
15899
|
+
loadPlanJsonOnly,
|
|
15900
|
+
regeneratePlanMarkdown
|
|
15901
|
+
};
|
|
15849
15902
|
});
|
|
15850
15903
|
|
|
15851
15904
|
// src/commands/acknowledge-spec-drift.ts
|
|
@@ -19360,7 +19413,7 @@ async function loadEvidence(directory, taskId) {
|
|
|
19360
19413
|
return { status: "invalid_schema", errors: ["Invalid JSON"] };
|
|
19361
19414
|
}
|
|
19362
19415
|
if (isFlatRetrospective(parsed)) {
|
|
19363
|
-
const wrappedBundle = wrapFlatRetrospective(parsed, sanitizedTaskId);
|
|
19416
|
+
const wrappedBundle = _internals4.wrapFlatRetrospective(parsed, sanitizedTaskId);
|
|
19364
19417
|
try {
|
|
19365
19418
|
const validated = EvidenceBundleSchema.parse(wrappedBundle);
|
|
19366
19419
|
try {
|
|
@@ -19456,14 +19509,14 @@ async function checkRequirementCoverage(phase, directory) {
|
|
|
19456
19509
|
}
|
|
19457
19510
|
}
|
|
19458
19511
|
async function archiveEvidence(directory, maxAgeDays, maxBundles) {
|
|
19459
|
-
const taskIds = await listEvidenceTaskIds(directory);
|
|
19512
|
+
const taskIds = await _internals4.listEvidenceTaskIds(directory);
|
|
19460
19513
|
const cutoffDate = new Date;
|
|
19461
19514
|
cutoffDate.setDate(cutoffDate.getDate() - maxAgeDays);
|
|
19462
19515
|
const cutoffIso = cutoffDate.toISOString();
|
|
19463
19516
|
const archived = [];
|
|
19464
19517
|
const remainingBundles = [];
|
|
19465
19518
|
for (const taskId of taskIds) {
|
|
19466
|
-
const result = await loadEvidence(directory, taskId);
|
|
19519
|
+
const result = await _internals4.loadEvidence(directory, taskId);
|
|
19467
19520
|
if (result.status !== "found") {
|
|
19468
19521
|
continue;
|
|
19469
19522
|
}
|
|
@@ -19491,7 +19544,7 @@ async function archiveEvidence(directory, maxAgeDays, maxBundles) {
|
|
|
19491
19544
|
}
|
|
19492
19545
|
return archived;
|
|
19493
19546
|
}
|
|
19494
|
-
var VALID_EVIDENCE_TYPES, sanitizeTaskId2, LEGACY_TASK_COMPLEXITY_MAP;
|
|
19547
|
+
var VALID_EVIDENCE_TYPES, sanitizeTaskId2, LEGACY_TASK_COMPLEXITY_MAP, _internals4;
|
|
19495
19548
|
var init_manager2 = __esm(() => {
|
|
19496
19549
|
init_zod();
|
|
19497
19550
|
init_evidence_schema();
|
|
@@ -19521,6 +19574,11 @@ var init_manager2 = __esm(() => {
|
|
|
19521
19574
|
medium: "moderate",
|
|
19522
19575
|
high: "complex"
|
|
19523
19576
|
};
|
|
19577
|
+
_internals4 = {
|
|
19578
|
+
wrapFlatRetrospective,
|
|
19579
|
+
loadEvidence,
|
|
19580
|
+
listEvidenceTaskIds
|
|
19581
|
+
};
|
|
19524
19582
|
});
|
|
19525
19583
|
|
|
19526
19584
|
// src/commands/archive.ts
|
|
@@ -19720,7 +19778,7 @@ function getProfile(directory, planId) {
|
|
|
19720
19778
|
return row ? rowToProfile(row) : null;
|
|
19721
19779
|
}
|
|
19722
19780
|
function getOrCreateProfile(directory, planId, projectType) {
|
|
19723
|
-
const existing = getProfile(directory, planId);
|
|
19781
|
+
const existing = _internals5.getProfile(directory, planId);
|
|
19724
19782
|
if (existing)
|
|
19725
19783
|
return existing;
|
|
19726
19784
|
const db = getProjectDb(directory);
|
|
@@ -19736,14 +19794,14 @@ function getOrCreateProfile(directory, planId, projectType) {
|
|
|
19736
19794
|
throw err;
|
|
19737
19795
|
}
|
|
19738
19796
|
}
|
|
19739
|
-
const after = getProfile(directory, planId);
|
|
19797
|
+
const after = _internals5.getProfile(directory, planId);
|
|
19740
19798
|
if (!after) {
|
|
19741
19799
|
throw new Error(`Failed to create or load QA gate profile for plan_id=${planId}`);
|
|
19742
19800
|
}
|
|
19743
19801
|
return after;
|
|
19744
19802
|
}
|
|
19745
19803
|
function setGates(directory, planId, gates) {
|
|
19746
|
-
const current = getProfile(directory, planId);
|
|
19804
|
+
const current = _internals5.getProfile(directory, planId);
|
|
19747
19805
|
if (!current) {
|
|
19748
19806
|
throw new Error(`No QA gate profile found for plan_id=${planId} \u2014 call getOrCreateProfile first`);
|
|
19749
19807
|
}
|
|
@@ -19767,7 +19825,7 @@ function setGates(directory, planId, gates) {
|
|
|
19767
19825
|
JSON.stringify(merged),
|
|
19768
19826
|
planId
|
|
19769
19827
|
]);
|
|
19770
|
-
const updated = getProfile(directory, planId);
|
|
19828
|
+
const updated = _internals5.getProfile(directory, planId);
|
|
19771
19829
|
if (!updated) {
|
|
19772
19830
|
throw new Error(`Failed to re-read QA gate profile after update for plan_id=${planId}`);
|
|
19773
19831
|
}
|
|
@@ -19789,9 +19847,16 @@ function getEffectiveGates(profile, sessionOverrides) {
|
|
|
19789
19847
|
}
|
|
19790
19848
|
return merged;
|
|
19791
19849
|
}
|
|
19792
|
-
var DEFAULT_QA_GATES;
|
|
19850
|
+
var _internals5, DEFAULT_QA_GATES;
|
|
19793
19851
|
var init_qa_gate_profile = __esm(() => {
|
|
19794
19852
|
init_project_db();
|
|
19853
|
+
_internals5 = {
|
|
19854
|
+
getProfile,
|
|
19855
|
+
getOrCreateProfile,
|
|
19856
|
+
setGates,
|
|
19857
|
+
getEffectiveGates,
|
|
19858
|
+
computeProfileHash
|
|
19859
|
+
};
|
|
19795
19860
|
DEFAULT_QA_GATES = {
|
|
19796
19861
|
reviewer: true,
|
|
19797
19862
|
test_engineer: true,
|
|
@@ -20121,6 +20186,7 @@ var init_config = __esm(() => {
|
|
|
20121
20186
|
init_constants();
|
|
20122
20187
|
init_evidence_schema();
|
|
20123
20188
|
init_loader();
|
|
20189
|
+
init_loader();
|
|
20124
20190
|
init_plan_schema();
|
|
20125
20191
|
init_schema();
|
|
20126
20192
|
init_spec_schema();
|
|
@@ -20245,12 +20311,15 @@ ${RESPONSE_FORMAT}
|
|
|
20245
20311
|
${HARD_RULES}
|
|
20246
20312
|
`;
|
|
20247
20313
|
});
|
|
20314
|
+
|
|
20315
|
+
// src/agents/critic.ts
|
|
20316
|
+
var init_critic = () => {};
|
|
20248
20317
|
// src/agents/curator-agent.ts
|
|
20249
20318
|
var init_curator_agent = () => {};
|
|
20250
20319
|
// src/agents/reviewer.ts
|
|
20251
20320
|
var init_reviewer = () => {};
|
|
20252
20321
|
// src/agents/index.ts
|
|
20253
|
-
var warnedAgents;
|
|
20322
|
+
var warnedAgents, KNOWN_VARIANT_VALUES;
|
|
20254
20323
|
var init_agents2 = __esm(() => {
|
|
20255
20324
|
init_config();
|
|
20256
20325
|
init_constants();
|
|
@@ -20258,13 +20327,23 @@ var init_agents2 = __esm(() => {
|
|
|
20258
20327
|
init_warning_buffer();
|
|
20259
20328
|
init_architect();
|
|
20260
20329
|
init_council_prompts();
|
|
20330
|
+
init_critic();
|
|
20261
20331
|
init_curator_agent();
|
|
20262
20332
|
init_reviewer();
|
|
20263
20333
|
init_architect();
|
|
20264
20334
|
init_council_prompts();
|
|
20335
|
+
init_critic();
|
|
20265
20336
|
init_curator_agent();
|
|
20266
20337
|
init_reviewer();
|
|
20267
20338
|
warnedAgents = new Set;
|
|
20339
|
+
KNOWN_VARIANT_VALUES = new Set([
|
|
20340
|
+
"low",
|
|
20341
|
+
"medium",
|
|
20342
|
+
"high",
|
|
20343
|
+
"max",
|
|
20344
|
+
"xhigh",
|
|
20345
|
+
"thinking"
|
|
20346
|
+
]);
|
|
20268
20347
|
});
|
|
20269
20348
|
// src/scope/scope-persistence.ts
|
|
20270
20349
|
import * as fs5 from "fs";
|
|
@@ -20356,6 +20435,7 @@ function extractCurrentPhaseFromPlan(plan) {
|
|
|
20356
20435
|
const statusText = statusMap[phase.status] || "PENDING";
|
|
20357
20436
|
return `Phase ${phase.id}: ${phase.name} [${statusText}]`;
|
|
20358
20437
|
}
|
|
20438
|
+
var init_extractors = () => {};
|
|
20359
20439
|
|
|
20360
20440
|
// src/hooks/loop-detector.ts
|
|
20361
20441
|
var init_loop_detector = __esm(() => {
|
|
@@ -20385,8 +20465,10 @@ var init_guardrails = __esm(() => {
|
|
|
20385
20465
|
init_telemetry();
|
|
20386
20466
|
init_utils();
|
|
20387
20467
|
init_bun_compat();
|
|
20468
|
+
init_logger();
|
|
20388
20469
|
init_conflict_resolution();
|
|
20389
20470
|
init_delegation_gate();
|
|
20471
|
+
init_extractors();
|
|
20390
20472
|
init_loop_detector();
|
|
20391
20473
|
init_model_limits();
|
|
20392
20474
|
init_normalize_tool_name();
|
|
@@ -20434,6 +20516,7 @@ var init_delegation_gate = __esm(() => {
|
|
|
20434
20516
|
init_schema();
|
|
20435
20517
|
init_state();
|
|
20436
20518
|
init_telemetry();
|
|
20519
|
+
init_logger();
|
|
20437
20520
|
init_guardrails();
|
|
20438
20521
|
init_normalize_tool_name();
|
|
20439
20522
|
init_utils2();
|
|
@@ -34022,6 +34105,19 @@ function getCurrentBranch(cwd) {
|
|
|
34022
34105
|
const output = gitExec2(["rev-parse", "--abbrev-ref", "HEAD"], cwd);
|
|
34023
34106
|
return output.trim();
|
|
34024
34107
|
}
|
|
34108
|
+
function getDefaultBaseBranch(cwd) {
|
|
34109
|
+
try {
|
|
34110
|
+
gitExec2(["rev-parse", "--verify", "origin/main"], cwd);
|
|
34111
|
+
return "origin/main";
|
|
34112
|
+
} catch {
|
|
34113
|
+
try {
|
|
34114
|
+
gitExec2(["rev-parse", "--verify", "origin/master"], cwd);
|
|
34115
|
+
return "origin/master";
|
|
34116
|
+
} catch {
|
|
34117
|
+
return "origin/main";
|
|
34118
|
+
}
|
|
34119
|
+
}
|
|
34120
|
+
}
|
|
34025
34121
|
function hasUncommittedChanges(cwd) {
|
|
34026
34122
|
const status = gitExec2(["status", "--porcelain"], cwd);
|
|
34027
34123
|
return status.trim().length > 0;
|
|
@@ -34057,7 +34153,7 @@ function resetToRemoteBranch(cwd, options) {
|
|
|
34057
34153
|
const prunedBranches = [];
|
|
34058
34154
|
try {
|
|
34059
34155
|
const currentBranch = getCurrentBranch(cwd);
|
|
34060
|
-
const defaultRemoteBranch = detectDefaultRemoteBranch(cwd);
|
|
34156
|
+
const defaultRemoteBranch = _internals6.detectDefaultRemoteBranch(cwd);
|
|
34061
34157
|
if (!defaultRemoteBranch) {
|
|
34062
34158
|
return {
|
|
34063
34159
|
success: false,
|
|
@@ -34236,8 +34332,16 @@ function resetToRemoteBranch(cwd, options) {
|
|
|
34236
34332
|
};
|
|
34237
34333
|
}
|
|
34238
34334
|
}
|
|
34239
|
-
var GIT_TIMEOUT_MS2 = 30000;
|
|
34240
|
-
var init_branch = () => {
|
|
34335
|
+
var GIT_TIMEOUT_MS2 = 30000, _internals6;
|
|
34336
|
+
var init_branch = __esm(() => {
|
|
34337
|
+
init_logger();
|
|
34338
|
+
_internals6 = {
|
|
34339
|
+
gitExec: gitExec2,
|
|
34340
|
+
detectDefaultRemoteBranch,
|
|
34341
|
+
getDefaultBaseBranch,
|
|
34342
|
+
resetToRemoteBranch
|
|
34343
|
+
};
|
|
34344
|
+
});
|
|
34241
34345
|
|
|
34242
34346
|
// src/hooks/knowledge-store.ts
|
|
34243
34347
|
import { existsSync as existsSync7 } from "fs";
|
|
@@ -34407,13 +34511,77 @@ var init_knowledge_store = __esm(() => {
|
|
|
34407
34511
|
});
|
|
34408
34512
|
|
|
34409
34513
|
// src/hooks/knowledge-reader.ts
|
|
34514
|
+
import { existsSync as existsSync8 } from "fs";
|
|
34515
|
+
import { mkdir as mkdir3, readFile as readFile4, writeFile as writeFile4 } from "fs/promises";
|
|
34516
|
+
import * as path11 from "path";
|
|
34517
|
+
async function updateRetrievalOutcome(directory, phaseInfo, phaseSucceeded) {
|
|
34518
|
+
const shownFile = path11.join(directory, ".swarm", ".knowledge-shown.json");
|
|
34519
|
+
try {
|
|
34520
|
+
if (!existsSync8(shownFile)) {
|
|
34521
|
+
return;
|
|
34522
|
+
}
|
|
34523
|
+
const content = await readFile4(shownFile, "utf-8");
|
|
34524
|
+
const shownData = JSON.parse(content);
|
|
34525
|
+
const shownIds = shownData[phaseInfo];
|
|
34526
|
+
if (!shownIds || shownIds.length === 0) {
|
|
34527
|
+
return;
|
|
34528
|
+
}
|
|
34529
|
+
const swarmPath = resolveSwarmKnowledgePath(directory);
|
|
34530
|
+
const entries = await readKnowledge(swarmPath);
|
|
34531
|
+
let updated = false;
|
|
34532
|
+
const foundInSwarm = new Set;
|
|
34533
|
+
for (const entry of entries) {
|
|
34534
|
+
if (shownIds.includes(entry.id)) {
|
|
34535
|
+
entry.retrieval_outcomes.applied_count++;
|
|
34536
|
+
if (phaseSucceeded) {
|
|
34537
|
+
entry.retrieval_outcomes.succeeded_after_count++;
|
|
34538
|
+
} else {
|
|
34539
|
+
entry.retrieval_outcomes.failed_after_count++;
|
|
34540
|
+
}
|
|
34541
|
+
updated = true;
|
|
34542
|
+
foundInSwarm.add(entry.id);
|
|
34543
|
+
}
|
|
34544
|
+
}
|
|
34545
|
+
if (updated) {
|
|
34546
|
+
await rewriteKnowledge(swarmPath, entries);
|
|
34547
|
+
}
|
|
34548
|
+
const remainingIds = shownIds.filter((id) => !foundInSwarm.has(id));
|
|
34549
|
+
if (remainingIds.length === 0) {
|
|
34550
|
+
delete shownData[phaseInfo];
|
|
34551
|
+
await writeFile4(shownFile, JSON.stringify(shownData, null, 2), "utf-8");
|
|
34552
|
+
return;
|
|
34553
|
+
}
|
|
34554
|
+
const hivePath = resolveHiveKnowledgePath();
|
|
34555
|
+
const hiveEntries = await readKnowledge(hivePath);
|
|
34556
|
+
let hiveUpdated = false;
|
|
34557
|
+
for (const entry of hiveEntries) {
|
|
34558
|
+
if (remainingIds.includes(entry.id)) {
|
|
34559
|
+
entry.retrieval_outcomes.applied_count++;
|
|
34560
|
+
if (phaseSucceeded) {
|
|
34561
|
+
entry.retrieval_outcomes.succeeded_after_count++;
|
|
34562
|
+
} else {
|
|
34563
|
+
entry.retrieval_outcomes.failed_after_count++;
|
|
34564
|
+
}
|
|
34565
|
+
hiveUpdated = true;
|
|
34566
|
+
}
|
|
34567
|
+
}
|
|
34568
|
+
if (hiveUpdated) {
|
|
34569
|
+
await rewriteKnowledge(hivePath, hiveEntries);
|
|
34570
|
+
}
|
|
34571
|
+
delete shownData[phaseInfo];
|
|
34572
|
+
await writeFile4(shownFile, JSON.stringify(shownData, null, 2), "utf-8");
|
|
34573
|
+
} catch {
|
|
34574
|
+
warn("[swarm] Knowledge: failed to update retrieval outcomes");
|
|
34575
|
+
}
|
|
34576
|
+
}
|
|
34410
34577
|
var init_knowledge_reader = __esm(() => {
|
|
34578
|
+
init_logger();
|
|
34411
34579
|
init_knowledge_store();
|
|
34412
34580
|
});
|
|
34413
34581
|
|
|
34414
34582
|
// src/hooks/knowledge-validator.ts
|
|
34415
|
-
import { appendFile as appendFile3, mkdir as
|
|
34416
|
-
import * as
|
|
34583
|
+
import { appendFile as appendFile3, mkdir as mkdir4, writeFile as writeFile5 } from "fs/promises";
|
|
34584
|
+
import * as path12 from "path";
|
|
34417
34585
|
function normalizeText(text) {
|
|
34418
34586
|
return text.normalize("NFKC").toLowerCase().replace(/[^\w\s]/g, " ").replace(/\s+/g, " ").trim();
|
|
34419
34587
|
}
|
|
@@ -34567,11 +34735,11 @@ async function quarantineEntry(directory, entryId, reason, reportedBy) {
|
|
|
34567
34735
|
return;
|
|
34568
34736
|
}
|
|
34569
34737
|
const sanitizedReason = reason.slice(0, 500).replace(/[\x00-\x08\x0b-\x0c\x0e-\x1f\x7f\x0d]/g, "");
|
|
34570
|
-
const knowledgePath =
|
|
34571
|
-
const quarantinePath =
|
|
34572
|
-
const rejectedPath =
|
|
34573
|
-
const swarmDir =
|
|
34574
|
-
await
|
|
34738
|
+
const knowledgePath = path12.join(directory, ".swarm", "knowledge.jsonl");
|
|
34739
|
+
const quarantinePath = path12.join(directory, ".swarm", "knowledge-quarantined.jsonl");
|
|
34740
|
+
const rejectedPath = path12.join(directory, ".swarm", "knowledge-rejected.jsonl");
|
|
34741
|
+
const swarmDir = path12.join(directory, ".swarm");
|
|
34742
|
+
await mkdir4(swarmDir, { recursive: true });
|
|
34575
34743
|
let release;
|
|
34576
34744
|
try {
|
|
34577
34745
|
release = await import_proper_lockfile4.default.lock(swarmDir, {
|
|
@@ -34592,7 +34760,7 @@ async function quarantineEntry(directory, entryId, reason, reportedBy) {
|
|
|
34592
34760
|
const jsonlContent = remaining.length > 0 ? `${remaining.map((e) => JSON.stringify(e)).join(`
|
|
34593
34761
|
`)}
|
|
34594
34762
|
` : "";
|
|
34595
|
-
await
|
|
34763
|
+
await writeFile5(knowledgePath, jsonlContent, "utf-8");
|
|
34596
34764
|
await appendFile3(quarantinePath, `${JSON.stringify(quarantined)}
|
|
34597
34765
|
`, "utf-8");
|
|
34598
34766
|
const quarantinedEntries = await readKnowledge(quarantinePath);
|
|
@@ -34601,7 +34769,7 @@ async function quarantineEntry(directory, entryId, reason, reportedBy) {
|
|
|
34601
34769
|
const capContent = trimmed.length > 0 ? `${trimmed.map((e) => JSON.stringify(e)).join(`
|
|
34602
34770
|
`)}
|
|
34603
34771
|
` : "";
|
|
34604
|
-
await
|
|
34772
|
+
await writeFile5(quarantinePath, capContent, "utf-8");
|
|
34605
34773
|
}
|
|
34606
34774
|
const rejectedRecord = {
|
|
34607
34775
|
id: entryId,
|
|
@@ -34627,11 +34795,11 @@ async function restoreEntry(directory, entryId) {
|
|
|
34627
34795
|
warn("[knowledge-validator] restoreEntry: invalid entryId rejected");
|
|
34628
34796
|
return;
|
|
34629
34797
|
}
|
|
34630
|
-
const knowledgePath =
|
|
34631
|
-
const quarantinePath =
|
|
34632
|
-
const rejectedPath =
|
|
34633
|
-
const swarmDir =
|
|
34634
|
-
await
|
|
34798
|
+
const knowledgePath = path12.join(directory, ".swarm", "knowledge.jsonl");
|
|
34799
|
+
const quarantinePath = path12.join(directory, ".swarm", "knowledge-quarantined.jsonl");
|
|
34800
|
+
const rejectedPath = path12.join(directory, ".swarm", "knowledge-rejected.jsonl");
|
|
34801
|
+
const swarmDir = path12.join(directory, ".swarm");
|
|
34802
|
+
await mkdir4(swarmDir, { recursive: true });
|
|
34635
34803
|
let release;
|
|
34636
34804
|
try {
|
|
34637
34805
|
release = await import_proper_lockfile4.default.lock(swarmDir, {
|
|
@@ -34647,7 +34815,7 @@ async function restoreEntry(directory, entryId) {
|
|
|
34647
34815
|
const jsonlContent = remaining.length > 0 ? `${remaining.map((e) => JSON.stringify(e)).join(`
|
|
34648
34816
|
`)}
|
|
34649
34817
|
` : "";
|
|
34650
|
-
await
|
|
34818
|
+
await writeFile5(quarantinePath, jsonlContent, "utf-8");
|
|
34651
34819
|
await appendFile3(knowledgePath, `${JSON.stringify(original)}
|
|
34652
34820
|
`, "utf-8");
|
|
34653
34821
|
const rejectedEntries = await readKnowledge(rejectedPath);
|
|
@@ -34655,7 +34823,7 @@ async function restoreEntry(directory, entryId) {
|
|
|
34655
34823
|
const rejectedContent = filtered.length > 0 ? `${filtered.map((e) => JSON.stringify(e)).join(`
|
|
34656
34824
|
`)}
|
|
34657
34825
|
` : "";
|
|
34658
|
-
await
|
|
34826
|
+
await writeFile5(rejectedPath, rejectedContent, "utf-8");
|
|
34659
34827
|
} finally {
|
|
34660
34828
|
if (release) {
|
|
34661
34829
|
await release();
|
|
@@ -34664,6 +34832,7 @@ async function restoreEntry(directory, entryId) {
|
|
|
34664
34832
|
}
|
|
34665
34833
|
var import_proper_lockfile4, DANGEROUS_COMMAND_PATTERNS, SECURITY_DEGRADING_PATTERNS, INVISIBLE_FORMAT_CHARS, INJECTION_PATTERNS, VALID_CATEGORIES, TECH_REFERENCE_WORDS, ACTION_VERB_WORDS, NEGATION_PAIRS;
|
|
34666
34834
|
var init_knowledge_validator = __esm(() => {
|
|
34835
|
+
init_logger();
|
|
34667
34836
|
init_knowledge_store();
|
|
34668
34837
|
import_proper_lockfile4 = __toESM(require_proper_lockfile(), 1);
|
|
34669
34838
|
DANGEROUS_COMMAND_PATTERNS = [
|
|
@@ -34770,6 +34939,134 @@ var init_knowledge_validator = __esm(() => {
|
|
|
34770
34939
|
});
|
|
34771
34940
|
|
|
34772
34941
|
// src/hooks/knowledge-curator.ts
|
|
34942
|
+
function pruneSeenRetroSections() {
|
|
34943
|
+
const cutoff = Date.now() - 86400000;
|
|
34944
|
+
for (const [key, entry] of seenRetroSections) {
|
|
34945
|
+
if (entry.timestamp < cutoff) {
|
|
34946
|
+
seenRetroSections.delete(key);
|
|
34947
|
+
}
|
|
34948
|
+
}
|
|
34949
|
+
}
|
|
34950
|
+
function isWriteToSwarmPlan(input) {
|
|
34951
|
+
if (typeof input !== "object" || input === null)
|
|
34952
|
+
return false;
|
|
34953
|
+
const record3 = input;
|
|
34954
|
+
const toolName = record3.toolName;
|
|
34955
|
+
if (typeof toolName !== "string")
|
|
34956
|
+
return false;
|
|
34957
|
+
if (!["write", "edit", "apply_patch"].includes(toolName))
|
|
34958
|
+
return false;
|
|
34959
|
+
const rawPath = record3.path;
|
|
34960
|
+
const rawFile = record3.file;
|
|
34961
|
+
const pathField = typeof rawPath === "string" ? rawPath.replace(/\\/g, "/") : undefined;
|
|
34962
|
+
const fileField = typeof rawFile === "string" ? rawFile.replace(/\\/g, "/") : undefined;
|
|
34963
|
+
if (typeof pathField === "string" && pathField.includes(".swarm/plan.md")) {
|
|
34964
|
+
return true;
|
|
34965
|
+
}
|
|
34966
|
+
if (typeof fileField === "string" && fileField.includes(".swarm/plan.md")) {
|
|
34967
|
+
return true;
|
|
34968
|
+
}
|
|
34969
|
+
return false;
|
|
34970
|
+
}
|
|
34971
|
+
function isWriteToEvidenceFile(input) {
|
|
34972
|
+
if (typeof input !== "object" || input === null)
|
|
34973
|
+
return false;
|
|
34974
|
+
const record3 = input;
|
|
34975
|
+
const toolName = record3.toolName;
|
|
34976
|
+
if (typeof toolName !== "string")
|
|
34977
|
+
return false;
|
|
34978
|
+
if (!["write", "edit", "apply_patch"].includes(toolName))
|
|
34979
|
+
return false;
|
|
34980
|
+
const rawPath = record3.path;
|
|
34981
|
+
const rawFile = record3.file;
|
|
34982
|
+
const pathField = typeof rawPath === "string" ? rawPath.replace(/\\/g, "/") : undefined;
|
|
34983
|
+
const fileField = typeof rawFile === "string" ? rawFile.replace(/\\/g, "/") : undefined;
|
|
34984
|
+
const evidenceRegex = /\.swarm\/+evidence\/+/i;
|
|
34985
|
+
if (typeof pathField === "string" && evidenceRegex.test(pathField)) {
|
|
34986
|
+
return true;
|
|
34987
|
+
}
|
|
34988
|
+
if (typeof fileField === "string" && evidenceRegex.test(fileField)) {
|
|
34989
|
+
return true;
|
|
34990
|
+
}
|
|
34991
|
+
return false;
|
|
34992
|
+
}
|
|
34993
|
+
function extractRetrospectiveSection(planContent) {
|
|
34994
|
+
const headingRegex = /^###\s+Lessons\s+Learned$/m;
|
|
34995
|
+
const match = headingRegex.exec(planContent);
|
|
34996
|
+
if (!match)
|
|
34997
|
+
return null;
|
|
34998
|
+
const startIndex = match.index;
|
|
34999
|
+
const restOfContent = planContent.slice(startIndex);
|
|
35000
|
+
const firstNewline = restOfContent.indexOf(`
|
|
35001
|
+
`);
|
|
35002
|
+
const contentAfterHeading = firstNewline === -1 ? "" : restOfContent.slice(firstNewline + 1);
|
|
35003
|
+
const nextHeadingRegex = /^#{1,2}\s+/m;
|
|
35004
|
+
const nextMatch = nextHeadingRegex.exec(contentAfterHeading);
|
|
35005
|
+
let endIndex;
|
|
35006
|
+
if (nextMatch) {
|
|
35007
|
+
endIndex = startIndex + firstNewline + 1 + nextMatch.index;
|
|
35008
|
+
} else {
|
|
35009
|
+
endIndex = planContent.length;
|
|
35010
|
+
}
|
|
35011
|
+
return planContent.slice(startIndex, endIndex).trim();
|
|
35012
|
+
}
|
|
35013
|
+
function checkRetroChanged(sessionID, section) {
|
|
35014
|
+
const hash3 = `${section.length}:${section.slice(0, 100)}`;
|
|
35015
|
+
const lastSeen = seenRetroSections.get(sessionID);
|
|
35016
|
+
if (lastSeen?.value === hash3) {
|
|
35017
|
+
return false;
|
|
35018
|
+
}
|
|
35019
|
+
seenRetroSections.set(sessionID, { value: hash3, timestamp: Date.now() });
|
|
35020
|
+
return true;
|
|
35021
|
+
}
|
|
35022
|
+
function extractLessonsFromRetro(section) {
|
|
35023
|
+
const lessons = [];
|
|
35024
|
+
const lines = section.split(`
|
|
35025
|
+
`);
|
|
35026
|
+
for (const line of lines) {
|
|
35027
|
+
const trimmed = line.trim();
|
|
35028
|
+
const bulletMatch = /^[-*]\s+(.+)$/.exec(trimmed);
|
|
35029
|
+
if (bulletMatch) {
|
|
35030
|
+
const content = bulletMatch[1].trim();
|
|
35031
|
+
if (content) {
|
|
35032
|
+
lessons.push(content);
|
|
35033
|
+
}
|
|
35034
|
+
}
|
|
35035
|
+
}
|
|
35036
|
+
return lessons;
|
|
35037
|
+
}
|
|
35038
|
+
function extractRetractionsAndLessons(allLessons) {
|
|
35039
|
+
const retractions = [];
|
|
35040
|
+
const normalLessons = [];
|
|
35041
|
+
for (const lesson of allLessons) {
|
|
35042
|
+
const upper = lesson.trimStart().toUpperCase();
|
|
35043
|
+
if (upper.startsWith("RETRACT:") || upper.startsWith("BAD RULE:")) {
|
|
35044
|
+
const colonIdx = lesson.indexOf(":");
|
|
35045
|
+
const text = colonIdx !== -1 ? lesson.slice(colonIdx + 1).trim() : "";
|
|
35046
|
+
if (text)
|
|
35047
|
+
retractions.push(text);
|
|
35048
|
+
} else {
|
|
35049
|
+
normalLessons.push(lesson);
|
|
35050
|
+
}
|
|
35051
|
+
}
|
|
35052
|
+
return { retractions, normalLessons };
|
|
35053
|
+
}
|
|
35054
|
+
async function processRetractions(retractions, directory) {
|
|
35055
|
+
if (retractions.length === 0)
|
|
35056
|
+
return;
|
|
35057
|
+
const knowledgePath = resolveSwarmKnowledgePath(directory);
|
|
35058
|
+
const entries = await readKnowledge(knowledgePath) ?? [];
|
|
35059
|
+
for (const retractionText of retractions) {
|
|
35060
|
+
const normalizedRetraction = normalize2(retractionText);
|
|
35061
|
+
for (const entry of entries) {
|
|
35062
|
+
const normalizedLesson = normalize2(entry.lesson);
|
|
35063
|
+
if (normalizedLesson === normalizedRetraction) {
|
|
35064
|
+
await quarantineEntry(directory, entry.id, `Retracted by architect: ${retractionText}`, "architect");
|
|
35065
|
+
console.info(`[knowledge-curator] Quarantined entry ${entry.id}: "${entry.lesson}"`);
|
|
35066
|
+
}
|
|
35067
|
+
}
|
|
35068
|
+
}
|
|
35069
|
+
}
|
|
34773
35070
|
async function curateAndStoreSwarm(lessons, projectName, phaseInfo, directory, config3) {
|
|
34774
35071
|
const knowledgePath = resolveSwarmKnowledgePath(directory);
|
|
34775
35072
|
const existingEntries = await readKnowledge(knowledgePath) ?? [];
|
|
@@ -34852,7 +35149,7 @@ async function curateAndStoreSwarm(lessons, projectName, phaseInfo, directory, c
|
|
|
34852
35149
|
existingEntries.push(entry);
|
|
34853
35150
|
}
|
|
34854
35151
|
await enforceKnowledgeCap(knowledgePath, config3.swarm_max_entries);
|
|
34855
|
-
await runAutoPromotion(directory, config3);
|
|
35152
|
+
await _internals7.runAutoPromotion(directory, config3);
|
|
34856
35153
|
return { stored, skipped, rejected };
|
|
34857
35154
|
}
|
|
34858
35155
|
async function runAutoPromotion(directory, config3) {
|
|
@@ -34885,18 +35182,100 @@ async function runAutoPromotion(directory, config3) {
|
|
|
34885
35182
|
await rewriteKnowledge(knowledgePath, entries);
|
|
34886
35183
|
}
|
|
34887
35184
|
}
|
|
34888
|
-
|
|
35185
|
+
function createKnowledgeCuratorHook(directory, config3) {
|
|
35186
|
+
const handler = async (input, _output) => {
|
|
35187
|
+
pruneSeenRetroSections();
|
|
35188
|
+
if (!config3.enabled)
|
|
35189
|
+
return;
|
|
35190
|
+
if (!isWriteToSwarmPlan(input) && !isWriteToEvidenceFile(input))
|
|
35191
|
+
return;
|
|
35192
|
+
const sessionID = input?.sessionID ?? "default";
|
|
35193
|
+
const isEvidenceTrigger = isWriteToEvidenceFile(input) && !isWriteToSwarmPlan(input);
|
|
35194
|
+
if (isEvidenceTrigger) {
|
|
35195
|
+
const record3 = input;
|
|
35196
|
+
const rawPath = record3.path;
|
|
35197
|
+
const rawFile = record3.file;
|
|
35198
|
+
const filePath = typeof rawPath === "string" ? rawPath.replace(/\\/g, "/") : typeof rawFile === "string" ? rawFile.replace(/\\/g, "/") : null;
|
|
35199
|
+
if (!filePath)
|
|
35200
|
+
return;
|
|
35201
|
+
const evidenceKey = `evidence:${sessionID}:${filePath}`;
|
|
35202
|
+
const lastSeenEvidence = seenRetroSections.get(evidenceKey);
|
|
35203
|
+
const evidenceContent = await readSwarmFileAsync(directory, filePath.replace(/^.*\.swarm\//, ""));
|
|
35204
|
+
if (!evidenceContent)
|
|
35205
|
+
return;
|
|
35206
|
+
let evidenceData;
|
|
35207
|
+
try {
|
|
35208
|
+
evidenceData = JSON.parse(evidenceContent);
|
|
35209
|
+
} catch {
|
|
35210
|
+
return;
|
|
35211
|
+
}
|
|
35212
|
+
let lessons = [];
|
|
35213
|
+
if (Array.isArray(evidenceData.entries) && evidenceData.entries.length > 0) {
|
|
35214
|
+
const firstEntry = evidenceData.entries[0];
|
|
35215
|
+
if (Array.isArray(firstEntry.lessons_learned)) {
|
|
35216
|
+
lessons = firstEntry.lessons_learned;
|
|
35217
|
+
}
|
|
35218
|
+
} else if (Array.isArray(evidenceData.lessons_learned)) {
|
|
35219
|
+
lessons = evidenceData.lessons_learned;
|
|
35220
|
+
}
|
|
35221
|
+
if (lessons.length === 0)
|
|
35222
|
+
return;
|
|
35223
|
+
const evidenceHash = `${lessons.length}:${lessons.slice(0, 3).join("|")}`;
|
|
35224
|
+
if (lastSeenEvidence?.value === evidenceHash) {
|
|
35225
|
+
return;
|
|
35226
|
+
}
|
|
35227
|
+
seenRetroSections.set(evidenceKey, {
|
|
35228
|
+
value: evidenceHash,
|
|
35229
|
+
timestamp: Date.now()
|
|
35230
|
+
});
|
|
35231
|
+
const projectName2 = evidenceData.project_name ?? "unknown";
|
|
35232
|
+
const phaseNumber2 = typeof evidenceData.phase_number === "number" ? evidenceData.phase_number : 1;
|
|
35233
|
+
await _internals7.curateAndStoreSwarm(lessons, projectName2, { phase_number: phaseNumber2 }, directory, config3);
|
|
35234
|
+
await updateRetrievalOutcome(directory, `Phase ${phaseNumber2}`, true);
|
|
35235
|
+
return;
|
|
35236
|
+
}
|
|
35237
|
+
const planContent = await readSwarmFileAsync(directory, "plan.md");
|
|
35238
|
+
if (!planContent)
|
|
35239
|
+
return;
|
|
35240
|
+
const section = extractRetrospectiveSection(planContent);
|
|
35241
|
+
if (!section)
|
|
35242
|
+
return;
|
|
35243
|
+
if (!checkRetroChanged(sessionID, section))
|
|
35244
|
+
return;
|
|
35245
|
+
const allLessons = extractLessonsFromRetro(section);
|
|
35246
|
+
if (allLessons.length === 0)
|
|
35247
|
+
return;
|
|
35248
|
+
const { retractions, normalLessons } = extractRetractionsAndLessons(allLessons);
|
|
35249
|
+
await processRetractions(retractions, directory);
|
|
35250
|
+
if (normalLessons.length === 0)
|
|
35251
|
+
return;
|
|
35252
|
+
const projectNameMatch = /^#\s+(.+)$/m.exec(planContent);
|
|
35253
|
+
const projectName = projectNameMatch ? projectNameMatch[1].trim() : "unknown";
|
|
35254
|
+
const phaseMatch = /^Phase:\s*(\d+)/m.exec(planContent);
|
|
35255
|
+
const phaseNumber = phaseMatch ? parseInt(phaseMatch[1], 10) : 1;
|
|
35256
|
+
await _internals7.curateAndStoreSwarm(normalLessons, projectName, { phase_number: phaseNumber }, directory, config3);
|
|
35257
|
+
await updateRetrievalOutcome(directory, `Phase ${phaseNumber}`, true);
|
|
35258
|
+
};
|
|
35259
|
+
return safeHook(handler);
|
|
35260
|
+
}
|
|
35261
|
+
var seenRetroSections, _internals7;
|
|
34889
35262
|
var init_knowledge_curator = __esm(() => {
|
|
34890
35263
|
init_knowledge_reader();
|
|
34891
35264
|
init_knowledge_store();
|
|
34892
35265
|
init_knowledge_validator();
|
|
34893
35266
|
init_utils2();
|
|
34894
35267
|
seenRetroSections = new Map;
|
|
35268
|
+
_internals7 = {
|
|
35269
|
+
isWriteToEvidenceFile,
|
|
35270
|
+
curateAndStoreSwarm,
|
|
35271
|
+
runAutoPromotion,
|
|
35272
|
+
createKnowledgeCuratorHook
|
|
35273
|
+
};
|
|
34895
35274
|
});
|
|
34896
35275
|
|
|
34897
35276
|
// src/session/snapshot-writer.ts
|
|
34898
35277
|
import { mkdirSync as mkdirSync7, renameSync as renameSync5 } from "fs";
|
|
34899
|
-
import * as
|
|
35278
|
+
import * as path13 from "path";
|
|
34900
35279
|
function serializeAgentSession(s) {
|
|
34901
35280
|
const gateLog = {};
|
|
34902
35281
|
const rawGateLog = s.gateLog ?? new Map;
|
|
@@ -34986,7 +35365,7 @@ async function writeSnapshot(directory, state) {
|
|
|
34986
35365
|
}
|
|
34987
35366
|
const content = JSON.stringify(snapshot, null, 2);
|
|
34988
35367
|
const resolvedPath = validateSwarmPath(directory, "session/state.json");
|
|
34989
|
-
const dir =
|
|
35368
|
+
const dir = path13.dirname(resolvedPath);
|
|
34990
35369
|
mkdirSync7(dir, { recursive: true });
|
|
34991
35370
|
const tempPath = `${resolvedPath}.tmp.${Date.now()}.${Math.random().toString(36).slice(2)}`;
|
|
34992
35371
|
await bunWrite(tempPath, content);
|
|
@@ -34997,17 +35376,28 @@ async function writeSnapshot(directory, state) {
|
|
|
34997
35376
|
});
|
|
34998
35377
|
}
|
|
34999
35378
|
}
|
|
35379
|
+
function createSnapshotWriterHook(directory) {
|
|
35380
|
+
return (_input, _output) => {
|
|
35381
|
+
_writeInFlight = _writeInFlight.then(() => _internals8.writeSnapshot(directory, swarmState), () => _internals8.writeSnapshot(directory, swarmState));
|
|
35382
|
+
return _writeInFlight;
|
|
35383
|
+
};
|
|
35384
|
+
}
|
|
35000
35385
|
async function flushPendingSnapshot(directory) {
|
|
35001
|
-
_writeInFlight = _writeInFlight.then(() => writeSnapshot(directory, swarmState), () => writeSnapshot(directory, swarmState));
|
|
35386
|
+
_writeInFlight = _writeInFlight.then(() => _internals8.writeSnapshot(directory, swarmState), () => _internals8.writeSnapshot(directory, swarmState));
|
|
35002
35387
|
await _writeInFlight;
|
|
35003
35388
|
}
|
|
35004
|
-
var _writeInFlight;
|
|
35389
|
+
var _writeInFlight, _internals8;
|
|
35005
35390
|
var init_snapshot_writer = __esm(() => {
|
|
35006
35391
|
init_utils2();
|
|
35007
35392
|
init_state();
|
|
35008
35393
|
init_utils();
|
|
35009
35394
|
init_bun_compat();
|
|
35010
35395
|
_writeInFlight = Promise.resolve();
|
|
35396
|
+
_internals8 = {
|
|
35397
|
+
writeSnapshot,
|
|
35398
|
+
createSnapshotWriterHook,
|
|
35399
|
+
flushPendingSnapshot
|
|
35400
|
+
};
|
|
35011
35401
|
});
|
|
35012
35402
|
|
|
35013
35403
|
// src/tools/write-retro.ts
|
|
@@ -35311,7 +35701,7 @@ async function executeWriteRetro(args, directory) {
|
|
|
35311
35701
|
}, null, 2);
|
|
35312
35702
|
}
|
|
35313
35703
|
}
|
|
35314
|
-
var write_retro;
|
|
35704
|
+
var write_retro, _internals9;
|
|
35315
35705
|
var init_write_retro = __esm(() => {
|
|
35316
35706
|
init_zod();
|
|
35317
35707
|
init_evidence_schema();
|
|
@@ -35358,17 +35748,21 @@ var init_write_retro = __esm(() => {
|
|
|
35358
35748
|
task_id: args.task_id !== undefined ? String(args.task_id) : undefined,
|
|
35359
35749
|
metadata: args.metadata
|
|
35360
35750
|
};
|
|
35361
|
-
return await executeWriteRetro(writeRetroArgs, directory);
|
|
35751
|
+
return await _internals9.executeWriteRetro(writeRetroArgs, directory);
|
|
35362
35752
|
} catch {
|
|
35363
35753
|
return JSON.stringify({ success: false, phase: rawPhase, message: "Invalid arguments" }, null, 2);
|
|
35364
35754
|
}
|
|
35365
35755
|
}
|
|
35366
35756
|
});
|
|
35757
|
+
_internals9 = {
|
|
35758
|
+
executeWriteRetro,
|
|
35759
|
+
write_retro
|
|
35760
|
+
};
|
|
35367
35761
|
});
|
|
35368
35762
|
|
|
35369
35763
|
// src/commands/close.ts
|
|
35370
35764
|
import { promises as fs7 } from "fs";
|
|
35371
|
-
import
|
|
35765
|
+
import path14 from "path";
|
|
35372
35766
|
function guaranteeAllPlansComplete(planData) {
|
|
35373
35767
|
const closedPhaseIds = [];
|
|
35374
35768
|
const closedTaskIds = [];
|
|
@@ -35391,10 +35785,10 @@ function guaranteeAllPlansComplete(planData) {
|
|
|
35391
35785
|
}
|
|
35392
35786
|
async function handleCloseCommand(directory, args) {
|
|
35393
35787
|
const planPath = validateSwarmPath(directory, "plan.json");
|
|
35394
|
-
const swarmDir =
|
|
35788
|
+
const swarmDir = path14.join(directory, ".swarm");
|
|
35395
35789
|
let planExists = false;
|
|
35396
35790
|
let planData = {
|
|
35397
|
-
title:
|
|
35791
|
+
title: path14.basename(directory) || "Ad-hoc session",
|
|
35398
35792
|
phases: []
|
|
35399
35793
|
};
|
|
35400
35794
|
try {
|
|
@@ -35499,7 +35893,7 @@ async function handleCloseCommand(directory, args) {
|
|
|
35499
35893
|
warnings.push(`Session retrospective write threw: ${retroError instanceof Error ? retroError.message : String(retroError)}`);
|
|
35500
35894
|
}
|
|
35501
35895
|
}
|
|
35502
|
-
const lessonsFilePath =
|
|
35896
|
+
const lessonsFilePath = path14.join(swarmDir, "close-lessons.md");
|
|
35503
35897
|
let explicitLessons = [];
|
|
35504
35898
|
try {
|
|
35505
35899
|
const lessonsText = await fs7.readFile(lessonsFilePath, "utf-8");
|
|
@@ -35508,11 +35902,11 @@ async function handleCloseCommand(directory, args) {
|
|
|
35508
35902
|
} catch {}
|
|
35509
35903
|
const retroLessons = [];
|
|
35510
35904
|
try {
|
|
35511
|
-
const evidenceDir =
|
|
35905
|
+
const evidenceDir = path14.join(swarmDir, "evidence");
|
|
35512
35906
|
const evidenceEntries = await fs7.readdir(evidenceDir);
|
|
35513
35907
|
const retroDirs = evidenceEntries.filter((e) => e.startsWith("retro-")).sort((a, b) => a.localeCompare(b, undefined, { numeric: true }));
|
|
35514
35908
|
for (const retroDir of retroDirs) {
|
|
35515
|
-
const evidencePath =
|
|
35909
|
+
const evidencePath = path14.join(evidenceDir, retroDir, "evidence.json");
|
|
35516
35910
|
try {
|
|
35517
35911
|
const content = await fs7.readFile(evidencePath, "utf-8");
|
|
35518
35912
|
const parsed = JSON.parse(content);
|
|
@@ -35566,15 +35960,15 @@ async function handleCloseCommand(directory, args) {
|
|
|
35566
35960
|
}
|
|
35567
35961
|
const timestamp = new Date().toISOString().replace(/[:.]/g, "-");
|
|
35568
35962
|
const suffix = Math.random().toString(36).slice(2, 8);
|
|
35569
|
-
const archiveDir =
|
|
35963
|
+
const archiveDir = path14.join(swarmDir, "archive", `swarm-${timestamp}-${suffix}`);
|
|
35570
35964
|
let archiveResult = "";
|
|
35571
35965
|
let archivedFileCount = 0;
|
|
35572
35966
|
const archivedActiveStateFiles = new Set;
|
|
35573
35967
|
try {
|
|
35574
35968
|
await fs7.mkdir(archiveDir, { recursive: true });
|
|
35575
35969
|
for (const artifact of ARCHIVE_ARTIFACTS) {
|
|
35576
|
-
const srcPath =
|
|
35577
|
-
const destPath =
|
|
35970
|
+
const srcPath = path14.join(swarmDir, artifact);
|
|
35971
|
+
const destPath = path14.join(archiveDir, artifact);
|
|
35578
35972
|
try {
|
|
35579
35973
|
await fs7.copyFile(srcPath, destPath);
|
|
35580
35974
|
archivedFileCount++;
|
|
@@ -35583,22 +35977,22 @@ async function handleCloseCommand(directory, args) {
|
|
|
35583
35977
|
}
|
|
35584
35978
|
} catch {}
|
|
35585
35979
|
}
|
|
35586
|
-
const evidenceDir =
|
|
35587
|
-
const archiveEvidenceDir =
|
|
35980
|
+
const evidenceDir = path14.join(swarmDir, "evidence");
|
|
35981
|
+
const archiveEvidenceDir = path14.join(archiveDir, "evidence");
|
|
35588
35982
|
try {
|
|
35589
35983
|
const evidenceEntries = await fs7.readdir(evidenceDir);
|
|
35590
35984
|
if (evidenceEntries.length > 0) {
|
|
35591
35985
|
await fs7.mkdir(archiveEvidenceDir, { recursive: true });
|
|
35592
35986
|
for (const entry of evidenceEntries) {
|
|
35593
|
-
const srcEntry =
|
|
35594
|
-
const destEntry =
|
|
35987
|
+
const srcEntry = path14.join(evidenceDir, entry);
|
|
35988
|
+
const destEntry = path14.join(archiveEvidenceDir, entry);
|
|
35595
35989
|
try {
|
|
35596
35990
|
const stat2 = await fs7.stat(srcEntry);
|
|
35597
35991
|
if (stat2.isDirectory()) {
|
|
35598
35992
|
await fs7.mkdir(destEntry, { recursive: true });
|
|
35599
35993
|
const subEntries = await fs7.readdir(srcEntry);
|
|
35600
35994
|
for (const sub of subEntries) {
|
|
35601
|
-
await fs7.copyFile(
|
|
35995
|
+
await fs7.copyFile(path14.join(srcEntry, sub), path14.join(destEntry, sub)).catch(() => {});
|
|
35602
35996
|
}
|
|
35603
35997
|
} else {
|
|
35604
35998
|
await fs7.copyFile(srcEntry, destEntry);
|
|
@@ -35608,11 +36002,11 @@ async function handleCloseCommand(directory, args) {
|
|
|
35608
36002
|
}
|
|
35609
36003
|
}
|
|
35610
36004
|
} catch {}
|
|
35611
|
-
const sessionStatePath =
|
|
36005
|
+
const sessionStatePath = path14.join(swarmDir, "session", "state.json");
|
|
35612
36006
|
try {
|
|
35613
|
-
const archiveSessionDir =
|
|
36007
|
+
const archiveSessionDir = path14.join(archiveDir, "session");
|
|
35614
36008
|
await fs7.mkdir(archiveSessionDir, { recursive: true });
|
|
35615
|
-
await fs7.copyFile(sessionStatePath,
|
|
36009
|
+
await fs7.copyFile(sessionStatePath, path14.join(archiveSessionDir, "state.json"));
|
|
35616
36010
|
archivedFileCount++;
|
|
35617
36011
|
} catch {}
|
|
35618
36012
|
archiveResult = `Archived ${archivedFileCount} artifact(s) to .swarm/archive/swarm-${timestamp}/`;
|
|
@@ -35635,7 +36029,7 @@ async function handleCloseCommand(directory, args) {
|
|
|
35635
36029
|
warnings.push(`Preserved ${artifact} because it was not successfully archived.`);
|
|
35636
36030
|
continue;
|
|
35637
36031
|
}
|
|
35638
|
-
const filePath =
|
|
36032
|
+
const filePath = path14.join(swarmDir, artifact);
|
|
35639
36033
|
try {
|
|
35640
36034
|
await fs7.unlink(filePath);
|
|
35641
36035
|
cleanedFiles.push(artifact);
|
|
@@ -35649,23 +36043,23 @@ async function handleCloseCommand(directory, args) {
|
|
|
35649
36043
|
const configBackups = swarmFiles.filter((f) => f.startsWith("config-backup-") && f.endsWith(".json"));
|
|
35650
36044
|
for (const backup of configBackups) {
|
|
35651
36045
|
try {
|
|
35652
|
-
await fs7.unlink(
|
|
36046
|
+
await fs7.unlink(path14.join(swarmDir, backup));
|
|
35653
36047
|
configBackupsRemoved++;
|
|
35654
36048
|
} catch {}
|
|
35655
36049
|
}
|
|
35656
36050
|
const ledgerSiblings = swarmFiles.filter((f) => (f.startsWith("plan-ledger.archived-") || f.startsWith("plan-ledger.backup-")) && f.endsWith(".jsonl"));
|
|
35657
36051
|
for (const sibling of ledgerSiblings) {
|
|
35658
36052
|
try {
|
|
35659
|
-
await fs7.unlink(
|
|
36053
|
+
await fs7.unlink(path14.join(swarmDir, sibling));
|
|
35660
36054
|
} catch {}
|
|
35661
36055
|
}
|
|
35662
36056
|
} catch {}
|
|
35663
36057
|
let swarmPlanFilesRemoved = 0;
|
|
35664
36058
|
const candidates = [
|
|
35665
|
-
|
|
35666
|
-
|
|
35667
|
-
|
|
35668
|
-
|
|
36059
|
+
path14.join(directory, ".swarm", "SWARM_PLAN.json"),
|
|
36060
|
+
path14.join(directory, ".swarm", "SWARM_PLAN.md"),
|
|
36061
|
+
path14.join(directory, "SWARM_PLAN.json"),
|
|
36062
|
+
path14.join(directory, "SWARM_PLAN.md")
|
|
35669
36063
|
];
|
|
35670
36064
|
for (const candidate of candidates) {
|
|
35671
36065
|
try {
|
|
@@ -35673,12 +36067,12 @@ async function handleCloseCommand(directory, args) {
|
|
|
35673
36067
|
swarmPlanFilesRemoved++;
|
|
35674
36068
|
} catch (err) {
|
|
35675
36069
|
if (err?.code !== "ENOENT") {
|
|
35676
|
-
warnings.push(`Failed to remove ${
|
|
36070
|
+
warnings.push(`Failed to remove ${path14.basename(candidate)}: ${err instanceof Error ? err.message : String(err)}`);
|
|
35677
36071
|
}
|
|
35678
36072
|
}
|
|
35679
36073
|
}
|
|
35680
36074
|
clearAllScopes(directory);
|
|
35681
|
-
const contextPath =
|
|
36075
|
+
const contextPath = path14.join(swarmDir, "context.md");
|
|
35682
36076
|
const contextContent = [
|
|
35683
36077
|
"# Context",
|
|
35684
36078
|
"",
|
|
@@ -35847,14 +36241,14 @@ var init_close = __esm(() => {
|
|
|
35847
36241
|
|
|
35848
36242
|
// src/commands/config.ts
|
|
35849
36243
|
import * as os4 from "os";
|
|
35850
|
-
import * as
|
|
36244
|
+
import * as path15 from "path";
|
|
35851
36245
|
function getUserConfigDir2() {
|
|
35852
|
-
return process.env.XDG_CONFIG_HOME ||
|
|
36246
|
+
return process.env.XDG_CONFIG_HOME || path15.join(os4.homedir(), ".config");
|
|
35853
36247
|
}
|
|
35854
36248
|
async function handleConfigCommand(directory, _args) {
|
|
35855
36249
|
const config3 = loadPluginConfig(directory);
|
|
35856
|
-
const userConfigPath =
|
|
35857
|
-
const projectConfigPath =
|
|
36250
|
+
const userConfigPath = path15.join(getUserConfigDir2(), "opencode", "opencode-swarm.json");
|
|
36251
|
+
const projectConfigPath = path15.join(directory, ".opencode", "opencode-swarm.json");
|
|
35858
36252
|
const lines = [
|
|
35859
36253
|
"## Swarm Configuration",
|
|
35860
36254
|
"",
|
|
@@ -36019,13 +36413,14 @@ var init_curator = __esm(() => {
|
|
|
36019
36413
|
init_event_bus();
|
|
36020
36414
|
init_manager();
|
|
36021
36415
|
init_bun_compat();
|
|
36416
|
+
init_logger();
|
|
36022
36417
|
init_knowledge_store();
|
|
36023
36418
|
init_knowledge_validator();
|
|
36024
36419
|
init_utils2();
|
|
36025
36420
|
});
|
|
36026
36421
|
|
|
36027
36422
|
// src/hooks/hive-promoter.ts
|
|
36028
|
-
import
|
|
36423
|
+
import path16 from "path";
|
|
36029
36424
|
function isAlreadyInHive(entry, hiveEntries, threshold) {
|
|
36030
36425
|
return findNearDuplicate(entry.lesson, hiveEntries, threshold) !== undefined;
|
|
36031
36426
|
}
|
|
@@ -36204,7 +36599,7 @@ async function promoteToHive(directory, lesson, category) {
|
|
|
36204
36599
|
schema_version: 1,
|
|
36205
36600
|
created_at: new Date().toISOString(),
|
|
36206
36601
|
updated_at: new Date().toISOString(),
|
|
36207
|
-
source_project:
|
|
36602
|
+
source_project: path16.basename(directory) || "unknown",
|
|
36208
36603
|
encounter_score: 1
|
|
36209
36604
|
};
|
|
36210
36605
|
await appendKnowledge(resolveHiveKnowledgePath(), newHiveEntry);
|
|
@@ -36295,8 +36690,8 @@ var init_curate = __esm(() => {
|
|
|
36295
36690
|
// src/tools/co-change-analyzer.ts
|
|
36296
36691
|
import * as child_process3 from "child_process";
|
|
36297
36692
|
import { randomUUID } from "crypto";
|
|
36298
|
-
import { readdir, readFile as
|
|
36299
|
-
import * as
|
|
36693
|
+
import { readdir, readFile as readFile5, stat as stat2 } from "fs/promises";
|
|
36694
|
+
import * as path17 from "path";
|
|
36300
36695
|
import { promisify } from "util";
|
|
36301
36696
|
function getExecFileAsync() {
|
|
36302
36697
|
return promisify(child_process3.execFile);
|
|
@@ -36398,7 +36793,7 @@ async function scanSourceFiles(dir) {
|
|
|
36398
36793
|
try {
|
|
36399
36794
|
const entries = await readdir(dir, { withFileTypes: true });
|
|
36400
36795
|
for (const entry of entries) {
|
|
36401
|
-
const fullPath =
|
|
36796
|
+
const fullPath = path17.join(dir, entry.name);
|
|
36402
36797
|
if (entry.isDirectory()) {
|
|
36403
36798
|
if (skipDirs.has(entry.name)) {
|
|
36404
36799
|
continue;
|
|
@@ -36406,7 +36801,7 @@ async function scanSourceFiles(dir) {
|
|
|
36406
36801
|
const subFiles = await scanSourceFiles(fullPath);
|
|
36407
36802
|
results.push(...subFiles);
|
|
36408
36803
|
} else if (entry.isFile()) {
|
|
36409
|
-
const ext =
|
|
36804
|
+
const ext = path17.extname(entry.name);
|
|
36410
36805
|
if ([".ts", ".tsx", ".js", ".jsx", ".mjs"].includes(ext)) {
|
|
36411
36806
|
results.push(fullPath);
|
|
36412
36807
|
}
|
|
@@ -36420,7 +36815,7 @@ async function getStaticEdges(directory) {
|
|
|
36420
36815
|
const sourceFiles = await scanSourceFiles(directory);
|
|
36421
36816
|
for (const sourceFile of sourceFiles) {
|
|
36422
36817
|
try {
|
|
36423
|
-
const content = await
|
|
36818
|
+
const content = await readFile5(sourceFile, "utf-8");
|
|
36424
36819
|
const importRegex = /(?:import|require)\s*(?:\(?\s*['"`]|.*?from\s+['"`])([^'"`]+)['"`]/g;
|
|
36425
36820
|
for (let match = importRegex.exec(content);match !== null; match = importRegex.exec(content)) {
|
|
36426
36821
|
const importPath = match[1].trim();
|
|
@@ -36428,8 +36823,8 @@ async function getStaticEdges(directory) {
|
|
|
36428
36823
|
continue;
|
|
36429
36824
|
}
|
|
36430
36825
|
try {
|
|
36431
|
-
const sourceDir =
|
|
36432
|
-
const resolvedPath =
|
|
36826
|
+
const sourceDir = path17.dirname(sourceFile);
|
|
36827
|
+
const resolvedPath = path17.resolve(sourceDir, importPath);
|
|
36433
36828
|
const extensions = [
|
|
36434
36829
|
"",
|
|
36435
36830
|
".ts",
|
|
@@ -36454,8 +36849,8 @@ async function getStaticEdges(directory) {
|
|
|
36454
36849
|
if (!targetFile) {
|
|
36455
36850
|
continue;
|
|
36456
36851
|
}
|
|
36457
|
-
const relSource =
|
|
36458
|
-
const relTarget =
|
|
36852
|
+
const relSource = path17.relative(directory, sourceFile).replace(/\\/g, "/");
|
|
36853
|
+
const relTarget = path17.relative(directory, targetFile).replace(/\\/g, "/");
|
|
36459
36854
|
const [key] = relSource < relTarget ? [`${relSource}::${relTarget}`, relSource, relTarget] : [`${relTarget}::${relSource}`, relTarget, relSource];
|
|
36460
36855
|
edges.add(key);
|
|
36461
36856
|
} catch {}
|
|
@@ -36467,7 +36862,7 @@ async function getStaticEdges(directory) {
|
|
|
36467
36862
|
function isTestImplementationPair(fileA, fileB) {
|
|
36468
36863
|
const testPatterns = [".test.ts", ".test.js", ".spec.ts", ".spec.js"];
|
|
36469
36864
|
const getBaseName = (filePath) => {
|
|
36470
|
-
const base =
|
|
36865
|
+
const base = path17.basename(filePath);
|
|
36471
36866
|
for (const pattern of testPatterns) {
|
|
36472
36867
|
if (base.endsWith(pattern)) {
|
|
36473
36868
|
return base.slice(0, -pattern.length);
|
|
@@ -36477,16 +36872,16 @@ function isTestImplementationPair(fileA, fileB) {
|
|
|
36477
36872
|
};
|
|
36478
36873
|
const baseA = getBaseName(fileA);
|
|
36479
36874
|
const baseB = getBaseName(fileB);
|
|
36480
|
-
return baseA === baseB && baseA !==
|
|
36875
|
+
return baseA === baseB && baseA !== path17.basename(fileA) && baseA !== path17.basename(fileB);
|
|
36481
36876
|
}
|
|
36482
36877
|
function hasSharedPrefix(fileA, fileB) {
|
|
36483
|
-
const dirA =
|
|
36484
|
-
const dirB =
|
|
36878
|
+
const dirA = path17.dirname(fileA);
|
|
36879
|
+
const dirB = path17.dirname(fileB);
|
|
36485
36880
|
if (dirA !== dirB) {
|
|
36486
36881
|
return false;
|
|
36487
36882
|
}
|
|
36488
|
-
const baseA =
|
|
36489
|
-
const baseB =
|
|
36883
|
+
const baseA = path17.basename(fileA).replace(/\.(ts|js|tsx|jsx|mjs)$/, "");
|
|
36884
|
+
const baseB = path17.basename(fileB).replace(/\.(ts|js|tsx|jsx|mjs)$/, "");
|
|
36490
36885
|
if (baseA.startsWith(baseB) || baseB.startsWith(baseA)) {
|
|
36491
36886
|
return true;
|
|
36492
36887
|
}
|
|
@@ -36514,9 +36909,9 @@ async function detectDarkMatter(directory, options) {
|
|
|
36514
36909
|
} catch {
|
|
36515
36910
|
return [];
|
|
36516
36911
|
}
|
|
36517
|
-
const commitMap = await parseGitLog(directory, maxCommitsToAnalyze);
|
|
36518
|
-
const matrix = buildCoChangeMatrix(commitMap);
|
|
36519
|
-
const staticEdges = await getStaticEdges(directory);
|
|
36912
|
+
const commitMap = await _internals10.parseGitLog(directory, maxCommitsToAnalyze);
|
|
36913
|
+
const matrix = _internals10.buildCoChangeMatrix(commitMap);
|
|
36914
|
+
const staticEdges = await _internals10.getStaticEdges(directory);
|
|
36520
36915
|
const results = [];
|
|
36521
36916
|
for (const entry of matrix.values()) {
|
|
36522
36917
|
const key = `${entry.fileA}::${entry.fileB}`;
|
|
@@ -36540,8 +36935,8 @@ function darkMatterToKnowledgeEntries(pairs, projectName) {
|
|
|
36540
36935
|
const entries = [];
|
|
36541
36936
|
const now = new Date().toISOString();
|
|
36542
36937
|
for (const pair of pairs.slice(0, 10)) {
|
|
36543
|
-
const baseA =
|
|
36544
|
-
const baseB =
|
|
36938
|
+
const baseA = path17.basename(pair.fileA);
|
|
36939
|
+
const baseB = path17.basename(pair.fileB);
|
|
36545
36940
|
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.`;
|
|
36546
36941
|
if (lesson.length > 280) {
|
|
36547
36942
|
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.`;
|
|
@@ -36596,7 +36991,7 @@ ${rows}
|
|
|
36596
36991
|
These pairs likely share an architectural concern invisible to static analysis.
|
|
36597
36992
|
Consider adding explicit documentation or extracting the shared concern.`;
|
|
36598
36993
|
}
|
|
36599
|
-
var co_change_analyzer;
|
|
36994
|
+
var co_change_analyzer, _internals10;
|
|
36600
36995
|
var init_co_change_analyzer = __esm(() => {
|
|
36601
36996
|
init_zod();
|
|
36602
36997
|
init_create_tool();
|
|
@@ -36628,14 +37023,22 @@ var init_co_change_analyzer = __esm(() => {
|
|
|
36628
37023
|
npmiThreshold,
|
|
36629
37024
|
maxCommitsToAnalyze
|
|
36630
37025
|
};
|
|
36631
|
-
const pairs = await detectDarkMatter(directory, options);
|
|
36632
|
-
return formatDarkMatterOutput(pairs);
|
|
37026
|
+
const pairs = await _internals10.detectDarkMatter(directory, options);
|
|
37027
|
+
return _internals10.formatDarkMatterOutput(pairs);
|
|
36633
37028
|
}
|
|
36634
37029
|
});
|
|
37030
|
+
_internals10 = {
|
|
37031
|
+
parseGitLog,
|
|
37032
|
+
buildCoChangeMatrix,
|
|
37033
|
+
getStaticEdges,
|
|
37034
|
+
detectDarkMatter,
|
|
37035
|
+
darkMatterToKnowledgeEntries,
|
|
37036
|
+
formatDarkMatterOutput
|
|
37037
|
+
};
|
|
36635
37038
|
});
|
|
36636
37039
|
|
|
36637
37040
|
// src/commands/dark-matter.ts
|
|
36638
|
-
import
|
|
37041
|
+
import path18 from "path";
|
|
36639
37042
|
async function handleDarkMatterCommand(directory, args) {
|
|
36640
37043
|
const options = {};
|
|
36641
37044
|
for (let i = 0;i < args.length; i++) {
|
|
@@ -36657,7 +37060,7 @@ async function handleDarkMatterCommand(directory, args) {
|
|
|
36657
37060
|
const output = formatDarkMatterOutput(pairs);
|
|
36658
37061
|
if (pairs.length > 0) {
|
|
36659
37062
|
try {
|
|
36660
|
-
const projectName =
|
|
37063
|
+
const projectName = path18.basename(path18.resolve(directory));
|
|
36661
37064
|
const entries = darkMatterToKnowledgeEntries(pairs, projectName);
|
|
36662
37065
|
if (entries.length > 0) {
|
|
36663
37066
|
const knowledgePath = resolveSwarmKnowledgePath(directory);
|
|
@@ -36682,67 +37085,67 @@ var init_dark_matter = __esm(() => {
|
|
|
36682
37085
|
|
|
36683
37086
|
// src/config/cache-paths.ts
|
|
36684
37087
|
import * as os5 from "os";
|
|
36685
|
-
import * as
|
|
37088
|
+
import * as path19 from "path";
|
|
36686
37089
|
function getPluginConfigDir() {
|
|
36687
|
-
return
|
|
37090
|
+
return path19.join(process.env.XDG_CONFIG_HOME || path19.join(os5.homedir(), ".config"), "opencode");
|
|
36688
37091
|
}
|
|
36689
37092
|
function getPluginCachePaths() {
|
|
36690
|
-
const cacheBase = process.env.XDG_CACHE_HOME ||
|
|
37093
|
+
const cacheBase = process.env.XDG_CACHE_HOME || path19.join(os5.homedir(), ".cache");
|
|
36691
37094
|
const configDir = getPluginConfigDir();
|
|
36692
37095
|
const paths = [
|
|
36693
|
-
|
|
36694
|
-
|
|
36695
|
-
|
|
37096
|
+
path19.join(cacheBase, "opencode", "node_modules", "opencode-swarm"),
|
|
37097
|
+
path19.join(cacheBase, "opencode", "packages", "opencode-swarm@latest"),
|
|
37098
|
+
path19.join(configDir, "node_modules", "opencode-swarm")
|
|
36696
37099
|
];
|
|
36697
37100
|
if (process.platform === "darwin") {
|
|
36698
|
-
const libCaches =
|
|
36699
|
-
paths.push(
|
|
37101
|
+
const libCaches = path19.join(os5.homedir(), "Library", "Caches");
|
|
37102
|
+
paths.push(path19.join(libCaches, "opencode", "node_modules", "opencode-swarm"), path19.join(libCaches, "opencode", "packages", "opencode-swarm@latest"));
|
|
36700
37103
|
}
|
|
36701
37104
|
if (process.platform === "win32") {
|
|
36702
|
-
const localAppData = process.env.LOCALAPPDATA ||
|
|
36703
|
-
const appData = process.env.APPDATA ||
|
|
36704
|
-
paths.push(
|
|
37105
|
+
const localAppData = process.env.LOCALAPPDATA || path19.join(os5.homedir(), "AppData", "Local");
|
|
37106
|
+
const appData = process.env.APPDATA || path19.join(os5.homedir(), "AppData", "Roaming");
|
|
37107
|
+
paths.push(path19.join(localAppData, "opencode", "node_modules", "opencode-swarm"), path19.join(localAppData, "opencode", "packages", "opencode-swarm@latest"), path19.join(appData, "opencode", "node_modules", "opencode-swarm"));
|
|
36705
37108
|
}
|
|
36706
37109
|
return paths;
|
|
36707
37110
|
}
|
|
36708
37111
|
function getPluginLockFilePaths() {
|
|
36709
|
-
const cacheBase = process.env.XDG_CACHE_HOME ||
|
|
37112
|
+
const cacheBase = process.env.XDG_CACHE_HOME || path19.join(os5.homedir(), ".cache");
|
|
36710
37113
|
const configDir = getPluginConfigDir();
|
|
36711
37114
|
const paths = [
|
|
36712
|
-
|
|
36713
|
-
|
|
36714
|
-
|
|
37115
|
+
path19.join(cacheBase, "opencode", "bun.lock"),
|
|
37116
|
+
path19.join(cacheBase, "opencode", "bun.lockb"),
|
|
37117
|
+
path19.join(configDir, "package-lock.json")
|
|
36715
37118
|
];
|
|
36716
37119
|
if (process.platform === "darwin") {
|
|
36717
|
-
const libCaches =
|
|
36718
|
-
paths.push(
|
|
37120
|
+
const libCaches = path19.join(os5.homedir(), "Library", "Caches");
|
|
37121
|
+
paths.push(path19.join(libCaches, "opencode", "bun.lock"), path19.join(libCaches, "opencode", "bun.lockb"));
|
|
36719
37122
|
}
|
|
36720
37123
|
if (process.platform === "win32") {
|
|
36721
|
-
const localAppData = process.env.LOCALAPPDATA ||
|
|
36722
|
-
paths.push(
|
|
37124
|
+
const localAppData = process.env.LOCALAPPDATA || path19.join(os5.homedir(), "AppData", "Local");
|
|
37125
|
+
paths.push(path19.join(localAppData, "opencode", "bun.lock"), path19.join(localAppData, "opencode", "bun.lockb"));
|
|
36723
37126
|
}
|
|
36724
37127
|
return paths;
|
|
36725
37128
|
}
|
|
36726
37129
|
var init_cache_paths = () => {};
|
|
36727
37130
|
|
|
36728
37131
|
// src/services/version-check.ts
|
|
36729
|
-
import { existsSync as
|
|
37132
|
+
import { existsSync as existsSync9, mkdirSync as mkdirSync8, readFileSync as readFileSync5, writeFileSync as writeFileSync4 } from "fs";
|
|
36730
37133
|
import { homedir as homedir5 } from "os";
|
|
36731
|
-
import { join as
|
|
37134
|
+
import { join as join17 } from "path";
|
|
36732
37135
|
function cacheDir() {
|
|
36733
37136
|
const xdg = process.env.XDG_CACHE_HOME;
|
|
36734
|
-
const base = xdg && xdg.length > 0 ? xdg :
|
|
36735
|
-
return
|
|
37137
|
+
const base = xdg && xdg.length > 0 ? xdg : join17(homedir5(), ".cache");
|
|
37138
|
+
return join17(base, "opencode-swarm");
|
|
36736
37139
|
}
|
|
36737
37140
|
function cacheFile() {
|
|
36738
|
-
return
|
|
37141
|
+
return join17(cacheDir(), "version-check.json");
|
|
36739
37142
|
}
|
|
36740
37143
|
function readVersionCache() {
|
|
36741
37144
|
try {
|
|
36742
|
-
const
|
|
36743
|
-
if (!
|
|
37145
|
+
const path20 = cacheFile();
|
|
37146
|
+
if (!existsSync9(path20))
|
|
36744
37147
|
return null;
|
|
36745
|
-
const raw = readFileSync5(
|
|
37148
|
+
const raw = readFileSync5(path20, "utf-8");
|
|
36746
37149
|
const parsed = JSON.parse(raw);
|
|
36747
37150
|
if (typeof parsed?.checkedAt !== "number")
|
|
36748
37151
|
return null;
|
|
@@ -36781,8 +37184,8 @@ var init_version_check = __esm(() => {
|
|
|
36781
37184
|
|
|
36782
37185
|
// src/services/diagnose-service.ts
|
|
36783
37186
|
import * as child_process4 from "child_process";
|
|
36784
|
-
import { existsSync as
|
|
36785
|
-
import
|
|
37187
|
+
import { existsSync as existsSync10, readdirSync as readdirSync4, readFileSync as readFileSync6, statSync as statSync6 } from "fs";
|
|
37188
|
+
import path20 from "path";
|
|
36786
37189
|
import { fileURLToPath } from "url";
|
|
36787
37190
|
function validateTaskDag(plan) {
|
|
36788
37191
|
const allTaskIds = new Set;
|
|
@@ -37015,7 +37418,7 @@ async function checkConfigBackups(directory) {
|
|
|
37015
37418
|
}
|
|
37016
37419
|
async function checkGitRepository(directory) {
|
|
37017
37420
|
try {
|
|
37018
|
-
if (!
|
|
37421
|
+
if (!existsSync10(directory) || !statSync6(directory).isDirectory()) {
|
|
37019
37422
|
return {
|
|
37020
37423
|
name: "Git Repository",
|
|
37021
37424
|
status: "\u274C",
|
|
@@ -37079,8 +37482,8 @@ async function checkSpecStaleness(directory, plan) {
|
|
|
37079
37482
|
};
|
|
37080
37483
|
}
|
|
37081
37484
|
async function checkConfigParseability(directory) {
|
|
37082
|
-
const configPath =
|
|
37083
|
-
if (!
|
|
37485
|
+
const configPath = path20.join(directory, ".opencode/opencode-swarm.json");
|
|
37486
|
+
if (!existsSync10(configPath)) {
|
|
37084
37487
|
return {
|
|
37085
37488
|
name: "Config Parseability",
|
|
37086
37489
|
status: "\u2705",
|
|
@@ -37108,7 +37511,7 @@ function resolveGrammarDir(thisDir) {
|
|
|
37108
37511
|
const normalized = thisDir.replace(/\\/g, "/");
|
|
37109
37512
|
const isSource = normalized.endsWith("/src/services");
|
|
37110
37513
|
const isCliBundle = normalized.endsWith("/cli");
|
|
37111
|
-
return isSource || isCliBundle ?
|
|
37514
|
+
return isSource || isCliBundle ? path20.join(thisDir, "..", "lang", "grammars") : path20.join(thisDir, "lang", "grammars");
|
|
37112
37515
|
}
|
|
37113
37516
|
async function checkGrammarWasmFiles() {
|
|
37114
37517
|
const grammarFiles = [
|
|
@@ -37132,14 +37535,14 @@ async function checkGrammarWasmFiles() {
|
|
|
37132
37535
|
"tree-sitter-ini.wasm",
|
|
37133
37536
|
"tree-sitter-regex.wasm"
|
|
37134
37537
|
];
|
|
37135
|
-
const thisDir =
|
|
37538
|
+
const thisDir = path20.dirname(fileURLToPath(import.meta.url));
|
|
37136
37539
|
const grammarDir = resolveGrammarDir(thisDir);
|
|
37137
37540
|
const missing = [];
|
|
37138
|
-
if (!
|
|
37541
|
+
if (!existsSync10(path20.join(grammarDir, "tree-sitter.wasm"))) {
|
|
37139
37542
|
missing.push("tree-sitter.wasm (core runtime)");
|
|
37140
37543
|
}
|
|
37141
37544
|
for (const file3 of grammarFiles) {
|
|
37142
|
-
if (!
|
|
37545
|
+
if (!existsSync10(path20.join(grammarDir, file3))) {
|
|
37143
37546
|
missing.push(file3);
|
|
37144
37547
|
}
|
|
37145
37548
|
}
|
|
@@ -37157,8 +37560,8 @@ async function checkGrammarWasmFiles() {
|
|
|
37157
37560
|
};
|
|
37158
37561
|
}
|
|
37159
37562
|
async function checkCheckpointManifest(directory) {
|
|
37160
|
-
const manifestPath =
|
|
37161
|
-
if (!
|
|
37563
|
+
const manifestPath = path20.join(directory, ".swarm/checkpoints.json");
|
|
37564
|
+
if (!existsSync10(manifestPath)) {
|
|
37162
37565
|
return {
|
|
37163
37566
|
name: "Checkpoint Manifest",
|
|
37164
37567
|
status: "\u2705",
|
|
@@ -37209,8 +37612,8 @@ async function checkCheckpointManifest(directory) {
|
|
|
37209
37612
|
}
|
|
37210
37613
|
}
|
|
37211
37614
|
async function checkEventStreamIntegrity(directory) {
|
|
37212
|
-
const eventsPath =
|
|
37213
|
-
if (!
|
|
37615
|
+
const eventsPath = path20.join(directory, ".swarm/events.jsonl");
|
|
37616
|
+
if (!existsSync10(eventsPath)) {
|
|
37214
37617
|
return {
|
|
37215
37618
|
name: "Event Stream",
|
|
37216
37619
|
status: "\u2705",
|
|
@@ -37250,8 +37653,8 @@ async function checkEventStreamIntegrity(directory) {
|
|
|
37250
37653
|
}
|
|
37251
37654
|
}
|
|
37252
37655
|
async function checkSteeringDirectives(directory) {
|
|
37253
|
-
const eventsPath =
|
|
37254
|
-
if (!
|
|
37656
|
+
const eventsPath = path20.join(directory, ".swarm/events.jsonl");
|
|
37657
|
+
if (!existsSync10(eventsPath)) {
|
|
37255
37658
|
return {
|
|
37256
37659
|
name: "Steering Directives",
|
|
37257
37660
|
status: "\u2705",
|
|
@@ -37306,8 +37709,8 @@ async function checkCurator(directory) {
|
|
|
37306
37709
|
detail: "Disabled (enable via curator.enabled)"
|
|
37307
37710
|
};
|
|
37308
37711
|
}
|
|
37309
|
-
const summaryPath =
|
|
37310
|
-
if (!
|
|
37712
|
+
const summaryPath = path20.join(directory, ".swarm/curator-summary.json");
|
|
37713
|
+
if (!existsSync10(summaryPath)) {
|
|
37311
37714
|
return {
|
|
37312
37715
|
name: "Curator",
|
|
37313
37716
|
status: "\u2705",
|
|
@@ -37472,8 +37875,8 @@ async function getDiagnoseData(directory) {
|
|
|
37472
37875
|
checks5.push(await checkSteeringDirectives(directory));
|
|
37473
37876
|
checks5.push(await checkCurator(directory));
|
|
37474
37877
|
try {
|
|
37475
|
-
const evidenceDir =
|
|
37476
|
-
const snapshotFiles =
|
|
37878
|
+
const evidenceDir = path20.join(directory, ".swarm", "evidence");
|
|
37879
|
+
const snapshotFiles = existsSync10(evidenceDir) ? readdirSync4(evidenceDir).filter((f) => f.startsWith("agent-tools-") && f.endsWith(".json")) : [];
|
|
37477
37880
|
if (snapshotFiles.length > 0) {
|
|
37478
37881
|
const latest = snapshotFiles.sort().pop();
|
|
37479
37882
|
checks5.push({
|
|
@@ -37506,11 +37909,11 @@ async function getDiagnoseData(directory) {
|
|
|
37506
37909
|
const cacheRows = [];
|
|
37507
37910
|
for (const cachePath of cachePaths) {
|
|
37508
37911
|
try {
|
|
37509
|
-
if (!
|
|
37912
|
+
if (!existsSync10(cachePath)) {
|
|
37510
37913
|
cacheRows.push(`\u2B1C ${cachePath} \u2014 absent`);
|
|
37511
37914
|
continue;
|
|
37512
37915
|
}
|
|
37513
|
-
const pkgJsonPath =
|
|
37916
|
+
const pkgJsonPath = path20.join(cachePath, "package.json");
|
|
37514
37917
|
try {
|
|
37515
37918
|
const raw = readFileSync6(pkgJsonPath, "utf-8");
|
|
37516
37919
|
const parsed = JSON.parse(raw);
|
|
@@ -37598,13 +38001,13 @@ __export(exports_config_doctor, {
|
|
|
37598
38001
|
import * as crypto3 from "crypto";
|
|
37599
38002
|
import * as fs8 from "fs";
|
|
37600
38003
|
import * as os6 from "os";
|
|
37601
|
-
import * as
|
|
38004
|
+
import * as path21 from "path";
|
|
37602
38005
|
function getUserConfigDir3() {
|
|
37603
|
-
return process.env.XDG_CONFIG_HOME ||
|
|
38006
|
+
return process.env.XDG_CONFIG_HOME || path21.join(os6.homedir(), ".config");
|
|
37604
38007
|
}
|
|
37605
38008
|
function getConfigPaths(directory) {
|
|
37606
|
-
const userConfigPath =
|
|
37607
|
-
const projectConfigPath =
|
|
38009
|
+
const userConfigPath = path21.join(getUserConfigDir3(), "opencode", "opencode-swarm.json");
|
|
38010
|
+
const projectConfigPath = path21.join(directory, ".opencode", "opencode-swarm.json");
|
|
37608
38011
|
return { userConfigPath, projectConfigPath };
|
|
37609
38012
|
}
|
|
37610
38013
|
function computeHash(content) {
|
|
@@ -37629,9 +38032,9 @@ function isValidConfigPath(configPath, directory) {
|
|
|
37629
38032
|
const normalizedUser = userConfigPath.replace(/\\/g, "/");
|
|
37630
38033
|
const normalizedProject = projectConfigPath.replace(/\\/g, "/");
|
|
37631
38034
|
try {
|
|
37632
|
-
const resolvedConfig =
|
|
37633
|
-
const resolvedUser =
|
|
37634
|
-
const resolvedProject =
|
|
38035
|
+
const resolvedConfig = path21.resolve(configPath);
|
|
38036
|
+
const resolvedUser = path21.resolve(normalizedUser);
|
|
38037
|
+
const resolvedProject = path21.resolve(normalizedProject);
|
|
37635
38038
|
return resolvedConfig === resolvedUser || resolvedConfig === resolvedProject;
|
|
37636
38039
|
} catch {
|
|
37637
38040
|
return false;
|
|
@@ -37671,12 +38074,12 @@ function createConfigBackup(directory) {
|
|
|
37671
38074
|
};
|
|
37672
38075
|
}
|
|
37673
38076
|
function writeBackupArtifact(directory, backup) {
|
|
37674
|
-
const swarmDir =
|
|
38077
|
+
const swarmDir = path21.join(directory, ".swarm");
|
|
37675
38078
|
if (!fs8.existsSync(swarmDir)) {
|
|
37676
38079
|
fs8.mkdirSync(swarmDir, { recursive: true });
|
|
37677
38080
|
}
|
|
37678
38081
|
const backupFilename = `config-backup-${backup.createdAt}.json`;
|
|
37679
|
-
const backupPath =
|
|
38082
|
+
const backupPath = path21.join(swarmDir, backupFilename);
|
|
37680
38083
|
const artifact = {
|
|
37681
38084
|
createdAt: backup.createdAt,
|
|
37682
38085
|
configPath: backup.configPath,
|
|
@@ -37706,7 +38109,7 @@ function restoreFromBackup(backupPath, directory) {
|
|
|
37706
38109
|
return null;
|
|
37707
38110
|
}
|
|
37708
38111
|
const targetPath = artifact.configPath;
|
|
37709
|
-
const targetDir =
|
|
38112
|
+
const targetDir = path21.dirname(targetPath);
|
|
37710
38113
|
if (!fs8.existsSync(targetDir)) {
|
|
37711
38114
|
fs8.mkdirSync(targetDir, { recursive: true });
|
|
37712
38115
|
}
|
|
@@ -37737,9 +38140,9 @@ function readConfigFromFile(directory) {
|
|
|
37737
38140
|
return null;
|
|
37738
38141
|
}
|
|
37739
38142
|
}
|
|
37740
|
-
function validateConfigKey(
|
|
38143
|
+
function validateConfigKey(path22, value, _config) {
|
|
37741
38144
|
const findings = [];
|
|
37742
|
-
switch (
|
|
38145
|
+
switch (path22) {
|
|
37743
38146
|
case "agents": {
|
|
37744
38147
|
if (value !== undefined) {
|
|
37745
38148
|
findings.push({
|
|
@@ -37986,27 +38389,27 @@ function validateConfigKey(path21, value, _config) {
|
|
|
37986
38389
|
}
|
|
37987
38390
|
return findings;
|
|
37988
38391
|
}
|
|
37989
|
-
function walkConfigAndValidate(obj,
|
|
38392
|
+
function walkConfigAndValidate(obj, path22, config3, findings) {
|
|
37990
38393
|
if (obj === null || obj === undefined) {
|
|
37991
38394
|
return;
|
|
37992
38395
|
}
|
|
37993
|
-
if (
|
|
37994
|
-
const keyFindings = validateConfigKey(
|
|
38396
|
+
if (path22 && typeof obj === "object" && !Array.isArray(obj)) {
|
|
38397
|
+
const keyFindings = validateConfigKey(path22, obj, config3);
|
|
37995
38398
|
findings.push(...keyFindings);
|
|
37996
38399
|
}
|
|
37997
38400
|
if (typeof obj !== "object") {
|
|
37998
|
-
const keyFindings = validateConfigKey(
|
|
38401
|
+
const keyFindings = validateConfigKey(path22, obj, config3);
|
|
37999
38402
|
findings.push(...keyFindings);
|
|
38000
38403
|
return;
|
|
38001
38404
|
}
|
|
38002
38405
|
if (Array.isArray(obj)) {
|
|
38003
38406
|
obj.forEach((item, index) => {
|
|
38004
|
-
walkConfigAndValidate(item, `${
|
|
38407
|
+
walkConfigAndValidate(item, `${path22}[${index}]`, config3, findings);
|
|
38005
38408
|
});
|
|
38006
38409
|
return;
|
|
38007
38410
|
}
|
|
38008
38411
|
for (const [key, value] of Object.entries(obj)) {
|
|
38009
|
-
const newPath =
|
|
38412
|
+
const newPath = path22 ? `${path22}.${key}` : key;
|
|
38010
38413
|
walkConfigAndValidate(value, newPath, config3, findings);
|
|
38011
38414
|
}
|
|
38012
38415
|
}
|
|
@@ -38126,7 +38529,7 @@ function applySafeAutoFixes(directory, result) {
|
|
|
38126
38529
|
}
|
|
38127
38530
|
}
|
|
38128
38531
|
if (appliedFixes.length > 0) {
|
|
38129
|
-
const configDir =
|
|
38532
|
+
const configDir = path21.dirname(configPath);
|
|
38130
38533
|
if (!fs8.existsSync(configDir)) {
|
|
38131
38534
|
fs8.mkdirSync(configDir, { recursive: true });
|
|
38132
38535
|
}
|
|
@@ -38136,12 +38539,12 @@ function applySafeAutoFixes(directory, result) {
|
|
|
38136
38539
|
return { appliedFixes, updatedConfigPath };
|
|
38137
38540
|
}
|
|
38138
38541
|
function writeDoctorArtifact(directory, result) {
|
|
38139
|
-
const swarmDir =
|
|
38542
|
+
const swarmDir = path21.join(directory, ".swarm");
|
|
38140
38543
|
if (!fs8.existsSync(swarmDir)) {
|
|
38141
38544
|
fs8.mkdirSync(swarmDir, { recursive: true });
|
|
38142
38545
|
}
|
|
38143
38546
|
const artifactFilename = "config-doctor.json";
|
|
38144
|
-
const artifactPath =
|
|
38547
|
+
const artifactPath = path21.join(swarmDir, artifactFilename);
|
|
38145
38548
|
const guiOutput = {
|
|
38146
38549
|
timestamp: result.timestamp,
|
|
38147
38550
|
summary: result.summary,
|
|
@@ -39188,7 +39591,7 @@ var init_profiles = __esm(() => {
|
|
|
39188
39591
|
|
|
39189
39592
|
// src/lang/detector.ts
|
|
39190
39593
|
import { access as access3, readdir as readdir2 } from "fs/promises";
|
|
39191
|
-
import { extname as extname2, join as
|
|
39594
|
+
import { extname as extname2, join as join19 } from "path";
|
|
39192
39595
|
async function detectProjectLanguages(projectDir) {
|
|
39193
39596
|
const detected = new Set;
|
|
39194
39597
|
async function scanDir(dir) {
|
|
@@ -39204,7 +39607,7 @@ async function detectProjectLanguages(projectDir) {
|
|
|
39204
39607
|
if (detectFile.includes("*") || detectFile.includes("?"))
|
|
39205
39608
|
continue;
|
|
39206
39609
|
try {
|
|
39207
|
-
await access3(
|
|
39610
|
+
await access3(join19(dir, detectFile));
|
|
39208
39611
|
detected.add(profile.id);
|
|
39209
39612
|
break;
|
|
39210
39613
|
} catch {}
|
|
@@ -39225,7 +39628,7 @@ async function detectProjectLanguages(projectDir) {
|
|
|
39225
39628
|
const topEntries = await readdir2(projectDir, { withFileTypes: true });
|
|
39226
39629
|
for (const entry of topEntries) {
|
|
39227
39630
|
if (entry.isDirectory() && !entry.name.startsWith(".") && entry.name !== "node_modules") {
|
|
39228
|
-
await scanDir(
|
|
39631
|
+
await scanDir(join19(projectDir, entry.name));
|
|
39229
39632
|
}
|
|
39230
39633
|
}
|
|
39231
39634
|
} catch {}
|
|
@@ -39244,7 +39647,7 @@ var init_detector = __esm(() => {
|
|
|
39244
39647
|
|
|
39245
39648
|
// src/build/discovery.ts
|
|
39246
39649
|
import * as fs9 from "fs";
|
|
39247
|
-
import * as
|
|
39650
|
+
import * as path22 from "path";
|
|
39248
39651
|
function isCommandAvailable(command) {
|
|
39249
39652
|
if (toolchainCache.has(command)) {
|
|
39250
39653
|
return toolchainCache.get(command);
|
|
@@ -39276,11 +39679,11 @@ function findBuildFiles(workingDir, patterns) {
|
|
|
39276
39679
|
const regex = simpleGlobToRegex(pattern);
|
|
39277
39680
|
const matches = files.filter((f) => regex.test(f));
|
|
39278
39681
|
if (matches.length > 0) {
|
|
39279
|
-
return
|
|
39682
|
+
return path22.join(dir, matches[0]);
|
|
39280
39683
|
}
|
|
39281
39684
|
} catch {}
|
|
39282
39685
|
} else {
|
|
39283
|
-
const filePath =
|
|
39686
|
+
const filePath = path22.join(workingDir, pattern);
|
|
39284
39687
|
if (fs9.existsSync(filePath)) {
|
|
39285
39688
|
return filePath;
|
|
39286
39689
|
}
|
|
@@ -39289,7 +39692,7 @@ function findBuildFiles(workingDir, patterns) {
|
|
|
39289
39692
|
return null;
|
|
39290
39693
|
}
|
|
39291
39694
|
function getRepoDefinedScripts(workingDir, scripts) {
|
|
39292
|
-
const packageJsonPath =
|
|
39695
|
+
const packageJsonPath = path22.join(workingDir, "package.json");
|
|
39293
39696
|
if (!fs9.existsSync(packageJsonPath)) {
|
|
39294
39697
|
return [];
|
|
39295
39698
|
}
|
|
@@ -39330,7 +39733,7 @@ function findAllBuildFiles(workingDir) {
|
|
|
39330
39733
|
const regex = simpleGlobToRegex(pattern);
|
|
39331
39734
|
findFilesRecursive(workingDir, regex, allBuildFiles);
|
|
39332
39735
|
} else {
|
|
39333
|
-
const filePath =
|
|
39736
|
+
const filePath = path22.join(workingDir, pattern);
|
|
39334
39737
|
if (fs9.existsSync(filePath)) {
|
|
39335
39738
|
allBuildFiles.add(filePath);
|
|
39336
39739
|
}
|
|
@@ -39343,7 +39746,7 @@ function findFilesRecursive(dir, regex, results) {
|
|
|
39343
39746
|
try {
|
|
39344
39747
|
const entries = fs9.readdirSync(dir, { withFileTypes: true });
|
|
39345
39748
|
for (const entry of entries) {
|
|
39346
|
-
const fullPath =
|
|
39749
|
+
const fullPath = path22.join(dir, entry.name);
|
|
39347
39750
|
if (entry.isDirectory() && !["node_modules", ".git", "dist", "build", "target"].includes(entry.name)) {
|
|
39348
39751
|
findFilesRecursive(fullPath, regex, results);
|
|
39349
39752
|
} else if (entry.isFile() && regex.test(entry.name)) {
|
|
@@ -39366,7 +39769,7 @@ async function discoverBuildCommandsFromProfiles(workingDir) {
|
|
|
39366
39769
|
let foundCommand = false;
|
|
39367
39770
|
for (const cmd of sortedCommands) {
|
|
39368
39771
|
if (cmd.detectFile) {
|
|
39369
|
-
const detectFilePath =
|
|
39772
|
+
const detectFilePath = path22.join(workingDir, cmd.detectFile);
|
|
39370
39773
|
if (!fs9.existsSync(detectFilePath)) {
|
|
39371
39774
|
continue;
|
|
39372
39775
|
}
|
|
@@ -39399,7 +39802,7 @@ async function discoverBuildCommands(workingDir, options) {
|
|
|
39399
39802
|
const scope = options?.scope ?? "all";
|
|
39400
39803
|
const changedFiles = options?.changedFiles ?? [];
|
|
39401
39804
|
const _filesToCheck = filterByScope(workingDir, scope, changedFiles);
|
|
39402
|
-
const profileResult = await discoverBuildCommandsFromProfiles(workingDir);
|
|
39805
|
+
const profileResult = await _internals11.discoverBuildCommandsFromProfiles(workingDir);
|
|
39403
39806
|
const profileCommands = profileResult.commands;
|
|
39404
39807
|
const profileSkipped = profileResult.skipped;
|
|
39405
39808
|
const coveredEcosystems = new Set;
|
|
@@ -39456,7 +39859,13 @@ async function discoverBuildCommands(workingDir, options) {
|
|
|
39456
39859
|
commands.sort((a, b) => a.priority - b.priority);
|
|
39457
39860
|
return { commands, skipped };
|
|
39458
39861
|
}
|
|
39459
|
-
|
|
39862
|
+
function clearToolchainCache() {
|
|
39863
|
+
toolchainCache.clear();
|
|
39864
|
+
}
|
|
39865
|
+
function getEcosystems() {
|
|
39866
|
+
return ECOSYSTEMS.map((e) => e.ecosystem);
|
|
39867
|
+
}
|
|
39868
|
+
var ECOSYSTEMS, PROFILE_TO_ECOSYSTEM_NAMES, toolchainCache, _internals11, build_discovery;
|
|
39460
39869
|
var init_discovery = __esm(() => {
|
|
39461
39870
|
init_dist();
|
|
39462
39871
|
init_detector();
|
|
@@ -39574,6 +39983,13 @@ var init_discovery = __esm(() => {
|
|
|
39574
39983
|
php: ["php-composer"]
|
|
39575
39984
|
};
|
|
39576
39985
|
toolchainCache = new Map;
|
|
39986
|
+
_internals11 = {
|
|
39987
|
+
isCommandAvailable,
|
|
39988
|
+
discoverBuildCommandsFromProfiles,
|
|
39989
|
+
discoverBuildCommands,
|
|
39990
|
+
clearToolchainCache,
|
|
39991
|
+
getEcosystems
|
|
39992
|
+
};
|
|
39577
39993
|
build_discovery = tool({
|
|
39578
39994
|
description: "Discover build commands for various ecosystems in a project directory",
|
|
39579
39995
|
args: {
|
|
@@ -39593,7 +40009,7 @@ var init_discovery = __esm(() => {
|
|
|
39593
40009
|
|
|
39594
40010
|
// src/services/tool-doctor.ts
|
|
39595
40011
|
import * as fs10 from "fs";
|
|
39596
|
-
import * as
|
|
40012
|
+
import * as path23 from "path";
|
|
39597
40013
|
function extractRegisteredToolKeys(indexPath) {
|
|
39598
40014
|
const registeredKeys = new Set;
|
|
39599
40015
|
try {
|
|
@@ -39648,8 +40064,8 @@ function checkBinaryReadiness() {
|
|
|
39648
40064
|
}
|
|
39649
40065
|
function runToolDoctor(_directory, pluginRoot) {
|
|
39650
40066
|
const findings = [];
|
|
39651
|
-
const resolvedPluginRoot = pluginRoot ??
|
|
39652
|
-
const indexPath =
|
|
40067
|
+
const resolvedPluginRoot = pluginRoot ?? path23.resolve(import.meta.dir, "..", "..");
|
|
40068
|
+
const indexPath = path23.join(resolvedPluginRoot, "src", "index.ts");
|
|
39653
40069
|
if (!fs10.existsSync(indexPath)) {
|
|
39654
40070
|
return {
|
|
39655
40071
|
findings: [
|
|
@@ -39819,6 +40235,7 @@ var exports_evidence_summary_service = {};
|
|
|
39819
40235
|
__export(exports_evidence_summary_service, {
|
|
39820
40236
|
isAutoSummaryEnabled: () => isAutoSummaryEnabled,
|
|
39821
40237
|
buildEvidenceSummary: () => buildEvidenceSummary,
|
|
40238
|
+
_internals: () => _internals12,
|
|
39822
40239
|
REQUIRED_EVIDENCE_TYPES: () => REQUIRED_EVIDENCE_TYPES,
|
|
39823
40240
|
EVIDENCE_SUMMARY_VERSION: () => EVIDENCE_SUMMARY_VERSION
|
|
39824
40241
|
});
|
|
@@ -39856,14 +40273,14 @@ function getTaskStatus(task, bundle) {
|
|
|
39856
40273
|
if (task?.status) {
|
|
39857
40274
|
return task.status;
|
|
39858
40275
|
}
|
|
39859
|
-
const entries = normalizeBundleEntries(bundle);
|
|
40276
|
+
const entries = _internals12.normalizeBundleEntries(bundle);
|
|
39860
40277
|
if (entries.length > 0) {
|
|
39861
40278
|
return "completed";
|
|
39862
40279
|
}
|
|
39863
40280
|
return "pending";
|
|
39864
40281
|
}
|
|
39865
40282
|
function isEvidenceComplete(bundle) {
|
|
39866
|
-
const entries = normalizeBundleEntries(bundle);
|
|
40283
|
+
const entries = _internals12.normalizeBundleEntries(bundle);
|
|
39867
40284
|
if (entries.length === 0) {
|
|
39868
40285
|
return {
|
|
39869
40286
|
isComplete: false,
|
|
@@ -39899,10 +40316,10 @@ async function buildTaskSummary(directory, task, taskId) {
|
|
|
39899
40316
|
const result = await loadEvidence(directory, taskId);
|
|
39900
40317
|
const bundle = result.status === "found" ? result.bundle : null;
|
|
39901
40318
|
const phase = task?.phase ?? 0;
|
|
39902
|
-
const status = getTaskStatus(task, bundle);
|
|
39903
|
-
const evidenceCheck = isEvidenceComplete(bundle);
|
|
39904
|
-
const blockers = getTaskBlockers(task, evidenceCheck, status);
|
|
39905
|
-
const entries = normalizeBundleEntries(bundle);
|
|
40319
|
+
const status = _internals12.getTaskStatus(task, bundle);
|
|
40320
|
+
const evidenceCheck = _internals12.isEvidenceComplete(bundle);
|
|
40321
|
+
const blockers = _internals12.getTaskBlockers(task, evidenceCheck, status);
|
|
40322
|
+
const entries = _internals12.normalizeBundleEntries(bundle);
|
|
39906
40323
|
const hasReview = entries.some((e) => e.type === "review");
|
|
39907
40324
|
const hasTest = entries.some((e) => e.type === "test");
|
|
39908
40325
|
const hasApproval = entries.some((e) => e.type === "approval");
|
|
@@ -39931,12 +40348,12 @@ async function buildPhaseSummary(directory, phase) {
|
|
|
39931
40348
|
const taskSummaries = [];
|
|
39932
40349
|
const _taskMap = new Map(phase.tasks.map((t) => [t.id, t]));
|
|
39933
40350
|
for (const task of phase.tasks) {
|
|
39934
|
-
const summary = await buildTaskSummary(directory, task, task.id);
|
|
40351
|
+
const summary = await _internals12.buildTaskSummary(directory, task, task.id);
|
|
39935
40352
|
taskSummaries.push(summary);
|
|
39936
40353
|
}
|
|
39937
40354
|
const extraTaskIds = taskIds.filter((id) => !phaseTaskIds.has(id));
|
|
39938
40355
|
for (const taskId of extraTaskIds) {
|
|
39939
|
-
const summary = await buildTaskSummary(directory, undefined, taskId);
|
|
40356
|
+
const summary = await _internals12.buildTaskSummary(directory, undefined, taskId);
|
|
39940
40357
|
if (summary.phase === phase.id) {
|
|
39941
40358
|
taskSummaries.push(summary);
|
|
39942
40359
|
}
|
|
@@ -40037,7 +40454,7 @@ async function buildEvidenceSummary(directory, currentPhase) {
|
|
|
40037
40454
|
let totalTasks = 0;
|
|
40038
40455
|
let completedTasks = 0;
|
|
40039
40456
|
for (const phase of phasesToProcess) {
|
|
40040
|
-
const summary = await buildPhaseSummary(directory, phase);
|
|
40457
|
+
const summary = await _internals12.buildPhaseSummary(directory, phase);
|
|
40041
40458
|
phaseSummaries.push(summary);
|
|
40042
40459
|
totalTasks += summary.totalTasks;
|
|
40043
40460
|
completedTasks += summary.completedTasks;
|
|
@@ -40059,7 +40476,7 @@ async function buildEvidenceSummary(directory, currentPhase) {
|
|
|
40059
40476
|
overallBlockers,
|
|
40060
40477
|
summaryText: ""
|
|
40061
40478
|
};
|
|
40062
|
-
artifact.summaryText = generateSummaryText(artifact);
|
|
40479
|
+
artifact.summaryText = _internals12.generateSummaryText(artifact);
|
|
40063
40480
|
log("[EvidenceSummary] Summary built", {
|
|
40064
40481
|
phases: phaseSummaries.length,
|
|
40065
40482
|
totalTasks,
|
|
@@ -40078,7 +40495,7 @@ function isAutoSummaryEnabled(automationConfig) {
|
|
|
40078
40495
|
}
|
|
40079
40496
|
return automationConfig.capabilities?.evidence_auto_summaries === true;
|
|
40080
40497
|
}
|
|
40081
|
-
var VALID_EVIDENCE_TYPES2, REQUIRED_EVIDENCE_TYPES, EVIDENCE_SUMMARY_VERSION = "1.0.0";
|
|
40498
|
+
var VALID_EVIDENCE_TYPES2, REQUIRED_EVIDENCE_TYPES, EVIDENCE_SUMMARY_VERSION = "1.0.0", _internals12;
|
|
40082
40499
|
var init_evidence_summary_service = __esm(() => {
|
|
40083
40500
|
init_manager2();
|
|
40084
40501
|
init_manager();
|
|
@@ -40092,6 +40509,17 @@ var init_evidence_summary_service = __esm(() => {
|
|
|
40092
40509
|
"retrospective"
|
|
40093
40510
|
]);
|
|
40094
40511
|
REQUIRED_EVIDENCE_TYPES = ["review", "test"];
|
|
40512
|
+
_internals12 = {
|
|
40513
|
+
buildEvidenceSummary,
|
|
40514
|
+
isAutoSummaryEnabled,
|
|
40515
|
+
normalizeBundleEntries,
|
|
40516
|
+
getTaskStatus,
|
|
40517
|
+
isEvidenceComplete,
|
|
40518
|
+
getTaskBlockers,
|
|
40519
|
+
buildTaskSummary,
|
|
40520
|
+
buildPhaseSummary,
|
|
40521
|
+
generateSummaryText
|
|
40522
|
+
};
|
|
40095
40523
|
});
|
|
40096
40524
|
|
|
40097
40525
|
// src/services/evidence-service.ts
|
|
@@ -40391,7 +40819,7 @@ function extractCurrentPhaseFromPlan2(plan) {
|
|
|
40391
40819
|
if (!plan) {
|
|
40392
40820
|
return { currentPhase: null, currentTask: null, incompleteTasks: [] };
|
|
40393
40821
|
}
|
|
40394
|
-
if (!validatePlanPhases(plan)) {
|
|
40822
|
+
if (!_internals13.validatePlanPhases(plan)) {
|
|
40395
40823
|
return { currentPhase: null, currentTask: null, incompleteTasks: [] };
|
|
40396
40824
|
}
|
|
40397
40825
|
let currentPhase = null;
|
|
@@ -40533,9 +40961,9 @@ function extractPhaseMetrics(content) {
|
|
|
40533
40961
|
async function getHandoffData(directory) {
|
|
40534
40962
|
const now = new Date().toISOString();
|
|
40535
40963
|
const sessionContent = await readSwarmFileAsync(directory, "session/state.json");
|
|
40536
|
-
const sessionState = parseSessionState(sessionContent);
|
|
40964
|
+
const sessionState = _internals13.parseSessionState(sessionContent);
|
|
40537
40965
|
const plan = await loadPlanJsonOnly(directory);
|
|
40538
|
-
const planInfo =
|
|
40966
|
+
const planInfo = _internals13.extractCurrentPhaseFromPlan(plan);
|
|
40539
40967
|
if (!plan) {
|
|
40540
40968
|
const planMdContent = await readSwarmFileAsync(directory, "plan.md");
|
|
40541
40969
|
if (planMdContent) {
|
|
@@ -40554,8 +40982,8 @@ async function getHandoffData(directory) {
|
|
|
40554
40982
|
}
|
|
40555
40983
|
}
|
|
40556
40984
|
const contextContent = await readSwarmFileAsync(directory, "context.md");
|
|
40557
|
-
const recentDecisions = extractDecisions(contextContent);
|
|
40558
|
-
const rawPhaseMetrics = extractPhaseMetrics(contextContent);
|
|
40985
|
+
const recentDecisions = _internals13.extractDecisions(contextContent);
|
|
40986
|
+
const rawPhaseMetrics = _internals13.extractPhaseMetrics(contextContent);
|
|
40559
40987
|
const phaseMetrics = sanitizeString(rawPhaseMetrics, 1000);
|
|
40560
40988
|
let delegationState = null;
|
|
40561
40989
|
if (sessionState?.delegationState) {
|
|
@@ -40719,12 +41147,24 @@ ${lines.join(`
|
|
|
40719
41147
|
`)}
|
|
40720
41148
|
\`\`\``;
|
|
40721
41149
|
}
|
|
40722
|
-
var RTL_OVERRIDE_PATTERN, MAX_TASK_ID_LENGTH = 100, MAX_DECISION_LENGTH = 500, MAX_INCOMPLETE_TASKS = 20;
|
|
41150
|
+
var RTL_OVERRIDE_PATTERN, MAX_TASK_ID_LENGTH = 100, MAX_DECISION_LENGTH = 500, MAX_INCOMPLETE_TASKS = 20, _internals13;
|
|
40723
41151
|
var init_handoff_service = __esm(() => {
|
|
40724
41152
|
init_utils2();
|
|
40725
41153
|
init_manager();
|
|
40726
41154
|
init_utils();
|
|
40727
41155
|
RTL_OVERRIDE_PATTERN = /[\u202e\u202d\u202c\u200f]/g;
|
|
41156
|
+
_internals13 = {
|
|
41157
|
+
getHandoffData,
|
|
41158
|
+
formatHandoffMarkdown,
|
|
41159
|
+
formatContinuationPrompt,
|
|
41160
|
+
escapeHtml,
|
|
41161
|
+
sanitizeString,
|
|
41162
|
+
validatePlanPhases,
|
|
41163
|
+
extractCurrentPhaseFromPlan: extractCurrentPhaseFromPlan2,
|
|
41164
|
+
parseSessionState,
|
|
41165
|
+
extractDecisions,
|
|
41166
|
+
extractPhaseMetrics
|
|
41167
|
+
};
|
|
40728
41168
|
});
|
|
40729
41169
|
|
|
40730
41170
|
// src/commands/handoff.ts
|
|
@@ -41116,14 +41556,23 @@ var init_issue = __esm(() => {
|
|
|
41116
41556
|
|
|
41117
41557
|
// src/hooks/knowledge-migrator.ts
|
|
41118
41558
|
import { randomUUID as randomUUID2 } from "crypto";
|
|
41119
|
-
import { existsSync as
|
|
41120
|
-
import { mkdir as
|
|
41121
|
-
import * as
|
|
41559
|
+
import { existsSync as existsSync14, readFileSync as readFileSync10 } from "fs";
|
|
41560
|
+
import { mkdir as mkdir5, readFile as readFile6, writeFile as writeFile6 } from "fs/promises";
|
|
41561
|
+
import * as path24 from "path";
|
|
41562
|
+
async function migrateKnowledgeToExternal(_directory, _config) {
|
|
41563
|
+
return {
|
|
41564
|
+
migrated: false,
|
|
41565
|
+
entriesMigrated: 0,
|
|
41566
|
+
entriesDropped: 0,
|
|
41567
|
+
entriesTotal: 0,
|
|
41568
|
+
skippedReason: "no-context-file"
|
|
41569
|
+
};
|
|
41570
|
+
}
|
|
41122
41571
|
async function migrateContextToKnowledge(directory, config3) {
|
|
41123
|
-
const sentinelPath =
|
|
41124
|
-
const contextPath =
|
|
41572
|
+
const sentinelPath = path24.join(directory, ".swarm", ".knowledge-migrated");
|
|
41573
|
+
const contextPath = path24.join(directory, ".swarm", "context.md");
|
|
41125
41574
|
const knowledgePath = resolveSwarmKnowledgePath(directory);
|
|
41126
|
-
if (
|
|
41575
|
+
if (existsSync14(sentinelPath)) {
|
|
41127
41576
|
return {
|
|
41128
41577
|
migrated: false,
|
|
41129
41578
|
entriesMigrated: 0,
|
|
@@ -41132,7 +41581,7 @@ async function migrateContextToKnowledge(directory, config3) {
|
|
|
41132
41581
|
skippedReason: "sentinel-exists"
|
|
41133
41582
|
};
|
|
41134
41583
|
}
|
|
41135
|
-
if (!
|
|
41584
|
+
if (!existsSync14(contextPath)) {
|
|
41136
41585
|
return {
|
|
41137
41586
|
migrated: false,
|
|
41138
41587
|
entriesMigrated: 0,
|
|
@@ -41141,7 +41590,7 @@ async function migrateContextToKnowledge(directory, config3) {
|
|
|
41141
41590
|
skippedReason: "no-context-file"
|
|
41142
41591
|
};
|
|
41143
41592
|
}
|
|
41144
|
-
const contextContent = await
|
|
41593
|
+
const contextContent = await readFile6(contextPath, "utf-8");
|
|
41145
41594
|
if (contextContent.trim().length === 0) {
|
|
41146
41595
|
return {
|
|
41147
41596
|
migrated: false,
|
|
@@ -41151,9 +41600,9 @@ async function migrateContextToKnowledge(directory, config3) {
|
|
|
41151
41600
|
skippedReason: "empty-context"
|
|
41152
41601
|
};
|
|
41153
41602
|
}
|
|
41154
|
-
const rawEntries = parseContextMd(contextContent);
|
|
41603
|
+
const rawEntries = _internals14.parseContextMd(contextContent);
|
|
41155
41604
|
if (rawEntries.length === 0) {
|
|
41156
|
-
await writeSentinel(sentinelPath, 0, 0);
|
|
41605
|
+
await _internals14.writeSentinel(sentinelPath, 0, 0);
|
|
41157
41606
|
return {
|
|
41158
41607
|
migrated: true,
|
|
41159
41608
|
entriesMigrated: 0,
|
|
@@ -41164,10 +41613,10 @@ async function migrateContextToKnowledge(directory, config3) {
|
|
|
41164
41613
|
const existing = await readKnowledge(knowledgePath);
|
|
41165
41614
|
let migrated = 0;
|
|
41166
41615
|
let dropped = 0;
|
|
41167
|
-
const projectName = inferProjectName(directory);
|
|
41616
|
+
const projectName = _internals14.inferProjectName(directory);
|
|
41168
41617
|
for (const raw of rawEntries) {
|
|
41169
41618
|
if (config3.validation_enabled !== false) {
|
|
41170
|
-
const category = raw.categoryHint ?? inferCategoryFromText(raw.text);
|
|
41619
|
+
const category = raw.categoryHint ?? _internals14.inferCategoryFromText(raw.text);
|
|
41171
41620
|
const result = validateLesson(raw.text, existing.map((e) => e.lesson), {
|
|
41172
41621
|
category,
|
|
41173
41622
|
scope: "global",
|
|
@@ -41187,8 +41636,8 @@ async function migrateContextToKnowledge(directory, config3) {
|
|
|
41187
41636
|
const entry = {
|
|
41188
41637
|
id: randomUUID2(),
|
|
41189
41638
|
tier: "swarm",
|
|
41190
|
-
lesson: truncateLesson(raw.text),
|
|
41191
|
-
category: raw.categoryHint ?? inferCategoryFromText(raw.text),
|
|
41639
|
+
lesson: _internals14.truncateLesson(raw.text),
|
|
41640
|
+
category: raw.categoryHint ?? _internals14.inferCategoryFromText(raw.text),
|
|
41192
41641
|
tags: [...inferredTags, `migration:${raw.sourceSection}`],
|
|
41193
41642
|
scope: "global",
|
|
41194
41643
|
confidence: 0.3,
|
|
@@ -41211,7 +41660,7 @@ async function migrateContextToKnowledge(directory, config3) {
|
|
|
41211
41660
|
if (migrated > 0) {
|
|
41212
41661
|
await rewriteKnowledge(knowledgePath, existing);
|
|
41213
41662
|
}
|
|
41214
|
-
await writeSentinel(sentinelPath, migrated, dropped);
|
|
41663
|
+
await _internals14.writeSentinel(sentinelPath, migrated, dropped);
|
|
41215
41664
|
log(`[knowledge-migrator] Migrated ${migrated} entries, dropped ${dropped}`);
|
|
41216
41665
|
return {
|
|
41217
41666
|
migrated: true,
|
|
@@ -41221,7 +41670,7 @@ async function migrateContextToKnowledge(directory, config3) {
|
|
|
41221
41670
|
};
|
|
41222
41671
|
}
|
|
41223
41672
|
function parseContextMd(content) {
|
|
41224
|
-
const sections = splitIntoSections(content);
|
|
41673
|
+
const sections = _internals14.splitIntoSections(content);
|
|
41225
41674
|
const entries = [];
|
|
41226
41675
|
const seen = new Set;
|
|
41227
41676
|
const sectionPatterns = [
|
|
@@ -41237,7 +41686,7 @@ function parseContextMd(content) {
|
|
|
41237
41686
|
const match = sectionPatterns.find((sp) => sp.pattern.test(section.heading));
|
|
41238
41687
|
if (!match)
|
|
41239
41688
|
continue;
|
|
41240
|
-
const bullets = extractBullets(section.body);
|
|
41689
|
+
const bullets = _internals14.extractBullets(section.body);
|
|
41241
41690
|
for (const bullet of bullets) {
|
|
41242
41691
|
if (bullet.length < 15)
|
|
41243
41692
|
continue;
|
|
@@ -41246,9 +41695,9 @@ function parseContextMd(content) {
|
|
|
41246
41695
|
continue;
|
|
41247
41696
|
seen.add(normalized);
|
|
41248
41697
|
entries.push({
|
|
41249
|
-
text: truncateLesson(bullet),
|
|
41698
|
+
text: _internals14.truncateLesson(bullet),
|
|
41250
41699
|
sourceSection: match.sourceSection,
|
|
41251
|
-
categoryHint: inferCategoryFromText(bullet)
|
|
41700
|
+
categoryHint: _internals14.inferCategoryFromText(bullet)
|
|
41252
41701
|
});
|
|
41253
41702
|
}
|
|
41254
41703
|
}
|
|
@@ -41317,8 +41766,8 @@ function truncateLesson(text) {
|
|
|
41317
41766
|
return `${text.slice(0, 277)}...`;
|
|
41318
41767
|
}
|
|
41319
41768
|
function inferProjectName(directory) {
|
|
41320
|
-
const packageJsonPath =
|
|
41321
|
-
if (
|
|
41769
|
+
const packageJsonPath = path24.join(directory, "package.json");
|
|
41770
|
+
if (existsSync14(packageJsonPath)) {
|
|
41322
41771
|
try {
|
|
41323
41772
|
const pkg = JSON.parse(readFileSync10(packageJsonPath, "utf-8"));
|
|
41324
41773
|
if (pkg.name && typeof pkg.name === "string") {
|
|
@@ -41326,7 +41775,7 @@ function inferProjectName(directory) {
|
|
|
41326
41775
|
}
|
|
41327
41776
|
} catch {}
|
|
41328
41777
|
}
|
|
41329
|
-
return
|
|
41778
|
+
return path24.basename(directory);
|
|
41330
41779
|
}
|
|
41331
41780
|
async function writeSentinel(sentinelPath, migrated, dropped) {
|
|
41332
41781
|
const sentinel = {
|
|
@@ -41338,16 +41787,29 @@ async function writeSentinel(sentinelPath, migrated, dropped) {
|
|
|
41338
41787
|
schema_version: 1,
|
|
41339
41788
|
migration_tool: "knowledge-migrator.ts"
|
|
41340
41789
|
};
|
|
41341
|
-
await
|
|
41342
|
-
await
|
|
41790
|
+
await mkdir5(path24.dirname(sentinelPath), { recursive: true });
|
|
41791
|
+
await writeFile6(sentinelPath, JSON.stringify(sentinel, null, 2), "utf-8");
|
|
41343
41792
|
}
|
|
41793
|
+
var _internals14;
|
|
41344
41794
|
var init_knowledge_migrator = __esm(() => {
|
|
41795
|
+
init_logger();
|
|
41345
41796
|
init_knowledge_store();
|
|
41346
41797
|
init_knowledge_validator();
|
|
41798
|
+
_internals14 = {
|
|
41799
|
+
migrateContextToKnowledge,
|
|
41800
|
+
migrateKnowledgeToExternal,
|
|
41801
|
+
parseContextMd,
|
|
41802
|
+
splitIntoSections,
|
|
41803
|
+
extractBullets,
|
|
41804
|
+
inferCategoryFromText,
|
|
41805
|
+
truncateLesson,
|
|
41806
|
+
inferProjectName,
|
|
41807
|
+
writeSentinel
|
|
41808
|
+
};
|
|
41347
41809
|
});
|
|
41348
41810
|
|
|
41349
41811
|
// src/commands/knowledge.ts
|
|
41350
|
-
import { join as
|
|
41812
|
+
import { join as join23 } from "path";
|
|
41351
41813
|
function resolveEntryByPrefix(entries, inputId) {
|
|
41352
41814
|
const exact = entries.find((e) => e.id === inputId);
|
|
41353
41815
|
if (exact)
|
|
@@ -41398,7 +41860,7 @@ async function handleKnowledgeRestoreCommand(directory, args) {
|
|
|
41398
41860
|
return "Invalid entry ID. IDs must be 1-64 characters: letters, digits, hyphens, underscores only.";
|
|
41399
41861
|
}
|
|
41400
41862
|
try {
|
|
41401
|
-
const quarantinePath =
|
|
41863
|
+
const quarantinePath = join23(directory, ".swarm", "knowledge-quarantined.jsonl");
|
|
41402
41864
|
const entries = await readKnowledge(quarantinePath);
|
|
41403
41865
|
const resolved = resolveEntryByPrefix(entries, inputId);
|
|
41404
41866
|
if ("error" in resolved) {
|
|
@@ -41847,7 +42309,7 @@ var init_path_security = () => {};
|
|
|
41847
42309
|
|
|
41848
42310
|
// src/tools/lint.ts
|
|
41849
42311
|
import * as fs11 from "fs";
|
|
41850
|
-
import * as
|
|
42312
|
+
import * as path25 from "path";
|
|
41851
42313
|
function validateArgs(args) {
|
|
41852
42314
|
if (typeof args !== "object" || args === null)
|
|
41853
42315
|
return false;
|
|
@@ -41858,9 +42320,9 @@ function validateArgs(args) {
|
|
|
41858
42320
|
}
|
|
41859
42321
|
function getLinterCommand(linter, mode, projectDir) {
|
|
41860
42322
|
const isWindows = process.platform === "win32";
|
|
41861
|
-
const binDir =
|
|
41862
|
-
const biomeBin = isWindows ?
|
|
41863
|
-
const eslintBin = isWindows ?
|
|
42323
|
+
const binDir = path25.join(projectDir, "node_modules", ".bin");
|
|
42324
|
+
const biomeBin = isWindows ? path25.join(binDir, "biome.EXE") : path25.join(binDir, "biome");
|
|
42325
|
+
const eslintBin = isWindows ? path25.join(binDir, "eslint.cmd") : path25.join(binDir, "eslint");
|
|
41864
42326
|
switch (linter) {
|
|
41865
42327
|
case "biome":
|
|
41866
42328
|
if (mode === "fix") {
|
|
@@ -41876,7 +42338,7 @@ function getLinterCommand(linter, mode, projectDir) {
|
|
|
41876
42338
|
}
|
|
41877
42339
|
function getAdditionalLinterCommand(linter, mode, cwd) {
|
|
41878
42340
|
const gradlewName = process.platform === "win32" ? "gradlew.bat" : "gradlew";
|
|
41879
|
-
const gradlew = fs11.existsSync(
|
|
42341
|
+
const gradlew = fs11.existsSync(path25.join(cwd, gradlewName)) ? path25.join(cwd, gradlewName) : null;
|
|
41880
42342
|
switch (linter) {
|
|
41881
42343
|
case "ruff":
|
|
41882
42344
|
return mode === "fix" ? ["ruff", "check", "--fix", "."] : ["ruff", "check", "."];
|
|
@@ -41910,10 +42372,10 @@ function getAdditionalLinterCommand(linter, mode, cwd) {
|
|
|
41910
42372
|
}
|
|
41911
42373
|
}
|
|
41912
42374
|
function detectRuff(cwd) {
|
|
41913
|
-
if (fs11.existsSync(
|
|
42375
|
+
if (fs11.existsSync(path25.join(cwd, "ruff.toml")))
|
|
41914
42376
|
return isCommandAvailable("ruff");
|
|
41915
42377
|
try {
|
|
41916
|
-
const pyproject =
|
|
42378
|
+
const pyproject = path25.join(cwd, "pyproject.toml");
|
|
41917
42379
|
if (fs11.existsSync(pyproject)) {
|
|
41918
42380
|
const content = fs11.readFileSync(pyproject, "utf-8");
|
|
41919
42381
|
if (content.includes("[tool.ruff]"))
|
|
@@ -41923,19 +42385,19 @@ function detectRuff(cwd) {
|
|
|
41923
42385
|
return false;
|
|
41924
42386
|
}
|
|
41925
42387
|
function detectClippy(cwd) {
|
|
41926
|
-
return fs11.existsSync(
|
|
42388
|
+
return fs11.existsSync(path25.join(cwd, "Cargo.toml")) && isCommandAvailable("cargo");
|
|
41927
42389
|
}
|
|
41928
42390
|
function detectGolangciLint(cwd) {
|
|
41929
|
-
return fs11.existsSync(
|
|
42391
|
+
return fs11.existsSync(path25.join(cwd, "go.mod")) && isCommandAvailable("golangci-lint");
|
|
41930
42392
|
}
|
|
41931
42393
|
function detectCheckstyle(cwd) {
|
|
41932
|
-
const hasMaven = fs11.existsSync(
|
|
41933
|
-
const hasGradle = fs11.existsSync(
|
|
41934
|
-
const hasBinary = hasMaven && isCommandAvailable("mvn") || hasGradle && (fs11.existsSync(
|
|
42394
|
+
const hasMaven = fs11.existsSync(path25.join(cwd, "pom.xml"));
|
|
42395
|
+
const hasGradle = fs11.existsSync(path25.join(cwd, "build.gradle")) || fs11.existsSync(path25.join(cwd, "build.gradle.kts"));
|
|
42396
|
+
const hasBinary = hasMaven && isCommandAvailable("mvn") || hasGradle && (fs11.existsSync(path25.join(cwd, "gradlew")) || isCommandAvailable("gradle"));
|
|
41935
42397
|
return (hasMaven || hasGradle) && hasBinary;
|
|
41936
42398
|
}
|
|
41937
42399
|
function detectKtlint(cwd) {
|
|
41938
|
-
const hasKotlin = fs11.existsSync(
|
|
42400
|
+
const hasKotlin = fs11.existsSync(path25.join(cwd, "build.gradle.kts")) || fs11.existsSync(path25.join(cwd, "build.gradle")) || (() => {
|
|
41939
42401
|
try {
|
|
41940
42402
|
return fs11.readdirSync(cwd).some((f) => f.endsWith(".kt") || f.endsWith(".kts"));
|
|
41941
42403
|
} catch {
|
|
@@ -41954,11 +42416,11 @@ function detectDotnetFormat(cwd) {
|
|
|
41954
42416
|
}
|
|
41955
42417
|
}
|
|
41956
42418
|
function detectCppcheck(cwd) {
|
|
41957
|
-
if (fs11.existsSync(
|
|
42419
|
+
if (fs11.existsSync(path25.join(cwd, "CMakeLists.txt"))) {
|
|
41958
42420
|
return isCommandAvailable("cppcheck");
|
|
41959
42421
|
}
|
|
41960
42422
|
try {
|
|
41961
|
-
const dirsToCheck = [cwd,
|
|
42423
|
+
const dirsToCheck = [cwd, path25.join(cwd, "src")];
|
|
41962
42424
|
const hasCpp = dirsToCheck.some((dir) => {
|
|
41963
42425
|
try {
|
|
41964
42426
|
return fs11.readdirSync(dir).some((f) => /\.(c|cpp|cc|cxx|h|hpp)$/.test(f));
|
|
@@ -41972,13 +42434,13 @@ function detectCppcheck(cwd) {
|
|
|
41972
42434
|
}
|
|
41973
42435
|
}
|
|
41974
42436
|
function detectSwiftlint(cwd) {
|
|
41975
|
-
return fs11.existsSync(
|
|
42437
|
+
return fs11.existsSync(path25.join(cwd, "Package.swift")) && isCommandAvailable("swiftlint");
|
|
41976
42438
|
}
|
|
41977
42439
|
function detectDartAnalyze(cwd) {
|
|
41978
|
-
return fs11.existsSync(
|
|
42440
|
+
return fs11.existsSync(path25.join(cwd, "pubspec.yaml")) && (isCommandAvailable("dart") || isCommandAvailable("flutter"));
|
|
41979
42441
|
}
|
|
41980
42442
|
function detectRubocop(cwd) {
|
|
41981
|
-
return (fs11.existsSync(
|
|
42443
|
+
return (fs11.existsSync(path25.join(cwd, "Gemfile")) || fs11.existsSync(path25.join(cwd, "gems.rb")) || fs11.existsSync(path25.join(cwd, ".rubocop.yml"))) && (isCommandAvailable("rubocop") || isCommandAvailable("bundle"));
|
|
41982
42444
|
}
|
|
41983
42445
|
function detectAdditionalLinter(cwd) {
|
|
41984
42446
|
if (detectRuff(cwd))
|
|
@@ -42006,10 +42468,10 @@ function detectAdditionalLinter(cwd) {
|
|
|
42006
42468
|
function findBinInAncestors(startDir, binName) {
|
|
42007
42469
|
let dir = startDir;
|
|
42008
42470
|
while (true) {
|
|
42009
|
-
const candidate =
|
|
42471
|
+
const candidate = path25.join(dir, "node_modules", ".bin", binName);
|
|
42010
42472
|
if (fs11.existsSync(candidate))
|
|
42011
42473
|
return candidate;
|
|
42012
|
-
const parent =
|
|
42474
|
+
const parent = path25.dirname(dir);
|
|
42013
42475
|
if (parent === dir)
|
|
42014
42476
|
break;
|
|
42015
42477
|
dir = parent;
|
|
@@ -42018,10 +42480,10 @@ function findBinInAncestors(startDir, binName) {
|
|
|
42018
42480
|
}
|
|
42019
42481
|
function findBinInEnvPath(binName) {
|
|
42020
42482
|
const searchPath = process.env.PATH ?? "";
|
|
42021
|
-
for (const dir of searchPath.split(
|
|
42483
|
+
for (const dir of searchPath.split(path25.delimiter)) {
|
|
42022
42484
|
if (!dir)
|
|
42023
42485
|
continue;
|
|
42024
|
-
const candidate =
|
|
42486
|
+
const candidate = path25.join(dir, binName);
|
|
42025
42487
|
if (fs11.existsSync(candidate))
|
|
42026
42488
|
return candidate;
|
|
42027
42489
|
}
|
|
@@ -42034,13 +42496,13 @@ async function detectAvailableLinter(directory) {
|
|
|
42034
42496
|
return null;
|
|
42035
42497
|
const projectDir = directory;
|
|
42036
42498
|
const isWindows = process.platform === "win32";
|
|
42037
|
-
const biomeBin = isWindows ?
|
|
42038
|
-
const eslintBin = isWindows ?
|
|
42499
|
+
const biomeBin = isWindows ? path25.join(projectDir, "node_modules", ".bin", "biome.EXE") : path25.join(projectDir, "node_modules", ".bin", "biome");
|
|
42500
|
+
const eslintBin = isWindows ? path25.join(projectDir, "node_modules", ".bin", "eslint.cmd") : path25.join(projectDir, "node_modules", ".bin", "eslint");
|
|
42039
42501
|
const localResult = await _detectAvailableLinter(projectDir, biomeBin, eslintBin);
|
|
42040
42502
|
if (localResult)
|
|
42041
42503
|
return localResult;
|
|
42042
|
-
const biomeAncestor = findBinInAncestors(
|
|
42043
|
-
const eslintAncestor = findBinInAncestors(
|
|
42504
|
+
const biomeAncestor = findBinInAncestors(path25.dirname(projectDir), isWindows ? "biome.EXE" : "biome");
|
|
42505
|
+
const eslintAncestor = findBinInAncestors(path25.dirname(projectDir), isWindows ? "eslint.cmd" : "eslint");
|
|
42044
42506
|
if (biomeAncestor || eslintAncestor) {
|
|
42045
42507
|
return _detectAvailableLinter(projectDir, biomeAncestor ?? biomeBin, eslintAncestor ?? eslintBin);
|
|
42046
42508
|
}
|
|
@@ -42199,7 +42661,7 @@ async function runAdditionalLint(linter, mode, cwd) {
|
|
|
42199
42661
|
};
|
|
42200
42662
|
}
|
|
42201
42663
|
}
|
|
42202
|
-
var MAX_OUTPUT_BYTES = 512000, MAX_COMMAND_LENGTH = 500, lint;
|
|
42664
|
+
var MAX_OUTPUT_BYTES = 512000, MAX_COMMAND_LENGTH = 500, lint, _internals15;
|
|
42203
42665
|
var init_lint = __esm(() => {
|
|
42204
42666
|
init_zod();
|
|
42205
42667
|
init_discovery();
|
|
@@ -42231,15 +42693,15 @@ var init_lint = __esm(() => {
|
|
|
42231
42693
|
}
|
|
42232
42694
|
const { mode } = args;
|
|
42233
42695
|
const cwd = directory;
|
|
42234
|
-
const linter = await detectAvailableLinter(directory);
|
|
42696
|
+
const linter = await _internals15.detectAvailableLinter(directory);
|
|
42235
42697
|
if (linter) {
|
|
42236
|
-
const result = await runLint(linter, mode, directory);
|
|
42698
|
+
const result = await _internals15.runLint(linter, mode, directory);
|
|
42237
42699
|
return JSON.stringify(result, null, 2);
|
|
42238
42700
|
}
|
|
42239
|
-
const additionalLinter = detectAdditionalLinter(cwd);
|
|
42701
|
+
const additionalLinter = _internals15.detectAdditionalLinter(cwd);
|
|
42240
42702
|
if (additionalLinter) {
|
|
42241
42703
|
warn(`[lint] Using ${additionalLinter} linter for this project`);
|
|
42242
|
-
const result = await runAdditionalLint(additionalLinter, mode, cwd);
|
|
42704
|
+
const result = await _internals15.runAdditionalLint(additionalLinter, mode, cwd);
|
|
42243
42705
|
return JSON.stringify(result, null, 2);
|
|
42244
42706
|
}
|
|
42245
42707
|
const errorResult = {
|
|
@@ -42253,11 +42715,17 @@ For Rust: rustup component add clippy`
|
|
|
42253
42715
|
return JSON.stringify(errorResult, null, 2);
|
|
42254
42716
|
}
|
|
42255
42717
|
});
|
|
42718
|
+
_internals15 = {
|
|
42719
|
+
detectAvailableLinter,
|
|
42720
|
+
runLint,
|
|
42721
|
+
detectAdditionalLinter,
|
|
42722
|
+
runAdditionalLint
|
|
42723
|
+
};
|
|
42256
42724
|
});
|
|
42257
42725
|
|
|
42258
42726
|
// src/tools/secretscan.ts
|
|
42259
42727
|
import * as fs12 from "fs";
|
|
42260
|
-
import * as
|
|
42728
|
+
import * as path26 from "path";
|
|
42261
42729
|
function calculateShannonEntropy(str) {
|
|
42262
42730
|
if (str.length === 0)
|
|
42263
42731
|
return 0;
|
|
@@ -42305,7 +42773,7 @@ function isGlobOrPathPattern(pattern) {
|
|
|
42305
42773
|
return pattern.includes("/") || pattern.includes("\\") || /[*?[\]{}]/.test(pattern);
|
|
42306
42774
|
}
|
|
42307
42775
|
function loadSecretScanIgnore(scanDir) {
|
|
42308
|
-
const ignorePath =
|
|
42776
|
+
const ignorePath = path26.join(scanDir, ".secretscanignore");
|
|
42309
42777
|
try {
|
|
42310
42778
|
if (!fs12.existsSync(ignorePath))
|
|
42311
42779
|
return [];
|
|
@@ -42328,7 +42796,7 @@ function isExcluded(entry, relPath, exactNames, globPatterns) {
|
|
|
42328
42796
|
if (exactNames.has(entry))
|
|
42329
42797
|
return true;
|
|
42330
42798
|
for (const pattern of globPatterns) {
|
|
42331
|
-
if (
|
|
42799
|
+
if (path26.matchesGlob(relPath, pattern))
|
|
42332
42800
|
return true;
|
|
42333
42801
|
}
|
|
42334
42802
|
return false;
|
|
@@ -42349,7 +42817,7 @@ function validateDirectoryInput(dir) {
|
|
|
42349
42817
|
return null;
|
|
42350
42818
|
}
|
|
42351
42819
|
function isBinaryFile(filePath, buffer) {
|
|
42352
|
-
const ext =
|
|
42820
|
+
const ext = path26.extname(filePath).toLowerCase();
|
|
42353
42821
|
if (DEFAULT_EXCLUDE_EXTENSIONS.has(ext)) {
|
|
42354
42822
|
return true;
|
|
42355
42823
|
}
|
|
@@ -42485,9 +42953,9 @@ function isSymlinkLoop(realPath, visited) {
|
|
|
42485
42953
|
return false;
|
|
42486
42954
|
}
|
|
42487
42955
|
function isPathWithinScope(realPath, scanDir) {
|
|
42488
|
-
const resolvedScanDir =
|
|
42489
|
-
const resolvedRealPath =
|
|
42490
|
-
return resolvedRealPath === resolvedScanDir || resolvedRealPath.startsWith(resolvedScanDir +
|
|
42956
|
+
const resolvedScanDir = path26.resolve(scanDir);
|
|
42957
|
+
const resolvedRealPath = path26.resolve(realPath);
|
|
42958
|
+
return resolvedRealPath === resolvedScanDir || resolvedRealPath.startsWith(resolvedScanDir + path26.sep) || resolvedRealPath.startsWith(`${resolvedScanDir}/`) || resolvedRealPath.startsWith(`${resolvedScanDir}\\`);
|
|
42491
42959
|
}
|
|
42492
42960
|
function findScannableFiles(dir, excludeExact, excludeGlobs, scanDir, visited, stats = {
|
|
42493
42961
|
skippedDirs: 0,
|
|
@@ -42513,8 +42981,8 @@ function findScannableFiles(dir, excludeExact, excludeGlobs, scanDir, visited, s
|
|
|
42513
42981
|
return a.localeCompare(b);
|
|
42514
42982
|
});
|
|
42515
42983
|
for (const entry of entries) {
|
|
42516
|
-
const fullPath =
|
|
42517
|
-
const relPath =
|
|
42984
|
+
const fullPath = path26.join(dir, entry);
|
|
42985
|
+
const relPath = path26.relative(scanDir, fullPath).replace(/\\/g, "/");
|
|
42518
42986
|
if (isExcluded(entry, relPath, excludeExact, excludeGlobs)) {
|
|
42519
42987
|
stats.skippedDirs++;
|
|
42520
42988
|
continue;
|
|
@@ -42549,7 +43017,7 @@ function findScannableFiles(dir, excludeExact, excludeGlobs, scanDir, visited, s
|
|
|
42549
43017
|
const subFiles = findScannableFiles(fullPath, excludeExact, excludeGlobs, scanDir, visited, stats);
|
|
42550
43018
|
files.push(...subFiles);
|
|
42551
43019
|
} else if (lstat.isFile()) {
|
|
42552
|
-
const ext =
|
|
43020
|
+
const ext = path26.extname(fullPath).toLowerCase();
|
|
42553
43021
|
if (!DEFAULT_EXCLUDE_EXTENSIONS.has(ext)) {
|
|
42554
43022
|
files.push(fullPath);
|
|
42555
43023
|
} else {
|
|
@@ -42561,7 +43029,7 @@ function findScannableFiles(dir, excludeExact, excludeGlobs, scanDir, visited, s
|
|
|
42561
43029
|
}
|
|
42562
43030
|
async function runSecretscan(directory) {
|
|
42563
43031
|
try {
|
|
42564
|
-
const result = await secretscan.execute({ directory }, {});
|
|
43032
|
+
const result = await _internals16.secretscan.execute({ directory }, {});
|
|
42565
43033
|
const jsonStr = typeof result === "string" ? result : result.output;
|
|
42566
43034
|
return JSON.parse(jsonStr);
|
|
42567
43035
|
} catch (e) {
|
|
@@ -42576,7 +43044,7 @@ async function runSecretscan(directory) {
|
|
|
42576
43044
|
return errorResult;
|
|
42577
43045
|
}
|
|
42578
43046
|
}
|
|
42579
|
-
var MAX_FILE_PATH_LENGTH = 500, MAX_FILE_SIZE_BYTES, MAX_FILES_SCANNED = 1000, MAX_FINDINGS = 100, MAX_OUTPUT_BYTES2 = 512000, MAX_LINE_LENGTH = 1e4, MAX_CONTENT_BYTES, BINARY_SIGNATURES, BINARY_PREFIX_BYTES = 4, BINARY_NULL_CHECK_BYTES = 8192, BINARY_NULL_THRESHOLD = 0.1, DEFAULT_EXCLUDE_DIRS, DEFAULT_EXCLUDE_EXTENSIONS, SECRET_PATTERNS, O_NOFOLLOW, secretscan;
|
|
43047
|
+
var MAX_FILE_PATH_LENGTH = 500, MAX_FILE_SIZE_BYTES, MAX_FILES_SCANNED = 1000, MAX_FINDINGS = 100, MAX_OUTPUT_BYTES2 = 512000, MAX_LINE_LENGTH = 1e4, MAX_CONTENT_BYTES, BINARY_SIGNATURES, BINARY_PREFIX_BYTES = 4, BINARY_NULL_CHECK_BYTES = 8192, BINARY_NULL_THRESHOLD = 0.1, DEFAULT_EXCLUDE_DIRS, DEFAULT_EXCLUDE_EXTENSIONS, SECRET_PATTERNS, O_NOFOLLOW, secretscan, _internals16;
|
|
42580
43048
|
var init_secretscan = __esm(() => {
|
|
42581
43049
|
init_zod();
|
|
42582
43050
|
init_path_security();
|
|
@@ -42809,7 +43277,7 @@ var init_secretscan = __esm(() => {
|
|
|
42809
43277
|
}
|
|
42810
43278
|
}
|
|
42811
43279
|
try {
|
|
42812
|
-
const _scanDirRaw =
|
|
43280
|
+
const _scanDirRaw = path26.resolve(directory);
|
|
42813
43281
|
const scanDir = (() => {
|
|
42814
43282
|
try {
|
|
42815
43283
|
return fs12.realpathSync(_scanDirRaw);
|
|
@@ -42948,11 +43416,15 @@ var init_secretscan = __esm(() => {
|
|
|
42948
43416
|
}
|
|
42949
43417
|
}
|
|
42950
43418
|
});
|
|
43419
|
+
_internals16 = {
|
|
43420
|
+
secretscan,
|
|
43421
|
+
runSecretscan
|
|
43422
|
+
};
|
|
42951
43423
|
});
|
|
42952
43424
|
|
|
42953
43425
|
// src/test-impact/analyzer.ts
|
|
42954
43426
|
import fs13 from "fs";
|
|
42955
|
-
import
|
|
43427
|
+
import path27 from "path";
|
|
42956
43428
|
function normalizePath(p) {
|
|
42957
43429
|
return p.replace(/\\/g, "/");
|
|
42958
43430
|
}
|
|
@@ -42973,8 +43445,8 @@ function resolveRelativeImport(fromDir, importPath) {
|
|
|
42973
43445
|
if (!importPath.startsWith(".")) {
|
|
42974
43446
|
return null;
|
|
42975
43447
|
}
|
|
42976
|
-
const resolved =
|
|
42977
|
-
if (
|
|
43448
|
+
const resolved = path27.resolve(fromDir, importPath);
|
|
43449
|
+
if (path27.extname(resolved)) {
|
|
42978
43450
|
if (fs13.existsSync(resolved) && fs13.statSync(resolved).isFile()) {
|
|
42979
43451
|
return normalizePath(resolved);
|
|
42980
43452
|
}
|
|
@@ -43019,12 +43491,12 @@ function findTestFilesSync(cwd) {
|
|
|
43019
43491
|
for (const entry of entries) {
|
|
43020
43492
|
if (entry.isDirectory()) {
|
|
43021
43493
|
if (!skipDirs.has(entry.name)) {
|
|
43022
|
-
walk(
|
|
43494
|
+
walk(path27.join(dir, entry.name), visitedInodes);
|
|
43023
43495
|
}
|
|
43024
43496
|
} else if (entry.isFile()) {
|
|
43025
43497
|
const name = entry.name;
|
|
43026
43498
|
if (/\.(test|spec)\.(ts|tsx|js|jsx)$/.test(name) || dir.includes("__tests__") && /\.(ts|tsx|js|jsx)$/.test(name)) {
|
|
43027
|
-
testFiles.push(normalizePath(
|
|
43499
|
+
testFiles.push(normalizePath(path27.join(dir, entry.name)));
|
|
43028
43500
|
}
|
|
43029
43501
|
}
|
|
43030
43502
|
}
|
|
@@ -43062,7 +43534,7 @@ async function buildImpactMapInternal(cwd) {
|
|
|
43062
43534
|
continue;
|
|
43063
43535
|
}
|
|
43064
43536
|
const imports = extractImports(content);
|
|
43065
|
-
const testDir =
|
|
43537
|
+
const testDir = path27.dirname(testFile);
|
|
43066
43538
|
for (const importPath of imports) {
|
|
43067
43539
|
const resolvedSource = resolveRelativeImport(testDir, importPath);
|
|
43068
43540
|
if (resolvedSource === null) {
|
|
@@ -43079,28 +43551,28 @@ async function buildImpactMapInternal(cwd) {
|
|
|
43079
43551
|
return impactMap;
|
|
43080
43552
|
}
|
|
43081
43553
|
async function buildImpactMap(cwd) {
|
|
43082
|
-
const impactMap = await buildImpactMapInternal(cwd);
|
|
43083
|
-
await saveImpactMap(cwd, impactMap);
|
|
43554
|
+
const impactMap = await _internals17.buildImpactMapInternal(cwd);
|
|
43555
|
+
await _internals17.saveImpactMap(cwd, impactMap);
|
|
43084
43556
|
return impactMap;
|
|
43085
43557
|
}
|
|
43086
43558
|
async function loadImpactMap(cwd) {
|
|
43087
|
-
const cachePath =
|
|
43559
|
+
const cachePath = path27.join(cwd, ".swarm", "cache", "impact-map.json");
|
|
43088
43560
|
if (fs13.existsSync(cachePath)) {
|
|
43089
43561
|
try {
|
|
43090
43562
|
const content = fs13.readFileSync(cachePath, "utf-8");
|
|
43091
43563
|
const data = JSON.parse(content);
|
|
43092
43564
|
const map3 = data.map;
|
|
43093
43565
|
const generatedAt = new Date(data.generatedAt).getTime();
|
|
43094
|
-
if (!isCacheStale(map3, generatedAt)) {
|
|
43566
|
+
if (!_internals17.isCacheStale(map3, generatedAt)) {
|
|
43095
43567
|
return map3;
|
|
43096
43568
|
}
|
|
43097
43569
|
} catch {}
|
|
43098
43570
|
}
|
|
43099
|
-
return buildImpactMap(cwd);
|
|
43571
|
+
return _internals17.buildImpactMap(cwd);
|
|
43100
43572
|
}
|
|
43101
43573
|
async function saveImpactMap(cwd, impactMap) {
|
|
43102
|
-
const cacheDir2 =
|
|
43103
|
-
const cachePath =
|
|
43574
|
+
const cacheDir2 = path27.join(cwd, ".swarm", "cache");
|
|
43575
|
+
const cachePath = path27.join(cacheDir2, "impact-map.json");
|
|
43104
43576
|
if (!fs13.existsSync(cacheDir2)) {
|
|
43105
43577
|
fs13.mkdirSync(cacheDir2, { recursive: true });
|
|
43106
43578
|
}
|
|
@@ -43122,11 +43594,11 @@ async function analyzeImpact(changedFiles, cwd) {
|
|
|
43122
43594
|
};
|
|
43123
43595
|
}
|
|
43124
43596
|
const validFiles = changedFiles.filter((f) => typeof f === "string" && f.length > 0 && !f.includes("\x00"));
|
|
43125
|
-
const impactMap = await loadImpactMap(cwd);
|
|
43597
|
+
const impactMap = await _internals17.loadImpactMap(cwd);
|
|
43126
43598
|
const impactedTestsSet = new Set;
|
|
43127
43599
|
const untestedFiles = [];
|
|
43128
43600
|
for (const changedFile of validFiles) {
|
|
43129
|
-
const normalizedChanged = normalizePath(
|
|
43601
|
+
const normalizedChanged = normalizePath(path27.resolve(changedFile));
|
|
43130
43602
|
const tests = impactMap[normalizedChanged];
|
|
43131
43603
|
if (tests && tests.length > 0) {
|
|
43132
43604
|
for (const test of tests) {
|
|
@@ -43163,12 +43635,24 @@ async function analyzeImpact(changedFiles, cwd) {
|
|
|
43163
43635
|
impactMap
|
|
43164
43636
|
};
|
|
43165
43637
|
}
|
|
43166
|
-
var IMPORT_REGEX_ES, IMPORT_REGEX_REQUIRE, IMPORT_REGEX_REEXPORT, EXTENSIONS_TO_TRY;
|
|
43638
|
+
var IMPORT_REGEX_ES, IMPORT_REGEX_REQUIRE, IMPORT_REGEX_REEXPORT, EXTENSIONS_TO_TRY, _internals17;
|
|
43167
43639
|
var init_analyzer = __esm(() => {
|
|
43168
43640
|
IMPORT_REGEX_ES = /import\s+.*?\s+from\s+['"]([^'"]+)['"]/g;
|
|
43169
43641
|
IMPORT_REGEX_REQUIRE = /require\s*\(\s*['"]([^'"]+)['"]\s*\)/g;
|
|
43170
43642
|
IMPORT_REGEX_REEXPORT = /export\s+(?:\{[^}]*\}|\*)\s+from\s+['"]([^'"]+)['"]/g;
|
|
43171
43643
|
EXTENSIONS_TO_TRY = [".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs"];
|
|
43644
|
+
_internals17 = {
|
|
43645
|
+
normalizePath,
|
|
43646
|
+
isCacheStale,
|
|
43647
|
+
resolveRelativeImport,
|
|
43648
|
+
findTestFilesSync,
|
|
43649
|
+
extractImports,
|
|
43650
|
+
buildImpactMapInternal,
|
|
43651
|
+
buildImpactMap,
|
|
43652
|
+
loadImpactMap,
|
|
43653
|
+
saveImpactMap,
|
|
43654
|
+
analyzeImpact
|
|
43655
|
+
};
|
|
43172
43656
|
});
|
|
43173
43657
|
|
|
43174
43658
|
// src/test-impact/failure-classifier.ts
|
|
@@ -43378,9 +43862,9 @@ var FLAKY_THRESHOLD = 0.3, MIN_RUNS_FOR_QUARANTINE = 5, MAX_HISTORY_RUNS = 20;
|
|
|
43378
43862
|
|
|
43379
43863
|
// src/test-impact/history-store.ts
|
|
43380
43864
|
import fs14 from "fs";
|
|
43381
|
-
import
|
|
43865
|
+
import path28 from "path";
|
|
43382
43866
|
function getHistoryPath(workingDir) {
|
|
43383
|
-
return
|
|
43867
|
+
return path28.join(workingDir || process.cwd(), ".swarm", "cache", "test-history.jsonl");
|
|
43384
43868
|
}
|
|
43385
43869
|
function sanitizeErrorMessage(errorMessage) {
|
|
43386
43870
|
if (errorMessage === undefined) {
|
|
@@ -43435,7 +43919,7 @@ function appendTestRun(record3, workingDir) {
|
|
|
43435
43919
|
changedFiles: sanitizeChangedFiles(record3.changedFiles || [])
|
|
43436
43920
|
};
|
|
43437
43921
|
const historyPath = getHistoryPath(workingDir);
|
|
43438
|
-
const historyDir =
|
|
43922
|
+
const historyDir = path28.dirname(historyPath);
|
|
43439
43923
|
if (!fs14.existsSync(historyDir)) {
|
|
43440
43924
|
fs14.mkdirSync(historyDir, { recursive: true });
|
|
43441
43925
|
}
|
|
@@ -43517,7 +44001,7 @@ var init_history_store = __esm(() => {
|
|
|
43517
44001
|
|
|
43518
44002
|
// src/tools/resolve-working-directory.ts
|
|
43519
44003
|
import * as fs15 from "fs";
|
|
43520
|
-
import * as
|
|
44004
|
+
import * as path29 from "path";
|
|
43521
44005
|
function resolveWorkingDirectory(workingDirectory, fallbackDirectory) {
|
|
43522
44006
|
if (workingDirectory == null || workingDirectory === "") {
|
|
43523
44007
|
return { success: true, directory: fallbackDirectory };
|
|
@@ -43537,15 +44021,15 @@ function resolveWorkingDirectory(workingDirectory, fallbackDirectory) {
|
|
|
43537
44021
|
};
|
|
43538
44022
|
}
|
|
43539
44023
|
}
|
|
43540
|
-
const normalizedDir =
|
|
43541
|
-
const pathParts = normalizedDir.split(
|
|
44024
|
+
const normalizedDir = path29.normalize(workingDirectory);
|
|
44025
|
+
const pathParts = normalizedDir.split(path29.sep);
|
|
43542
44026
|
if (pathParts.includes("..")) {
|
|
43543
44027
|
return {
|
|
43544
44028
|
success: false,
|
|
43545
44029
|
message: "Invalid working_directory: path traversal sequences (..) are not allowed"
|
|
43546
44030
|
};
|
|
43547
44031
|
}
|
|
43548
|
-
const resolvedDir =
|
|
44032
|
+
const resolvedDir = path29.resolve(normalizedDir);
|
|
43549
44033
|
let statResult;
|
|
43550
44034
|
try {
|
|
43551
44035
|
statResult = fs15.statSync(resolvedDir);
|
|
@@ -43561,7 +44045,7 @@ function resolveWorkingDirectory(workingDirectory, fallbackDirectory) {
|
|
|
43561
44045
|
message: `Invalid working_directory: path "${resolvedDir}" is not a directory`
|
|
43562
44046
|
};
|
|
43563
44047
|
}
|
|
43564
|
-
const resolvedFallback =
|
|
44048
|
+
const resolvedFallback = path29.resolve(fallbackDirectory);
|
|
43565
44049
|
let fallbackExists = false;
|
|
43566
44050
|
try {
|
|
43567
44051
|
fs15.statSync(resolvedFallback);
|
|
@@ -43571,7 +44055,7 @@ function resolveWorkingDirectory(workingDirectory, fallbackDirectory) {
|
|
|
43571
44055
|
}
|
|
43572
44056
|
if (workingDirectory != null && workingDirectory !== "") {
|
|
43573
44057
|
if (fallbackExists) {
|
|
43574
|
-
const isSubdirectory = resolvedDir.startsWith(resolvedFallback +
|
|
44058
|
+
const isSubdirectory = resolvedDir.startsWith(resolvedFallback + path29.sep);
|
|
43575
44059
|
if (isSubdirectory) {
|
|
43576
44060
|
return {
|
|
43577
44061
|
success: false,
|
|
@@ -43593,7 +44077,7 @@ var init_resolve_working_directory = () => {};
|
|
|
43593
44077
|
|
|
43594
44078
|
// src/tools/test-runner.ts
|
|
43595
44079
|
import * as fs16 from "fs";
|
|
43596
|
-
import * as
|
|
44080
|
+
import * as path30 from "path";
|
|
43597
44081
|
function isAbsolutePath(str) {
|
|
43598
44082
|
if (str.startsWith("/"))
|
|
43599
44083
|
return true;
|
|
@@ -43658,14 +44142,14 @@ function hasDevDependency(devDeps, ...patterns) {
|
|
|
43658
44142
|
return hasPackageJsonDependency(devDeps, ...patterns);
|
|
43659
44143
|
}
|
|
43660
44144
|
function detectGoTest(cwd) {
|
|
43661
|
-
return fs16.existsSync(
|
|
44145
|
+
return fs16.existsSync(path30.join(cwd, "go.mod")) && isCommandAvailable("go");
|
|
43662
44146
|
}
|
|
43663
44147
|
function detectJavaMaven(cwd) {
|
|
43664
|
-
return fs16.existsSync(
|
|
44148
|
+
return fs16.existsSync(path30.join(cwd, "pom.xml")) && isCommandAvailable("mvn");
|
|
43665
44149
|
}
|
|
43666
44150
|
function detectGradle(cwd) {
|
|
43667
|
-
const hasBuildFile = fs16.existsSync(
|
|
43668
|
-
const hasGradlew = fs16.existsSync(
|
|
44151
|
+
const hasBuildFile = fs16.existsSync(path30.join(cwd, "build.gradle")) || fs16.existsSync(path30.join(cwd, "build.gradle.kts"));
|
|
44152
|
+
const hasGradlew = fs16.existsSync(path30.join(cwd, "gradlew")) || fs16.existsSync(path30.join(cwd, "gradlew.bat"));
|
|
43669
44153
|
return hasBuildFile && (hasGradlew || isCommandAvailable("gradle"));
|
|
43670
44154
|
}
|
|
43671
44155
|
function detectDotnetTest(cwd) {
|
|
@@ -43678,30 +44162,30 @@ function detectDotnetTest(cwd) {
|
|
|
43678
44162
|
}
|
|
43679
44163
|
}
|
|
43680
44164
|
function detectCTest(cwd) {
|
|
43681
|
-
const hasSource = fs16.existsSync(
|
|
43682
|
-
const hasBuildCache = fs16.existsSync(
|
|
44165
|
+
const hasSource = fs16.existsSync(path30.join(cwd, "CMakeLists.txt"));
|
|
44166
|
+
const hasBuildCache = fs16.existsSync(path30.join(cwd, "CMakeCache.txt")) || fs16.existsSync(path30.join(cwd, "build", "CMakeCache.txt"));
|
|
43683
44167
|
return (hasSource || hasBuildCache) && isCommandAvailable("ctest");
|
|
43684
44168
|
}
|
|
43685
44169
|
function detectSwiftTest(cwd) {
|
|
43686
|
-
return fs16.existsSync(
|
|
44170
|
+
return fs16.existsSync(path30.join(cwd, "Package.swift")) && isCommandAvailable("swift");
|
|
43687
44171
|
}
|
|
43688
44172
|
function detectDartTest(cwd) {
|
|
43689
|
-
return fs16.existsSync(
|
|
44173
|
+
return fs16.existsSync(path30.join(cwd, "pubspec.yaml")) && (isCommandAvailable("dart") || isCommandAvailable("flutter"));
|
|
43690
44174
|
}
|
|
43691
44175
|
function detectRSpec(cwd) {
|
|
43692
|
-
const hasRSpecFile = fs16.existsSync(
|
|
43693
|
-
const hasGemfile = fs16.existsSync(
|
|
43694
|
-
const hasSpecDir = fs16.existsSync(
|
|
44176
|
+
const hasRSpecFile = fs16.existsSync(path30.join(cwd, ".rspec"));
|
|
44177
|
+
const hasGemfile = fs16.existsSync(path30.join(cwd, "Gemfile"));
|
|
44178
|
+
const hasSpecDir = fs16.existsSync(path30.join(cwd, "spec"));
|
|
43695
44179
|
const hasRSpec = hasRSpecFile || hasGemfile && hasSpecDir;
|
|
43696
44180
|
return hasRSpec && (isCommandAvailable("bundle") || isCommandAvailable("rspec"));
|
|
43697
44181
|
}
|
|
43698
44182
|
function detectMinitest(cwd) {
|
|
43699
|
-
return fs16.existsSync(
|
|
44183
|
+
return fs16.existsSync(path30.join(cwd, "test")) && (fs16.existsSync(path30.join(cwd, "Gemfile")) || fs16.existsSync(path30.join(cwd, "Rakefile"))) && isCommandAvailable("ruby");
|
|
43700
44184
|
}
|
|
43701
44185
|
async function detectTestFramework(cwd) {
|
|
43702
44186
|
const baseDir = cwd;
|
|
43703
44187
|
try {
|
|
43704
|
-
const packageJsonPath =
|
|
44188
|
+
const packageJsonPath = path30.join(baseDir, "package.json");
|
|
43705
44189
|
if (fs16.existsSync(packageJsonPath)) {
|
|
43706
44190
|
const content = fs16.readFileSync(packageJsonPath, "utf-8");
|
|
43707
44191
|
const pkg = JSON.parse(content);
|
|
@@ -43722,16 +44206,16 @@ async function detectTestFramework(cwd) {
|
|
|
43722
44206
|
return "jest";
|
|
43723
44207
|
if (hasDevDependency(devDeps, "mocha", "@types/mocha"))
|
|
43724
44208
|
return "mocha";
|
|
43725
|
-
if (fs16.existsSync(
|
|
44209
|
+
if (fs16.existsSync(path30.join(baseDir, "bun.lockb")) || fs16.existsSync(path30.join(baseDir, "bun.lock"))) {
|
|
43726
44210
|
if (scripts.test?.includes("bun"))
|
|
43727
44211
|
return "bun";
|
|
43728
44212
|
}
|
|
43729
44213
|
}
|
|
43730
44214
|
} catch {}
|
|
43731
44215
|
try {
|
|
43732
|
-
const pyprojectTomlPath =
|
|
43733
|
-
const setupCfgPath =
|
|
43734
|
-
const requirementsTxtPath =
|
|
44216
|
+
const pyprojectTomlPath = path30.join(baseDir, "pyproject.toml");
|
|
44217
|
+
const setupCfgPath = path30.join(baseDir, "setup.cfg");
|
|
44218
|
+
const requirementsTxtPath = path30.join(baseDir, "requirements.txt");
|
|
43735
44219
|
if (fs16.existsSync(pyprojectTomlPath)) {
|
|
43736
44220
|
const content = fs16.readFileSync(pyprojectTomlPath, "utf-8");
|
|
43737
44221
|
if (content.includes("[tool.pytest"))
|
|
@@ -43751,7 +44235,7 @@ async function detectTestFramework(cwd) {
|
|
|
43751
44235
|
}
|
|
43752
44236
|
} catch {}
|
|
43753
44237
|
try {
|
|
43754
|
-
const cargoTomlPath =
|
|
44238
|
+
const cargoTomlPath = path30.join(baseDir, "Cargo.toml");
|
|
43755
44239
|
if (fs16.existsSync(cargoTomlPath)) {
|
|
43756
44240
|
const content = fs16.readFileSync(cargoTomlPath, "utf-8");
|
|
43757
44241
|
if (content.includes("[dev-dependencies]")) {
|
|
@@ -43762,9 +44246,9 @@ async function detectTestFramework(cwd) {
|
|
|
43762
44246
|
}
|
|
43763
44247
|
} catch {}
|
|
43764
44248
|
try {
|
|
43765
|
-
const pesterConfigPath =
|
|
43766
|
-
const pesterConfigJsonPath =
|
|
43767
|
-
const pesterPs1Path =
|
|
44249
|
+
const pesterConfigPath = path30.join(baseDir, "pester.config.ps1");
|
|
44250
|
+
const pesterConfigJsonPath = path30.join(baseDir, "pester.config.ps1.json");
|
|
44251
|
+
const pesterPs1Path = path30.join(baseDir, "tests.ps1");
|
|
43768
44252
|
if (fs16.existsSync(pesterConfigPath) || fs16.existsSync(pesterConfigJsonPath) || fs16.existsSync(pesterPs1Path)) {
|
|
43769
44253
|
return "pester";
|
|
43770
44254
|
}
|
|
@@ -43793,12 +44277,12 @@ function isTestDirectoryPath(normalizedPath) {
|
|
|
43793
44277
|
return normalizedPath.split("/").some((segment) => TEST_DIRECTORY_NAMES.includes(segment));
|
|
43794
44278
|
}
|
|
43795
44279
|
function resolveWorkspacePath(file3, workingDir) {
|
|
43796
|
-
return
|
|
44280
|
+
return path30.isAbsolute(file3) ? path30.resolve(file3) : path30.resolve(workingDir, file3);
|
|
43797
44281
|
}
|
|
43798
44282
|
function toWorkspaceOutputPath(absolutePath, workingDir, preferRelative) {
|
|
43799
44283
|
if (!preferRelative)
|
|
43800
44284
|
return absolutePath;
|
|
43801
|
-
return
|
|
44285
|
+
return path30.relative(workingDir, absolutePath);
|
|
43802
44286
|
}
|
|
43803
44287
|
function dedupePush(target, value) {
|
|
43804
44288
|
if (!target.includes(value)) {
|
|
@@ -43835,18 +44319,18 @@ function buildLanguageSpecificTestNames(nameWithoutExt, ext) {
|
|
|
43835
44319
|
}
|
|
43836
44320
|
}
|
|
43837
44321
|
function getRepoLevelCandidateDirectories(workingDir, relativePath, ext) {
|
|
43838
|
-
const relativeDir =
|
|
44322
|
+
const relativeDir = path30.dirname(relativePath);
|
|
43839
44323
|
const nestedRelativeDir = relativeDir === "." ? "" : relativeDir;
|
|
43840
44324
|
const directories = TEST_DIRECTORY_NAMES.flatMap((dirName) => {
|
|
43841
|
-
const rootDir =
|
|
43842
|
-
return nestedRelativeDir ? [rootDir,
|
|
44325
|
+
const rootDir = path30.join(workingDir, dirName);
|
|
44326
|
+
return nestedRelativeDir ? [rootDir, path30.join(rootDir, nestedRelativeDir)] : [rootDir];
|
|
43843
44327
|
});
|
|
43844
44328
|
const normalizedRelativePath = relativePath.replace(/\\/g, "/");
|
|
43845
44329
|
if (ext === ".java" && normalizedRelativePath.startsWith("src/main/java/")) {
|
|
43846
|
-
directories.push(
|
|
44330
|
+
directories.push(path30.join(workingDir, "src/test/java", path30.dirname(normalizedRelativePath.slice("src/main/java/".length))));
|
|
43847
44331
|
}
|
|
43848
44332
|
if ((ext === ".kt" || ext === ".java") && normalizedRelativePath.startsWith("src/main/kotlin/")) {
|
|
43849
|
-
directories.push(
|
|
44333
|
+
directories.push(path30.join(workingDir, "src/test/kotlin", path30.dirname(normalizedRelativePath.slice("src/main/kotlin/".length))));
|
|
43850
44334
|
}
|
|
43851
44335
|
return [...new Set(directories)];
|
|
43852
44336
|
}
|
|
@@ -43874,23 +44358,23 @@ function isLanguageSpecificTestFile(basename5) {
|
|
|
43874
44358
|
}
|
|
43875
44359
|
function isConventionTestFilePath(filePath) {
|
|
43876
44360
|
const normalizedPath = filePath.replace(/\\/g, "/");
|
|
43877
|
-
const basename5 =
|
|
44361
|
+
const basename5 = path30.basename(filePath);
|
|
43878
44362
|
return hasCompoundTestExtension(basename5) || basename5.includes(".spec.") || basename5.includes(".test.") || isLanguageSpecificTestFile(basename5) || isTestDirectoryPath(normalizedPath);
|
|
43879
44363
|
}
|
|
43880
44364
|
function getTestFilesFromConvention(sourceFiles, workingDir = process.cwd()) {
|
|
43881
44365
|
const testFiles = [];
|
|
43882
44366
|
for (const file3 of sourceFiles) {
|
|
43883
44367
|
const absoluteFile = resolveWorkspacePath(file3, workingDir);
|
|
43884
|
-
const relativeFile =
|
|
43885
|
-
const basename5 =
|
|
43886
|
-
const
|
|
43887
|
-
const preferRelativeOutput = !
|
|
44368
|
+
const relativeFile = path30.relative(workingDir, absoluteFile);
|
|
44369
|
+
const basename5 = path30.basename(absoluteFile);
|
|
44370
|
+
const dirname13 = path30.dirname(absoluteFile);
|
|
44371
|
+
const preferRelativeOutput = !path30.isAbsolute(file3);
|
|
43888
44372
|
if (isConventionTestFilePath(relativeFile) || isConventionTestFilePath(file3)) {
|
|
43889
44373
|
dedupePush(testFiles, toWorkspaceOutputPath(absoluteFile, workingDir, preferRelativeOutput));
|
|
43890
44374
|
continue;
|
|
43891
44375
|
}
|
|
43892
44376
|
const nameWithoutExt = basename5.replace(/\.[^.]+$/, "");
|
|
43893
|
-
const ext =
|
|
44377
|
+
const ext = path30.extname(basename5);
|
|
43894
44378
|
const genericTestNames = [
|
|
43895
44379
|
`${nameWithoutExt}.spec${ext}`,
|
|
43896
44380
|
`${nameWithoutExt}.test${ext}`
|
|
@@ -43899,7 +44383,7 @@ function getTestFilesFromConvention(sourceFiles, workingDir = process.cwd()) {
|
|
|
43899
44383
|
const colocatedCandidates = [
|
|
43900
44384
|
...genericTestNames,
|
|
43901
44385
|
...languageSpecificTestNames
|
|
43902
|
-
].map((candidateName) =>
|
|
44386
|
+
].map((candidateName) => path30.join(dirname13, candidateName));
|
|
43903
44387
|
const testDirectoryNames = [
|
|
43904
44388
|
basename5,
|
|
43905
44389
|
...genericTestNames,
|
|
@@ -43908,8 +44392,8 @@ function getTestFilesFromConvention(sourceFiles, workingDir = process.cwd()) {
|
|
|
43908
44392
|
const repoLevelDirectories = getRepoLevelCandidateDirectories(workingDir, relativeFile, ext);
|
|
43909
44393
|
const possibleTestFiles = [
|
|
43910
44394
|
...colocatedCandidates,
|
|
43911
|
-
...TEST_DIRECTORY_NAMES.flatMap((dirName) => testDirectoryNames.map((candidateName) =>
|
|
43912
|
-
...repoLevelDirectories.flatMap((candidateDir) => testDirectoryNames.map((candidateName) =>
|
|
44395
|
+
...TEST_DIRECTORY_NAMES.flatMap((dirName) => testDirectoryNames.map((candidateName) => path30.join(dirname13, dirName, candidateName))),
|
|
44396
|
+
...repoLevelDirectories.flatMap((candidateDir) => testDirectoryNames.map((candidateName) => path30.join(candidateDir, candidateName)))
|
|
43913
44397
|
];
|
|
43914
44398
|
for (const testFile of possibleTestFiles) {
|
|
43915
44399
|
if (fs16.existsSync(testFile)) {
|
|
@@ -43930,7 +44414,7 @@ async function getTestFilesFromGraph(sourceFiles, workingDir) {
|
|
|
43930
44414
|
try {
|
|
43931
44415
|
const absoluteTestFile = resolveWorkspacePath(testFile, workingDir);
|
|
43932
44416
|
const content = fs16.readFileSync(absoluteTestFile, "utf-8");
|
|
43933
|
-
const testDir =
|
|
44417
|
+
const testDir = path30.dirname(absoluteTestFile);
|
|
43934
44418
|
const importRegex = /import\s+.*?\s+from\s+['"]([^'"]+)['"]/g;
|
|
43935
44419
|
let match;
|
|
43936
44420
|
match = importRegex.exec(content);
|
|
@@ -43938,8 +44422,8 @@ async function getTestFilesFromGraph(sourceFiles, workingDir) {
|
|
|
43938
44422
|
const importPath = match[1];
|
|
43939
44423
|
let resolvedImport;
|
|
43940
44424
|
if (importPath.startsWith(".")) {
|
|
43941
|
-
resolvedImport =
|
|
43942
|
-
const existingExt =
|
|
44425
|
+
resolvedImport = path30.resolve(testDir, importPath);
|
|
44426
|
+
const existingExt = path30.extname(resolvedImport);
|
|
43943
44427
|
if (!existingExt) {
|
|
43944
44428
|
for (const extToTry of [
|
|
43945
44429
|
".ts",
|
|
@@ -43959,12 +44443,12 @@ async function getTestFilesFromGraph(sourceFiles, workingDir) {
|
|
|
43959
44443
|
} else {
|
|
43960
44444
|
continue;
|
|
43961
44445
|
}
|
|
43962
|
-
const importBasename =
|
|
43963
|
-
const importDir =
|
|
44446
|
+
const importBasename = path30.basename(resolvedImport, path30.extname(resolvedImport));
|
|
44447
|
+
const importDir = path30.dirname(resolvedImport);
|
|
43964
44448
|
for (const sourceFile of absoluteSourceFiles) {
|
|
43965
|
-
const sourceDir =
|
|
43966
|
-
const sourceBasename =
|
|
43967
|
-
const isRelatedDir = importDir === sourceDir || importDir ===
|
|
44449
|
+
const sourceDir = path30.dirname(sourceFile);
|
|
44450
|
+
const sourceBasename = path30.basename(sourceFile, path30.extname(sourceFile));
|
|
44451
|
+
const isRelatedDir = importDir === sourceDir || importDir === path30.join(sourceDir, "__tests__") || importDir === path30.join(sourceDir, "tests") || importDir === path30.join(sourceDir, "test") || importDir === path30.join(sourceDir, "spec");
|
|
43968
44452
|
if (resolvedImport === sourceFile || importBasename === sourceBasename && isRelatedDir) {
|
|
43969
44453
|
dedupePush(testFiles, testFile);
|
|
43970
44454
|
break;
|
|
@@ -43977,8 +44461,8 @@ async function getTestFilesFromGraph(sourceFiles, workingDir) {
|
|
|
43977
44461
|
while (match !== null) {
|
|
43978
44462
|
const importPath = match[1];
|
|
43979
44463
|
if (importPath.startsWith(".")) {
|
|
43980
|
-
let resolvedImport =
|
|
43981
|
-
const existingExt =
|
|
44464
|
+
let resolvedImport = path30.resolve(testDir, importPath);
|
|
44465
|
+
const existingExt = path30.extname(resolvedImport);
|
|
43982
44466
|
if (!existingExt) {
|
|
43983
44467
|
for (const extToTry of [
|
|
43984
44468
|
".ts",
|
|
@@ -43995,12 +44479,12 @@ async function getTestFilesFromGraph(sourceFiles, workingDir) {
|
|
|
43995
44479
|
}
|
|
43996
44480
|
}
|
|
43997
44481
|
}
|
|
43998
|
-
const importDir =
|
|
43999
|
-
const importBasename =
|
|
44482
|
+
const importDir = path30.dirname(resolvedImport);
|
|
44483
|
+
const importBasename = path30.basename(resolvedImport, path30.extname(resolvedImport));
|
|
44000
44484
|
for (const sourceFile of absoluteSourceFiles) {
|
|
44001
|
-
const sourceDir =
|
|
44002
|
-
const sourceBasename =
|
|
44003
|
-
const isRelatedDir = importDir === sourceDir || importDir ===
|
|
44485
|
+
const sourceDir = path30.dirname(sourceFile);
|
|
44486
|
+
const sourceBasename = path30.basename(sourceFile, path30.extname(sourceFile));
|
|
44487
|
+
const isRelatedDir = importDir === sourceDir || importDir === path30.join(sourceDir, "__tests__") || importDir === path30.join(sourceDir, "tests") || importDir === path30.join(sourceDir, "test") || importDir === path30.join(sourceDir, "spec");
|
|
44004
44488
|
if (resolvedImport === sourceFile || importBasename === sourceBasename && isRelatedDir) {
|
|
44005
44489
|
dedupePush(testFiles, testFile);
|
|
44006
44490
|
break;
|
|
@@ -44103,8 +44587,8 @@ function buildTestCommand(framework, scope, files, coverage, baseDir) {
|
|
|
44103
44587
|
return ["mvn", "test"];
|
|
44104
44588
|
case "gradle": {
|
|
44105
44589
|
const isWindows = process.platform === "win32";
|
|
44106
|
-
const hasGradlewBat = fs16.existsSync(
|
|
44107
|
-
const hasGradlew = fs16.existsSync(
|
|
44590
|
+
const hasGradlewBat = fs16.existsSync(path30.join(baseDir, "gradlew.bat"));
|
|
44591
|
+
const hasGradlew = fs16.existsSync(path30.join(baseDir, "gradlew"));
|
|
44108
44592
|
if (hasGradlewBat && isWindows)
|
|
44109
44593
|
return ["gradlew.bat", "test"];
|
|
44110
44594
|
if (hasGradlew)
|
|
@@ -44121,7 +44605,7 @@ function buildTestCommand(framework, scope, files, coverage, baseDir) {
|
|
|
44121
44605
|
"cmake-build-release",
|
|
44122
44606
|
"out"
|
|
44123
44607
|
];
|
|
44124
|
-
const actualBuildDir = buildDirCandidates.find((d) => fs16.existsSync(
|
|
44608
|
+
const actualBuildDir = buildDirCandidates.find((d) => fs16.existsSync(path30.join(baseDir, d, "CMakeCache.txt"))) ?? "build";
|
|
44125
44609
|
return ["ctest", "--test-dir", actualBuildDir];
|
|
44126
44610
|
}
|
|
44127
44611
|
case "swift-test":
|
|
@@ -44774,7 +45258,7 @@ var init_test_runner = __esm(() => {
|
|
|
44774
45258
|
const sourceFiles = args.files.filter((file3) => {
|
|
44775
45259
|
if (directTestFiles.includes(file3))
|
|
44776
45260
|
return false;
|
|
44777
|
-
const ext =
|
|
45261
|
+
const ext = path30.extname(file3).toLowerCase();
|
|
44778
45262
|
return SOURCE_EXTENSIONS.has(ext);
|
|
44779
45263
|
});
|
|
44780
45264
|
const invalidFiles = args.files.filter((file3) => !directTestFiles.includes(file3) && !sourceFiles.includes(file3));
|
|
@@ -44809,7 +45293,7 @@ var init_test_runner = __esm(() => {
|
|
|
44809
45293
|
if (isConventionTestFilePath(f)) {
|
|
44810
45294
|
return false;
|
|
44811
45295
|
}
|
|
44812
|
-
const ext =
|
|
45296
|
+
const ext = path30.extname(f).toLowerCase();
|
|
44813
45297
|
return SOURCE_EXTENSIONS.has(ext);
|
|
44814
45298
|
});
|
|
44815
45299
|
if (sourceFiles.length === 0) {
|
|
@@ -44836,7 +45320,7 @@ var init_test_runner = __esm(() => {
|
|
|
44836
45320
|
if (isConventionTestFilePath(f)) {
|
|
44837
45321
|
return false;
|
|
44838
45322
|
}
|
|
44839
|
-
const ext =
|
|
45323
|
+
const ext = path30.extname(f).toLowerCase();
|
|
44840
45324
|
return SOURCE_EXTENSIONS.has(ext);
|
|
44841
45325
|
});
|
|
44842
45326
|
if (sourceFiles.length === 0) {
|
|
@@ -44854,8 +45338,8 @@ var init_test_runner = __esm(() => {
|
|
|
44854
45338
|
const impactResult = await analyzeImpact(sourceFiles, workingDir);
|
|
44855
45339
|
if (impactResult.impactedTests.length > 0) {
|
|
44856
45340
|
testFiles = impactResult.impactedTests.map((absPath) => {
|
|
44857
|
-
const relativePath =
|
|
44858
|
-
return
|
|
45341
|
+
const relativePath = path30.relative(workingDir, absPath);
|
|
45342
|
+
return path30.isAbsolute(relativePath) ? absPath : relativePath;
|
|
44859
45343
|
});
|
|
44860
45344
|
} else {
|
|
44861
45345
|
graphFallbackReason = "no impacted tests found via impact analysis, falling back to graph";
|
|
@@ -44931,7 +45415,7 @@ var init_test_runner = __esm(() => {
|
|
|
44931
45415
|
|
|
44932
45416
|
// src/services/preflight-service.ts
|
|
44933
45417
|
import * as fs17 from "fs";
|
|
44934
|
-
import * as
|
|
45418
|
+
import * as path31 from "path";
|
|
44935
45419
|
function validateDirectoryPath(dir) {
|
|
44936
45420
|
if (!dir || typeof dir !== "string") {
|
|
44937
45421
|
throw new Error("Directory path is required");
|
|
@@ -44939,8 +45423,8 @@ function validateDirectoryPath(dir) {
|
|
|
44939
45423
|
if (dir.includes("..")) {
|
|
44940
45424
|
throw new Error("Directory path must not contain path traversal sequences");
|
|
44941
45425
|
}
|
|
44942
|
-
const normalized =
|
|
44943
|
-
const absolutePath =
|
|
45426
|
+
const normalized = path31.normalize(dir);
|
|
45427
|
+
const absolutePath = path31.isAbsolute(normalized) ? normalized : path31.resolve(normalized);
|
|
44944
45428
|
return absolutePath;
|
|
44945
45429
|
}
|
|
44946
45430
|
function validateTimeout(timeoutMs, defaultValue) {
|
|
@@ -44963,7 +45447,7 @@ function validateTimeout(timeoutMs, defaultValue) {
|
|
|
44963
45447
|
}
|
|
44964
45448
|
function getPackageVersion(dir) {
|
|
44965
45449
|
try {
|
|
44966
|
-
const packagePath =
|
|
45450
|
+
const packagePath = path31.join(dir, "package.json");
|
|
44967
45451
|
if (fs17.existsSync(packagePath)) {
|
|
44968
45452
|
const content = fs17.readFileSync(packagePath, "utf-8");
|
|
44969
45453
|
const pkg = JSON.parse(content);
|
|
@@ -44974,7 +45458,7 @@ function getPackageVersion(dir) {
|
|
|
44974
45458
|
}
|
|
44975
45459
|
function getChangelogVersion(dir) {
|
|
44976
45460
|
try {
|
|
44977
|
-
const changelogPath =
|
|
45461
|
+
const changelogPath = path31.join(dir, "CHANGELOG.md");
|
|
44978
45462
|
if (fs17.existsSync(changelogPath)) {
|
|
44979
45463
|
const content = fs17.readFileSync(changelogPath, "utf-8");
|
|
44980
45464
|
const match = content.match(/^##\s*\[?(\d+\.\d+\.\d+)\]?/m);
|
|
@@ -44988,7 +45472,7 @@ function getChangelogVersion(dir) {
|
|
|
44988
45472
|
function getVersionFileVersion(dir) {
|
|
44989
45473
|
const possibleFiles = ["VERSION.txt", "version.txt", "VERSION", "version"];
|
|
44990
45474
|
for (const file3 of possibleFiles) {
|
|
44991
|
-
const filePath =
|
|
45475
|
+
const filePath = path31.join(dir, file3);
|
|
44992
45476
|
if (fs17.existsSync(filePath)) {
|
|
44993
45477
|
try {
|
|
44994
45478
|
const content = fs17.readFileSync(filePath, "utf-8").trim();
|
|
@@ -45004,9 +45488,9 @@ function getVersionFileVersion(dir) {
|
|
|
45004
45488
|
async function runVersionCheck(dir, _timeoutMs) {
|
|
45005
45489
|
const startTime = Date.now();
|
|
45006
45490
|
try {
|
|
45007
|
-
const packageVersion = getPackageVersion(dir);
|
|
45008
|
-
const changelogVersion = getChangelogVersion(dir);
|
|
45009
|
-
const versionFileVersion = getVersionFileVersion(dir);
|
|
45491
|
+
const packageVersion = _internals18.getPackageVersion(dir);
|
|
45492
|
+
const changelogVersion = _internals18.getChangelogVersion(dir);
|
|
45493
|
+
const versionFileVersion = _internals18.getVersionFileVersion(dir);
|
|
45010
45494
|
const versions3 = [];
|
|
45011
45495
|
if (packageVersion)
|
|
45012
45496
|
versions3.push(`package.json: ${packageVersion}`);
|
|
@@ -45315,7 +45799,7 @@ async function runEvidenceCheck(dir) {
|
|
|
45315
45799
|
async function runRequirementCoverageCheck(dir, currentPhase) {
|
|
45316
45800
|
const startTime = Date.now();
|
|
45317
45801
|
try {
|
|
45318
|
-
const specPath =
|
|
45802
|
+
const specPath = path31.join(dir, ".swarm", "spec.md");
|
|
45319
45803
|
if (!fs17.existsSync(specPath)) {
|
|
45320
45804
|
return {
|
|
45321
45805
|
type: "req_coverage",
|
|
@@ -45356,7 +45840,7 @@ async function runPreflight(dir, phase, config3) {
|
|
|
45356
45840
|
const reportId = `preflight-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
|
|
45357
45841
|
let validatedDir;
|
|
45358
45842
|
try {
|
|
45359
|
-
validatedDir = validateDirectoryPath(dir);
|
|
45843
|
+
validatedDir = _internals18.validateDirectoryPath(dir);
|
|
45360
45844
|
} catch (error93) {
|
|
45361
45845
|
return {
|
|
45362
45846
|
id: reportId,
|
|
@@ -45376,7 +45860,7 @@ async function runPreflight(dir, phase, config3) {
|
|
|
45376
45860
|
}
|
|
45377
45861
|
let validatedTimeout;
|
|
45378
45862
|
try {
|
|
45379
|
-
validatedTimeout = validateTimeout(config3?.checkTimeoutMs, DEFAULT_CONFIG.checkTimeoutMs);
|
|
45863
|
+
validatedTimeout = _internals18.validateTimeout(config3?.checkTimeoutMs, DEFAULT_CONFIG.checkTimeoutMs);
|
|
45380
45864
|
} catch (error93) {
|
|
45381
45865
|
return {
|
|
45382
45866
|
id: reportId,
|
|
@@ -45417,12 +45901,12 @@ async function runPreflight(dir, phase, config3) {
|
|
|
45417
45901
|
});
|
|
45418
45902
|
const checks5 = [];
|
|
45419
45903
|
log("[Preflight] Running lint check...");
|
|
45420
|
-
const lintResult = await runLintCheck(validatedDir, cfg.linter, cfg.checkTimeoutMs);
|
|
45904
|
+
const lintResult = await _internals18.runLintCheck(validatedDir, cfg.linter, cfg.checkTimeoutMs);
|
|
45421
45905
|
checks5.push(lintResult);
|
|
45422
45906
|
log(`[Preflight] Lint check: ${lintResult.status} ${lintResult.message}`);
|
|
45423
45907
|
if (!cfg.skipTests) {
|
|
45424
45908
|
log("[Preflight] Running tests check...");
|
|
45425
|
-
const testsResult = await runTestsCheck(validatedDir, cfg.testScope, cfg.checkTimeoutMs);
|
|
45909
|
+
const testsResult = await _internals18.runTestsCheck(validatedDir, cfg.testScope, cfg.checkTimeoutMs);
|
|
45426
45910
|
checks5.push(testsResult);
|
|
45427
45911
|
log(`[Preflight] Tests check: ${testsResult.status} ${testsResult.message}`);
|
|
45428
45912
|
} else {
|
|
@@ -45434,7 +45918,7 @@ async function runPreflight(dir, phase, config3) {
|
|
|
45434
45918
|
}
|
|
45435
45919
|
if (!cfg.skipSecrets) {
|
|
45436
45920
|
log("[Preflight] Running secrets check...");
|
|
45437
|
-
const secretsResult = await runSecretsCheck(validatedDir, cfg.checkTimeoutMs);
|
|
45921
|
+
const secretsResult = await _internals18.runSecretsCheck(validatedDir, cfg.checkTimeoutMs);
|
|
45438
45922
|
checks5.push(secretsResult);
|
|
45439
45923
|
log(`[Preflight] Secrets check: ${secretsResult.status} ${secretsResult.message}`);
|
|
45440
45924
|
} else {
|
|
@@ -45446,7 +45930,7 @@ async function runPreflight(dir, phase, config3) {
|
|
|
45446
45930
|
}
|
|
45447
45931
|
if (!cfg.skipEvidence) {
|
|
45448
45932
|
log("[Preflight] Running evidence check...");
|
|
45449
|
-
const evidenceResult = await runEvidenceCheck(validatedDir);
|
|
45933
|
+
const evidenceResult = await _internals18.runEvidenceCheck(validatedDir);
|
|
45450
45934
|
checks5.push(evidenceResult);
|
|
45451
45935
|
log(`[Preflight] Evidence check: ${evidenceResult.status} ${evidenceResult.message}`);
|
|
45452
45936
|
} else {
|
|
@@ -45457,12 +45941,12 @@ async function runPreflight(dir, phase, config3) {
|
|
|
45457
45941
|
});
|
|
45458
45942
|
}
|
|
45459
45943
|
log("[Preflight] Running requirement coverage check...");
|
|
45460
|
-
const reqCoverageResult = await runRequirementCoverageCheck(validatedDir, phase);
|
|
45944
|
+
const reqCoverageResult = await _internals18.runRequirementCoverageCheck(validatedDir, phase);
|
|
45461
45945
|
checks5.push(reqCoverageResult);
|
|
45462
45946
|
log(`[Preflight] Requirement coverage check: ${reqCoverageResult.status} ${reqCoverageResult.message}`);
|
|
45463
45947
|
if (!cfg.skipVersion) {
|
|
45464
45948
|
log("[Preflight] Running version check...");
|
|
45465
|
-
const versionResult = await runVersionCheck(validatedDir, cfg.checkTimeoutMs);
|
|
45949
|
+
const versionResult = await _internals18.runVersionCheck(validatedDir, cfg.checkTimeoutMs);
|
|
45466
45950
|
checks5.push(versionResult);
|
|
45467
45951
|
log(`[Preflight] Version check: ${versionResult.status} ${versionResult.message}`);
|
|
45468
45952
|
} else {
|
|
@@ -45525,10 +46009,10 @@ function formatPreflightMarkdown(report) {
|
|
|
45525
46009
|
async function handlePreflightCommand(directory, _args) {
|
|
45526
46010
|
const plan = await loadPlan(directory);
|
|
45527
46011
|
const phase = plan?.current_phase ?? 1;
|
|
45528
|
-
const report = await runPreflight(directory, phase);
|
|
45529
|
-
return formatPreflightMarkdown(report);
|
|
46012
|
+
const report = await _internals18.runPreflight(directory, phase);
|
|
46013
|
+
return _internals18.formatPreflightMarkdown(report);
|
|
45530
46014
|
}
|
|
45531
|
-
var MIN_CHECK_TIMEOUT_MS = 5000, MAX_CHECK_TIMEOUT_MS = 300000, DEFAULT_CONFIG;
|
|
46015
|
+
var MIN_CHECK_TIMEOUT_MS = 5000, MAX_CHECK_TIMEOUT_MS = 300000, DEFAULT_CONFIG, _internals18;
|
|
45532
46016
|
var init_preflight_service = __esm(() => {
|
|
45533
46017
|
init_manager2();
|
|
45534
46018
|
init_manager();
|
|
@@ -45545,6 +46029,22 @@ var init_preflight_service = __esm(() => {
|
|
|
45545
46029
|
testScope: "convention",
|
|
45546
46030
|
linter: "biome"
|
|
45547
46031
|
};
|
|
46032
|
+
_internals18 = {
|
|
46033
|
+
runPreflight,
|
|
46034
|
+
formatPreflightMarkdown,
|
|
46035
|
+
handlePreflightCommand,
|
|
46036
|
+
validateDirectoryPath,
|
|
46037
|
+
validateTimeout,
|
|
46038
|
+
getPackageVersion,
|
|
46039
|
+
getChangelogVersion,
|
|
46040
|
+
getVersionFileVersion,
|
|
46041
|
+
runVersionCheck,
|
|
46042
|
+
runLintCheck,
|
|
46043
|
+
runTestsCheck,
|
|
46044
|
+
runSecretsCheck,
|
|
46045
|
+
runEvidenceCheck,
|
|
46046
|
+
runRequirementCoverageCheck
|
|
46047
|
+
};
|
|
45548
46048
|
});
|
|
45549
46049
|
|
|
45550
46050
|
// src/commands/preflight.ts
|
|
@@ -46418,7 +46918,7 @@ var init_manager3 = __esm(() => {
|
|
|
46418
46918
|
|
|
46419
46919
|
// src/commands/reset.ts
|
|
46420
46920
|
import * as fs18 from "fs";
|
|
46421
|
-
import * as
|
|
46921
|
+
import * as path32 from "path";
|
|
46422
46922
|
async function handleResetCommand(directory, args) {
|
|
46423
46923
|
const hasConfirm = args.includes("--confirm");
|
|
46424
46924
|
if (!hasConfirm) {
|
|
@@ -46458,7 +46958,7 @@ async function handleResetCommand(directory, args) {
|
|
|
46458
46958
|
}
|
|
46459
46959
|
for (const filename of ["SWARM_PLAN.md", "SWARM_PLAN.json"]) {
|
|
46460
46960
|
try {
|
|
46461
|
-
const rootPath =
|
|
46961
|
+
const rootPath = path32.join(directory, filename);
|
|
46462
46962
|
if (fs18.existsSync(rootPath)) {
|
|
46463
46963
|
fs18.unlinkSync(rootPath);
|
|
46464
46964
|
results.push(`- \u2705 Deleted ${filename} (root)`);
|
|
@@ -46498,7 +46998,7 @@ var init_reset = __esm(() => {
|
|
|
46498
46998
|
|
|
46499
46999
|
// src/commands/reset-session.ts
|
|
46500
47000
|
import * as fs19 from "fs";
|
|
46501
|
-
import * as
|
|
47001
|
+
import * as path33 from "path";
|
|
46502
47002
|
async function handleResetSessionCommand(directory, _args) {
|
|
46503
47003
|
const results = [];
|
|
46504
47004
|
try {
|
|
@@ -46513,13 +47013,13 @@ async function handleResetSessionCommand(directory, _args) {
|
|
|
46513
47013
|
results.push("\u274C Failed to delete state.json");
|
|
46514
47014
|
}
|
|
46515
47015
|
try {
|
|
46516
|
-
const sessionDir =
|
|
47016
|
+
const sessionDir = path33.dirname(validateSwarmPath(directory, "session/state.json"));
|
|
46517
47017
|
if (fs19.existsSync(sessionDir)) {
|
|
46518
47018
|
const files = fs19.readdirSync(sessionDir);
|
|
46519
47019
|
const otherFiles = files.filter((f) => f !== "state.json");
|
|
46520
47020
|
let deletedCount = 0;
|
|
46521
47021
|
for (const file3 of otherFiles) {
|
|
46522
|
-
const filePath =
|
|
47022
|
+
const filePath = path33.join(sessionDir, file3);
|
|
46523
47023
|
if (fs19.lstatSync(filePath).isFile()) {
|
|
46524
47024
|
fs19.unlinkSync(filePath);
|
|
46525
47025
|
deletedCount++;
|
|
@@ -46551,7 +47051,7 @@ var init_reset_session = __esm(() => {
|
|
|
46551
47051
|
});
|
|
46552
47052
|
|
|
46553
47053
|
// src/summaries/manager.ts
|
|
46554
|
-
import * as
|
|
47054
|
+
import * as path34 from "path";
|
|
46555
47055
|
function sanitizeSummaryId(id) {
|
|
46556
47056
|
if (!id || id.length === 0) {
|
|
46557
47057
|
throw new Error("Invalid summary ID: empty string");
|
|
@@ -46574,7 +47074,7 @@ function sanitizeSummaryId(id) {
|
|
|
46574
47074
|
}
|
|
46575
47075
|
async function loadFullOutput(directory, id) {
|
|
46576
47076
|
const sanitizedId = sanitizeSummaryId(id);
|
|
46577
|
-
const relativePath =
|
|
47077
|
+
const relativePath = path34.join("summaries", `${sanitizedId}.json`);
|
|
46578
47078
|
validateSwarmPath(directory, relativePath);
|
|
46579
47079
|
const content = await readSwarmFileAsync(directory, relativePath);
|
|
46580
47080
|
if (content === null) {
|
|
@@ -46637,7 +47137,7 @@ var init_retrieve = __esm(() => {
|
|
|
46637
47137
|
|
|
46638
47138
|
// src/commands/rollback.ts
|
|
46639
47139
|
import * as fs20 from "fs";
|
|
46640
|
-
import * as
|
|
47140
|
+
import * as path35 from "path";
|
|
46641
47141
|
async function handleRollbackCommand(directory, args) {
|
|
46642
47142
|
const phaseArg = args[0];
|
|
46643
47143
|
if (!phaseArg) {
|
|
@@ -46702,8 +47202,8 @@ async function handleRollbackCommand(directory, args) {
|
|
|
46702
47202
|
if (EXCLUDE_FILES.has(file3) || file3.startsWith("plan-ledger.archived-")) {
|
|
46703
47203
|
continue;
|
|
46704
47204
|
}
|
|
46705
|
-
const src =
|
|
46706
|
-
const dest =
|
|
47205
|
+
const src = path35.join(checkpointDir, file3);
|
|
47206
|
+
const dest = path35.join(swarmDir, file3);
|
|
46707
47207
|
try {
|
|
46708
47208
|
fs20.cpSync(src, dest, { recursive: true, force: true });
|
|
46709
47209
|
successes.push(file3);
|
|
@@ -46722,12 +47222,12 @@ async function handleRollbackCommand(directory, args) {
|
|
|
46722
47222
|
].join(`
|
|
46723
47223
|
`);
|
|
46724
47224
|
}
|
|
46725
|
-
const existingLedgerPath =
|
|
47225
|
+
const existingLedgerPath = path35.join(swarmDir, "plan-ledger.jsonl");
|
|
46726
47226
|
if (fs20.existsSync(existingLedgerPath)) {
|
|
46727
47227
|
fs20.unlinkSync(existingLedgerPath);
|
|
46728
47228
|
}
|
|
46729
47229
|
try {
|
|
46730
|
-
const planJsonPath =
|
|
47230
|
+
const planJsonPath = path35.join(swarmDir, "plan.json");
|
|
46731
47231
|
if (fs20.existsSync(planJsonPath)) {
|
|
46732
47232
|
const planRaw = fs20.readFileSync(planJsonPath, "utf-8");
|
|
46733
47233
|
const plan = PlanSchema.parse(JSON.parse(planRaw));
|
|
@@ -46805,9 +47305,9 @@ async function handleSimulateCommand(directory, args) {
|
|
|
46805
47305
|
const report = reportLines.filter(Boolean).join(`
|
|
46806
47306
|
`);
|
|
46807
47307
|
const fs21 = await import("fs/promises");
|
|
46808
|
-
const
|
|
46809
|
-
const reportPath =
|
|
46810
|
-
await fs21.mkdir(
|
|
47308
|
+
const path36 = await import("path");
|
|
47309
|
+
const reportPath = path36.join(directory, ".swarm", "simulate-report.md");
|
|
47310
|
+
await fs21.mkdir(path36.dirname(reportPath), { recursive: true });
|
|
46811
47311
|
await fs21.writeFile(reportPath, report, "utf-8");
|
|
46812
47312
|
return `${darkMatterPairs.length} hidden coupling pairs detected`;
|
|
46813
47313
|
}
|
|
@@ -46982,6 +47482,7 @@ async function handleStatusCommand(directory, agents) {
|
|
|
46982
47482
|
return formatStatusMarkdown(statusData);
|
|
46983
47483
|
}
|
|
46984
47484
|
var init_status_service = __esm(() => {
|
|
47485
|
+
init_extractors();
|
|
46985
47486
|
init_utils2();
|
|
46986
47487
|
init_manager();
|
|
46987
47488
|
init_state();
|
|
@@ -47161,7 +47662,7 @@ __export(exports_commands, {
|
|
|
47161
47662
|
COMMAND_REGISTRY: () => COMMAND_REGISTRY
|
|
47162
47663
|
});
|
|
47163
47664
|
import fs21 from "fs";
|
|
47164
|
-
import
|
|
47665
|
+
import path36 from "path";
|
|
47165
47666
|
function buildHelpText() {
|
|
47166
47667
|
const lines = ["## Swarm Commands", ""];
|
|
47167
47668
|
const CATEGORIES = [
|
|
@@ -47270,9 +47771,9 @@ function createSwarmCommandHandler(directory, agents) {
|
|
|
47270
47771
|
return;
|
|
47271
47772
|
}
|
|
47272
47773
|
let isFirstRun = false;
|
|
47273
|
-
const sentinelPath =
|
|
47774
|
+
const sentinelPath = path36.join(directory, ".swarm", ".first-run-complete");
|
|
47274
47775
|
try {
|
|
47275
|
-
const swarmDir =
|
|
47776
|
+
const swarmDir = path36.join(directory, ".swarm");
|
|
47276
47777
|
fs21.mkdirSync(swarmDir, { recursive: true });
|
|
47277
47778
|
fs21.writeFileSync(sentinelPath, `first-run-complete: ${new Date().toISOString()}
|
|
47278
47779
|
`, { flag: "wx" });
|
|
@@ -47387,7 +47888,7 @@ function findSimilarCommands(query) {
|
|
|
47387
47888
|
return cmd.toLowerCase().includes(q) || q.includes(cmd.toLowerCase());
|
|
47388
47889
|
}).map((cmd) => ({
|
|
47389
47890
|
cmd,
|
|
47390
|
-
score: cmd.length < q.length ? q.length - cmd.length : levenshteinDistance(q, cmd)
|
|
47891
|
+
score: cmd.length < q.length ? q.length - cmd.length : _internals19.levenshteinDistance(q, cmd)
|
|
47391
47892
|
}));
|
|
47392
47893
|
scored.sort((a, b) => a.score - b.score);
|
|
47393
47894
|
return scored.slice(0, 3).map((s) => s.cmd);
|
|
@@ -47417,11 +47918,11 @@ async function handleHelpCommand(ctx) {
|
|
|
47417
47918
|
return buildHelpText2();
|
|
47418
47919
|
}
|
|
47419
47920
|
const tokens = targetCommand.split(/\s+/);
|
|
47420
|
-
const resolved = resolveCommand(tokens);
|
|
47921
|
+
const resolved = _internals19.resolveCommand(tokens);
|
|
47421
47922
|
if (resolved) {
|
|
47422
|
-
return buildDetailedHelp(resolved.key, resolved.entry);
|
|
47923
|
+
return _internals19.buildDetailedHelp(resolved.key, resolved.entry);
|
|
47423
47924
|
}
|
|
47424
|
-
const similar = findSimilarCommands(targetCommand);
|
|
47925
|
+
const similar = _internals19.findSimilarCommands(targetCommand);
|
|
47425
47926
|
const { buildHelpText: fullHelp } = await Promise.resolve().then(() => (init_commands(), exports_commands));
|
|
47426
47927
|
if (similar.length > 0) {
|
|
47427
47928
|
return `Command '/swarm ${targetCommand}' not found.
|
|
@@ -47457,24 +47958,24 @@ function validateAliases() {
|
|
|
47457
47958
|
}
|
|
47458
47959
|
aliasTargets.get(target).push(name);
|
|
47459
47960
|
const visited = new Set;
|
|
47460
|
-
const
|
|
47961
|
+
const path37 = [];
|
|
47461
47962
|
let current = target;
|
|
47462
47963
|
while (current) {
|
|
47463
47964
|
const currentEntry = COMMAND_REGISTRY[current];
|
|
47464
47965
|
if (!currentEntry)
|
|
47465
47966
|
break;
|
|
47466
47967
|
if (visited.has(current)) {
|
|
47467
|
-
const cycleStart =
|
|
47968
|
+
const cycleStart = path37.indexOf(current);
|
|
47468
47969
|
const fullChain = [
|
|
47469
47970
|
name,
|
|
47470
|
-
...
|
|
47971
|
+
...path37.slice(0, cycleStart > 0 ? cycleStart : path37.length),
|
|
47471
47972
|
current
|
|
47472
47973
|
].join(" \u2192 ");
|
|
47473
47974
|
errors5.push(`Circular alias detected: ${fullChain}`);
|
|
47474
47975
|
break;
|
|
47475
47976
|
}
|
|
47476
47977
|
visited.add(current);
|
|
47477
|
-
|
|
47978
|
+
path37.push(current);
|
|
47478
47979
|
current = currentEntry.aliasOf || "";
|
|
47479
47980
|
}
|
|
47480
47981
|
}
|
|
@@ -47515,7 +48016,7 @@ function resolveCommand(tokens) {
|
|
|
47515
48016
|
}
|
|
47516
48017
|
return null;
|
|
47517
48018
|
}
|
|
47518
|
-
var COMMAND_REGISTRY, VALID_COMMANDS, validation;
|
|
48019
|
+
var COMMAND_REGISTRY, VALID_COMMANDS, _internals19, validation;
|
|
47519
48020
|
var init_registry = __esm(() => {
|
|
47520
48021
|
init_acknowledge_spec_drift();
|
|
47521
48022
|
init_agents();
|
|
@@ -47576,7 +48077,7 @@ var init_registry = __esm(() => {
|
|
|
47576
48077
|
clashesWithNativeCcCommand: "/agents"
|
|
47577
48078
|
},
|
|
47578
48079
|
help: {
|
|
47579
|
-
handler: (ctx) => handleHelpCommand(ctx),
|
|
48080
|
+
handler: (ctx) => _internals19.handleHelpCommand(ctx),
|
|
47580
48081
|
description: "Show help for swarm commands",
|
|
47581
48082
|
category: "core",
|
|
47582
48083
|
args: "[command]",
|
|
@@ -47906,7 +48407,15 @@ var init_registry = __esm(() => {
|
|
|
47906
48407
|
}
|
|
47907
48408
|
};
|
|
47908
48409
|
VALID_COMMANDS = Object.keys(COMMAND_REGISTRY);
|
|
47909
|
-
|
|
48410
|
+
_internals19 = {
|
|
48411
|
+
handleHelpCommand,
|
|
48412
|
+
validateAliases,
|
|
48413
|
+
resolveCommand,
|
|
48414
|
+
levenshteinDistance,
|
|
48415
|
+
findSimilarCommands,
|
|
48416
|
+
buildDetailedHelp
|
|
48417
|
+
};
|
|
48418
|
+
validation = _internals19.validateAliases();
|
|
47910
48419
|
if (!validation.valid) {
|
|
47911
48420
|
throw new Error(`COMMAND_REGISTRY alias validation failed:
|
|
47912
48421
|
${validation.errors.join(`
|
|
@@ -47926,53 +48435,53 @@ init_cache_paths();
|
|
|
47926
48435
|
init_constants();
|
|
47927
48436
|
import * as fs22 from "fs";
|
|
47928
48437
|
import * as os7 from "os";
|
|
47929
|
-
import * as
|
|
48438
|
+
import * as path37 from "path";
|
|
47930
48439
|
var { version: version4 } = package_default;
|
|
47931
48440
|
var CONFIG_DIR = getPluginConfigDir();
|
|
47932
|
-
var OPENCODE_CONFIG_PATH =
|
|
47933
|
-
var PLUGIN_CONFIG_PATH =
|
|
47934
|
-
var PROMPTS_DIR =
|
|
48441
|
+
var OPENCODE_CONFIG_PATH = path37.join(CONFIG_DIR, "opencode.json");
|
|
48442
|
+
var PLUGIN_CONFIG_PATH = path37.join(CONFIG_DIR, "opencode-swarm.json");
|
|
48443
|
+
var PROMPTS_DIR = path37.join(CONFIG_DIR, "opencode-swarm");
|
|
47935
48444
|
var OPENCODE_PLUGIN_CACHE_PATHS = getPluginCachePaths();
|
|
47936
48445
|
var OPENCODE_PLUGIN_LOCK_FILE_PATHS = getPluginLockFilePaths();
|
|
47937
48446
|
function isSafeCachePath(p) {
|
|
47938
|
-
const resolved =
|
|
47939
|
-
const home =
|
|
48447
|
+
const resolved = path37.resolve(p);
|
|
48448
|
+
const home = path37.resolve(os7.homedir());
|
|
47940
48449
|
if (resolved === "/" || resolved === home || resolved.length <= home.length) {
|
|
47941
48450
|
return false;
|
|
47942
48451
|
}
|
|
47943
|
-
const segments = resolved.split(
|
|
48452
|
+
const segments = resolved.split(path37.sep).filter((s) => s.length > 0);
|
|
47944
48453
|
if (segments.length < 4) {
|
|
47945
48454
|
return false;
|
|
47946
48455
|
}
|
|
47947
|
-
const leaf =
|
|
48456
|
+
const leaf = path37.basename(resolved);
|
|
47948
48457
|
if (leaf !== "opencode-swarm@latest" && leaf !== "opencode-swarm") {
|
|
47949
48458
|
return false;
|
|
47950
48459
|
}
|
|
47951
|
-
const parent =
|
|
48460
|
+
const parent = path37.basename(path37.dirname(resolved));
|
|
47952
48461
|
if (parent !== "packages" && parent !== "node_modules") {
|
|
47953
48462
|
return false;
|
|
47954
48463
|
}
|
|
47955
|
-
const grandparent =
|
|
48464
|
+
const grandparent = path37.basename(path37.dirname(path37.dirname(resolved)));
|
|
47956
48465
|
if (grandparent !== "opencode") {
|
|
47957
48466
|
return false;
|
|
47958
48467
|
}
|
|
47959
48468
|
return true;
|
|
47960
48469
|
}
|
|
47961
48470
|
function isSafeLockFilePath(p) {
|
|
47962
|
-
const resolved =
|
|
47963
|
-
const home =
|
|
48471
|
+
const resolved = path37.resolve(p);
|
|
48472
|
+
const home = path37.resolve(os7.homedir());
|
|
47964
48473
|
if (resolved === "/" || resolved === home || resolved.length <= home.length) {
|
|
47965
48474
|
return false;
|
|
47966
48475
|
}
|
|
47967
|
-
const segments = resolved.split(
|
|
48476
|
+
const segments = resolved.split(path37.sep).filter((s) => s.length > 0);
|
|
47968
48477
|
if (segments.length < 4) {
|
|
47969
48478
|
return false;
|
|
47970
48479
|
}
|
|
47971
|
-
const leaf =
|
|
48480
|
+
const leaf = path37.basename(resolved);
|
|
47972
48481
|
if (leaf !== "bun.lock" && leaf !== "bun.lockb" && leaf !== "package-lock.json") {
|
|
47973
48482
|
return false;
|
|
47974
48483
|
}
|
|
47975
|
-
const parent =
|
|
48484
|
+
const parent = path37.basename(path37.dirname(resolved));
|
|
47976
48485
|
if (parent !== "opencode") {
|
|
47977
48486
|
return false;
|
|
47978
48487
|
}
|
|
@@ -47998,8 +48507,8 @@ function saveJson(filepath, data) {
|
|
|
47998
48507
|
}
|
|
47999
48508
|
function writeProjectConfigIfMissing(cwd) {
|
|
48000
48509
|
try {
|
|
48001
|
-
const opencodeDir =
|
|
48002
|
-
const projectConfigPath =
|
|
48510
|
+
const opencodeDir = path37.join(cwd, ".opencode");
|
|
48511
|
+
const projectConfigPath = path37.join(opencodeDir, "opencode-swarm.json");
|
|
48003
48512
|
if (fs22.existsSync(projectConfigPath)) {
|
|
48004
48513
|
return;
|
|
48005
48514
|
}
|
|
@@ -48020,7 +48529,7 @@ async function install() {
|
|
|
48020
48529
|
`);
|
|
48021
48530
|
ensureDir(CONFIG_DIR);
|
|
48022
48531
|
ensureDir(PROMPTS_DIR);
|
|
48023
|
-
const LEGACY_CONFIG_PATH =
|
|
48532
|
+
const LEGACY_CONFIG_PATH = path37.join(CONFIG_DIR, "config.json");
|
|
48024
48533
|
let opencodeConfig = loadJson(OPENCODE_CONFIG_PATH);
|
|
48025
48534
|
if (!opencodeConfig) {
|
|
48026
48535
|
const legacyConfig = loadJson(LEGACY_CONFIG_PATH);
|