opencode-swarm 7.5.1 → 7.5.2
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 +931 -430
- 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 +958 -567
- 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.2",
|
|
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,6 +20311,9 @@ ${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
|
|
@@ -20258,10 +20327,12 @@ 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;
|
|
@@ -20356,6 +20427,7 @@ function extractCurrentPhaseFromPlan(plan) {
|
|
|
20356
20427
|
const statusText = statusMap[phase.status] || "PENDING";
|
|
20357
20428
|
return `Phase ${phase.id}: ${phase.name} [${statusText}]`;
|
|
20358
20429
|
}
|
|
20430
|
+
var init_extractors = () => {};
|
|
20359
20431
|
|
|
20360
20432
|
// src/hooks/loop-detector.ts
|
|
20361
20433
|
var init_loop_detector = __esm(() => {
|
|
@@ -20385,8 +20457,10 @@ var init_guardrails = __esm(() => {
|
|
|
20385
20457
|
init_telemetry();
|
|
20386
20458
|
init_utils();
|
|
20387
20459
|
init_bun_compat();
|
|
20460
|
+
init_logger();
|
|
20388
20461
|
init_conflict_resolution();
|
|
20389
20462
|
init_delegation_gate();
|
|
20463
|
+
init_extractors();
|
|
20390
20464
|
init_loop_detector();
|
|
20391
20465
|
init_model_limits();
|
|
20392
20466
|
init_normalize_tool_name();
|
|
@@ -20434,6 +20508,7 @@ var init_delegation_gate = __esm(() => {
|
|
|
20434
20508
|
init_schema();
|
|
20435
20509
|
init_state();
|
|
20436
20510
|
init_telemetry();
|
|
20511
|
+
init_logger();
|
|
20437
20512
|
init_guardrails();
|
|
20438
20513
|
init_normalize_tool_name();
|
|
20439
20514
|
init_utils2();
|
|
@@ -34022,6 +34097,19 @@ function getCurrentBranch(cwd) {
|
|
|
34022
34097
|
const output = gitExec2(["rev-parse", "--abbrev-ref", "HEAD"], cwd);
|
|
34023
34098
|
return output.trim();
|
|
34024
34099
|
}
|
|
34100
|
+
function getDefaultBaseBranch(cwd) {
|
|
34101
|
+
try {
|
|
34102
|
+
gitExec2(["rev-parse", "--verify", "origin/main"], cwd);
|
|
34103
|
+
return "origin/main";
|
|
34104
|
+
} catch {
|
|
34105
|
+
try {
|
|
34106
|
+
gitExec2(["rev-parse", "--verify", "origin/master"], cwd);
|
|
34107
|
+
return "origin/master";
|
|
34108
|
+
} catch {
|
|
34109
|
+
return "origin/main";
|
|
34110
|
+
}
|
|
34111
|
+
}
|
|
34112
|
+
}
|
|
34025
34113
|
function hasUncommittedChanges(cwd) {
|
|
34026
34114
|
const status = gitExec2(["status", "--porcelain"], cwd);
|
|
34027
34115
|
return status.trim().length > 0;
|
|
@@ -34057,7 +34145,7 @@ function resetToRemoteBranch(cwd, options) {
|
|
|
34057
34145
|
const prunedBranches = [];
|
|
34058
34146
|
try {
|
|
34059
34147
|
const currentBranch = getCurrentBranch(cwd);
|
|
34060
|
-
const defaultRemoteBranch = detectDefaultRemoteBranch(cwd);
|
|
34148
|
+
const defaultRemoteBranch = _internals6.detectDefaultRemoteBranch(cwd);
|
|
34061
34149
|
if (!defaultRemoteBranch) {
|
|
34062
34150
|
return {
|
|
34063
34151
|
success: false,
|
|
@@ -34236,8 +34324,16 @@ function resetToRemoteBranch(cwd, options) {
|
|
|
34236
34324
|
};
|
|
34237
34325
|
}
|
|
34238
34326
|
}
|
|
34239
|
-
var GIT_TIMEOUT_MS2 = 30000;
|
|
34240
|
-
var init_branch = () => {
|
|
34327
|
+
var GIT_TIMEOUT_MS2 = 30000, _internals6;
|
|
34328
|
+
var init_branch = __esm(() => {
|
|
34329
|
+
init_logger();
|
|
34330
|
+
_internals6 = {
|
|
34331
|
+
gitExec: gitExec2,
|
|
34332
|
+
detectDefaultRemoteBranch,
|
|
34333
|
+
getDefaultBaseBranch,
|
|
34334
|
+
resetToRemoteBranch
|
|
34335
|
+
};
|
|
34336
|
+
});
|
|
34241
34337
|
|
|
34242
34338
|
// src/hooks/knowledge-store.ts
|
|
34243
34339
|
import { existsSync as existsSync7 } from "fs";
|
|
@@ -34407,13 +34503,77 @@ var init_knowledge_store = __esm(() => {
|
|
|
34407
34503
|
});
|
|
34408
34504
|
|
|
34409
34505
|
// src/hooks/knowledge-reader.ts
|
|
34506
|
+
import { existsSync as existsSync8 } from "fs";
|
|
34507
|
+
import { mkdir as mkdir3, readFile as readFile4, writeFile as writeFile4 } from "fs/promises";
|
|
34508
|
+
import * as path11 from "path";
|
|
34509
|
+
async function updateRetrievalOutcome(directory, phaseInfo, phaseSucceeded) {
|
|
34510
|
+
const shownFile = path11.join(directory, ".swarm", ".knowledge-shown.json");
|
|
34511
|
+
try {
|
|
34512
|
+
if (!existsSync8(shownFile)) {
|
|
34513
|
+
return;
|
|
34514
|
+
}
|
|
34515
|
+
const content = await readFile4(shownFile, "utf-8");
|
|
34516
|
+
const shownData = JSON.parse(content);
|
|
34517
|
+
const shownIds = shownData[phaseInfo];
|
|
34518
|
+
if (!shownIds || shownIds.length === 0) {
|
|
34519
|
+
return;
|
|
34520
|
+
}
|
|
34521
|
+
const swarmPath = resolveSwarmKnowledgePath(directory);
|
|
34522
|
+
const entries = await readKnowledge(swarmPath);
|
|
34523
|
+
let updated = false;
|
|
34524
|
+
const foundInSwarm = new Set;
|
|
34525
|
+
for (const entry of entries) {
|
|
34526
|
+
if (shownIds.includes(entry.id)) {
|
|
34527
|
+
entry.retrieval_outcomes.applied_count++;
|
|
34528
|
+
if (phaseSucceeded) {
|
|
34529
|
+
entry.retrieval_outcomes.succeeded_after_count++;
|
|
34530
|
+
} else {
|
|
34531
|
+
entry.retrieval_outcomes.failed_after_count++;
|
|
34532
|
+
}
|
|
34533
|
+
updated = true;
|
|
34534
|
+
foundInSwarm.add(entry.id);
|
|
34535
|
+
}
|
|
34536
|
+
}
|
|
34537
|
+
if (updated) {
|
|
34538
|
+
await rewriteKnowledge(swarmPath, entries);
|
|
34539
|
+
}
|
|
34540
|
+
const remainingIds = shownIds.filter((id) => !foundInSwarm.has(id));
|
|
34541
|
+
if (remainingIds.length === 0) {
|
|
34542
|
+
delete shownData[phaseInfo];
|
|
34543
|
+
await writeFile4(shownFile, JSON.stringify(shownData, null, 2), "utf-8");
|
|
34544
|
+
return;
|
|
34545
|
+
}
|
|
34546
|
+
const hivePath = resolveHiveKnowledgePath();
|
|
34547
|
+
const hiveEntries = await readKnowledge(hivePath);
|
|
34548
|
+
let hiveUpdated = false;
|
|
34549
|
+
for (const entry of hiveEntries) {
|
|
34550
|
+
if (remainingIds.includes(entry.id)) {
|
|
34551
|
+
entry.retrieval_outcomes.applied_count++;
|
|
34552
|
+
if (phaseSucceeded) {
|
|
34553
|
+
entry.retrieval_outcomes.succeeded_after_count++;
|
|
34554
|
+
} else {
|
|
34555
|
+
entry.retrieval_outcomes.failed_after_count++;
|
|
34556
|
+
}
|
|
34557
|
+
hiveUpdated = true;
|
|
34558
|
+
}
|
|
34559
|
+
}
|
|
34560
|
+
if (hiveUpdated) {
|
|
34561
|
+
await rewriteKnowledge(hivePath, hiveEntries);
|
|
34562
|
+
}
|
|
34563
|
+
delete shownData[phaseInfo];
|
|
34564
|
+
await writeFile4(shownFile, JSON.stringify(shownData, null, 2), "utf-8");
|
|
34565
|
+
} catch {
|
|
34566
|
+
warn("[swarm] Knowledge: failed to update retrieval outcomes");
|
|
34567
|
+
}
|
|
34568
|
+
}
|
|
34410
34569
|
var init_knowledge_reader = __esm(() => {
|
|
34570
|
+
init_logger();
|
|
34411
34571
|
init_knowledge_store();
|
|
34412
34572
|
});
|
|
34413
34573
|
|
|
34414
34574
|
// src/hooks/knowledge-validator.ts
|
|
34415
|
-
import { appendFile as appendFile3, mkdir as
|
|
34416
|
-
import * as
|
|
34575
|
+
import { appendFile as appendFile3, mkdir as mkdir4, writeFile as writeFile5 } from "fs/promises";
|
|
34576
|
+
import * as path12 from "path";
|
|
34417
34577
|
function normalizeText(text) {
|
|
34418
34578
|
return text.normalize("NFKC").toLowerCase().replace(/[^\w\s]/g, " ").replace(/\s+/g, " ").trim();
|
|
34419
34579
|
}
|
|
@@ -34567,11 +34727,11 @@ async function quarantineEntry(directory, entryId, reason, reportedBy) {
|
|
|
34567
34727
|
return;
|
|
34568
34728
|
}
|
|
34569
34729
|
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
|
|
34730
|
+
const knowledgePath = path12.join(directory, ".swarm", "knowledge.jsonl");
|
|
34731
|
+
const quarantinePath = path12.join(directory, ".swarm", "knowledge-quarantined.jsonl");
|
|
34732
|
+
const rejectedPath = path12.join(directory, ".swarm", "knowledge-rejected.jsonl");
|
|
34733
|
+
const swarmDir = path12.join(directory, ".swarm");
|
|
34734
|
+
await mkdir4(swarmDir, { recursive: true });
|
|
34575
34735
|
let release;
|
|
34576
34736
|
try {
|
|
34577
34737
|
release = await import_proper_lockfile4.default.lock(swarmDir, {
|
|
@@ -34592,7 +34752,7 @@ async function quarantineEntry(directory, entryId, reason, reportedBy) {
|
|
|
34592
34752
|
const jsonlContent = remaining.length > 0 ? `${remaining.map((e) => JSON.stringify(e)).join(`
|
|
34593
34753
|
`)}
|
|
34594
34754
|
` : "";
|
|
34595
|
-
await
|
|
34755
|
+
await writeFile5(knowledgePath, jsonlContent, "utf-8");
|
|
34596
34756
|
await appendFile3(quarantinePath, `${JSON.stringify(quarantined)}
|
|
34597
34757
|
`, "utf-8");
|
|
34598
34758
|
const quarantinedEntries = await readKnowledge(quarantinePath);
|
|
@@ -34601,7 +34761,7 @@ async function quarantineEntry(directory, entryId, reason, reportedBy) {
|
|
|
34601
34761
|
const capContent = trimmed.length > 0 ? `${trimmed.map((e) => JSON.stringify(e)).join(`
|
|
34602
34762
|
`)}
|
|
34603
34763
|
` : "";
|
|
34604
|
-
await
|
|
34764
|
+
await writeFile5(quarantinePath, capContent, "utf-8");
|
|
34605
34765
|
}
|
|
34606
34766
|
const rejectedRecord = {
|
|
34607
34767
|
id: entryId,
|
|
@@ -34627,11 +34787,11 @@ async function restoreEntry(directory, entryId) {
|
|
|
34627
34787
|
warn("[knowledge-validator] restoreEntry: invalid entryId rejected");
|
|
34628
34788
|
return;
|
|
34629
34789
|
}
|
|
34630
|
-
const knowledgePath =
|
|
34631
|
-
const quarantinePath =
|
|
34632
|
-
const rejectedPath =
|
|
34633
|
-
const swarmDir =
|
|
34634
|
-
await
|
|
34790
|
+
const knowledgePath = path12.join(directory, ".swarm", "knowledge.jsonl");
|
|
34791
|
+
const quarantinePath = path12.join(directory, ".swarm", "knowledge-quarantined.jsonl");
|
|
34792
|
+
const rejectedPath = path12.join(directory, ".swarm", "knowledge-rejected.jsonl");
|
|
34793
|
+
const swarmDir = path12.join(directory, ".swarm");
|
|
34794
|
+
await mkdir4(swarmDir, { recursive: true });
|
|
34635
34795
|
let release;
|
|
34636
34796
|
try {
|
|
34637
34797
|
release = await import_proper_lockfile4.default.lock(swarmDir, {
|
|
@@ -34647,7 +34807,7 @@ async function restoreEntry(directory, entryId) {
|
|
|
34647
34807
|
const jsonlContent = remaining.length > 0 ? `${remaining.map((e) => JSON.stringify(e)).join(`
|
|
34648
34808
|
`)}
|
|
34649
34809
|
` : "";
|
|
34650
|
-
await
|
|
34810
|
+
await writeFile5(quarantinePath, jsonlContent, "utf-8");
|
|
34651
34811
|
await appendFile3(knowledgePath, `${JSON.stringify(original)}
|
|
34652
34812
|
`, "utf-8");
|
|
34653
34813
|
const rejectedEntries = await readKnowledge(rejectedPath);
|
|
@@ -34655,7 +34815,7 @@ async function restoreEntry(directory, entryId) {
|
|
|
34655
34815
|
const rejectedContent = filtered.length > 0 ? `${filtered.map((e) => JSON.stringify(e)).join(`
|
|
34656
34816
|
`)}
|
|
34657
34817
|
` : "";
|
|
34658
|
-
await
|
|
34818
|
+
await writeFile5(rejectedPath, rejectedContent, "utf-8");
|
|
34659
34819
|
} finally {
|
|
34660
34820
|
if (release) {
|
|
34661
34821
|
await release();
|
|
@@ -34664,6 +34824,7 @@ async function restoreEntry(directory, entryId) {
|
|
|
34664
34824
|
}
|
|
34665
34825
|
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
34826
|
var init_knowledge_validator = __esm(() => {
|
|
34827
|
+
init_logger();
|
|
34667
34828
|
init_knowledge_store();
|
|
34668
34829
|
import_proper_lockfile4 = __toESM(require_proper_lockfile(), 1);
|
|
34669
34830
|
DANGEROUS_COMMAND_PATTERNS = [
|
|
@@ -34770,6 +34931,134 @@ var init_knowledge_validator = __esm(() => {
|
|
|
34770
34931
|
});
|
|
34771
34932
|
|
|
34772
34933
|
// src/hooks/knowledge-curator.ts
|
|
34934
|
+
function pruneSeenRetroSections() {
|
|
34935
|
+
const cutoff = Date.now() - 86400000;
|
|
34936
|
+
for (const [key, entry] of seenRetroSections) {
|
|
34937
|
+
if (entry.timestamp < cutoff) {
|
|
34938
|
+
seenRetroSections.delete(key);
|
|
34939
|
+
}
|
|
34940
|
+
}
|
|
34941
|
+
}
|
|
34942
|
+
function isWriteToSwarmPlan(input) {
|
|
34943
|
+
if (typeof input !== "object" || input === null)
|
|
34944
|
+
return false;
|
|
34945
|
+
const record3 = input;
|
|
34946
|
+
const toolName = record3.toolName;
|
|
34947
|
+
if (typeof toolName !== "string")
|
|
34948
|
+
return false;
|
|
34949
|
+
if (!["write", "edit", "apply_patch"].includes(toolName))
|
|
34950
|
+
return false;
|
|
34951
|
+
const rawPath = record3.path;
|
|
34952
|
+
const rawFile = record3.file;
|
|
34953
|
+
const pathField = typeof rawPath === "string" ? rawPath.replace(/\\/g, "/") : undefined;
|
|
34954
|
+
const fileField = typeof rawFile === "string" ? rawFile.replace(/\\/g, "/") : undefined;
|
|
34955
|
+
if (typeof pathField === "string" && pathField.includes(".swarm/plan.md")) {
|
|
34956
|
+
return true;
|
|
34957
|
+
}
|
|
34958
|
+
if (typeof fileField === "string" && fileField.includes(".swarm/plan.md")) {
|
|
34959
|
+
return true;
|
|
34960
|
+
}
|
|
34961
|
+
return false;
|
|
34962
|
+
}
|
|
34963
|
+
function isWriteToEvidenceFile(input) {
|
|
34964
|
+
if (typeof input !== "object" || input === null)
|
|
34965
|
+
return false;
|
|
34966
|
+
const record3 = input;
|
|
34967
|
+
const toolName = record3.toolName;
|
|
34968
|
+
if (typeof toolName !== "string")
|
|
34969
|
+
return false;
|
|
34970
|
+
if (!["write", "edit", "apply_patch"].includes(toolName))
|
|
34971
|
+
return false;
|
|
34972
|
+
const rawPath = record3.path;
|
|
34973
|
+
const rawFile = record3.file;
|
|
34974
|
+
const pathField = typeof rawPath === "string" ? rawPath.replace(/\\/g, "/") : undefined;
|
|
34975
|
+
const fileField = typeof rawFile === "string" ? rawFile.replace(/\\/g, "/") : undefined;
|
|
34976
|
+
const evidenceRegex = /\.swarm\/+evidence\/+/i;
|
|
34977
|
+
if (typeof pathField === "string" && evidenceRegex.test(pathField)) {
|
|
34978
|
+
return true;
|
|
34979
|
+
}
|
|
34980
|
+
if (typeof fileField === "string" && evidenceRegex.test(fileField)) {
|
|
34981
|
+
return true;
|
|
34982
|
+
}
|
|
34983
|
+
return false;
|
|
34984
|
+
}
|
|
34985
|
+
function extractRetrospectiveSection(planContent) {
|
|
34986
|
+
const headingRegex = /^###\s+Lessons\s+Learned$/m;
|
|
34987
|
+
const match = headingRegex.exec(planContent);
|
|
34988
|
+
if (!match)
|
|
34989
|
+
return null;
|
|
34990
|
+
const startIndex = match.index;
|
|
34991
|
+
const restOfContent = planContent.slice(startIndex);
|
|
34992
|
+
const firstNewline = restOfContent.indexOf(`
|
|
34993
|
+
`);
|
|
34994
|
+
const contentAfterHeading = firstNewline === -1 ? "" : restOfContent.slice(firstNewline + 1);
|
|
34995
|
+
const nextHeadingRegex = /^#{1,2}\s+/m;
|
|
34996
|
+
const nextMatch = nextHeadingRegex.exec(contentAfterHeading);
|
|
34997
|
+
let endIndex;
|
|
34998
|
+
if (nextMatch) {
|
|
34999
|
+
endIndex = startIndex + firstNewline + 1 + nextMatch.index;
|
|
35000
|
+
} else {
|
|
35001
|
+
endIndex = planContent.length;
|
|
35002
|
+
}
|
|
35003
|
+
return planContent.slice(startIndex, endIndex).trim();
|
|
35004
|
+
}
|
|
35005
|
+
function checkRetroChanged(sessionID, section) {
|
|
35006
|
+
const hash3 = `${section.length}:${section.slice(0, 100)}`;
|
|
35007
|
+
const lastSeen = seenRetroSections.get(sessionID);
|
|
35008
|
+
if (lastSeen?.value === hash3) {
|
|
35009
|
+
return false;
|
|
35010
|
+
}
|
|
35011
|
+
seenRetroSections.set(sessionID, { value: hash3, timestamp: Date.now() });
|
|
35012
|
+
return true;
|
|
35013
|
+
}
|
|
35014
|
+
function extractLessonsFromRetro(section) {
|
|
35015
|
+
const lessons = [];
|
|
35016
|
+
const lines = section.split(`
|
|
35017
|
+
`);
|
|
35018
|
+
for (const line of lines) {
|
|
35019
|
+
const trimmed = line.trim();
|
|
35020
|
+
const bulletMatch = /^[-*]\s+(.+)$/.exec(trimmed);
|
|
35021
|
+
if (bulletMatch) {
|
|
35022
|
+
const content = bulletMatch[1].trim();
|
|
35023
|
+
if (content) {
|
|
35024
|
+
lessons.push(content);
|
|
35025
|
+
}
|
|
35026
|
+
}
|
|
35027
|
+
}
|
|
35028
|
+
return lessons;
|
|
35029
|
+
}
|
|
35030
|
+
function extractRetractionsAndLessons(allLessons) {
|
|
35031
|
+
const retractions = [];
|
|
35032
|
+
const normalLessons = [];
|
|
35033
|
+
for (const lesson of allLessons) {
|
|
35034
|
+
const upper = lesson.trimStart().toUpperCase();
|
|
35035
|
+
if (upper.startsWith("RETRACT:") || upper.startsWith("BAD RULE:")) {
|
|
35036
|
+
const colonIdx = lesson.indexOf(":");
|
|
35037
|
+
const text = colonIdx !== -1 ? lesson.slice(colonIdx + 1).trim() : "";
|
|
35038
|
+
if (text)
|
|
35039
|
+
retractions.push(text);
|
|
35040
|
+
} else {
|
|
35041
|
+
normalLessons.push(lesson);
|
|
35042
|
+
}
|
|
35043
|
+
}
|
|
35044
|
+
return { retractions, normalLessons };
|
|
35045
|
+
}
|
|
35046
|
+
async function processRetractions(retractions, directory) {
|
|
35047
|
+
if (retractions.length === 0)
|
|
35048
|
+
return;
|
|
35049
|
+
const knowledgePath = resolveSwarmKnowledgePath(directory);
|
|
35050
|
+
const entries = await readKnowledge(knowledgePath) ?? [];
|
|
35051
|
+
for (const retractionText of retractions) {
|
|
35052
|
+
const normalizedRetraction = normalize2(retractionText);
|
|
35053
|
+
for (const entry of entries) {
|
|
35054
|
+
const normalizedLesson = normalize2(entry.lesson);
|
|
35055
|
+
if (normalizedLesson === normalizedRetraction) {
|
|
35056
|
+
await quarantineEntry(directory, entry.id, `Retracted by architect: ${retractionText}`, "architect");
|
|
35057
|
+
console.info(`[knowledge-curator] Quarantined entry ${entry.id}: "${entry.lesson}"`);
|
|
35058
|
+
}
|
|
35059
|
+
}
|
|
35060
|
+
}
|
|
35061
|
+
}
|
|
34773
35062
|
async function curateAndStoreSwarm(lessons, projectName, phaseInfo, directory, config3) {
|
|
34774
35063
|
const knowledgePath = resolveSwarmKnowledgePath(directory);
|
|
34775
35064
|
const existingEntries = await readKnowledge(knowledgePath) ?? [];
|
|
@@ -34852,7 +35141,7 @@ async function curateAndStoreSwarm(lessons, projectName, phaseInfo, directory, c
|
|
|
34852
35141
|
existingEntries.push(entry);
|
|
34853
35142
|
}
|
|
34854
35143
|
await enforceKnowledgeCap(knowledgePath, config3.swarm_max_entries);
|
|
34855
|
-
await runAutoPromotion(directory, config3);
|
|
35144
|
+
await _internals7.runAutoPromotion(directory, config3);
|
|
34856
35145
|
return { stored, skipped, rejected };
|
|
34857
35146
|
}
|
|
34858
35147
|
async function runAutoPromotion(directory, config3) {
|
|
@@ -34885,18 +35174,100 @@ async function runAutoPromotion(directory, config3) {
|
|
|
34885
35174
|
await rewriteKnowledge(knowledgePath, entries);
|
|
34886
35175
|
}
|
|
34887
35176
|
}
|
|
34888
|
-
|
|
35177
|
+
function createKnowledgeCuratorHook(directory, config3) {
|
|
35178
|
+
const handler = async (input, _output) => {
|
|
35179
|
+
pruneSeenRetroSections();
|
|
35180
|
+
if (!config3.enabled)
|
|
35181
|
+
return;
|
|
35182
|
+
if (!isWriteToSwarmPlan(input) && !isWriteToEvidenceFile(input))
|
|
35183
|
+
return;
|
|
35184
|
+
const sessionID = input?.sessionID ?? "default";
|
|
35185
|
+
const isEvidenceTrigger = isWriteToEvidenceFile(input) && !isWriteToSwarmPlan(input);
|
|
35186
|
+
if (isEvidenceTrigger) {
|
|
35187
|
+
const record3 = input;
|
|
35188
|
+
const rawPath = record3.path;
|
|
35189
|
+
const rawFile = record3.file;
|
|
35190
|
+
const filePath = typeof rawPath === "string" ? rawPath.replace(/\\/g, "/") : typeof rawFile === "string" ? rawFile.replace(/\\/g, "/") : null;
|
|
35191
|
+
if (!filePath)
|
|
35192
|
+
return;
|
|
35193
|
+
const evidenceKey = `evidence:${sessionID}:${filePath}`;
|
|
35194
|
+
const lastSeenEvidence = seenRetroSections.get(evidenceKey);
|
|
35195
|
+
const evidenceContent = await readSwarmFileAsync(directory, filePath.replace(/^.*\.swarm\//, ""));
|
|
35196
|
+
if (!evidenceContent)
|
|
35197
|
+
return;
|
|
35198
|
+
let evidenceData;
|
|
35199
|
+
try {
|
|
35200
|
+
evidenceData = JSON.parse(evidenceContent);
|
|
35201
|
+
} catch {
|
|
35202
|
+
return;
|
|
35203
|
+
}
|
|
35204
|
+
let lessons = [];
|
|
35205
|
+
if (Array.isArray(evidenceData.entries) && evidenceData.entries.length > 0) {
|
|
35206
|
+
const firstEntry = evidenceData.entries[0];
|
|
35207
|
+
if (Array.isArray(firstEntry.lessons_learned)) {
|
|
35208
|
+
lessons = firstEntry.lessons_learned;
|
|
35209
|
+
}
|
|
35210
|
+
} else if (Array.isArray(evidenceData.lessons_learned)) {
|
|
35211
|
+
lessons = evidenceData.lessons_learned;
|
|
35212
|
+
}
|
|
35213
|
+
if (lessons.length === 0)
|
|
35214
|
+
return;
|
|
35215
|
+
const evidenceHash = `${lessons.length}:${lessons.slice(0, 3).join("|")}`;
|
|
35216
|
+
if (lastSeenEvidence?.value === evidenceHash) {
|
|
35217
|
+
return;
|
|
35218
|
+
}
|
|
35219
|
+
seenRetroSections.set(evidenceKey, {
|
|
35220
|
+
value: evidenceHash,
|
|
35221
|
+
timestamp: Date.now()
|
|
35222
|
+
});
|
|
35223
|
+
const projectName2 = evidenceData.project_name ?? "unknown";
|
|
35224
|
+
const phaseNumber2 = typeof evidenceData.phase_number === "number" ? evidenceData.phase_number : 1;
|
|
35225
|
+
await _internals7.curateAndStoreSwarm(lessons, projectName2, { phase_number: phaseNumber2 }, directory, config3);
|
|
35226
|
+
await updateRetrievalOutcome(directory, `Phase ${phaseNumber2}`, true);
|
|
35227
|
+
return;
|
|
35228
|
+
}
|
|
35229
|
+
const planContent = await readSwarmFileAsync(directory, "plan.md");
|
|
35230
|
+
if (!planContent)
|
|
35231
|
+
return;
|
|
35232
|
+
const section = extractRetrospectiveSection(planContent);
|
|
35233
|
+
if (!section)
|
|
35234
|
+
return;
|
|
35235
|
+
if (!checkRetroChanged(sessionID, section))
|
|
35236
|
+
return;
|
|
35237
|
+
const allLessons = extractLessonsFromRetro(section);
|
|
35238
|
+
if (allLessons.length === 0)
|
|
35239
|
+
return;
|
|
35240
|
+
const { retractions, normalLessons } = extractRetractionsAndLessons(allLessons);
|
|
35241
|
+
await processRetractions(retractions, directory);
|
|
35242
|
+
if (normalLessons.length === 0)
|
|
35243
|
+
return;
|
|
35244
|
+
const projectNameMatch = /^#\s+(.+)$/m.exec(planContent);
|
|
35245
|
+
const projectName = projectNameMatch ? projectNameMatch[1].trim() : "unknown";
|
|
35246
|
+
const phaseMatch = /^Phase:\s*(\d+)/m.exec(planContent);
|
|
35247
|
+
const phaseNumber = phaseMatch ? parseInt(phaseMatch[1], 10) : 1;
|
|
35248
|
+
await _internals7.curateAndStoreSwarm(normalLessons, projectName, { phase_number: phaseNumber }, directory, config3);
|
|
35249
|
+
await updateRetrievalOutcome(directory, `Phase ${phaseNumber}`, true);
|
|
35250
|
+
};
|
|
35251
|
+
return safeHook(handler);
|
|
35252
|
+
}
|
|
35253
|
+
var seenRetroSections, _internals7;
|
|
34889
35254
|
var init_knowledge_curator = __esm(() => {
|
|
34890
35255
|
init_knowledge_reader();
|
|
34891
35256
|
init_knowledge_store();
|
|
34892
35257
|
init_knowledge_validator();
|
|
34893
35258
|
init_utils2();
|
|
34894
35259
|
seenRetroSections = new Map;
|
|
35260
|
+
_internals7 = {
|
|
35261
|
+
isWriteToEvidenceFile,
|
|
35262
|
+
curateAndStoreSwarm,
|
|
35263
|
+
runAutoPromotion,
|
|
35264
|
+
createKnowledgeCuratorHook
|
|
35265
|
+
};
|
|
34895
35266
|
});
|
|
34896
35267
|
|
|
34897
35268
|
// src/session/snapshot-writer.ts
|
|
34898
35269
|
import { mkdirSync as mkdirSync7, renameSync as renameSync5 } from "fs";
|
|
34899
|
-
import * as
|
|
35270
|
+
import * as path13 from "path";
|
|
34900
35271
|
function serializeAgentSession(s) {
|
|
34901
35272
|
const gateLog = {};
|
|
34902
35273
|
const rawGateLog = s.gateLog ?? new Map;
|
|
@@ -34986,7 +35357,7 @@ async function writeSnapshot(directory, state) {
|
|
|
34986
35357
|
}
|
|
34987
35358
|
const content = JSON.stringify(snapshot, null, 2);
|
|
34988
35359
|
const resolvedPath = validateSwarmPath(directory, "session/state.json");
|
|
34989
|
-
const dir =
|
|
35360
|
+
const dir = path13.dirname(resolvedPath);
|
|
34990
35361
|
mkdirSync7(dir, { recursive: true });
|
|
34991
35362
|
const tempPath = `${resolvedPath}.tmp.${Date.now()}.${Math.random().toString(36).slice(2)}`;
|
|
34992
35363
|
await bunWrite(tempPath, content);
|
|
@@ -34997,17 +35368,28 @@ async function writeSnapshot(directory, state) {
|
|
|
34997
35368
|
});
|
|
34998
35369
|
}
|
|
34999
35370
|
}
|
|
35371
|
+
function createSnapshotWriterHook(directory) {
|
|
35372
|
+
return (_input, _output) => {
|
|
35373
|
+
_writeInFlight = _writeInFlight.then(() => _internals8.writeSnapshot(directory, swarmState), () => _internals8.writeSnapshot(directory, swarmState));
|
|
35374
|
+
return _writeInFlight;
|
|
35375
|
+
};
|
|
35376
|
+
}
|
|
35000
35377
|
async function flushPendingSnapshot(directory) {
|
|
35001
|
-
_writeInFlight = _writeInFlight.then(() => writeSnapshot(directory, swarmState), () => writeSnapshot(directory, swarmState));
|
|
35378
|
+
_writeInFlight = _writeInFlight.then(() => _internals8.writeSnapshot(directory, swarmState), () => _internals8.writeSnapshot(directory, swarmState));
|
|
35002
35379
|
await _writeInFlight;
|
|
35003
35380
|
}
|
|
35004
|
-
var _writeInFlight;
|
|
35381
|
+
var _writeInFlight, _internals8;
|
|
35005
35382
|
var init_snapshot_writer = __esm(() => {
|
|
35006
35383
|
init_utils2();
|
|
35007
35384
|
init_state();
|
|
35008
35385
|
init_utils();
|
|
35009
35386
|
init_bun_compat();
|
|
35010
35387
|
_writeInFlight = Promise.resolve();
|
|
35388
|
+
_internals8 = {
|
|
35389
|
+
writeSnapshot,
|
|
35390
|
+
createSnapshotWriterHook,
|
|
35391
|
+
flushPendingSnapshot
|
|
35392
|
+
};
|
|
35011
35393
|
});
|
|
35012
35394
|
|
|
35013
35395
|
// src/tools/write-retro.ts
|
|
@@ -35311,7 +35693,7 @@ async function executeWriteRetro(args, directory) {
|
|
|
35311
35693
|
}, null, 2);
|
|
35312
35694
|
}
|
|
35313
35695
|
}
|
|
35314
|
-
var write_retro;
|
|
35696
|
+
var write_retro, _internals9;
|
|
35315
35697
|
var init_write_retro = __esm(() => {
|
|
35316
35698
|
init_zod();
|
|
35317
35699
|
init_evidence_schema();
|
|
@@ -35358,17 +35740,21 @@ var init_write_retro = __esm(() => {
|
|
|
35358
35740
|
task_id: args.task_id !== undefined ? String(args.task_id) : undefined,
|
|
35359
35741
|
metadata: args.metadata
|
|
35360
35742
|
};
|
|
35361
|
-
return await executeWriteRetro(writeRetroArgs, directory);
|
|
35743
|
+
return await _internals9.executeWriteRetro(writeRetroArgs, directory);
|
|
35362
35744
|
} catch {
|
|
35363
35745
|
return JSON.stringify({ success: false, phase: rawPhase, message: "Invalid arguments" }, null, 2);
|
|
35364
35746
|
}
|
|
35365
35747
|
}
|
|
35366
35748
|
});
|
|
35749
|
+
_internals9 = {
|
|
35750
|
+
executeWriteRetro,
|
|
35751
|
+
write_retro
|
|
35752
|
+
};
|
|
35367
35753
|
});
|
|
35368
35754
|
|
|
35369
35755
|
// src/commands/close.ts
|
|
35370
35756
|
import { promises as fs7 } from "fs";
|
|
35371
|
-
import
|
|
35757
|
+
import path14 from "path";
|
|
35372
35758
|
function guaranteeAllPlansComplete(planData) {
|
|
35373
35759
|
const closedPhaseIds = [];
|
|
35374
35760
|
const closedTaskIds = [];
|
|
@@ -35391,10 +35777,10 @@ function guaranteeAllPlansComplete(planData) {
|
|
|
35391
35777
|
}
|
|
35392
35778
|
async function handleCloseCommand(directory, args) {
|
|
35393
35779
|
const planPath = validateSwarmPath(directory, "plan.json");
|
|
35394
|
-
const swarmDir =
|
|
35780
|
+
const swarmDir = path14.join(directory, ".swarm");
|
|
35395
35781
|
let planExists = false;
|
|
35396
35782
|
let planData = {
|
|
35397
|
-
title:
|
|
35783
|
+
title: path14.basename(directory) || "Ad-hoc session",
|
|
35398
35784
|
phases: []
|
|
35399
35785
|
};
|
|
35400
35786
|
try {
|
|
@@ -35499,7 +35885,7 @@ async function handleCloseCommand(directory, args) {
|
|
|
35499
35885
|
warnings.push(`Session retrospective write threw: ${retroError instanceof Error ? retroError.message : String(retroError)}`);
|
|
35500
35886
|
}
|
|
35501
35887
|
}
|
|
35502
|
-
const lessonsFilePath =
|
|
35888
|
+
const lessonsFilePath = path14.join(swarmDir, "close-lessons.md");
|
|
35503
35889
|
let explicitLessons = [];
|
|
35504
35890
|
try {
|
|
35505
35891
|
const lessonsText = await fs7.readFile(lessonsFilePath, "utf-8");
|
|
@@ -35508,11 +35894,11 @@ async function handleCloseCommand(directory, args) {
|
|
|
35508
35894
|
} catch {}
|
|
35509
35895
|
const retroLessons = [];
|
|
35510
35896
|
try {
|
|
35511
|
-
const evidenceDir =
|
|
35897
|
+
const evidenceDir = path14.join(swarmDir, "evidence");
|
|
35512
35898
|
const evidenceEntries = await fs7.readdir(evidenceDir);
|
|
35513
35899
|
const retroDirs = evidenceEntries.filter((e) => e.startsWith("retro-")).sort((a, b) => a.localeCompare(b, undefined, { numeric: true }));
|
|
35514
35900
|
for (const retroDir of retroDirs) {
|
|
35515
|
-
const evidencePath =
|
|
35901
|
+
const evidencePath = path14.join(evidenceDir, retroDir, "evidence.json");
|
|
35516
35902
|
try {
|
|
35517
35903
|
const content = await fs7.readFile(evidencePath, "utf-8");
|
|
35518
35904
|
const parsed = JSON.parse(content);
|
|
@@ -35566,15 +35952,15 @@ async function handleCloseCommand(directory, args) {
|
|
|
35566
35952
|
}
|
|
35567
35953
|
const timestamp = new Date().toISOString().replace(/[:.]/g, "-");
|
|
35568
35954
|
const suffix = Math.random().toString(36).slice(2, 8);
|
|
35569
|
-
const archiveDir =
|
|
35955
|
+
const archiveDir = path14.join(swarmDir, "archive", `swarm-${timestamp}-${suffix}`);
|
|
35570
35956
|
let archiveResult = "";
|
|
35571
35957
|
let archivedFileCount = 0;
|
|
35572
35958
|
const archivedActiveStateFiles = new Set;
|
|
35573
35959
|
try {
|
|
35574
35960
|
await fs7.mkdir(archiveDir, { recursive: true });
|
|
35575
35961
|
for (const artifact of ARCHIVE_ARTIFACTS) {
|
|
35576
|
-
const srcPath =
|
|
35577
|
-
const destPath =
|
|
35962
|
+
const srcPath = path14.join(swarmDir, artifact);
|
|
35963
|
+
const destPath = path14.join(archiveDir, artifact);
|
|
35578
35964
|
try {
|
|
35579
35965
|
await fs7.copyFile(srcPath, destPath);
|
|
35580
35966
|
archivedFileCount++;
|
|
@@ -35583,22 +35969,22 @@ async function handleCloseCommand(directory, args) {
|
|
|
35583
35969
|
}
|
|
35584
35970
|
} catch {}
|
|
35585
35971
|
}
|
|
35586
|
-
const evidenceDir =
|
|
35587
|
-
const archiveEvidenceDir =
|
|
35972
|
+
const evidenceDir = path14.join(swarmDir, "evidence");
|
|
35973
|
+
const archiveEvidenceDir = path14.join(archiveDir, "evidence");
|
|
35588
35974
|
try {
|
|
35589
35975
|
const evidenceEntries = await fs7.readdir(evidenceDir);
|
|
35590
35976
|
if (evidenceEntries.length > 0) {
|
|
35591
35977
|
await fs7.mkdir(archiveEvidenceDir, { recursive: true });
|
|
35592
35978
|
for (const entry of evidenceEntries) {
|
|
35593
|
-
const srcEntry =
|
|
35594
|
-
const destEntry =
|
|
35979
|
+
const srcEntry = path14.join(evidenceDir, entry);
|
|
35980
|
+
const destEntry = path14.join(archiveEvidenceDir, entry);
|
|
35595
35981
|
try {
|
|
35596
35982
|
const stat2 = await fs7.stat(srcEntry);
|
|
35597
35983
|
if (stat2.isDirectory()) {
|
|
35598
35984
|
await fs7.mkdir(destEntry, { recursive: true });
|
|
35599
35985
|
const subEntries = await fs7.readdir(srcEntry);
|
|
35600
35986
|
for (const sub of subEntries) {
|
|
35601
|
-
await fs7.copyFile(
|
|
35987
|
+
await fs7.copyFile(path14.join(srcEntry, sub), path14.join(destEntry, sub)).catch(() => {});
|
|
35602
35988
|
}
|
|
35603
35989
|
} else {
|
|
35604
35990
|
await fs7.copyFile(srcEntry, destEntry);
|
|
@@ -35608,11 +35994,11 @@ async function handleCloseCommand(directory, args) {
|
|
|
35608
35994
|
}
|
|
35609
35995
|
}
|
|
35610
35996
|
} catch {}
|
|
35611
|
-
const sessionStatePath =
|
|
35997
|
+
const sessionStatePath = path14.join(swarmDir, "session", "state.json");
|
|
35612
35998
|
try {
|
|
35613
|
-
const archiveSessionDir =
|
|
35999
|
+
const archiveSessionDir = path14.join(archiveDir, "session");
|
|
35614
36000
|
await fs7.mkdir(archiveSessionDir, { recursive: true });
|
|
35615
|
-
await fs7.copyFile(sessionStatePath,
|
|
36001
|
+
await fs7.copyFile(sessionStatePath, path14.join(archiveSessionDir, "state.json"));
|
|
35616
36002
|
archivedFileCount++;
|
|
35617
36003
|
} catch {}
|
|
35618
36004
|
archiveResult = `Archived ${archivedFileCount} artifact(s) to .swarm/archive/swarm-${timestamp}/`;
|
|
@@ -35635,7 +36021,7 @@ async function handleCloseCommand(directory, args) {
|
|
|
35635
36021
|
warnings.push(`Preserved ${artifact} because it was not successfully archived.`);
|
|
35636
36022
|
continue;
|
|
35637
36023
|
}
|
|
35638
|
-
const filePath =
|
|
36024
|
+
const filePath = path14.join(swarmDir, artifact);
|
|
35639
36025
|
try {
|
|
35640
36026
|
await fs7.unlink(filePath);
|
|
35641
36027
|
cleanedFiles.push(artifact);
|
|
@@ -35649,23 +36035,23 @@ async function handleCloseCommand(directory, args) {
|
|
|
35649
36035
|
const configBackups = swarmFiles.filter((f) => f.startsWith("config-backup-") && f.endsWith(".json"));
|
|
35650
36036
|
for (const backup of configBackups) {
|
|
35651
36037
|
try {
|
|
35652
|
-
await fs7.unlink(
|
|
36038
|
+
await fs7.unlink(path14.join(swarmDir, backup));
|
|
35653
36039
|
configBackupsRemoved++;
|
|
35654
36040
|
} catch {}
|
|
35655
36041
|
}
|
|
35656
36042
|
const ledgerSiblings = swarmFiles.filter((f) => (f.startsWith("plan-ledger.archived-") || f.startsWith("plan-ledger.backup-")) && f.endsWith(".jsonl"));
|
|
35657
36043
|
for (const sibling of ledgerSiblings) {
|
|
35658
36044
|
try {
|
|
35659
|
-
await fs7.unlink(
|
|
36045
|
+
await fs7.unlink(path14.join(swarmDir, sibling));
|
|
35660
36046
|
} catch {}
|
|
35661
36047
|
}
|
|
35662
36048
|
} catch {}
|
|
35663
36049
|
let swarmPlanFilesRemoved = 0;
|
|
35664
36050
|
const candidates = [
|
|
35665
|
-
|
|
35666
|
-
|
|
35667
|
-
|
|
35668
|
-
|
|
36051
|
+
path14.join(directory, ".swarm", "SWARM_PLAN.json"),
|
|
36052
|
+
path14.join(directory, ".swarm", "SWARM_PLAN.md"),
|
|
36053
|
+
path14.join(directory, "SWARM_PLAN.json"),
|
|
36054
|
+
path14.join(directory, "SWARM_PLAN.md")
|
|
35669
36055
|
];
|
|
35670
36056
|
for (const candidate of candidates) {
|
|
35671
36057
|
try {
|
|
@@ -35673,12 +36059,12 @@ async function handleCloseCommand(directory, args) {
|
|
|
35673
36059
|
swarmPlanFilesRemoved++;
|
|
35674
36060
|
} catch (err) {
|
|
35675
36061
|
if (err?.code !== "ENOENT") {
|
|
35676
|
-
warnings.push(`Failed to remove ${
|
|
36062
|
+
warnings.push(`Failed to remove ${path14.basename(candidate)}: ${err instanceof Error ? err.message : String(err)}`);
|
|
35677
36063
|
}
|
|
35678
36064
|
}
|
|
35679
36065
|
}
|
|
35680
36066
|
clearAllScopes(directory);
|
|
35681
|
-
const contextPath =
|
|
36067
|
+
const contextPath = path14.join(swarmDir, "context.md");
|
|
35682
36068
|
const contextContent = [
|
|
35683
36069
|
"# Context",
|
|
35684
36070
|
"",
|
|
@@ -35847,14 +36233,14 @@ var init_close = __esm(() => {
|
|
|
35847
36233
|
|
|
35848
36234
|
// src/commands/config.ts
|
|
35849
36235
|
import * as os4 from "os";
|
|
35850
|
-
import * as
|
|
36236
|
+
import * as path15 from "path";
|
|
35851
36237
|
function getUserConfigDir2() {
|
|
35852
|
-
return process.env.XDG_CONFIG_HOME ||
|
|
36238
|
+
return process.env.XDG_CONFIG_HOME || path15.join(os4.homedir(), ".config");
|
|
35853
36239
|
}
|
|
35854
36240
|
async function handleConfigCommand(directory, _args) {
|
|
35855
36241
|
const config3 = loadPluginConfig(directory);
|
|
35856
|
-
const userConfigPath =
|
|
35857
|
-
const projectConfigPath =
|
|
36242
|
+
const userConfigPath = path15.join(getUserConfigDir2(), "opencode", "opencode-swarm.json");
|
|
36243
|
+
const projectConfigPath = path15.join(directory, ".opencode", "opencode-swarm.json");
|
|
35858
36244
|
const lines = [
|
|
35859
36245
|
"## Swarm Configuration",
|
|
35860
36246
|
"",
|
|
@@ -36019,13 +36405,14 @@ var init_curator = __esm(() => {
|
|
|
36019
36405
|
init_event_bus();
|
|
36020
36406
|
init_manager();
|
|
36021
36407
|
init_bun_compat();
|
|
36408
|
+
init_logger();
|
|
36022
36409
|
init_knowledge_store();
|
|
36023
36410
|
init_knowledge_validator();
|
|
36024
36411
|
init_utils2();
|
|
36025
36412
|
});
|
|
36026
36413
|
|
|
36027
36414
|
// src/hooks/hive-promoter.ts
|
|
36028
|
-
import
|
|
36415
|
+
import path16 from "path";
|
|
36029
36416
|
function isAlreadyInHive(entry, hiveEntries, threshold) {
|
|
36030
36417
|
return findNearDuplicate(entry.lesson, hiveEntries, threshold) !== undefined;
|
|
36031
36418
|
}
|
|
@@ -36204,7 +36591,7 @@ async function promoteToHive(directory, lesson, category) {
|
|
|
36204
36591
|
schema_version: 1,
|
|
36205
36592
|
created_at: new Date().toISOString(),
|
|
36206
36593
|
updated_at: new Date().toISOString(),
|
|
36207
|
-
source_project:
|
|
36594
|
+
source_project: path16.basename(directory) || "unknown",
|
|
36208
36595
|
encounter_score: 1
|
|
36209
36596
|
};
|
|
36210
36597
|
await appendKnowledge(resolveHiveKnowledgePath(), newHiveEntry);
|
|
@@ -36295,8 +36682,8 @@ var init_curate = __esm(() => {
|
|
|
36295
36682
|
// src/tools/co-change-analyzer.ts
|
|
36296
36683
|
import * as child_process3 from "child_process";
|
|
36297
36684
|
import { randomUUID } from "crypto";
|
|
36298
|
-
import { readdir, readFile as
|
|
36299
|
-
import * as
|
|
36685
|
+
import { readdir, readFile as readFile5, stat as stat2 } from "fs/promises";
|
|
36686
|
+
import * as path17 from "path";
|
|
36300
36687
|
import { promisify } from "util";
|
|
36301
36688
|
function getExecFileAsync() {
|
|
36302
36689
|
return promisify(child_process3.execFile);
|
|
@@ -36398,7 +36785,7 @@ async function scanSourceFiles(dir) {
|
|
|
36398
36785
|
try {
|
|
36399
36786
|
const entries = await readdir(dir, { withFileTypes: true });
|
|
36400
36787
|
for (const entry of entries) {
|
|
36401
|
-
const fullPath =
|
|
36788
|
+
const fullPath = path17.join(dir, entry.name);
|
|
36402
36789
|
if (entry.isDirectory()) {
|
|
36403
36790
|
if (skipDirs.has(entry.name)) {
|
|
36404
36791
|
continue;
|
|
@@ -36406,7 +36793,7 @@ async function scanSourceFiles(dir) {
|
|
|
36406
36793
|
const subFiles = await scanSourceFiles(fullPath);
|
|
36407
36794
|
results.push(...subFiles);
|
|
36408
36795
|
} else if (entry.isFile()) {
|
|
36409
|
-
const ext =
|
|
36796
|
+
const ext = path17.extname(entry.name);
|
|
36410
36797
|
if ([".ts", ".tsx", ".js", ".jsx", ".mjs"].includes(ext)) {
|
|
36411
36798
|
results.push(fullPath);
|
|
36412
36799
|
}
|
|
@@ -36420,7 +36807,7 @@ async function getStaticEdges(directory) {
|
|
|
36420
36807
|
const sourceFiles = await scanSourceFiles(directory);
|
|
36421
36808
|
for (const sourceFile of sourceFiles) {
|
|
36422
36809
|
try {
|
|
36423
|
-
const content = await
|
|
36810
|
+
const content = await readFile5(sourceFile, "utf-8");
|
|
36424
36811
|
const importRegex = /(?:import|require)\s*(?:\(?\s*['"`]|.*?from\s+['"`])([^'"`]+)['"`]/g;
|
|
36425
36812
|
for (let match = importRegex.exec(content);match !== null; match = importRegex.exec(content)) {
|
|
36426
36813
|
const importPath = match[1].trim();
|
|
@@ -36428,8 +36815,8 @@ async function getStaticEdges(directory) {
|
|
|
36428
36815
|
continue;
|
|
36429
36816
|
}
|
|
36430
36817
|
try {
|
|
36431
|
-
const sourceDir =
|
|
36432
|
-
const resolvedPath =
|
|
36818
|
+
const sourceDir = path17.dirname(sourceFile);
|
|
36819
|
+
const resolvedPath = path17.resolve(sourceDir, importPath);
|
|
36433
36820
|
const extensions = [
|
|
36434
36821
|
"",
|
|
36435
36822
|
".ts",
|
|
@@ -36454,8 +36841,8 @@ async function getStaticEdges(directory) {
|
|
|
36454
36841
|
if (!targetFile) {
|
|
36455
36842
|
continue;
|
|
36456
36843
|
}
|
|
36457
|
-
const relSource =
|
|
36458
|
-
const relTarget =
|
|
36844
|
+
const relSource = path17.relative(directory, sourceFile).replace(/\\/g, "/");
|
|
36845
|
+
const relTarget = path17.relative(directory, targetFile).replace(/\\/g, "/");
|
|
36459
36846
|
const [key] = relSource < relTarget ? [`${relSource}::${relTarget}`, relSource, relTarget] : [`${relTarget}::${relSource}`, relTarget, relSource];
|
|
36460
36847
|
edges.add(key);
|
|
36461
36848
|
} catch {}
|
|
@@ -36467,7 +36854,7 @@ async function getStaticEdges(directory) {
|
|
|
36467
36854
|
function isTestImplementationPair(fileA, fileB) {
|
|
36468
36855
|
const testPatterns = [".test.ts", ".test.js", ".spec.ts", ".spec.js"];
|
|
36469
36856
|
const getBaseName = (filePath) => {
|
|
36470
|
-
const base =
|
|
36857
|
+
const base = path17.basename(filePath);
|
|
36471
36858
|
for (const pattern of testPatterns) {
|
|
36472
36859
|
if (base.endsWith(pattern)) {
|
|
36473
36860
|
return base.slice(0, -pattern.length);
|
|
@@ -36477,16 +36864,16 @@ function isTestImplementationPair(fileA, fileB) {
|
|
|
36477
36864
|
};
|
|
36478
36865
|
const baseA = getBaseName(fileA);
|
|
36479
36866
|
const baseB = getBaseName(fileB);
|
|
36480
|
-
return baseA === baseB && baseA !==
|
|
36867
|
+
return baseA === baseB && baseA !== path17.basename(fileA) && baseA !== path17.basename(fileB);
|
|
36481
36868
|
}
|
|
36482
36869
|
function hasSharedPrefix(fileA, fileB) {
|
|
36483
|
-
const dirA =
|
|
36484
|
-
const dirB =
|
|
36870
|
+
const dirA = path17.dirname(fileA);
|
|
36871
|
+
const dirB = path17.dirname(fileB);
|
|
36485
36872
|
if (dirA !== dirB) {
|
|
36486
36873
|
return false;
|
|
36487
36874
|
}
|
|
36488
|
-
const baseA =
|
|
36489
|
-
const baseB =
|
|
36875
|
+
const baseA = path17.basename(fileA).replace(/\.(ts|js|tsx|jsx|mjs)$/, "");
|
|
36876
|
+
const baseB = path17.basename(fileB).replace(/\.(ts|js|tsx|jsx|mjs)$/, "");
|
|
36490
36877
|
if (baseA.startsWith(baseB) || baseB.startsWith(baseA)) {
|
|
36491
36878
|
return true;
|
|
36492
36879
|
}
|
|
@@ -36514,9 +36901,9 @@ async function detectDarkMatter(directory, options) {
|
|
|
36514
36901
|
} catch {
|
|
36515
36902
|
return [];
|
|
36516
36903
|
}
|
|
36517
|
-
const commitMap = await parseGitLog(directory, maxCommitsToAnalyze);
|
|
36518
|
-
const matrix = buildCoChangeMatrix(commitMap);
|
|
36519
|
-
const staticEdges = await getStaticEdges(directory);
|
|
36904
|
+
const commitMap = await _internals10.parseGitLog(directory, maxCommitsToAnalyze);
|
|
36905
|
+
const matrix = _internals10.buildCoChangeMatrix(commitMap);
|
|
36906
|
+
const staticEdges = await _internals10.getStaticEdges(directory);
|
|
36520
36907
|
const results = [];
|
|
36521
36908
|
for (const entry of matrix.values()) {
|
|
36522
36909
|
const key = `${entry.fileA}::${entry.fileB}`;
|
|
@@ -36540,8 +36927,8 @@ function darkMatterToKnowledgeEntries(pairs, projectName) {
|
|
|
36540
36927
|
const entries = [];
|
|
36541
36928
|
const now = new Date().toISOString();
|
|
36542
36929
|
for (const pair of pairs.slice(0, 10)) {
|
|
36543
|
-
const baseA =
|
|
36544
|
-
const baseB =
|
|
36930
|
+
const baseA = path17.basename(pair.fileA);
|
|
36931
|
+
const baseB = path17.basename(pair.fileB);
|
|
36545
36932
|
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
36933
|
if (lesson.length > 280) {
|
|
36547
36934
|
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 +36983,7 @@ ${rows}
|
|
|
36596
36983
|
These pairs likely share an architectural concern invisible to static analysis.
|
|
36597
36984
|
Consider adding explicit documentation or extracting the shared concern.`;
|
|
36598
36985
|
}
|
|
36599
|
-
var co_change_analyzer;
|
|
36986
|
+
var co_change_analyzer, _internals10;
|
|
36600
36987
|
var init_co_change_analyzer = __esm(() => {
|
|
36601
36988
|
init_zod();
|
|
36602
36989
|
init_create_tool();
|
|
@@ -36628,14 +37015,22 @@ var init_co_change_analyzer = __esm(() => {
|
|
|
36628
37015
|
npmiThreshold,
|
|
36629
37016
|
maxCommitsToAnalyze
|
|
36630
37017
|
};
|
|
36631
|
-
const pairs = await detectDarkMatter(directory, options);
|
|
36632
|
-
return formatDarkMatterOutput(pairs);
|
|
37018
|
+
const pairs = await _internals10.detectDarkMatter(directory, options);
|
|
37019
|
+
return _internals10.formatDarkMatterOutput(pairs);
|
|
36633
37020
|
}
|
|
36634
37021
|
});
|
|
37022
|
+
_internals10 = {
|
|
37023
|
+
parseGitLog,
|
|
37024
|
+
buildCoChangeMatrix,
|
|
37025
|
+
getStaticEdges,
|
|
37026
|
+
detectDarkMatter,
|
|
37027
|
+
darkMatterToKnowledgeEntries,
|
|
37028
|
+
formatDarkMatterOutput
|
|
37029
|
+
};
|
|
36635
37030
|
});
|
|
36636
37031
|
|
|
36637
37032
|
// src/commands/dark-matter.ts
|
|
36638
|
-
import
|
|
37033
|
+
import path18 from "path";
|
|
36639
37034
|
async function handleDarkMatterCommand(directory, args) {
|
|
36640
37035
|
const options = {};
|
|
36641
37036
|
for (let i = 0;i < args.length; i++) {
|
|
@@ -36657,7 +37052,7 @@ async function handleDarkMatterCommand(directory, args) {
|
|
|
36657
37052
|
const output = formatDarkMatterOutput(pairs);
|
|
36658
37053
|
if (pairs.length > 0) {
|
|
36659
37054
|
try {
|
|
36660
|
-
const projectName =
|
|
37055
|
+
const projectName = path18.basename(path18.resolve(directory));
|
|
36661
37056
|
const entries = darkMatterToKnowledgeEntries(pairs, projectName);
|
|
36662
37057
|
if (entries.length > 0) {
|
|
36663
37058
|
const knowledgePath = resolveSwarmKnowledgePath(directory);
|
|
@@ -36682,67 +37077,67 @@ var init_dark_matter = __esm(() => {
|
|
|
36682
37077
|
|
|
36683
37078
|
// src/config/cache-paths.ts
|
|
36684
37079
|
import * as os5 from "os";
|
|
36685
|
-
import * as
|
|
37080
|
+
import * as path19 from "path";
|
|
36686
37081
|
function getPluginConfigDir() {
|
|
36687
|
-
return
|
|
37082
|
+
return path19.join(process.env.XDG_CONFIG_HOME || path19.join(os5.homedir(), ".config"), "opencode");
|
|
36688
37083
|
}
|
|
36689
37084
|
function getPluginCachePaths() {
|
|
36690
|
-
const cacheBase = process.env.XDG_CACHE_HOME ||
|
|
37085
|
+
const cacheBase = process.env.XDG_CACHE_HOME || path19.join(os5.homedir(), ".cache");
|
|
36691
37086
|
const configDir = getPluginConfigDir();
|
|
36692
37087
|
const paths = [
|
|
36693
|
-
|
|
36694
|
-
|
|
36695
|
-
|
|
37088
|
+
path19.join(cacheBase, "opencode", "node_modules", "opencode-swarm"),
|
|
37089
|
+
path19.join(cacheBase, "opencode", "packages", "opencode-swarm@latest"),
|
|
37090
|
+
path19.join(configDir, "node_modules", "opencode-swarm")
|
|
36696
37091
|
];
|
|
36697
37092
|
if (process.platform === "darwin") {
|
|
36698
|
-
const libCaches =
|
|
36699
|
-
paths.push(
|
|
37093
|
+
const libCaches = path19.join(os5.homedir(), "Library", "Caches");
|
|
37094
|
+
paths.push(path19.join(libCaches, "opencode", "node_modules", "opencode-swarm"), path19.join(libCaches, "opencode", "packages", "opencode-swarm@latest"));
|
|
36700
37095
|
}
|
|
36701
37096
|
if (process.platform === "win32") {
|
|
36702
|
-
const localAppData = process.env.LOCALAPPDATA ||
|
|
36703
|
-
const appData = process.env.APPDATA ||
|
|
36704
|
-
paths.push(
|
|
37097
|
+
const localAppData = process.env.LOCALAPPDATA || path19.join(os5.homedir(), "AppData", "Local");
|
|
37098
|
+
const appData = process.env.APPDATA || path19.join(os5.homedir(), "AppData", "Roaming");
|
|
37099
|
+
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
37100
|
}
|
|
36706
37101
|
return paths;
|
|
36707
37102
|
}
|
|
36708
37103
|
function getPluginLockFilePaths() {
|
|
36709
|
-
const cacheBase = process.env.XDG_CACHE_HOME ||
|
|
37104
|
+
const cacheBase = process.env.XDG_CACHE_HOME || path19.join(os5.homedir(), ".cache");
|
|
36710
37105
|
const configDir = getPluginConfigDir();
|
|
36711
37106
|
const paths = [
|
|
36712
|
-
|
|
36713
|
-
|
|
36714
|
-
|
|
37107
|
+
path19.join(cacheBase, "opencode", "bun.lock"),
|
|
37108
|
+
path19.join(cacheBase, "opencode", "bun.lockb"),
|
|
37109
|
+
path19.join(configDir, "package-lock.json")
|
|
36715
37110
|
];
|
|
36716
37111
|
if (process.platform === "darwin") {
|
|
36717
|
-
const libCaches =
|
|
36718
|
-
paths.push(
|
|
37112
|
+
const libCaches = path19.join(os5.homedir(), "Library", "Caches");
|
|
37113
|
+
paths.push(path19.join(libCaches, "opencode", "bun.lock"), path19.join(libCaches, "opencode", "bun.lockb"));
|
|
36719
37114
|
}
|
|
36720
37115
|
if (process.platform === "win32") {
|
|
36721
|
-
const localAppData = process.env.LOCALAPPDATA ||
|
|
36722
|
-
paths.push(
|
|
37116
|
+
const localAppData = process.env.LOCALAPPDATA || path19.join(os5.homedir(), "AppData", "Local");
|
|
37117
|
+
paths.push(path19.join(localAppData, "opencode", "bun.lock"), path19.join(localAppData, "opencode", "bun.lockb"));
|
|
36723
37118
|
}
|
|
36724
37119
|
return paths;
|
|
36725
37120
|
}
|
|
36726
37121
|
var init_cache_paths = () => {};
|
|
36727
37122
|
|
|
36728
37123
|
// src/services/version-check.ts
|
|
36729
|
-
import { existsSync as
|
|
37124
|
+
import { existsSync as existsSync9, mkdirSync as mkdirSync8, readFileSync as readFileSync5, writeFileSync as writeFileSync4 } from "fs";
|
|
36730
37125
|
import { homedir as homedir5 } from "os";
|
|
36731
|
-
import { join as
|
|
37126
|
+
import { join as join17 } from "path";
|
|
36732
37127
|
function cacheDir() {
|
|
36733
37128
|
const xdg = process.env.XDG_CACHE_HOME;
|
|
36734
|
-
const base = xdg && xdg.length > 0 ? xdg :
|
|
36735
|
-
return
|
|
37129
|
+
const base = xdg && xdg.length > 0 ? xdg : join17(homedir5(), ".cache");
|
|
37130
|
+
return join17(base, "opencode-swarm");
|
|
36736
37131
|
}
|
|
36737
37132
|
function cacheFile() {
|
|
36738
|
-
return
|
|
37133
|
+
return join17(cacheDir(), "version-check.json");
|
|
36739
37134
|
}
|
|
36740
37135
|
function readVersionCache() {
|
|
36741
37136
|
try {
|
|
36742
|
-
const
|
|
36743
|
-
if (!
|
|
37137
|
+
const path20 = cacheFile();
|
|
37138
|
+
if (!existsSync9(path20))
|
|
36744
37139
|
return null;
|
|
36745
|
-
const raw = readFileSync5(
|
|
37140
|
+
const raw = readFileSync5(path20, "utf-8");
|
|
36746
37141
|
const parsed = JSON.parse(raw);
|
|
36747
37142
|
if (typeof parsed?.checkedAt !== "number")
|
|
36748
37143
|
return null;
|
|
@@ -36781,8 +37176,8 @@ var init_version_check = __esm(() => {
|
|
|
36781
37176
|
|
|
36782
37177
|
// src/services/diagnose-service.ts
|
|
36783
37178
|
import * as child_process4 from "child_process";
|
|
36784
|
-
import { existsSync as
|
|
36785
|
-
import
|
|
37179
|
+
import { existsSync as existsSync10, readdirSync as readdirSync4, readFileSync as readFileSync6, statSync as statSync6 } from "fs";
|
|
37180
|
+
import path20 from "path";
|
|
36786
37181
|
import { fileURLToPath } from "url";
|
|
36787
37182
|
function validateTaskDag(plan) {
|
|
36788
37183
|
const allTaskIds = new Set;
|
|
@@ -37015,7 +37410,7 @@ async function checkConfigBackups(directory) {
|
|
|
37015
37410
|
}
|
|
37016
37411
|
async function checkGitRepository(directory) {
|
|
37017
37412
|
try {
|
|
37018
|
-
if (!
|
|
37413
|
+
if (!existsSync10(directory) || !statSync6(directory).isDirectory()) {
|
|
37019
37414
|
return {
|
|
37020
37415
|
name: "Git Repository",
|
|
37021
37416
|
status: "\u274C",
|
|
@@ -37079,8 +37474,8 @@ async function checkSpecStaleness(directory, plan) {
|
|
|
37079
37474
|
};
|
|
37080
37475
|
}
|
|
37081
37476
|
async function checkConfigParseability(directory) {
|
|
37082
|
-
const configPath =
|
|
37083
|
-
if (!
|
|
37477
|
+
const configPath = path20.join(directory, ".opencode/opencode-swarm.json");
|
|
37478
|
+
if (!existsSync10(configPath)) {
|
|
37084
37479
|
return {
|
|
37085
37480
|
name: "Config Parseability",
|
|
37086
37481
|
status: "\u2705",
|
|
@@ -37108,7 +37503,7 @@ function resolveGrammarDir(thisDir) {
|
|
|
37108
37503
|
const normalized = thisDir.replace(/\\/g, "/");
|
|
37109
37504
|
const isSource = normalized.endsWith("/src/services");
|
|
37110
37505
|
const isCliBundle = normalized.endsWith("/cli");
|
|
37111
|
-
return isSource || isCliBundle ?
|
|
37506
|
+
return isSource || isCliBundle ? path20.join(thisDir, "..", "lang", "grammars") : path20.join(thisDir, "lang", "grammars");
|
|
37112
37507
|
}
|
|
37113
37508
|
async function checkGrammarWasmFiles() {
|
|
37114
37509
|
const grammarFiles = [
|
|
@@ -37132,14 +37527,14 @@ async function checkGrammarWasmFiles() {
|
|
|
37132
37527
|
"tree-sitter-ini.wasm",
|
|
37133
37528
|
"tree-sitter-regex.wasm"
|
|
37134
37529
|
];
|
|
37135
|
-
const thisDir =
|
|
37530
|
+
const thisDir = path20.dirname(fileURLToPath(import.meta.url));
|
|
37136
37531
|
const grammarDir = resolveGrammarDir(thisDir);
|
|
37137
37532
|
const missing = [];
|
|
37138
|
-
if (!
|
|
37533
|
+
if (!existsSync10(path20.join(grammarDir, "tree-sitter.wasm"))) {
|
|
37139
37534
|
missing.push("tree-sitter.wasm (core runtime)");
|
|
37140
37535
|
}
|
|
37141
37536
|
for (const file3 of grammarFiles) {
|
|
37142
|
-
if (!
|
|
37537
|
+
if (!existsSync10(path20.join(grammarDir, file3))) {
|
|
37143
37538
|
missing.push(file3);
|
|
37144
37539
|
}
|
|
37145
37540
|
}
|
|
@@ -37157,8 +37552,8 @@ async function checkGrammarWasmFiles() {
|
|
|
37157
37552
|
};
|
|
37158
37553
|
}
|
|
37159
37554
|
async function checkCheckpointManifest(directory) {
|
|
37160
|
-
const manifestPath =
|
|
37161
|
-
if (!
|
|
37555
|
+
const manifestPath = path20.join(directory, ".swarm/checkpoints.json");
|
|
37556
|
+
if (!existsSync10(manifestPath)) {
|
|
37162
37557
|
return {
|
|
37163
37558
|
name: "Checkpoint Manifest",
|
|
37164
37559
|
status: "\u2705",
|
|
@@ -37209,8 +37604,8 @@ async function checkCheckpointManifest(directory) {
|
|
|
37209
37604
|
}
|
|
37210
37605
|
}
|
|
37211
37606
|
async function checkEventStreamIntegrity(directory) {
|
|
37212
|
-
const eventsPath =
|
|
37213
|
-
if (!
|
|
37607
|
+
const eventsPath = path20.join(directory, ".swarm/events.jsonl");
|
|
37608
|
+
if (!existsSync10(eventsPath)) {
|
|
37214
37609
|
return {
|
|
37215
37610
|
name: "Event Stream",
|
|
37216
37611
|
status: "\u2705",
|
|
@@ -37250,8 +37645,8 @@ async function checkEventStreamIntegrity(directory) {
|
|
|
37250
37645
|
}
|
|
37251
37646
|
}
|
|
37252
37647
|
async function checkSteeringDirectives(directory) {
|
|
37253
|
-
const eventsPath =
|
|
37254
|
-
if (!
|
|
37648
|
+
const eventsPath = path20.join(directory, ".swarm/events.jsonl");
|
|
37649
|
+
if (!existsSync10(eventsPath)) {
|
|
37255
37650
|
return {
|
|
37256
37651
|
name: "Steering Directives",
|
|
37257
37652
|
status: "\u2705",
|
|
@@ -37306,8 +37701,8 @@ async function checkCurator(directory) {
|
|
|
37306
37701
|
detail: "Disabled (enable via curator.enabled)"
|
|
37307
37702
|
};
|
|
37308
37703
|
}
|
|
37309
|
-
const summaryPath =
|
|
37310
|
-
if (!
|
|
37704
|
+
const summaryPath = path20.join(directory, ".swarm/curator-summary.json");
|
|
37705
|
+
if (!existsSync10(summaryPath)) {
|
|
37311
37706
|
return {
|
|
37312
37707
|
name: "Curator",
|
|
37313
37708
|
status: "\u2705",
|
|
@@ -37472,8 +37867,8 @@ async function getDiagnoseData(directory) {
|
|
|
37472
37867
|
checks5.push(await checkSteeringDirectives(directory));
|
|
37473
37868
|
checks5.push(await checkCurator(directory));
|
|
37474
37869
|
try {
|
|
37475
|
-
const evidenceDir =
|
|
37476
|
-
const snapshotFiles =
|
|
37870
|
+
const evidenceDir = path20.join(directory, ".swarm", "evidence");
|
|
37871
|
+
const snapshotFiles = existsSync10(evidenceDir) ? readdirSync4(evidenceDir).filter((f) => f.startsWith("agent-tools-") && f.endsWith(".json")) : [];
|
|
37477
37872
|
if (snapshotFiles.length > 0) {
|
|
37478
37873
|
const latest = snapshotFiles.sort().pop();
|
|
37479
37874
|
checks5.push({
|
|
@@ -37506,11 +37901,11 @@ async function getDiagnoseData(directory) {
|
|
|
37506
37901
|
const cacheRows = [];
|
|
37507
37902
|
for (const cachePath of cachePaths) {
|
|
37508
37903
|
try {
|
|
37509
|
-
if (!
|
|
37904
|
+
if (!existsSync10(cachePath)) {
|
|
37510
37905
|
cacheRows.push(`\u2B1C ${cachePath} \u2014 absent`);
|
|
37511
37906
|
continue;
|
|
37512
37907
|
}
|
|
37513
|
-
const pkgJsonPath =
|
|
37908
|
+
const pkgJsonPath = path20.join(cachePath, "package.json");
|
|
37514
37909
|
try {
|
|
37515
37910
|
const raw = readFileSync6(pkgJsonPath, "utf-8");
|
|
37516
37911
|
const parsed = JSON.parse(raw);
|
|
@@ -37598,13 +37993,13 @@ __export(exports_config_doctor, {
|
|
|
37598
37993
|
import * as crypto3 from "crypto";
|
|
37599
37994
|
import * as fs8 from "fs";
|
|
37600
37995
|
import * as os6 from "os";
|
|
37601
|
-
import * as
|
|
37996
|
+
import * as path21 from "path";
|
|
37602
37997
|
function getUserConfigDir3() {
|
|
37603
|
-
return process.env.XDG_CONFIG_HOME ||
|
|
37998
|
+
return process.env.XDG_CONFIG_HOME || path21.join(os6.homedir(), ".config");
|
|
37604
37999
|
}
|
|
37605
38000
|
function getConfigPaths(directory) {
|
|
37606
|
-
const userConfigPath =
|
|
37607
|
-
const projectConfigPath =
|
|
38001
|
+
const userConfigPath = path21.join(getUserConfigDir3(), "opencode", "opencode-swarm.json");
|
|
38002
|
+
const projectConfigPath = path21.join(directory, ".opencode", "opencode-swarm.json");
|
|
37608
38003
|
return { userConfigPath, projectConfigPath };
|
|
37609
38004
|
}
|
|
37610
38005
|
function computeHash(content) {
|
|
@@ -37629,9 +38024,9 @@ function isValidConfigPath(configPath, directory) {
|
|
|
37629
38024
|
const normalizedUser = userConfigPath.replace(/\\/g, "/");
|
|
37630
38025
|
const normalizedProject = projectConfigPath.replace(/\\/g, "/");
|
|
37631
38026
|
try {
|
|
37632
|
-
const resolvedConfig =
|
|
37633
|
-
const resolvedUser =
|
|
37634
|
-
const resolvedProject =
|
|
38027
|
+
const resolvedConfig = path21.resolve(configPath);
|
|
38028
|
+
const resolvedUser = path21.resolve(normalizedUser);
|
|
38029
|
+
const resolvedProject = path21.resolve(normalizedProject);
|
|
37635
38030
|
return resolvedConfig === resolvedUser || resolvedConfig === resolvedProject;
|
|
37636
38031
|
} catch {
|
|
37637
38032
|
return false;
|
|
@@ -37671,12 +38066,12 @@ function createConfigBackup(directory) {
|
|
|
37671
38066
|
};
|
|
37672
38067
|
}
|
|
37673
38068
|
function writeBackupArtifact(directory, backup) {
|
|
37674
|
-
const swarmDir =
|
|
38069
|
+
const swarmDir = path21.join(directory, ".swarm");
|
|
37675
38070
|
if (!fs8.existsSync(swarmDir)) {
|
|
37676
38071
|
fs8.mkdirSync(swarmDir, { recursive: true });
|
|
37677
38072
|
}
|
|
37678
38073
|
const backupFilename = `config-backup-${backup.createdAt}.json`;
|
|
37679
|
-
const backupPath =
|
|
38074
|
+
const backupPath = path21.join(swarmDir, backupFilename);
|
|
37680
38075
|
const artifact = {
|
|
37681
38076
|
createdAt: backup.createdAt,
|
|
37682
38077
|
configPath: backup.configPath,
|
|
@@ -37706,7 +38101,7 @@ function restoreFromBackup(backupPath, directory) {
|
|
|
37706
38101
|
return null;
|
|
37707
38102
|
}
|
|
37708
38103
|
const targetPath = artifact.configPath;
|
|
37709
|
-
const targetDir =
|
|
38104
|
+
const targetDir = path21.dirname(targetPath);
|
|
37710
38105
|
if (!fs8.existsSync(targetDir)) {
|
|
37711
38106
|
fs8.mkdirSync(targetDir, { recursive: true });
|
|
37712
38107
|
}
|
|
@@ -37737,9 +38132,9 @@ function readConfigFromFile(directory) {
|
|
|
37737
38132
|
return null;
|
|
37738
38133
|
}
|
|
37739
38134
|
}
|
|
37740
|
-
function validateConfigKey(
|
|
38135
|
+
function validateConfigKey(path22, value, _config) {
|
|
37741
38136
|
const findings = [];
|
|
37742
|
-
switch (
|
|
38137
|
+
switch (path22) {
|
|
37743
38138
|
case "agents": {
|
|
37744
38139
|
if (value !== undefined) {
|
|
37745
38140
|
findings.push({
|
|
@@ -37986,27 +38381,27 @@ function validateConfigKey(path21, value, _config) {
|
|
|
37986
38381
|
}
|
|
37987
38382
|
return findings;
|
|
37988
38383
|
}
|
|
37989
|
-
function walkConfigAndValidate(obj,
|
|
38384
|
+
function walkConfigAndValidate(obj, path22, config3, findings) {
|
|
37990
38385
|
if (obj === null || obj === undefined) {
|
|
37991
38386
|
return;
|
|
37992
38387
|
}
|
|
37993
|
-
if (
|
|
37994
|
-
const keyFindings = validateConfigKey(
|
|
38388
|
+
if (path22 && typeof obj === "object" && !Array.isArray(obj)) {
|
|
38389
|
+
const keyFindings = validateConfigKey(path22, obj, config3);
|
|
37995
38390
|
findings.push(...keyFindings);
|
|
37996
38391
|
}
|
|
37997
38392
|
if (typeof obj !== "object") {
|
|
37998
|
-
const keyFindings = validateConfigKey(
|
|
38393
|
+
const keyFindings = validateConfigKey(path22, obj, config3);
|
|
37999
38394
|
findings.push(...keyFindings);
|
|
38000
38395
|
return;
|
|
38001
38396
|
}
|
|
38002
38397
|
if (Array.isArray(obj)) {
|
|
38003
38398
|
obj.forEach((item, index) => {
|
|
38004
|
-
walkConfigAndValidate(item, `${
|
|
38399
|
+
walkConfigAndValidate(item, `${path22}[${index}]`, config3, findings);
|
|
38005
38400
|
});
|
|
38006
38401
|
return;
|
|
38007
38402
|
}
|
|
38008
38403
|
for (const [key, value] of Object.entries(obj)) {
|
|
38009
|
-
const newPath =
|
|
38404
|
+
const newPath = path22 ? `${path22}.${key}` : key;
|
|
38010
38405
|
walkConfigAndValidate(value, newPath, config3, findings);
|
|
38011
38406
|
}
|
|
38012
38407
|
}
|
|
@@ -38126,7 +38521,7 @@ function applySafeAutoFixes(directory, result) {
|
|
|
38126
38521
|
}
|
|
38127
38522
|
}
|
|
38128
38523
|
if (appliedFixes.length > 0) {
|
|
38129
|
-
const configDir =
|
|
38524
|
+
const configDir = path21.dirname(configPath);
|
|
38130
38525
|
if (!fs8.existsSync(configDir)) {
|
|
38131
38526
|
fs8.mkdirSync(configDir, { recursive: true });
|
|
38132
38527
|
}
|
|
@@ -38136,12 +38531,12 @@ function applySafeAutoFixes(directory, result) {
|
|
|
38136
38531
|
return { appliedFixes, updatedConfigPath };
|
|
38137
38532
|
}
|
|
38138
38533
|
function writeDoctorArtifact(directory, result) {
|
|
38139
|
-
const swarmDir =
|
|
38534
|
+
const swarmDir = path21.join(directory, ".swarm");
|
|
38140
38535
|
if (!fs8.existsSync(swarmDir)) {
|
|
38141
38536
|
fs8.mkdirSync(swarmDir, { recursive: true });
|
|
38142
38537
|
}
|
|
38143
38538
|
const artifactFilename = "config-doctor.json";
|
|
38144
|
-
const artifactPath =
|
|
38539
|
+
const artifactPath = path21.join(swarmDir, artifactFilename);
|
|
38145
38540
|
const guiOutput = {
|
|
38146
38541
|
timestamp: result.timestamp,
|
|
38147
38542
|
summary: result.summary,
|
|
@@ -39188,7 +39583,7 @@ var init_profiles = __esm(() => {
|
|
|
39188
39583
|
|
|
39189
39584
|
// src/lang/detector.ts
|
|
39190
39585
|
import { access as access3, readdir as readdir2 } from "fs/promises";
|
|
39191
|
-
import { extname as extname2, join as
|
|
39586
|
+
import { extname as extname2, join as join19 } from "path";
|
|
39192
39587
|
async function detectProjectLanguages(projectDir) {
|
|
39193
39588
|
const detected = new Set;
|
|
39194
39589
|
async function scanDir(dir) {
|
|
@@ -39204,7 +39599,7 @@ async function detectProjectLanguages(projectDir) {
|
|
|
39204
39599
|
if (detectFile.includes("*") || detectFile.includes("?"))
|
|
39205
39600
|
continue;
|
|
39206
39601
|
try {
|
|
39207
|
-
await access3(
|
|
39602
|
+
await access3(join19(dir, detectFile));
|
|
39208
39603
|
detected.add(profile.id);
|
|
39209
39604
|
break;
|
|
39210
39605
|
} catch {}
|
|
@@ -39225,7 +39620,7 @@ async function detectProjectLanguages(projectDir) {
|
|
|
39225
39620
|
const topEntries = await readdir2(projectDir, { withFileTypes: true });
|
|
39226
39621
|
for (const entry of topEntries) {
|
|
39227
39622
|
if (entry.isDirectory() && !entry.name.startsWith(".") && entry.name !== "node_modules") {
|
|
39228
|
-
await scanDir(
|
|
39623
|
+
await scanDir(join19(projectDir, entry.name));
|
|
39229
39624
|
}
|
|
39230
39625
|
}
|
|
39231
39626
|
} catch {}
|
|
@@ -39244,7 +39639,7 @@ var init_detector = __esm(() => {
|
|
|
39244
39639
|
|
|
39245
39640
|
// src/build/discovery.ts
|
|
39246
39641
|
import * as fs9 from "fs";
|
|
39247
|
-
import * as
|
|
39642
|
+
import * as path22 from "path";
|
|
39248
39643
|
function isCommandAvailable(command) {
|
|
39249
39644
|
if (toolchainCache.has(command)) {
|
|
39250
39645
|
return toolchainCache.get(command);
|
|
@@ -39276,11 +39671,11 @@ function findBuildFiles(workingDir, patterns) {
|
|
|
39276
39671
|
const regex = simpleGlobToRegex(pattern);
|
|
39277
39672
|
const matches = files.filter((f) => regex.test(f));
|
|
39278
39673
|
if (matches.length > 0) {
|
|
39279
|
-
return
|
|
39674
|
+
return path22.join(dir, matches[0]);
|
|
39280
39675
|
}
|
|
39281
39676
|
} catch {}
|
|
39282
39677
|
} else {
|
|
39283
|
-
const filePath =
|
|
39678
|
+
const filePath = path22.join(workingDir, pattern);
|
|
39284
39679
|
if (fs9.existsSync(filePath)) {
|
|
39285
39680
|
return filePath;
|
|
39286
39681
|
}
|
|
@@ -39289,7 +39684,7 @@ function findBuildFiles(workingDir, patterns) {
|
|
|
39289
39684
|
return null;
|
|
39290
39685
|
}
|
|
39291
39686
|
function getRepoDefinedScripts(workingDir, scripts) {
|
|
39292
|
-
const packageJsonPath =
|
|
39687
|
+
const packageJsonPath = path22.join(workingDir, "package.json");
|
|
39293
39688
|
if (!fs9.existsSync(packageJsonPath)) {
|
|
39294
39689
|
return [];
|
|
39295
39690
|
}
|
|
@@ -39330,7 +39725,7 @@ function findAllBuildFiles(workingDir) {
|
|
|
39330
39725
|
const regex = simpleGlobToRegex(pattern);
|
|
39331
39726
|
findFilesRecursive(workingDir, regex, allBuildFiles);
|
|
39332
39727
|
} else {
|
|
39333
|
-
const filePath =
|
|
39728
|
+
const filePath = path22.join(workingDir, pattern);
|
|
39334
39729
|
if (fs9.existsSync(filePath)) {
|
|
39335
39730
|
allBuildFiles.add(filePath);
|
|
39336
39731
|
}
|
|
@@ -39343,7 +39738,7 @@ function findFilesRecursive(dir, regex, results) {
|
|
|
39343
39738
|
try {
|
|
39344
39739
|
const entries = fs9.readdirSync(dir, { withFileTypes: true });
|
|
39345
39740
|
for (const entry of entries) {
|
|
39346
|
-
const fullPath =
|
|
39741
|
+
const fullPath = path22.join(dir, entry.name);
|
|
39347
39742
|
if (entry.isDirectory() && !["node_modules", ".git", "dist", "build", "target"].includes(entry.name)) {
|
|
39348
39743
|
findFilesRecursive(fullPath, regex, results);
|
|
39349
39744
|
} else if (entry.isFile() && regex.test(entry.name)) {
|
|
@@ -39366,7 +39761,7 @@ async function discoverBuildCommandsFromProfiles(workingDir) {
|
|
|
39366
39761
|
let foundCommand = false;
|
|
39367
39762
|
for (const cmd of sortedCommands) {
|
|
39368
39763
|
if (cmd.detectFile) {
|
|
39369
|
-
const detectFilePath =
|
|
39764
|
+
const detectFilePath = path22.join(workingDir, cmd.detectFile);
|
|
39370
39765
|
if (!fs9.existsSync(detectFilePath)) {
|
|
39371
39766
|
continue;
|
|
39372
39767
|
}
|
|
@@ -39399,7 +39794,7 @@ async function discoverBuildCommands(workingDir, options) {
|
|
|
39399
39794
|
const scope = options?.scope ?? "all";
|
|
39400
39795
|
const changedFiles = options?.changedFiles ?? [];
|
|
39401
39796
|
const _filesToCheck = filterByScope(workingDir, scope, changedFiles);
|
|
39402
|
-
const profileResult = await discoverBuildCommandsFromProfiles(workingDir);
|
|
39797
|
+
const profileResult = await _internals11.discoverBuildCommandsFromProfiles(workingDir);
|
|
39403
39798
|
const profileCommands = profileResult.commands;
|
|
39404
39799
|
const profileSkipped = profileResult.skipped;
|
|
39405
39800
|
const coveredEcosystems = new Set;
|
|
@@ -39456,7 +39851,13 @@ async function discoverBuildCommands(workingDir, options) {
|
|
|
39456
39851
|
commands.sort((a, b) => a.priority - b.priority);
|
|
39457
39852
|
return { commands, skipped };
|
|
39458
39853
|
}
|
|
39459
|
-
|
|
39854
|
+
function clearToolchainCache() {
|
|
39855
|
+
toolchainCache.clear();
|
|
39856
|
+
}
|
|
39857
|
+
function getEcosystems() {
|
|
39858
|
+
return ECOSYSTEMS.map((e) => e.ecosystem);
|
|
39859
|
+
}
|
|
39860
|
+
var ECOSYSTEMS, PROFILE_TO_ECOSYSTEM_NAMES, toolchainCache, _internals11, build_discovery;
|
|
39460
39861
|
var init_discovery = __esm(() => {
|
|
39461
39862
|
init_dist();
|
|
39462
39863
|
init_detector();
|
|
@@ -39574,6 +39975,13 @@ var init_discovery = __esm(() => {
|
|
|
39574
39975
|
php: ["php-composer"]
|
|
39575
39976
|
};
|
|
39576
39977
|
toolchainCache = new Map;
|
|
39978
|
+
_internals11 = {
|
|
39979
|
+
isCommandAvailable,
|
|
39980
|
+
discoverBuildCommandsFromProfiles,
|
|
39981
|
+
discoverBuildCommands,
|
|
39982
|
+
clearToolchainCache,
|
|
39983
|
+
getEcosystems
|
|
39984
|
+
};
|
|
39577
39985
|
build_discovery = tool({
|
|
39578
39986
|
description: "Discover build commands for various ecosystems in a project directory",
|
|
39579
39987
|
args: {
|
|
@@ -39593,7 +40001,7 @@ var init_discovery = __esm(() => {
|
|
|
39593
40001
|
|
|
39594
40002
|
// src/services/tool-doctor.ts
|
|
39595
40003
|
import * as fs10 from "fs";
|
|
39596
|
-
import * as
|
|
40004
|
+
import * as path23 from "path";
|
|
39597
40005
|
function extractRegisteredToolKeys(indexPath) {
|
|
39598
40006
|
const registeredKeys = new Set;
|
|
39599
40007
|
try {
|
|
@@ -39648,8 +40056,8 @@ function checkBinaryReadiness() {
|
|
|
39648
40056
|
}
|
|
39649
40057
|
function runToolDoctor(_directory, pluginRoot) {
|
|
39650
40058
|
const findings = [];
|
|
39651
|
-
const resolvedPluginRoot = pluginRoot ??
|
|
39652
|
-
const indexPath =
|
|
40059
|
+
const resolvedPluginRoot = pluginRoot ?? path23.resolve(import.meta.dir, "..", "..");
|
|
40060
|
+
const indexPath = path23.join(resolvedPluginRoot, "src", "index.ts");
|
|
39653
40061
|
if (!fs10.existsSync(indexPath)) {
|
|
39654
40062
|
return {
|
|
39655
40063
|
findings: [
|
|
@@ -39819,6 +40227,7 @@ var exports_evidence_summary_service = {};
|
|
|
39819
40227
|
__export(exports_evidence_summary_service, {
|
|
39820
40228
|
isAutoSummaryEnabled: () => isAutoSummaryEnabled,
|
|
39821
40229
|
buildEvidenceSummary: () => buildEvidenceSummary,
|
|
40230
|
+
_internals: () => _internals12,
|
|
39822
40231
|
REQUIRED_EVIDENCE_TYPES: () => REQUIRED_EVIDENCE_TYPES,
|
|
39823
40232
|
EVIDENCE_SUMMARY_VERSION: () => EVIDENCE_SUMMARY_VERSION
|
|
39824
40233
|
});
|
|
@@ -39856,14 +40265,14 @@ function getTaskStatus(task, bundle) {
|
|
|
39856
40265
|
if (task?.status) {
|
|
39857
40266
|
return task.status;
|
|
39858
40267
|
}
|
|
39859
|
-
const entries = normalizeBundleEntries(bundle);
|
|
40268
|
+
const entries = _internals12.normalizeBundleEntries(bundle);
|
|
39860
40269
|
if (entries.length > 0) {
|
|
39861
40270
|
return "completed";
|
|
39862
40271
|
}
|
|
39863
40272
|
return "pending";
|
|
39864
40273
|
}
|
|
39865
40274
|
function isEvidenceComplete(bundle) {
|
|
39866
|
-
const entries = normalizeBundleEntries(bundle);
|
|
40275
|
+
const entries = _internals12.normalizeBundleEntries(bundle);
|
|
39867
40276
|
if (entries.length === 0) {
|
|
39868
40277
|
return {
|
|
39869
40278
|
isComplete: false,
|
|
@@ -39899,10 +40308,10 @@ async function buildTaskSummary(directory, task, taskId) {
|
|
|
39899
40308
|
const result = await loadEvidence(directory, taskId);
|
|
39900
40309
|
const bundle = result.status === "found" ? result.bundle : null;
|
|
39901
40310
|
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);
|
|
40311
|
+
const status = _internals12.getTaskStatus(task, bundle);
|
|
40312
|
+
const evidenceCheck = _internals12.isEvidenceComplete(bundle);
|
|
40313
|
+
const blockers = _internals12.getTaskBlockers(task, evidenceCheck, status);
|
|
40314
|
+
const entries = _internals12.normalizeBundleEntries(bundle);
|
|
39906
40315
|
const hasReview = entries.some((e) => e.type === "review");
|
|
39907
40316
|
const hasTest = entries.some((e) => e.type === "test");
|
|
39908
40317
|
const hasApproval = entries.some((e) => e.type === "approval");
|
|
@@ -39931,12 +40340,12 @@ async function buildPhaseSummary(directory, phase) {
|
|
|
39931
40340
|
const taskSummaries = [];
|
|
39932
40341
|
const _taskMap = new Map(phase.tasks.map((t) => [t.id, t]));
|
|
39933
40342
|
for (const task of phase.tasks) {
|
|
39934
|
-
const summary = await buildTaskSummary(directory, task, task.id);
|
|
40343
|
+
const summary = await _internals12.buildTaskSummary(directory, task, task.id);
|
|
39935
40344
|
taskSummaries.push(summary);
|
|
39936
40345
|
}
|
|
39937
40346
|
const extraTaskIds = taskIds.filter((id) => !phaseTaskIds.has(id));
|
|
39938
40347
|
for (const taskId of extraTaskIds) {
|
|
39939
|
-
const summary = await buildTaskSummary(directory, undefined, taskId);
|
|
40348
|
+
const summary = await _internals12.buildTaskSummary(directory, undefined, taskId);
|
|
39940
40349
|
if (summary.phase === phase.id) {
|
|
39941
40350
|
taskSummaries.push(summary);
|
|
39942
40351
|
}
|
|
@@ -40037,7 +40446,7 @@ async function buildEvidenceSummary(directory, currentPhase) {
|
|
|
40037
40446
|
let totalTasks = 0;
|
|
40038
40447
|
let completedTasks = 0;
|
|
40039
40448
|
for (const phase of phasesToProcess) {
|
|
40040
|
-
const summary = await buildPhaseSummary(directory, phase);
|
|
40449
|
+
const summary = await _internals12.buildPhaseSummary(directory, phase);
|
|
40041
40450
|
phaseSummaries.push(summary);
|
|
40042
40451
|
totalTasks += summary.totalTasks;
|
|
40043
40452
|
completedTasks += summary.completedTasks;
|
|
@@ -40059,7 +40468,7 @@ async function buildEvidenceSummary(directory, currentPhase) {
|
|
|
40059
40468
|
overallBlockers,
|
|
40060
40469
|
summaryText: ""
|
|
40061
40470
|
};
|
|
40062
|
-
artifact.summaryText = generateSummaryText(artifact);
|
|
40471
|
+
artifact.summaryText = _internals12.generateSummaryText(artifact);
|
|
40063
40472
|
log("[EvidenceSummary] Summary built", {
|
|
40064
40473
|
phases: phaseSummaries.length,
|
|
40065
40474
|
totalTasks,
|
|
@@ -40078,7 +40487,7 @@ function isAutoSummaryEnabled(automationConfig) {
|
|
|
40078
40487
|
}
|
|
40079
40488
|
return automationConfig.capabilities?.evidence_auto_summaries === true;
|
|
40080
40489
|
}
|
|
40081
|
-
var VALID_EVIDENCE_TYPES2, REQUIRED_EVIDENCE_TYPES, EVIDENCE_SUMMARY_VERSION = "1.0.0";
|
|
40490
|
+
var VALID_EVIDENCE_TYPES2, REQUIRED_EVIDENCE_TYPES, EVIDENCE_SUMMARY_VERSION = "1.0.0", _internals12;
|
|
40082
40491
|
var init_evidence_summary_service = __esm(() => {
|
|
40083
40492
|
init_manager2();
|
|
40084
40493
|
init_manager();
|
|
@@ -40092,6 +40501,17 @@ var init_evidence_summary_service = __esm(() => {
|
|
|
40092
40501
|
"retrospective"
|
|
40093
40502
|
]);
|
|
40094
40503
|
REQUIRED_EVIDENCE_TYPES = ["review", "test"];
|
|
40504
|
+
_internals12 = {
|
|
40505
|
+
buildEvidenceSummary,
|
|
40506
|
+
isAutoSummaryEnabled,
|
|
40507
|
+
normalizeBundleEntries,
|
|
40508
|
+
getTaskStatus,
|
|
40509
|
+
isEvidenceComplete,
|
|
40510
|
+
getTaskBlockers,
|
|
40511
|
+
buildTaskSummary,
|
|
40512
|
+
buildPhaseSummary,
|
|
40513
|
+
generateSummaryText
|
|
40514
|
+
};
|
|
40095
40515
|
});
|
|
40096
40516
|
|
|
40097
40517
|
// src/services/evidence-service.ts
|
|
@@ -40391,7 +40811,7 @@ function extractCurrentPhaseFromPlan2(plan) {
|
|
|
40391
40811
|
if (!plan) {
|
|
40392
40812
|
return { currentPhase: null, currentTask: null, incompleteTasks: [] };
|
|
40393
40813
|
}
|
|
40394
|
-
if (!validatePlanPhases(plan)) {
|
|
40814
|
+
if (!_internals13.validatePlanPhases(plan)) {
|
|
40395
40815
|
return { currentPhase: null, currentTask: null, incompleteTasks: [] };
|
|
40396
40816
|
}
|
|
40397
40817
|
let currentPhase = null;
|
|
@@ -40533,9 +40953,9 @@ function extractPhaseMetrics(content) {
|
|
|
40533
40953
|
async function getHandoffData(directory) {
|
|
40534
40954
|
const now = new Date().toISOString();
|
|
40535
40955
|
const sessionContent = await readSwarmFileAsync(directory, "session/state.json");
|
|
40536
|
-
const sessionState = parseSessionState(sessionContent);
|
|
40956
|
+
const sessionState = _internals13.parseSessionState(sessionContent);
|
|
40537
40957
|
const plan = await loadPlanJsonOnly(directory);
|
|
40538
|
-
const planInfo =
|
|
40958
|
+
const planInfo = _internals13.extractCurrentPhaseFromPlan(plan);
|
|
40539
40959
|
if (!plan) {
|
|
40540
40960
|
const planMdContent = await readSwarmFileAsync(directory, "plan.md");
|
|
40541
40961
|
if (planMdContent) {
|
|
@@ -40554,8 +40974,8 @@ async function getHandoffData(directory) {
|
|
|
40554
40974
|
}
|
|
40555
40975
|
}
|
|
40556
40976
|
const contextContent = await readSwarmFileAsync(directory, "context.md");
|
|
40557
|
-
const recentDecisions = extractDecisions(contextContent);
|
|
40558
|
-
const rawPhaseMetrics = extractPhaseMetrics(contextContent);
|
|
40977
|
+
const recentDecisions = _internals13.extractDecisions(contextContent);
|
|
40978
|
+
const rawPhaseMetrics = _internals13.extractPhaseMetrics(contextContent);
|
|
40559
40979
|
const phaseMetrics = sanitizeString(rawPhaseMetrics, 1000);
|
|
40560
40980
|
let delegationState = null;
|
|
40561
40981
|
if (sessionState?.delegationState) {
|
|
@@ -40719,12 +41139,24 @@ ${lines.join(`
|
|
|
40719
41139
|
`)}
|
|
40720
41140
|
\`\`\``;
|
|
40721
41141
|
}
|
|
40722
|
-
var RTL_OVERRIDE_PATTERN, MAX_TASK_ID_LENGTH = 100, MAX_DECISION_LENGTH = 500, MAX_INCOMPLETE_TASKS = 20;
|
|
41142
|
+
var RTL_OVERRIDE_PATTERN, MAX_TASK_ID_LENGTH = 100, MAX_DECISION_LENGTH = 500, MAX_INCOMPLETE_TASKS = 20, _internals13;
|
|
40723
41143
|
var init_handoff_service = __esm(() => {
|
|
40724
41144
|
init_utils2();
|
|
40725
41145
|
init_manager();
|
|
40726
41146
|
init_utils();
|
|
40727
41147
|
RTL_OVERRIDE_PATTERN = /[\u202e\u202d\u202c\u200f]/g;
|
|
41148
|
+
_internals13 = {
|
|
41149
|
+
getHandoffData,
|
|
41150
|
+
formatHandoffMarkdown,
|
|
41151
|
+
formatContinuationPrompt,
|
|
41152
|
+
escapeHtml,
|
|
41153
|
+
sanitizeString,
|
|
41154
|
+
validatePlanPhases,
|
|
41155
|
+
extractCurrentPhaseFromPlan: extractCurrentPhaseFromPlan2,
|
|
41156
|
+
parseSessionState,
|
|
41157
|
+
extractDecisions,
|
|
41158
|
+
extractPhaseMetrics
|
|
41159
|
+
};
|
|
40728
41160
|
});
|
|
40729
41161
|
|
|
40730
41162
|
// src/commands/handoff.ts
|
|
@@ -41116,14 +41548,23 @@ var init_issue = __esm(() => {
|
|
|
41116
41548
|
|
|
41117
41549
|
// src/hooks/knowledge-migrator.ts
|
|
41118
41550
|
import { randomUUID as randomUUID2 } from "crypto";
|
|
41119
|
-
import { existsSync as
|
|
41120
|
-
import { mkdir as
|
|
41121
|
-
import * as
|
|
41551
|
+
import { existsSync as existsSync14, readFileSync as readFileSync10 } from "fs";
|
|
41552
|
+
import { mkdir as mkdir5, readFile as readFile6, writeFile as writeFile6 } from "fs/promises";
|
|
41553
|
+
import * as path24 from "path";
|
|
41554
|
+
async function migrateKnowledgeToExternal(_directory, _config) {
|
|
41555
|
+
return {
|
|
41556
|
+
migrated: false,
|
|
41557
|
+
entriesMigrated: 0,
|
|
41558
|
+
entriesDropped: 0,
|
|
41559
|
+
entriesTotal: 0,
|
|
41560
|
+
skippedReason: "no-context-file"
|
|
41561
|
+
};
|
|
41562
|
+
}
|
|
41122
41563
|
async function migrateContextToKnowledge(directory, config3) {
|
|
41123
|
-
const sentinelPath =
|
|
41124
|
-
const contextPath =
|
|
41564
|
+
const sentinelPath = path24.join(directory, ".swarm", ".knowledge-migrated");
|
|
41565
|
+
const contextPath = path24.join(directory, ".swarm", "context.md");
|
|
41125
41566
|
const knowledgePath = resolveSwarmKnowledgePath(directory);
|
|
41126
|
-
if (
|
|
41567
|
+
if (existsSync14(sentinelPath)) {
|
|
41127
41568
|
return {
|
|
41128
41569
|
migrated: false,
|
|
41129
41570
|
entriesMigrated: 0,
|
|
@@ -41132,7 +41573,7 @@ async function migrateContextToKnowledge(directory, config3) {
|
|
|
41132
41573
|
skippedReason: "sentinel-exists"
|
|
41133
41574
|
};
|
|
41134
41575
|
}
|
|
41135
|
-
if (!
|
|
41576
|
+
if (!existsSync14(contextPath)) {
|
|
41136
41577
|
return {
|
|
41137
41578
|
migrated: false,
|
|
41138
41579
|
entriesMigrated: 0,
|
|
@@ -41141,7 +41582,7 @@ async function migrateContextToKnowledge(directory, config3) {
|
|
|
41141
41582
|
skippedReason: "no-context-file"
|
|
41142
41583
|
};
|
|
41143
41584
|
}
|
|
41144
|
-
const contextContent = await
|
|
41585
|
+
const contextContent = await readFile6(contextPath, "utf-8");
|
|
41145
41586
|
if (contextContent.trim().length === 0) {
|
|
41146
41587
|
return {
|
|
41147
41588
|
migrated: false,
|
|
@@ -41151,9 +41592,9 @@ async function migrateContextToKnowledge(directory, config3) {
|
|
|
41151
41592
|
skippedReason: "empty-context"
|
|
41152
41593
|
};
|
|
41153
41594
|
}
|
|
41154
|
-
const rawEntries = parseContextMd(contextContent);
|
|
41595
|
+
const rawEntries = _internals14.parseContextMd(contextContent);
|
|
41155
41596
|
if (rawEntries.length === 0) {
|
|
41156
|
-
await writeSentinel(sentinelPath, 0, 0);
|
|
41597
|
+
await _internals14.writeSentinel(sentinelPath, 0, 0);
|
|
41157
41598
|
return {
|
|
41158
41599
|
migrated: true,
|
|
41159
41600
|
entriesMigrated: 0,
|
|
@@ -41164,10 +41605,10 @@ async function migrateContextToKnowledge(directory, config3) {
|
|
|
41164
41605
|
const existing = await readKnowledge(knowledgePath);
|
|
41165
41606
|
let migrated = 0;
|
|
41166
41607
|
let dropped = 0;
|
|
41167
|
-
const projectName = inferProjectName(directory);
|
|
41608
|
+
const projectName = _internals14.inferProjectName(directory);
|
|
41168
41609
|
for (const raw of rawEntries) {
|
|
41169
41610
|
if (config3.validation_enabled !== false) {
|
|
41170
|
-
const category = raw.categoryHint ?? inferCategoryFromText(raw.text);
|
|
41611
|
+
const category = raw.categoryHint ?? _internals14.inferCategoryFromText(raw.text);
|
|
41171
41612
|
const result = validateLesson(raw.text, existing.map((e) => e.lesson), {
|
|
41172
41613
|
category,
|
|
41173
41614
|
scope: "global",
|
|
@@ -41187,8 +41628,8 @@ async function migrateContextToKnowledge(directory, config3) {
|
|
|
41187
41628
|
const entry = {
|
|
41188
41629
|
id: randomUUID2(),
|
|
41189
41630
|
tier: "swarm",
|
|
41190
|
-
lesson: truncateLesson(raw.text),
|
|
41191
|
-
category: raw.categoryHint ?? inferCategoryFromText(raw.text),
|
|
41631
|
+
lesson: _internals14.truncateLesson(raw.text),
|
|
41632
|
+
category: raw.categoryHint ?? _internals14.inferCategoryFromText(raw.text),
|
|
41192
41633
|
tags: [...inferredTags, `migration:${raw.sourceSection}`],
|
|
41193
41634
|
scope: "global",
|
|
41194
41635
|
confidence: 0.3,
|
|
@@ -41211,7 +41652,7 @@ async function migrateContextToKnowledge(directory, config3) {
|
|
|
41211
41652
|
if (migrated > 0) {
|
|
41212
41653
|
await rewriteKnowledge(knowledgePath, existing);
|
|
41213
41654
|
}
|
|
41214
|
-
await writeSentinel(sentinelPath, migrated, dropped);
|
|
41655
|
+
await _internals14.writeSentinel(sentinelPath, migrated, dropped);
|
|
41215
41656
|
log(`[knowledge-migrator] Migrated ${migrated} entries, dropped ${dropped}`);
|
|
41216
41657
|
return {
|
|
41217
41658
|
migrated: true,
|
|
@@ -41221,7 +41662,7 @@ async function migrateContextToKnowledge(directory, config3) {
|
|
|
41221
41662
|
};
|
|
41222
41663
|
}
|
|
41223
41664
|
function parseContextMd(content) {
|
|
41224
|
-
const sections = splitIntoSections(content);
|
|
41665
|
+
const sections = _internals14.splitIntoSections(content);
|
|
41225
41666
|
const entries = [];
|
|
41226
41667
|
const seen = new Set;
|
|
41227
41668
|
const sectionPatterns = [
|
|
@@ -41237,7 +41678,7 @@ function parseContextMd(content) {
|
|
|
41237
41678
|
const match = sectionPatterns.find((sp) => sp.pattern.test(section.heading));
|
|
41238
41679
|
if (!match)
|
|
41239
41680
|
continue;
|
|
41240
|
-
const bullets = extractBullets(section.body);
|
|
41681
|
+
const bullets = _internals14.extractBullets(section.body);
|
|
41241
41682
|
for (const bullet of bullets) {
|
|
41242
41683
|
if (bullet.length < 15)
|
|
41243
41684
|
continue;
|
|
@@ -41246,9 +41687,9 @@ function parseContextMd(content) {
|
|
|
41246
41687
|
continue;
|
|
41247
41688
|
seen.add(normalized);
|
|
41248
41689
|
entries.push({
|
|
41249
|
-
text: truncateLesson(bullet),
|
|
41690
|
+
text: _internals14.truncateLesson(bullet),
|
|
41250
41691
|
sourceSection: match.sourceSection,
|
|
41251
|
-
categoryHint: inferCategoryFromText(bullet)
|
|
41692
|
+
categoryHint: _internals14.inferCategoryFromText(bullet)
|
|
41252
41693
|
});
|
|
41253
41694
|
}
|
|
41254
41695
|
}
|
|
@@ -41317,8 +41758,8 @@ function truncateLesson(text) {
|
|
|
41317
41758
|
return `${text.slice(0, 277)}...`;
|
|
41318
41759
|
}
|
|
41319
41760
|
function inferProjectName(directory) {
|
|
41320
|
-
const packageJsonPath =
|
|
41321
|
-
if (
|
|
41761
|
+
const packageJsonPath = path24.join(directory, "package.json");
|
|
41762
|
+
if (existsSync14(packageJsonPath)) {
|
|
41322
41763
|
try {
|
|
41323
41764
|
const pkg = JSON.parse(readFileSync10(packageJsonPath, "utf-8"));
|
|
41324
41765
|
if (pkg.name && typeof pkg.name === "string") {
|
|
@@ -41326,7 +41767,7 @@ function inferProjectName(directory) {
|
|
|
41326
41767
|
}
|
|
41327
41768
|
} catch {}
|
|
41328
41769
|
}
|
|
41329
|
-
return
|
|
41770
|
+
return path24.basename(directory);
|
|
41330
41771
|
}
|
|
41331
41772
|
async function writeSentinel(sentinelPath, migrated, dropped) {
|
|
41332
41773
|
const sentinel = {
|
|
@@ -41338,16 +41779,29 @@ async function writeSentinel(sentinelPath, migrated, dropped) {
|
|
|
41338
41779
|
schema_version: 1,
|
|
41339
41780
|
migration_tool: "knowledge-migrator.ts"
|
|
41340
41781
|
};
|
|
41341
|
-
await
|
|
41342
|
-
await
|
|
41782
|
+
await mkdir5(path24.dirname(sentinelPath), { recursive: true });
|
|
41783
|
+
await writeFile6(sentinelPath, JSON.stringify(sentinel, null, 2), "utf-8");
|
|
41343
41784
|
}
|
|
41785
|
+
var _internals14;
|
|
41344
41786
|
var init_knowledge_migrator = __esm(() => {
|
|
41787
|
+
init_logger();
|
|
41345
41788
|
init_knowledge_store();
|
|
41346
41789
|
init_knowledge_validator();
|
|
41790
|
+
_internals14 = {
|
|
41791
|
+
migrateContextToKnowledge,
|
|
41792
|
+
migrateKnowledgeToExternal,
|
|
41793
|
+
parseContextMd,
|
|
41794
|
+
splitIntoSections,
|
|
41795
|
+
extractBullets,
|
|
41796
|
+
inferCategoryFromText,
|
|
41797
|
+
truncateLesson,
|
|
41798
|
+
inferProjectName,
|
|
41799
|
+
writeSentinel
|
|
41800
|
+
};
|
|
41347
41801
|
});
|
|
41348
41802
|
|
|
41349
41803
|
// src/commands/knowledge.ts
|
|
41350
|
-
import { join as
|
|
41804
|
+
import { join as join23 } from "path";
|
|
41351
41805
|
function resolveEntryByPrefix(entries, inputId) {
|
|
41352
41806
|
const exact = entries.find((e) => e.id === inputId);
|
|
41353
41807
|
if (exact)
|
|
@@ -41398,7 +41852,7 @@ async function handleKnowledgeRestoreCommand(directory, args) {
|
|
|
41398
41852
|
return "Invalid entry ID. IDs must be 1-64 characters: letters, digits, hyphens, underscores only.";
|
|
41399
41853
|
}
|
|
41400
41854
|
try {
|
|
41401
|
-
const quarantinePath =
|
|
41855
|
+
const quarantinePath = join23(directory, ".swarm", "knowledge-quarantined.jsonl");
|
|
41402
41856
|
const entries = await readKnowledge(quarantinePath);
|
|
41403
41857
|
const resolved = resolveEntryByPrefix(entries, inputId);
|
|
41404
41858
|
if ("error" in resolved) {
|
|
@@ -41847,7 +42301,7 @@ var init_path_security = () => {};
|
|
|
41847
42301
|
|
|
41848
42302
|
// src/tools/lint.ts
|
|
41849
42303
|
import * as fs11 from "fs";
|
|
41850
|
-
import * as
|
|
42304
|
+
import * as path25 from "path";
|
|
41851
42305
|
function validateArgs(args) {
|
|
41852
42306
|
if (typeof args !== "object" || args === null)
|
|
41853
42307
|
return false;
|
|
@@ -41858,9 +42312,9 @@ function validateArgs(args) {
|
|
|
41858
42312
|
}
|
|
41859
42313
|
function getLinterCommand(linter, mode, projectDir) {
|
|
41860
42314
|
const isWindows = process.platform === "win32";
|
|
41861
|
-
const binDir =
|
|
41862
|
-
const biomeBin = isWindows ?
|
|
41863
|
-
const eslintBin = isWindows ?
|
|
42315
|
+
const binDir = path25.join(projectDir, "node_modules", ".bin");
|
|
42316
|
+
const biomeBin = isWindows ? path25.join(binDir, "biome.EXE") : path25.join(binDir, "biome");
|
|
42317
|
+
const eslintBin = isWindows ? path25.join(binDir, "eslint.cmd") : path25.join(binDir, "eslint");
|
|
41864
42318
|
switch (linter) {
|
|
41865
42319
|
case "biome":
|
|
41866
42320
|
if (mode === "fix") {
|
|
@@ -41876,7 +42330,7 @@ function getLinterCommand(linter, mode, projectDir) {
|
|
|
41876
42330
|
}
|
|
41877
42331
|
function getAdditionalLinterCommand(linter, mode, cwd) {
|
|
41878
42332
|
const gradlewName = process.platform === "win32" ? "gradlew.bat" : "gradlew";
|
|
41879
|
-
const gradlew = fs11.existsSync(
|
|
42333
|
+
const gradlew = fs11.existsSync(path25.join(cwd, gradlewName)) ? path25.join(cwd, gradlewName) : null;
|
|
41880
42334
|
switch (linter) {
|
|
41881
42335
|
case "ruff":
|
|
41882
42336
|
return mode === "fix" ? ["ruff", "check", "--fix", "."] : ["ruff", "check", "."];
|
|
@@ -41910,10 +42364,10 @@ function getAdditionalLinterCommand(linter, mode, cwd) {
|
|
|
41910
42364
|
}
|
|
41911
42365
|
}
|
|
41912
42366
|
function detectRuff(cwd) {
|
|
41913
|
-
if (fs11.existsSync(
|
|
42367
|
+
if (fs11.existsSync(path25.join(cwd, "ruff.toml")))
|
|
41914
42368
|
return isCommandAvailable("ruff");
|
|
41915
42369
|
try {
|
|
41916
|
-
const pyproject =
|
|
42370
|
+
const pyproject = path25.join(cwd, "pyproject.toml");
|
|
41917
42371
|
if (fs11.existsSync(pyproject)) {
|
|
41918
42372
|
const content = fs11.readFileSync(pyproject, "utf-8");
|
|
41919
42373
|
if (content.includes("[tool.ruff]"))
|
|
@@ -41923,19 +42377,19 @@ function detectRuff(cwd) {
|
|
|
41923
42377
|
return false;
|
|
41924
42378
|
}
|
|
41925
42379
|
function detectClippy(cwd) {
|
|
41926
|
-
return fs11.existsSync(
|
|
42380
|
+
return fs11.existsSync(path25.join(cwd, "Cargo.toml")) && isCommandAvailable("cargo");
|
|
41927
42381
|
}
|
|
41928
42382
|
function detectGolangciLint(cwd) {
|
|
41929
|
-
return fs11.existsSync(
|
|
42383
|
+
return fs11.existsSync(path25.join(cwd, "go.mod")) && isCommandAvailable("golangci-lint");
|
|
41930
42384
|
}
|
|
41931
42385
|
function detectCheckstyle(cwd) {
|
|
41932
|
-
const hasMaven = fs11.existsSync(
|
|
41933
|
-
const hasGradle = fs11.existsSync(
|
|
41934
|
-
const hasBinary = hasMaven && isCommandAvailable("mvn") || hasGradle && (fs11.existsSync(
|
|
42386
|
+
const hasMaven = fs11.existsSync(path25.join(cwd, "pom.xml"));
|
|
42387
|
+
const hasGradle = fs11.existsSync(path25.join(cwd, "build.gradle")) || fs11.existsSync(path25.join(cwd, "build.gradle.kts"));
|
|
42388
|
+
const hasBinary = hasMaven && isCommandAvailable("mvn") || hasGradle && (fs11.existsSync(path25.join(cwd, "gradlew")) || isCommandAvailable("gradle"));
|
|
41935
42389
|
return (hasMaven || hasGradle) && hasBinary;
|
|
41936
42390
|
}
|
|
41937
42391
|
function detectKtlint(cwd) {
|
|
41938
|
-
const hasKotlin = fs11.existsSync(
|
|
42392
|
+
const hasKotlin = fs11.existsSync(path25.join(cwd, "build.gradle.kts")) || fs11.existsSync(path25.join(cwd, "build.gradle")) || (() => {
|
|
41939
42393
|
try {
|
|
41940
42394
|
return fs11.readdirSync(cwd).some((f) => f.endsWith(".kt") || f.endsWith(".kts"));
|
|
41941
42395
|
} catch {
|
|
@@ -41954,11 +42408,11 @@ function detectDotnetFormat(cwd) {
|
|
|
41954
42408
|
}
|
|
41955
42409
|
}
|
|
41956
42410
|
function detectCppcheck(cwd) {
|
|
41957
|
-
if (fs11.existsSync(
|
|
42411
|
+
if (fs11.existsSync(path25.join(cwd, "CMakeLists.txt"))) {
|
|
41958
42412
|
return isCommandAvailable("cppcheck");
|
|
41959
42413
|
}
|
|
41960
42414
|
try {
|
|
41961
|
-
const dirsToCheck = [cwd,
|
|
42415
|
+
const dirsToCheck = [cwd, path25.join(cwd, "src")];
|
|
41962
42416
|
const hasCpp = dirsToCheck.some((dir) => {
|
|
41963
42417
|
try {
|
|
41964
42418
|
return fs11.readdirSync(dir).some((f) => /\.(c|cpp|cc|cxx|h|hpp)$/.test(f));
|
|
@@ -41972,13 +42426,13 @@ function detectCppcheck(cwd) {
|
|
|
41972
42426
|
}
|
|
41973
42427
|
}
|
|
41974
42428
|
function detectSwiftlint(cwd) {
|
|
41975
|
-
return fs11.existsSync(
|
|
42429
|
+
return fs11.existsSync(path25.join(cwd, "Package.swift")) && isCommandAvailable("swiftlint");
|
|
41976
42430
|
}
|
|
41977
42431
|
function detectDartAnalyze(cwd) {
|
|
41978
|
-
return fs11.existsSync(
|
|
42432
|
+
return fs11.existsSync(path25.join(cwd, "pubspec.yaml")) && (isCommandAvailable("dart") || isCommandAvailable("flutter"));
|
|
41979
42433
|
}
|
|
41980
42434
|
function detectRubocop(cwd) {
|
|
41981
|
-
return (fs11.existsSync(
|
|
42435
|
+
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
42436
|
}
|
|
41983
42437
|
function detectAdditionalLinter(cwd) {
|
|
41984
42438
|
if (detectRuff(cwd))
|
|
@@ -42006,10 +42460,10 @@ function detectAdditionalLinter(cwd) {
|
|
|
42006
42460
|
function findBinInAncestors(startDir, binName) {
|
|
42007
42461
|
let dir = startDir;
|
|
42008
42462
|
while (true) {
|
|
42009
|
-
const candidate =
|
|
42463
|
+
const candidate = path25.join(dir, "node_modules", ".bin", binName);
|
|
42010
42464
|
if (fs11.existsSync(candidate))
|
|
42011
42465
|
return candidate;
|
|
42012
|
-
const parent =
|
|
42466
|
+
const parent = path25.dirname(dir);
|
|
42013
42467
|
if (parent === dir)
|
|
42014
42468
|
break;
|
|
42015
42469
|
dir = parent;
|
|
@@ -42018,10 +42472,10 @@ function findBinInAncestors(startDir, binName) {
|
|
|
42018
42472
|
}
|
|
42019
42473
|
function findBinInEnvPath(binName) {
|
|
42020
42474
|
const searchPath = process.env.PATH ?? "";
|
|
42021
|
-
for (const dir of searchPath.split(
|
|
42475
|
+
for (const dir of searchPath.split(path25.delimiter)) {
|
|
42022
42476
|
if (!dir)
|
|
42023
42477
|
continue;
|
|
42024
|
-
const candidate =
|
|
42478
|
+
const candidate = path25.join(dir, binName);
|
|
42025
42479
|
if (fs11.existsSync(candidate))
|
|
42026
42480
|
return candidate;
|
|
42027
42481
|
}
|
|
@@ -42034,13 +42488,13 @@ async function detectAvailableLinter(directory) {
|
|
|
42034
42488
|
return null;
|
|
42035
42489
|
const projectDir = directory;
|
|
42036
42490
|
const isWindows = process.platform === "win32";
|
|
42037
|
-
const biomeBin = isWindows ?
|
|
42038
|
-
const eslintBin = isWindows ?
|
|
42491
|
+
const biomeBin = isWindows ? path25.join(projectDir, "node_modules", ".bin", "biome.EXE") : path25.join(projectDir, "node_modules", ".bin", "biome");
|
|
42492
|
+
const eslintBin = isWindows ? path25.join(projectDir, "node_modules", ".bin", "eslint.cmd") : path25.join(projectDir, "node_modules", ".bin", "eslint");
|
|
42039
42493
|
const localResult = await _detectAvailableLinter(projectDir, biomeBin, eslintBin);
|
|
42040
42494
|
if (localResult)
|
|
42041
42495
|
return localResult;
|
|
42042
|
-
const biomeAncestor = findBinInAncestors(
|
|
42043
|
-
const eslintAncestor = findBinInAncestors(
|
|
42496
|
+
const biomeAncestor = findBinInAncestors(path25.dirname(projectDir), isWindows ? "biome.EXE" : "biome");
|
|
42497
|
+
const eslintAncestor = findBinInAncestors(path25.dirname(projectDir), isWindows ? "eslint.cmd" : "eslint");
|
|
42044
42498
|
if (biomeAncestor || eslintAncestor) {
|
|
42045
42499
|
return _detectAvailableLinter(projectDir, biomeAncestor ?? biomeBin, eslintAncestor ?? eslintBin);
|
|
42046
42500
|
}
|
|
@@ -42199,7 +42653,7 @@ async function runAdditionalLint(linter, mode, cwd) {
|
|
|
42199
42653
|
};
|
|
42200
42654
|
}
|
|
42201
42655
|
}
|
|
42202
|
-
var MAX_OUTPUT_BYTES = 512000, MAX_COMMAND_LENGTH = 500, lint;
|
|
42656
|
+
var MAX_OUTPUT_BYTES = 512000, MAX_COMMAND_LENGTH = 500, lint, _internals15;
|
|
42203
42657
|
var init_lint = __esm(() => {
|
|
42204
42658
|
init_zod();
|
|
42205
42659
|
init_discovery();
|
|
@@ -42231,15 +42685,15 @@ var init_lint = __esm(() => {
|
|
|
42231
42685
|
}
|
|
42232
42686
|
const { mode } = args;
|
|
42233
42687
|
const cwd = directory;
|
|
42234
|
-
const linter = await detectAvailableLinter(directory);
|
|
42688
|
+
const linter = await _internals15.detectAvailableLinter(directory);
|
|
42235
42689
|
if (linter) {
|
|
42236
|
-
const result = await runLint(linter, mode, directory);
|
|
42690
|
+
const result = await _internals15.runLint(linter, mode, directory);
|
|
42237
42691
|
return JSON.stringify(result, null, 2);
|
|
42238
42692
|
}
|
|
42239
|
-
const additionalLinter = detectAdditionalLinter(cwd);
|
|
42693
|
+
const additionalLinter = _internals15.detectAdditionalLinter(cwd);
|
|
42240
42694
|
if (additionalLinter) {
|
|
42241
42695
|
warn(`[lint] Using ${additionalLinter} linter for this project`);
|
|
42242
|
-
const result = await runAdditionalLint(additionalLinter, mode, cwd);
|
|
42696
|
+
const result = await _internals15.runAdditionalLint(additionalLinter, mode, cwd);
|
|
42243
42697
|
return JSON.stringify(result, null, 2);
|
|
42244
42698
|
}
|
|
42245
42699
|
const errorResult = {
|
|
@@ -42253,11 +42707,17 @@ For Rust: rustup component add clippy`
|
|
|
42253
42707
|
return JSON.stringify(errorResult, null, 2);
|
|
42254
42708
|
}
|
|
42255
42709
|
});
|
|
42710
|
+
_internals15 = {
|
|
42711
|
+
detectAvailableLinter,
|
|
42712
|
+
runLint,
|
|
42713
|
+
detectAdditionalLinter,
|
|
42714
|
+
runAdditionalLint
|
|
42715
|
+
};
|
|
42256
42716
|
});
|
|
42257
42717
|
|
|
42258
42718
|
// src/tools/secretscan.ts
|
|
42259
42719
|
import * as fs12 from "fs";
|
|
42260
|
-
import * as
|
|
42720
|
+
import * as path26 from "path";
|
|
42261
42721
|
function calculateShannonEntropy(str) {
|
|
42262
42722
|
if (str.length === 0)
|
|
42263
42723
|
return 0;
|
|
@@ -42305,7 +42765,7 @@ function isGlobOrPathPattern(pattern) {
|
|
|
42305
42765
|
return pattern.includes("/") || pattern.includes("\\") || /[*?[\]{}]/.test(pattern);
|
|
42306
42766
|
}
|
|
42307
42767
|
function loadSecretScanIgnore(scanDir) {
|
|
42308
|
-
const ignorePath =
|
|
42768
|
+
const ignorePath = path26.join(scanDir, ".secretscanignore");
|
|
42309
42769
|
try {
|
|
42310
42770
|
if (!fs12.existsSync(ignorePath))
|
|
42311
42771
|
return [];
|
|
@@ -42328,7 +42788,7 @@ function isExcluded(entry, relPath, exactNames, globPatterns) {
|
|
|
42328
42788
|
if (exactNames.has(entry))
|
|
42329
42789
|
return true;
|
|
42330
42790
|
for (const pattern of globPatterns) {
|
|
42331
|
-
if (
|
|
42791
|
+
if (path26.matchesGlob(relPath, pattern))
|
|
42332
42792
|
return true;
|
|
42333
42793
|
}
|
|
42334
42794
|
return false;
|
|
@@ -42349,7 +42809,7 @@ function validateDirectoryInput(dir) {
|
|
|
42349
42809
|
return null;
|
|
42350
42810
|
}
|
|
42351
42811
|
function isBinaryFile(filePath, buffer) {
|
|
42352
|
-
const ext =
|
|
42812
|
+
const ext = path26.extname(filePath).toLowerCase();
|
|
42353
42813
|
if (DEFAULT_EXCLUDE_EXTENSIONS.has(ext)) {
|
|
42354
42814
|
return true;
|
|
42355
42815
|
}
|
|
@@ -42485,9 +42945,9 @@ function isSymlinkLoop(realPath, visited) {
|
|
|
42485
42945
|
return false;
|
|
42486
42946
|
}
|
|
42487
42947
|
function isPathWithinScope(realPath, scanDir) {
|
|
42488
|
-
const resolvedScanDir =
|
|
42489
|
-
const resolvedRealPath =
|
|
42490
|
-
return resolvedRealPath === resolvedScanDir || resolvedRealPath.startsWith(resolvedScanDir +
|
|
42948
|
+
const resolvedScanDir = path26.resolve(scanDir);
|
|
42949
|
+
const resolvedRealPath = path26.resolve(realPath);
|
|
42950
|
+
return resolvedRealPath === resolvedScanDir || resolvedRealPath.startsWith(resolvedScanDir + path26.sep) || resolvedRealPath.startsWith(`${resolvedScanDir}/`) || resolvedRealPath.startsWith(`${resolvedScanDir}\\`);
|
|
42491
42951
|
}
|
|
42492
42952
|
function findScannableFiles(dir, excludeExact, excludeGlobs, scanDir, visited, stats = {
|
|
42493
42953
|
skippedDirs: 0,
|
|
@@ -42513,8 +42973,8 @@ function findScannableFiles(dir, excludeExact, excludeGlobs, scanDir, visited, s
|
|
|
42513
42973
|
return a.localeCompare(b);
|
|
42514
42974
|
});
|
|
42515
42975
|
for (const entry of entries) {
|
|
42516
|
-
const fullPath =
|
|
42517
|
-
const relPath =
|
|
42976
|
+
const fullPath = path26.join(dir, entry);
|
|
42977
|
+
const relPath = path26.relative(scanDir, fullPath).replace(/\\/g, "/");
|
|
42518
42978
|
if (isExcluded(entry, relPath, excludeExact, excludeGlobs)) {
|
|
42519
42979
|
stats.skippedDirs++;
|
|
42520
42980
|
continue;
|
|
@@ -42549,7 +43009,7 @@ function findScannableFiles(dir, excludeExact, excludeGlobs, scanDir, visited, s
|
|
|
42549
43009
|
const subFiles = findScannableFiles(fullPath, excludeExact, excludeGlobs, scanDir, visited, stats);
|
|
42550
43010
|
files.push(...subFiles);
|
|
42551
43011
|
} else if (lstat.isFile()) {
|
|
42552
|
-
const ext =
|
|
43012
|
+
const ext = path26.extname(fullPath).toLowerCase();
|
|
42553
43013
|
if (!DEFAULT_EXCLUDE_EXTENSIONS.has(ext)) {
|
|
42554
43014
|
files.push(fullPath);
|
|
42555
43015
|
} else {
|
|
@@ -42561,7 +43021,7 @@ function findScannableFiles(dir, excludeExact, excludeGlobs, scanDir, visited, s
|
|
|
42561
43021
|
}
|
|
42562
43022
|
async function runSecretscan(directory) {
|
|
42563
43023
|
try {
|
|
42564
|
-
const result = await secretscan.execute({ directory }, {});
|
|
43024
|
+
const result = await _internals16.secretscan.execute({ directory }, {});
|
|
42565
43025
|
const jsonStr = typeof result === "string" ? result : result.output;
|
|
42566
43026
|
return JSON.parse(jsonStr);
|
|
42567
43027
|
} catch (e) {
|
|
@@ -42576,7 +43036,7 @@ async function runSecretscan(directory) {
|
|
|
42576
43036
|
return errorResult;
|
|
42577
43037
|
}
|
|
42578
43038
|
}
|
|
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;
|
|
43039
|
+
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
43040
|
var init_secretscan = __esm(() => {
|
|
42581
43041
|
init_zod();
|
|
42582
43042
|
init_path_security();
|
|
@@ -42809,7 +43269,7 @@ var init_secretscan = __esm(() => {
|
|
|
42809
43269
|
}
|
|
42810
43270
|
}
|
|
42811
43271
|
try {
|
|
42812
|
-
const _scanDirRaw =
|
|
43272
|
+
const _scanDirRaw = path26.resolve(directory);
|
|
42813
43273
|
const scanDir = (() => {
|
|
42814
43274
|
try {
|
|
42815
43275
|
return fs12.realpathSync(_scanDirRaw);
|
|
@@ -42948,11 +43408,15 @@ var init_secretscan = __esm(() => {
|
|
|
42948
43408
|
}
|
|
42949
43409
|
}
|
|
42950
43410
|
});
|
|
43411
|
+
_internals16 = {
|
|
43412
|
+
secretscan,
|
|
43413
|
+
runSecretscan
|
|
43414
|
+
};
|
|
42951
43415
|
});
|
|
42952
43416
|
|
|
42953
43417
|
// src/test-impact/analyzer.ts
|
|
42954
43418
|
import fs13 from "fs";
|
|
42955
|
-
import
|
|
43419
|
+
import path27 from "path";
|
|
42956
43420
|
function normalizePath(p) {
|
|
42957
43421
|
return p.replace(/\\/g, "/");
|
|
42958
43422
|
}
|
|
@@ -42973,8 +43437,8 @@ function resolveRelativeImport(fromDir, importPath) {
|
|
|
42973
43437
|
if (!importPath.startsWith(".")) {
|
|
42974
43438
|
return null;
|
|
42975
43439
|
}
|
|
42976
|
-
const resolved =
|
|
42977
|
-
if (
|
|
43440
|
+
const resolved = path27.resolve(fromDir, importPath);
|
|
43441
|
+
if (path27.extname(resolved)) {
|
|
42978
43442
|
if (fs13.existsSync(resolved) && fs13.statSync(resolved).isFile()) {
|
|
42979
43443
|
return normalizePath(resolved);
|
|
42980
43444
|
}
|
|
@@ -43019,12 +43483,12 @@ function findTestFilesSync(cwd) {
|
|
|
43019
43483
|
for (const entry of entries) {
|
|
43020
43484
|
if (entry.isDirectory()) {
|
|
43021
43485
|
if (!skipDirs.has(entry.name)) {
|
|
43022
|
-
walk(
|
|
43486
|
+
walk(path27.join(dir, entry.name), visitedInodes);
|
|
43023
43487
|
}
|
|
43024
43488
|
} else if (entry.isFile()) {
|
|
43025
43489
|
const name = entry.name;
|
|
43026
43490
|
if (/\.(test|spec)\.(ts|tsx|js|jsx)$/.test(name) || dir.includes("__tests__") && /\.(ts|tsx|js|jsx)$/.test(name)) {
|
|
43027
|
-
testFiles.push(normalizePath(
|
|
43491
|
+
testFiles.push(normalizePath(path27.join(dir, entry.name)));
|
|
43028
43492
|
}
|
|
43029
43493
|
}
|
|
43030
43494
|
}
|
|
@@ -43062,7 +43526,7 @@ async function buildImpactMapInternal(cwd) {
|
|
|
43062
43526
|
continue;
|
|
43063
43527
|
}
|
|
43064
43528
|
const imports = extractImports(content);
|
|
43065
|
-
const testDir =
|
|
43529
|
+
const testDir = path27.dirname(testFile);
|
|
43066
43530
|
for (const importPath of imports) {
|
|
43067
43531
|
const resolvedSource = resolveRelativeImport(testDir, importPath);
|
|
43068
43532
|
if (resolvedSource === null) {
|
|
@@ -43079,28 +43543,28 @@ async function buildImpactMapInternal(cwd) {
|
|
|
43079
43543
|
return impactMap;
|
|
43080
43544
|
}
|
|
43081
43545
|
async function buildImpactMap(cwd) {
|
|
43082
|
-
const impactMap = await buildImpactMapInternal(cwd);
|
|
43083
|
-
await saveImpactMap(cwd, impactMap);
|
|
43546
|
+
const impactMap = await _internals17.buildImpactMapInternal(cwd);
|
|
43547
|
+
await _internals17.saveImpactMap(cwd, impactMap);
|
|
43084
43548
|
return impactMap;
|
|
43085
43549
|
}
|
|
43086
43550
|
async function loadImpactMap(cwd) {
|
|
43087
|
-
const cachePath =
|
|
43551
|
+
const cachePath = path27.join(cwd, ".swarm", "cache", "impact-map.json");
|
|
43088
43552
|
if (fs13.existsSync(cachePath)) {
|
|
43089
43553
|
try {
|
|
43090
43554
|
const content = fs13.readFileSync(cachePath, "utf-8");
|
|
43091
43555
|
const data = JSON.parse(content);
|
|
43092
43556
|
const map3 = data.map;
|
|
43093
43557
|
const generatedAt = new Date(data.generatedAt).getTime();
|
|
43094
|
-
if (!isCacheStale(map3, generatedAt)) {
|
|
43558
|
+
if (!_internals17.isCacheStale(map3, generatedAt)) {
|
|
43095
43559
|
return map3;
|
|
43096
43560
|
}
|
|
43097
43561
|
} catch {}
|
|
43098
43562
|
}
|
|
43099
|
-
return buildImpactMap(cwd);
|
|
43563
|
+
return _internals17.buildImpactMap(cwd);
|
|
43100
43564
|
}
|
|
43101
43565
|
async function saveImpactMap(cwd, impactMap) {
|
|
43102
|
-
const cacheDir2 =
|
|
43103
|
-
const cachePath =
|
|
43566
|
+
const cacheDir2 = path27.join(cwd, ".swarm", "cache");
|
|
43567
|
+
const cachePath = path27.join(cacheDir2, "impact-map.json");
|
|
43104
43568
|
if (!fs13.existsSync(cacheDir2)) {
|
|
43105
43569
|
fs13.mkdirSync(cacheDir2, { recursive: true });
|
|
43106
43570
|
}
|
|
@@ -43122,11 +43586,11 @@ async function analyzeImpact(changedFiles, cwd) {
|
|
|
43122
43586
|
};
|
|
43123
43587
|
}
|
|
43124
43588
|
const validFiles = changedFiles.filter((f) => typeof f === "string" && f.length > 0 && !f.includes("\x00"));
|
|
43125
|
-
const impactMap = await loadImpactMap(cwd);
|
|
43589
|
+
const impactMap = await _internals17.loadImpactMap(cwd);
|
|
43126
43590
|
const impactedTestsSet = new Set;
|
|
43127
43591
|
const untestedFiles = [];
|
|
43128
43592
|
for (const changedFile of validFiles) {
|
|
43129
|
-
const normalizedChanged = normalizePath(
|
|
43593
|
+
const normalizedChanged = normalizePath(path27.resolve(changedFile));
|
|
43130
43594
|
const tests = impactMap[normalizedChanged];
|
|
43131
43595
|
if (tests && tests.length > 0) {
|
|
43132
43596
|
for (const test of tests) {
|
|
@@ -43163,12 +43627,24 @@ async function analyzeImpact(changedFiles, cwd) {
|
|
|
43163
43627
|
impactMap
|
|
43164
43628
|
};
|
|
43165
43629
|
}
|
|
43166
|
-
var IMPORT_REGEX_ES, IMPORT_REGEX_REQUIRE, IMPORT_REGEX_REEXPORT, EXTENSIONS_TO_TRY;
|
|
43630
|
+
var IMPORT_REGEX_ES, IMPORT_REGEX_REQUIRE, IMPORT_REGEX_REEXPORT, EXTENSIONS_TO_TRY, _internals17;
|
|
43167
43631
|
var init_analyzer = __esm(() => {
|
|
43168
43632
|
IMPORT_REGEX_ES = /import\s+.*?\s+from\s+['"]([^'"]+)['"]/g;
|
|
43169
43633
|
IMPORT_REGEX_REQUIRE = /require\s*\(\s*['"]([^'"]+)['"]\s*\)/g;
|
|
43170
43634
|
IMPORT_REGEX_REEXPORT = /export\s+(?:\{[^}]*\}|\*)\s+from\s+['"]([^'"]+)['"]/g;
|
|
43171
43635
|
EXTENSIONS_TO_TRY = [".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs"];
|
|
43636
|
+
_internals17 = {
|
|
43637
|
+
normalizePath,
|
|
43638
|
+
isCacheStale,
|
|
43639
|
+
resolveRelativeImport,
|
|
43640
|
+
findTestFilesSync,
|
|
43641
|
+
extractImports,
|
|
43642
|
+
buildImpactMapInternal,
|
|
43643
|
+
buildImpactMap,
|
|
43644
|
+
loadImpactMap,
|
|
43645
|
+
saveImpactMap,
|
|
43646
|
+
analyzeImpact
|
|
43647
|
+
};
|
|
43172
43648
|
});
|
|
43173
43649
|
|
|
43174
43650
|
// src/test-impact/failure-classifier.ts
|
|
@@ -43378,9 +43854,9 @@ var FLAKY_THRESHOLD = 0.3, MIN_RUNS_FOR_QUARANTINE = 5, MAX_HISTORY_RUNS = 20;
|
|
|
43378
43854
|
|
|
43379
43855
|
// src/test-impact/history-store.ts
|
|
43380
43856
|
import fs14 from "fs";
|
|
43381
|
-
import
|
|
43857
|
+
import path28 from "path";
|
|
43382
43858
|
function getHistoryPath(workingDir) {
|
|
43383
|
-
return
|
|
43859
|
+
return path28.join(workingDir || process.cwd(), ".swarm", "cache", "test-history.jsonl");
|
|
43384
43860
|
}
|
|
43385
43861
|
function sanitizeErrorMessage(errorMessage) {
|
|
43386
43862
|
if (errorMessage === undefined) {
|
|
@@ -43435,7 +43911,7 @@ function appendTestRun(record3, workingDir) {
|
|
|
43435
43911
|
changedFiles: sanitizeChangedFiles(record3.changedFiles || [])
|
|
43436
43912
|
};
|
|
43437
43913
|
const historyPath = getHistoryPath(workingDir);
|
|
43438
|
-
const historyDir =
|
|
43914
|
+
const historyDir = path28.dirname(historyPath);
|
|
43439
43915
|
if (!fs14.existsSync(historyDir)) {
|
|
43440
43916
|
fs14.mkdirSync(historyDir, { recursive: true });
|
|
43441
43917
|
}
|
|
@@ -43517,7 +43993,7 @@ var init_history_store = __esm(() => {
|
|
|
43517
43993
|
|
|
43518
43994
|
// src/tools/resolve-working-directory.ts
|
|
43519
43995
|
import * as fs15 from "fs";
|
|
43520
|
-
import * as
|
|
43996
|
+
import * as path29 from "path";
|
|
43521
43997
|
function resolveWorkingDirectory(workingDirectory, fallbackDirectory) {
|
|
43522
43998
|
if (workingDirectory == null || workingDirectory === "") {
|
|
43523
43999
|
return { success: true, directory: fallbackDirectory };
|
|
@@ -43537,15 +44013,15 @@ function resolveWorkingDirectory(workingDirectory, fallbackDirectory) {
|
|
|
43537
44013
|
};
|
|
43538
44014
|
}
|
|
43539
44015
|
}
|
|
43540
|
-
const normalizedDir =
|
|
43541
|
-
const pathParts = normalizedDir.split(
|
|
44016
|
+
const normalizedDir = path29.normalize(workingDirectory);
|
|
44017
|
+
const pathParts = normalizedDir.split(path29.sep);
|
|
43542
44018
|
if (pathParts.includes("..")) {
|
|
43543
44019
|
return {
|
|
43544
44020
|
success: false,
|
|
43545
44021
|
message: "Invalid working_directory: path traversal sequences (..) are not allowed"
|
|
43546
44022
|
};
|
|
43547
44023
|
}
|
|
43548
|
-
const resolvedDir =
|
|
44024
|
+
const resolvedDir = path29.resolve(normalizedDir);
|
|
43549
44025
|
let statResult;
|
|
43550
44026
|
try {
|
|
43551
44027
|
statResult = fs15.statSync(resolvedDir);
|
|
@@ -43561,7 +44037,7 @@ function resolveWorkingDirectory(workingDirectory, fallbackDirectory) {
|
|
|
43561
44037
|
message: `Invalid working_directory: path "${resolvedDir}" is not a directory`
|
|
43562
44038
|
};
|
|
43563
44039
|
}
|
|
43564
|
-
const resolvedFallback =
|
|
44040
|
+
const resolvedFallback = path29.resolve(fallbackDirectory);
|
|
43565
44041
|
let fallbackExists = false;
|
|
43566
44042
|
try {
|
|
43567
44043
|
fs15.statSync(resolvedFallback);
|
|
@@ -43571,7 +44047,7 @@ function resolveWorkingDirectory(workingDirectory, fallbackDirectory) {
|
|
|
43571
44047
|
}
|
|
43572
44048
|
if (workingDirectory != null && workingDirectory !== "") {
|
|
43573
44049
|
if (fallbackExists) {
|
|
43574
|
-
const isSubdirectory = resolvedDir.startsWith(resolvedFallback +
|
|
44050
|
+
const isSubdirectory = resolvedDir.startsWith(resolvedFallback + path29.sep);
|
|
43575
44051
|
if (isSubdirectory) {
|
|
43576
44052
|
return {
|
|
43577
44053
|
success: false,
|
|
@@ -43593,7 +44069,7 @@ var init_resolve_working_directory = () => {};
|
|
|
43593
44069
|
|
|
43594
44070
|
// src/tools/test-runner.ts
|
|
43595
44071
|
import * as fs16 from "fs";
|
|
43596
|
-
import * as
|
|
44072
|
+
import * as path30 from "path";
|
|
43597
44073
|
function isAbsolutePath(str) {
|
|
43598
44074
|
if (str.startsWith("/"))
|
|
43599
44075
|
return true;
|
|
@@ -43658,14 +44134,14 @@ function hasDevDependency(devDeps, ...patterns) {
|
|
|
43658
44134
|
return hasPackageJsonDependency(devDeps, ...patterns);
|
|
43659
44135
|
}
|
|
43660
44136
|
function detectGoTest(cwd) {
|
|
43661
|
-
return fs16.existsSync(
|
|
44137
|
+
return fs16.existsSync(path30.join(cwd, "go.mod")) && isCommandAvailable("go");
|
|
43662
44138
|
}
|
|
43663
44139
|
function detectJavaMaven(cwd) {
|
|
43664
|
-
return fs16.existsSync(
|
|
44140
|
+
return fs16.existsSync(path30.join(cwd, "pom.xml")) && isCommandAvailable("mvn");
|
|
43665
44141
|
}
|
|
43666
44142
|
function detectGradle(cwd) {
|
|
43667
|
-
const hasBuildFile = fs16.existsSync(
|
|
43668
|
-
const hasGradlew = fs16.existsSync(
|
|
44143
|
+
const hasBuildFile = fs16.existsSync(path30.join(cwd, "build.gradle")) || fs16.existsSync(path30.join(cwd, "build.gradle.kts"));
|
|
44144
|
+
const hasGradlew = fs16.existsSync(path30.join(cwd, "gradlew")) || fs16.existsSync(path30.join(cwd, "gradlew.bat"));
|
|
43669
44145
|
return hasBuildFile && (hasGradlew || isCommandAvailable("gradle"));
|
|
43670
44146
|
}
|
|
43671
44147
|
function detectDotnetTest(cwd) {
|
|
@@ -43678,30 +44154,30 @@ function detectDotnetTest(cwd) {
|
|
|
43678
44154
|
}
|
|
43679
44155
|
}
|
|
43680
44156
|
function detectCTest(cwd) {
|
|
43681
|
-
const hasSource = fs16.existsSync(
|
|
43682
|
-
const hasBuildCache = fs16.existsSync(
|
|
44157
|
+
const hasSource = fs16.existsSync(path30.join(cwd, "CMakeLists.txt"));
|
|
44158
|
+
const hasBuildCache = fs16.existsSync(path30.join(cwd, "CMakeCache.txt")) || fs16.existsSync(path30.join(cwd, "build", "CMakeCache.txt"));
|
|
43683
44159
|
return (hasSource || hasBuildCache) && isCommandAvailable("ctest");
|
|
43684
44160
|
}
|
|
43685
44161
|
function detectSwiftTest(cwd) {
|
|
43686
|
-
return fs16.existsSync(
|
|
44162
|
+
return fs16.existsSync(path30.join(cwd, "Package.swift")) && isCommandAvailable("swift");
|
|
43687
44163
|
}
|
|
43688
44164
|
function detectDartTest(cwd) {
|
|
43689
|
-
return fs16.existsSync(
|
|
44165
|
+
return fs16.existsSync(path30.join(cwd, "pubspec.yaml")) && (isCommandAvailable("dart") || isCommandAvailable("flutter"));
|
|
43690
44166
|
}
|
|
43691
44167
|
function detectRSpec(cwd) {
|
|
43692
|
-
const hasRSpecFile = fs16.existsSync(
|
|
43693
|
-
const hasGemfile = fs16.existsSync(
|
|
43694
|
-
const hasSpecDir = fs16.existsSync(
|
|
44168
|
+
const hasRSpecFile = fs16.existsSync(path30.join(cwd, ".rspec"));
|
|
44169
|
+
const hasGemfile = fs16.existsSync(path30.join(cwd, "Gemfile"));
|
|
44170
|
+
const hasSpecDir = fs16.existsSync(path30.join(cwd, "spec"));
|
|
43695
44171
|
const hasRSpec = hasRSpecFile || hasGemfile && hasSpecDir;
|
|
43696
44172
|
return hasRSpec && (isCommandAvailable("bundle") || isCommandAvailable("rspec"));
|
|
43697
44173
|
}
|
|
43698
44174
|
function detectMinitest(cwd) {
|
|
43699
|
-
return fs16.existsSync(
|
|
44175
|
+
return fs16.existsSync(path30.join(cwd, "test")) && (fs16.existsSync(path30.join(cwd, "Gemfile")) || fs16.existsSync(path30.join(cwd, "Rakefile"))) && isCommandAvailable("ruby");
|
|
43700
44176
|
}
|
|
43701
44177
|
async function detectTestFramework(cwd) {
|
|
43702
44178
|
const baseDir = cwd;
|
|
43703
44179
|
try {
|
|
43704
|
-
const packageJsonPath =
|
|
44180
|
+
const packageJsonPath = path30.join(baseDir, "package.json");
|
|
43705
44181
|
if (fs16.existsSync(packageJsonPath)) {
|
|
43706
44182
|
const content = fs16.readFileSync(packageJsonPath, "utf-8");
|
|
43707
44183
|
const pkg = JSON.parse(content);
|
|
@@ -43722,16 +44198,16 @@ async function detectTestFramework(cwd) {
|
|
|
43722
44198
|
return "jest";
|
|
43723
44199
|
if (hasDevDependency(devDeps, "mocha", "@types/mocha"))
|
|
43724
44200
|
return "mocha";
|
|
43725
|
-
if (fs16.existsSync(
|
|
44201
|
+
if (fs16.existsSync(path30.join(baseDir, "bun.lockb")) || fs16.existsSync(path30.join(baseDir, "bun.lock"))) {
|
|
43726
44202
|
if (scripts.test?.includes("bun"))
|
|
43727
44203
|
return "bun";
|
|
43728
44204
|
}
|
|
43729
44205
|
}
|
|
43730
44206
|
} catch {}
|
|
43731
44207
|
try {
|
|
43732
|
-
const pyprojectTomlPath =
|
|
43733
|
-
const setupCfgPath =
|
|
43734
|
-
const requirementsTxtPath =
|
|
44208
|
+
const pyprojectTomlPath = path30.join(baseDir, "pyproject.toml");
|
|
44209
|
+
const setupCfgPath = path30.join(baseDir, "setup.cfg");
|
|
44210
|
+
const requirementsTxtPath = path30.join(baseDir, "requirements.txt");
|
|
43735
44211
|
if (fs16.existsSync(pyprojectTomlPath)) {
|
|
43736
44212
|
const content = fs16.readFileSync(pyprojectTomlPath, "utf-8");
|
|
43737
44213
|
if (content.includes("[tool.pytest"))
|
|
@@ -43751,7 +44227,7 @@ async function detectTestFramework(cwd) {
|
|
|
43751
44227
|
}
|
|
43752
44228
|
} catch {}
|
|
43753
44229
|
try {
|
|
43754
|
-
const cargoTomlPath =
|
|
44230
|
+
const cargoTomlPath = path30.join(baseDir, "Cargo.toml");
|
|
43755
44231
|
if (fs16.existsSync(cargoTomlPath)) {
|
|
43756
44232
|
const content = fs16.readFileSync(cargoTomlPath, "utf-8");
|
|
43757
44233
|
if (content.includes("[dev-dependencies]")) {
|
|
@@ -43762,9 +44238,9 @@ async function detectTestFramework(cwd) {
|
|
|
43762
44238
|
}
|
|
43763
44239
|
} catch {}
|
|
43764
44240
|
try {
|
|
43765
|
-
const pesterConfigPath =
|
|
43766
|
-
const pesterConfigJsonPath =
|
|
43767
|
-
const pesterPs1Path =
|
|
44241
|
+
const pesterConfigPath = path30.join(baseDir, "pester.config.ps1");
|
|
44242
|
+
const pesterConfigJsonPath = path30.join(baseDir, "pester.config.ps1.json");
|
|
44243
|
+
const pesterPs1Path = path30.join(baseDir, "tests.ps1");
|
|
43768
44244
|
if (fs16.existsSync(pesterConfigPath) || fs16.existsSync(pesterConfigJsonPath) || fs16.existsSync(pesterPs1Path)) {
|
|
43769
44245
|
return "pester";
|
|
43770
44246
|
}
|
|
@@ -43793,12 +44269,12 @@ function isTestDirectoryPath(normalizedPath) {
|
|
|
43793
44269
|
return normalizedPath.split("/").some((segment) => TEST_DIRECTORY_NAMES.includes(segment));
|
|
43794
44270
|
}
|
|
43795
44271
|
function resolveWorkspacePath(file3, workingDir) {
|
|
43796
|
-
return
|
|
44272
|
+
return path30.isAbsolute(file3) ? path30.resolve(file3) : path30.resolve(workingDir, file3);
|
|
43797
44273
|
}
|
|
43798
44274
|
function toWorkspaceOutputPath(absolutePath, workingDir, preferRelative) {
|
|
43799
44275
|
if (!preferRelative)
|
|
43800
44276
|
return absolutePath;
|
|
43801
|
-
return
|
|
44277
|
+
return path30.relative(workingDir, absolutePath);
|
|
43802
44278
|
}
|
|
43803
44279
|
function dedupePush(target, value) {
|
|
43804
44280
|
if (!target.includes(value)) {
|
|
@@ -43835,18 +44311,18 @@ function buildLanguageSpecificTestNames(nameWithoutExt, ext) {
|
|
|
43835
44311
|
}
|
|
43836
44312
|
}
|
|
43837
44313
|
function getRepoLevelCandidateDirectories(workingDir, relativePath, ext) {
|
|
43838
|
-
const relativeDir =
|
|
44314
|
+
const relativeDir = path30.dirname(relativePath);
|
|
43839
44315
|
const nestedRelativeDir = relativeDir === "." ? "" : relativeDir;
|
|
43840
44316
|
const directories = TEST_DIRECTORY_NAMES.flatMap((dirName) => {
|
|
43841
|
-
const rootDir =
|
|
43842
|
-
return nestedRelativeDir ? [rootDir,
|
|
44317
|
+
const rootDir = path30.join(workingDir, dirName);
|
|
44318
|
+
return nestedRelativeDir ? [rootDir, path30.join(rootDir, nestedRelativeDir)] : [rootDir];
|
|
43843
44319
|
});
|
|
43844
44320
|
const normalizedRelativePath = relativePath.replace(/\\/g, "/");
|
|
43845
44321
|
if (ext === ".java" && normalizedRelativePath.startsWith("src/main/java/")) {
|
|
43846
|
-
directories.push(
|
|
44322
|
+
directories.push(path30.join(workingDir, "src/test/java", path30.dirname(normalizedRelativePath.slice("src/main/java/".length))));
|
|
43847
44323
|
}
|
|
43848
44324
|
if ((ext === ".kt" || ext === ".java") && normalizedRelativePath.startsWith("src/main/kotlin/")) {
|
|
43849
|
-
directories.push(
|
|
44325
|
+
directories.push(path30.join(workingDir, "src/test/kotlin", path30.dirname(normalizedRelativePath.slice("src/main/kotlin/".length))));
|
|
43850
44326
|
}
|
|
43851
44327
|
return [...new Set(directories)];
|
|
43852
44328
|
}
|
|
@@ -43874,23 +44350,23 @@ function isLanguageSpecificTestFile(basename5) {
|
|
|
43874
44350
|
}
|
|
43875
44351
|
function isConventionTestFilePath(filePath) {
|
|
43876
44352
|
const normalizedPath = filePath.replace(/\\/g, "/");
|
|
43877
|
-
const basename5 =
|
|
44353
|
+
const basename5 = path30.basename(filePath);
|
|
43878
44354
|
return hasCompoundTestExtension(basename5) || basename5.includes(".spec.") || basename5.includes(".test.") || isLanguageSpecificTestFile(basename5) || isTestDirectoryPath(normalizedPath);
|
|
43879
44355
|
}
|
|
43880
44356
|
function getTestFilesFromConvention(sourceFiles, workingDir = process.cwd()) {
|
|
43881
44357
|
const testFiles = [];
|
|
43882
44358
|
for (const file3 of sourceFiles) {
|
|
43883
44359
|
const absoluteFile = resolveWorkspacePath(file3, workingDir);
|
|
43884
|
-
const relativeFile =
|
|
43885
|
-
const basename5 =
|
|
43886
|
-
const
|
|
43887
|
-
const preferRelativeOutput = !
|
|
44360
|
+
const relativeFile = path30.relative(workingDir, absoluteFile);
|
|
44361
|
+
const basename5 = path30.basename(absoluteFile);
|
|
44362
|
+
const dirname13 = path30.dirname(absoluteFile);
|
|
44363
|
+
const preferRelativeOutput = !path30.isAbsolute(file3);
|
|
43888
44364
|
if (isConventionTestFilePath(relativeFile) || isConventionTestFilePath(file3)) {
|
|
43889
44365
|
dedupePush(testFiles, toWorkspaceOutputPath(absoluteFile, workingDir, preferRelativeOutput));
|
|
43890
44366
|
continue;
|
|
43891
44367
|
}
|
|
43892
44368
|
const nameWithoutExt = basename5.replace(/\.[^.]+$/, "");
|
|
43893
|
-
const ext =
|
|
44369
|
+
const ext = path30.extname(basename5);
|
|
43894
44370
|
const genericTestNames = [
|
|
43895
44371
|
`${nameWithoutExt}.spec${ext}`,
|
|
43896
44372
|
`${nameWithoutExt}.test${ext}`
|
|
@@ -43899,7 +44375,7 @@ function getTestFilesFromConvention(sourceFiles, workingDir = process.cwd()) {
|
|
|
43899
44375
|
const colocatedCandidates = [
|
|
43900
44376
|
...genericTestNames,
|
|
43901
44377
|
...languageSpecificTestNames
|
|
43902
|
-
].map((candidateName) =>
|
|
44378
|
+
].map((candidateName) => path30.join(dirname13, candidateName));
|
|
43903
44379
|
const testDirectoryNames = [
|
|
43904
44380
|
basename5,
|
|
43905
44381
|
...genericTestNames,
|
|
@@ -43908,8 +44384,8 @@ function getTestFilesFromConvention(sourceFiles, workingDir = process.cwd()) {
|
|
|
43908
44384
|
const repoLevelDirectories = getRepoLevelCandidateDirectories(workingDir, relativeFile, ext);
|
|
43909
44385
|
const possibleTestFiles = [
|
|
43910
44386
|
...colocatedCandidates,
|
|
43911
|
-
...TEST_DIRECTORY_NAMES.flatMap((dirName) => testDirectoryNames.map((candidateName) =>
|
|
43912
|
-
...repoLevelDirectories.flatMap((candidateDir) => testDirectoryNames.map((candidateName) =>
|
|
44387
|
+
...TEST_DIRECTORY_NAMES.flatMap((dirName) => testDirectoryNames.map((candidateName) => path30.join(dirname13, dirName, candidateName))),
|
|
44388
|
+
...repoLevelDirectories.flatMap((candidateDir) => testDirectoryNames.map((candidateName) => path30.join(candidateDir, candidateName)))
|
|
43913
44389
|
];
|
|
43914
44390
|
for (const testFile of possibleTestFiles) {
|
|
43915
44391
|
if (fs16.existsSync(testFile)) {
|
|
@@ -43930,7 +44406,7 @@ async function getTestFilesFromGraph(sourceFiles, workingDir) {
|
|
|
43930
44406
|
try {
|
|
43931
44407
|
const absoluteTestFile = resolveWorkspacePath(testFile, workingDir);
|
|
43932
44408
|
const content = fs16.readFileSync(absoluteTestFile, "utf-8");
|
|
43933
|
-
const testDir =
|
|
44409
|
+
const testDir = path30.dirname(absoluteTestFile);
|
|
43934
44410
|
const importRegex = /import\s+.*?\s+from\s+['"]([^'"]+)['"]/g;
|
|
43935
44411
|
let match;
|
|
43936
44412
|
match = importRegex.exec(content);
|
|
@@ -43938,8 +44414,8 @@ async function getTestFilesFromGraph(sourceFiles, workingDir) {
|
|
|
43938
44414
|
const importPath = match[1];
|
|
43939
44415
|
let resolvedImport;
|
|
43940
44416
|
if (importPath.startsWith(".")) {
|
|
43941
|
-
resolvedImport =
|
|
43942
|
-
const existingExt =
|
|
44417
|
+
resolvedImport = path30.resolve(testDir, importPath);
|
|
44418
|
+
const existingExt = path30.extname(resolvedImport);
|
|
43943
44419
|
if (!existingExt) {
|
|
43944
44420
|
for (const extToTry of [
|
|
43945
44421
|
".ts",
|
|
@@ -43959,12 +44435,12 @@ async function getTestFilesFromGraph(sourceFiles, workingDir) {
|
|
|
43959
44435
|
} else {
|
|
43960
44436
|
continue;
|
|
43961
44437
|
}
|
|
43962
|
-
const importBasename =
|
|
43963
|
-
const importDir =
|
|
44438
|
+
const importBasename = path30.basename(resolvedImport, path30.extname(resolvedImport));
|
|
44439
|
+
const importDir = path30.dirname(resolvedImport);
|
|
43964
44440
|
for (const sourceFile of absoluteSourceFiles) {
|
|
43965
|
-
const sourceDir =
|
|
43966
|
-
const sourceBasename =
|
|
43967
|
-
const isRelatedDir = importDir === sourceDir || importDir ===
|
|
44441
|
+
const sourceDir = path30.dirname(sourceFile);
|
|
44442
|
+
const sourceBasename = path30.basename(sourceFile, path30.extname(sourceFile));
|
|
44443
|
+
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
44444
|
if (resolvedImport === sourceFile || importBasename === sourceBasename && isRelatedDir) {
|
|
43969
44445
|
dedupePush(testFiles, testFile);
|
|
43970
44446
|
break;
|
|
@@ -43977,8 +44453,8 @@ async function getTestFilesFromGraph(sourceFiles, workingDir) {
|
|
|
43977
44453
|
while (match !== null) {
|
|
43978
44454
|
const importPath = match[1];
|
|
43979
44455
|
if (importPath.startsWith(".")) {
|
|
43980
|
-
let resolvedImport =
|
|
43981
|
-
const existingExt =
|
|
44456
|
+
let resolvedImport = path30.resolve(testDir, importPath);
|
|
44457
|
+
const existingExt = path30.extname(resolvedImport);
|
|
43982
44458
|
if (!existingExt) {
|
|
43983
44459
|
for (const extToTry of [
|
|
43984
44460
|
".ts",
|
|
@@ -43995,12 +44471,12 @@ async function getTestFilesFromGraph(sourceFiles, workingDir) {
|
|
|
43995
44471
|
}
|
|
43996
44472
|
}
|
|
43997
44473
|
}
|
|
43998
|
-
const importDir =
|
|
43999
|
-
const importBasename =
|
|
44474
|
+
const importDir = path30.dirname(resolvedImport);
|
|
44475
|
+
const importBasename = path30.basename(resolvedImport, path30.extname(resolvedImport));
|
|
44000
44476
|
for (const sourceFile of absoluteSourceFiles) {
|
|
44001
|
-
const sourceDir =
|
|
44002
|
-
const sourceBasename =
|
|
44003
|
-
const isRelatedDir = importDir === sourceDir || importDir ===
|
|
44477
|
+
const sourceDir = path30.dirname(sourceFile);
|
|
44478
|
+
const sourceBasename = path30.basename(sourceFile, path30.extname(sourceFile));
|
|
44479
|
+
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
44480
|
if (resolvedImport === sourceFile || importBasename === sourceBasename && isRelatedDir) {
|
|
44005
44481
|
dedupePush(testFiles, testFile);
|
|
44006
44482
|
break;
|
|
@@ -44103,8 +44579,8 @@ function buildTestCommand(framework, scope, files, coverage, baseDir) {
|
|
|
44103
44579
|
return ["mvn", "test"];
|
|
44104
44580
|
case "gradle": {
|
|
44105
44581
|
const isWindows = process.platform === "win32";
|
|
44106
|
-
const hasGradlewBat = fs16.existsSync(
|
|
44107
|
-
const hasGradlew = fs16.existsSync(
|
|
44582
|
+
const hasGradlewBat = fs16.existsSync(path30.join(baseDir, "gradlew.bat"));
|
|
44583
|
+
const hasGradlew = fs16.existsSync(path30.join(baseDir, "gradlew"));
|
|
44108
44584
|
if (hasGradlewBat && isWindows)
|
|
44109
44585
|
return ["gradlew.bat", "test"];
|
|
44110
44586
|
if (hasGradlew)
|
|
@@ -44121,7 +44597,7 @@ function buildTestCommand(framework, scope, files, coverage, baseDir) {
|
|
|
44121
44597
|
"cmake-build-release",
|
|
44122
44598
|
"out"
|
|
44123
44599
|
];
|
|
44124
|
-
const actualBuildDir = buildDirCandidates.find((d) => fs16.existsSync(
|
|
44600
|
+
const actualBuildDir = buildDirCandidates.find((d) => fs16.existsSync(path30.join(baseDir, d, "CMakeCache.txt"))) ?? "build";
|
|
44125
44601
|
return ["ctest", "--test-dir", actualBuildDir];
|
|
44126
44602
|
}
|
|
44127
44603
|
case "swift-test":
|
|
@@ -44774,7 +45250,7 @@ var init_test_runner = __esm(() => {
|
|
|
44774
45250
|
const sourceFiles = args.files.filter((file3) => {
|
|
44775
45251
|
if (directTestFiles.includes(file3))
|
|
44776
45252
|
return false;
|
|
44777
|
-
const ext =
|
|
45253
|
+
const ext = path30.extname(file3).toLowerCase();
|
|
44778
45254
|
return SOURCE_EXTENSIONS.has(ext);
|
|
44779
45255
|
});
|
|
44780
45256
|
const invalidFiles = args.files.filter((file3) => !directTestFiles.includes(file3) && !sourceFiles.includes(file3));
|
|
@@ -44809,7 +45285,7 @@ var init_test_runner = __esm(() => {
|
|
|
44809
45285
|
if (isConventionTestFilePath(f)) {
|
|
44810
45286
|
return false;
|
|
44811
45287
|
}
|
|
44812
|
-
const ext =
|
|
45288
|
+
const ext = path30.extname(f).toLowerCase();
|
|
44813
45289
|
return SOURCE_EXTENSIONS.has(ext);
|
|
44814
45290
|
});
|
|
44815
45291
|
if (sourceFiles.length === 0) {
|
|
@@ -44836,7 +45312,7 @@ var init_test_runner = __esm(() => {
|
|
|
44836
45312
|
if (isConventionTestFilePath(f)) {
|
|
44837
45313
|
return false;
|
|
44838
45314
|
}
|
|
44839
|
-
const ext =
|
|
45315
|
+
const ext = path30.extname(f).toLowerCase();
|
|
44840
45316
|
return SOURCE_EXTENSIONS.has(ext);
|
|
44841
45317
|
});
|
|
44842
45318
|
if (sourceFiles.length === 0) {
|
|
@@ -44854,8 +45330,8 @@ var init_test_runner = __esm(() => {
|
|
|
44854
45330
|
const impactResult = await analyzeImpact(sourceFiles, workingDir);
|
|
44855
45331
|
if (impactResult.impactedTests.length > 0) {
|
|
44856
45332
|
testFiles = impactResult.impactedTests.map((absPath) => {
|
|
44857
|
-
const relativePath =
|
|
44858
|
-
return
|
|
45333
|
+
const relativePath = path30.relative(workingDir, absPath);
|
|
45334
|
+
return path30.isAbsolute(relativePath) ? absPath : relativePath;
|
|
44859
45335
|
});
|
|
44860
45336
|
} else {
|
|
44861
45337
|
graphFallbackReason = "no impacted tests found via impact analysis, falling back to graph";
|
|
@@ -44931,7 +45407,7 @@ var init_test_runner = __esm(() => {
|
|
|
44931
45407
|
|
|
44932
45408
|
// src/services/preflight-service.ts
|
|
44933
45409
|
import * as fs17 from "fs";
|
|
44934
|
-
import * as
|
|
45410
|
+
import * as path31 from "path";
|
|
44935
45411
|
function validateDirectoryPath(dir) {
|
|
44936
45412
|
if (!dir || typeof dir !== "string") {
|
|
44937
45413
|
throw new Error("Directory path is required");
|
|
@@ -44939,8 +45415,8 @@ function validateDirectoryPath(dir) {
|
|
|
44939
45415
|
if (dir.includes("..")) {
|
|
44940
45416
|
throw new Error("Directory path must not contain path traversal sequences");
|
|
44941
45417
|
}
|
|
44942
|
-
const normalized =
|
|
44943
|
-
const absolutePath =
|
|
45418
|
+
const normalized = path31.normalize(dir);
|
|
45419
|
+
const absolutePath = path31.isAbsolute(normalized) ? normalized : path31.resolve(normalized);
|
|
44944
45420
|
return absolutePath;
|
|
44945
45421
|
}
|
|
44946
45422
|
function validateTimeout(timeoutMs, defaultValue) {
|
|
@@ -44963,7 +45439,7 @@ function validateTimeout(timeoutMs, defaultValue) {
|
|
|
44963
45439
|
}
|
|
44964
45440
|
function getPackageVersion(dir) {
|
|
44965
45441
|
try {
|
|
44966
|
-
const packagePath =
|
|
45442
|
+
const packagePath = path31.join(dir, "package.json");
|
|
44967
45443
|
if (fs17.existsSync(packagePath)) {
|
|
44968
45444
|
const content = fs17.readFileSync(packagePath, "utf-8");
|
|
44969
45445
|
const pkg = JSON.parse(content);
|
|
@@ -44974,7 +45450,7 @@ function getPackageVersion(dir) {
|
|
|
44974
45450
|
}
|
|
44975
45451
|
function getChangelogVersion(dir) {
|
|
44976
45452
|
try {
|
|
44977
|
-
const changelogPath =
|
|
45453
|
+
const changelogPath = path31.join(dir, "CHANGELOG.md");
|
|
44978
45454
|
if (fs17.existsSync(changelogPath)) {
|
|
44979
45455
|
const content = fs17.readFileSync(changelogPath, "utf-8");
|
|
44980
45456
|
const match = content.match(/^##\s*\[?(\d+\.\d+\.\d+)\]?/m);
|
|
@@ -44988,7 +45464,7 @@ function getChangelogVersion(dir) {
|
|
|
44988
45464
|
function getVersionFileVersion(dir) {
|
|
44989
45465
|
const possibleFiles = ["VERSION.txt", "version.txt", "VERSION", "version"];
|
|
44990
45466
|
for (const file3 of possibleFiles) {
|
|
44991
|
-
const filePath =
|
|
45467
|
+
const filePath = path31.join(dir, file3);
|
|
44992
45468
|
if (fs17.existsSync(filePath)) {
|
|
44993
45469
|
try {
|
|
44994
45470
|
const content = fs17.readFileSync(filePath, "utf-8").trim();
|
|
@@ -45004,9 +45480,9 @@ function getVersionFileVersion(dir) {
|
|
|
45004
45480
|
async function runVersionCheck(dir, _timeoutMs) {
|
|
45005
45481
|
const startTime = Date.now();
|
|
45006
45482
|
try {
|
|
45007
|
-
const packageVersion = getPackageVersion(dir);
|
|
45008
|
-
const changelogVersion = getChangelogVersion(dir);
|
|
45009
|
-
const versionFileVersion = getVersionFileVersion(dir);
|
|
45483
|
+
const packageVersion = _internals18.getPackageVersion(dir);
|
|
45484
|
+
const changelogVersion = _internals18.getChangelogVersion(dir);
|
|
45485
|
+
const versionFileVersion = _internals18.getVersionFileVersion(dir);
|
|
45010
45486
|
const versions3 = [];
|
|
45011
45487
|
if (packageVersion)
|
|
45012
45488
|
versions3.push(`package.json: ${packageVersion}`);
|
|
@@ -45315,7 +45791,7 @@ async function runEvidenceCheck(dir) {
|
|
|
45315
45791
|
async function runRequirementCoverageCheck(dir, currentPhase) {
|
|
45316
45792
|
const startTime = Date.now();
|
|
45317
45793
|
try {
|
|
45318
|
-
const specPath =
|
|
45794
|
+
const specPath = path31.join(dir, ".swarm", "spec.md");
|
|
45319
45795
|
if (!fs17.existsSync(specPath)) {
|
|
45320
45796
|
return {
|
|
45321
45797
|
type: "req_coverage",
|
|
@@ -45356,7 +45832,7 @@ async function runPreflight(dir, phase, config3) {
|
|
|
45356
45832
|
const reportId = `preflight-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
|
|
45357
45833
|
let validatedDir;
|
|
45358
45834
|
try {
|
|
45359
|
-
validatedDir = validateDirectoryPath(dir);
|
|
45835
|
+
validatedDir = _internals18.validateDirectoryPath(dir);
|
|
45360
45836
|
} catch (error93) {
|
|
45361
45837
|
return {
|
|
45362
45838
|
id: reportId,
|
|
@@ -45376,7 +45852,7 @@ async function runPreflight(dir, phase, config3) {
|
|
|
45376
45852
|
}
|
|
45377
45853
|
let validatedTimeout;
|
|
45378
45854
|
try {
|
|
45379
|
-
validatedTimeout = validateTimeout(config3?.checkTimeoutMs, DEFAULT_CONFIG.checkTimeoutMs);
|
|
45855
|
+
validatedTimeout = _internals18.validateTimeout(config3?.checkTimeoutMs, DEFAULT_CONFIG.checkTimeoutMs);
|
|
45380
45856
|
} catch (error93) {
|
|
45381
45857
|
return {
|
|
45382
45858
|
id: reportId,
|
|
@@ -45417,12 +45893,12 @@ async function runPreflight(dir, phase, config3) {
|
|
|
45417
45893
|
});
|
|
45418
45894
|
const checks5 = [];
|
|
45419
45895
|
log("[Preflight] Running lint check...");
|
|
45420
|
-
const lintResult = await runLintCheck(validatedDir, cfg.linter, cfg.checkTimeoutMs);
|
|
45896
|
+
const lintResult = await _internals18.runLintCheck(validatedDir, cfg.linter, cfg.checkTimeoutMs);
|
|
45421
45897
|
checks5.push(lintResult);
|
|
45422
45898
|
log(`[Preflight] Lint check: ${lintResult.status} ${lintResult.message}`);
|
|
45423
45899
|
if (!cfg.skipTests) {
|
|
45424
45900
|
log("[Preflight] Running tests check...");
|
|
45425
|
-
const testsResult = await runTestsCheck(validatedDir, cfg.testScope, cfg.checkTimeoutMs);
|
|
45901
|
+
const testsResult = await _internals18.runTestsCheck(validatedDir, cfg.testScope, cfg.checkTimeoutMs);
|
|
45426
45902
|
checks5.push(testsResult);
|
|
45427
45903
|
log(`[Preflight] Tests check: ${testsResult.status} ${testsResult.message}`);
|
|
45428
45904
|
} else {
|
|
@@ -45434,7 +45910,7 @@ async function runPreflight(dir, phase, config3) {
|
|
|
45434
45910
|
}
|
|
45435
45911
|
if (!cfg.skipSecrets) {
|
|
45436
45912
|
log("[Preflight] Running secrets check...");
|
|
45437
|
-
const secretsResult = await runSecretsCheck(validatedDir, cfg.checkTimeoutMs);
|
|
45913
|
+
const secretsResult = await _internals18.runSecretsCheck(validatedDir, cfg.checkTimeoutMs);
|
|
45438
45914
|
checks5.push(secretsResult);
|
|
45439
45915
|
log(`[Preflight] Secrets check: ${secretsResult.status} ${secretsResult.message}`);
|
|
45440
45916
|
} else {
|
|
@@ -45446,7 +45922,7 @@ async function runPreflight(dir, phase, config3) {
|
|
|
45446
45922
|
}
|
|
45447
45923
|
if (!cfg.skipEvidence) {
|
|
45448
45924
|
log("[Preflight] Running evidence check...");
|
|
45449
|
-
const evidenceResult = await runEvidenceCheck(validatedDir);
|
|
45925
|
+
const evidenceResult = await _internals18.runEvidenceCheck(validatedDir);
|
|
45450
45926
|
checks5.push(evidenceResult);
|
|
45451
45927
|
log(`[Preflight] Evidence check: ${evidenceResult.status} ${evidenceResult.message}`);
|
|
45452
45928
|
} else {
|
|
@@ -45457,12 +45933,12 @@ async function runPreflight(dir, phase, config3) {
|
|
|
45457
45933
|
});
|
|
45458
45934
|
}
|
|
45459
45935
|
log("[Preflight] Running requirement coverage check...");
|
|
45460
|
-
const reqCoverageResult = await runRequirementCoverageCheck(validatedDir, phase);
|
|
45936
|
+
const reqCoverageResult = await _internals18.runRequirementCoverageCheck(validatedDir, phase);
|
|
45461
45937
|
checks5.push(reqCoverageResult);
|
|
45462
45938
|
log(`[Preflight] Requirement coverage check: ${reqCoverageResult.status} ${reqCoverageResult.message}`);
|
|
45463
45939
|
if (!cfg.skipVersion) {
|
|
45464
45940
|
log("[Preflight] Running version check...");
|
|
45465
|
-
const versionResult = await runVersionCheck(validatedDir, cfg.checkTimeoutMs);
|
|
45941
|
+
const versionResult = await _internals18.runVersionCheck(validatedDir, cfg.checkTimeoutMs);
|
|
45466
45942
|
checks5.push(versionResult);
|
|
45467
45943
|
log(`[Preflight] Version check: ${versionResult.status} ${versionResult.message}`);
|
|
45468
45944
|
} else {
|
|
@@ -45525,10 +46001,10 @@ function formatPreflightMarkdown(report) {
|
|
|
45525
46001
|
async function handlePreflightCommand(directory, _args) {
|
|
45526
46002
|
const plan = await loadPlan(directory);
|
|
45527
46003
|
const phase = plan?.current_phase ?? 1;
|
|
45528
|
-
const report = await runPreflight(directory, phase);
|
|
45529
|
-
return formatPreflightMarkdown(report);
|
|
46004
|
+
const report = await _internals18.runPreflight(directory, phase);
|
|
46005
|
+
return _internals18.formatPreflightMarkdown(report);
|
|
45530
46006
|
}
|
|
45531
|
-
var MIN_CHECK_TIMEOUT_MS = 5000, MAX_CHECK_TIMEOUT_MS = 300000, DEFAULT_CONFIG;
|
|
46007
|
+
var MIN_CHECK_TIMEOUT_MS = 5000, MAX_CHECK_TIMEOUT_MS = 300000, DEFAULT_CONFIG, _internals18;
|
|
45532
46008
|
var init_preflight_service = __esm(() => {
|
|
45533
46009
|
init_manager2();
|
|
45534
46010
|
init_manager();
|
|
@@ -45545,6 +46021,22 @@ var init_preflight_service = __esm(() => {
|
|
|
45545
46021
|
testScope: "convention",
|
|
45546
46022
|
linter: "biome"
|
|
45547
46023
|
};
|
|
46024
|
+
_internals18 = {
|
|
46025
|
+
runPreflight,
|
|
46026
|
+
formatPreflightMarkdown,
|
|
46027
|
+
handlePreflightCommand,
|
|
46028
|
+
validateDirectoryPath,
|
|
46029
|
+
validateTimeout,
|
|
46030
|
+
getPackageVersion,
|
|
46031
|
+
getChangelogVersion,
|
|
46032
|
+
getVersionFileVersion,
|
|
46033
|
+
runVersionCheck,
|
|
46034
|
+
runLintCheck,
|
|
46035
|
+
runTestsCheck,
|
|
46036
|
+
runSecretsCheck,
|
|
46037
|
+
runEvidenceCheck,
|
|
46038
|
+
runRequirementCoverageCheck
|
|
46039
|
+
};
|
|
45548
46040
|
});
|
|
45549
46041
|
|
|
45550
46042
|
// src/commands/preflight.ts
|
|
@@ -46418,7 +46910,7 @@ var init_manager3 = __esm(() => {
|
|
|
46418
46910
|
|
|
46419
46911
|
// src/commands/reset.ts
|
|
46420
46912
|
import * as fs18 from "fs";
|
|
46421
|
-
import * as
|
|
46913
|
+
import * as path32 from "path";
|
|
46422
46914
|
async function handleResetCommand(directory, args) {
|
|
46423
46915
|
const hasConfirm = args.includes("--confirm");
|
|
46424
46916
|
if (!hasConfirm) {
|
|
@@ -46458,7 +46950,7 @@ async function handleResetCommand(directory, args) {
|
|
|
46458
46950
|
}
|
|
46459
46951
|
for (const filename of ["SWARM_PLAN.md", "SWARM_PLAN.json"]) {
|
|
46460
46952
|
try {
|
|
46461
|
-
const rootPath =
|
|
46953
|
+
const rootPath = path32.join(directory, filename);
|
|
46462
46954
|
if (fs18.existsSync(rootPath)) {
|
|
46463
46955
|
fs18.unlinkSync(rootPath);
|
|
46464
46956
|
results.push(`- \u2705 Deleted ${filename} (root)`);
|
|
@@ -46498,7 +46990,7 @@ var init_reset = __esm(() => {
|
|
|
46498
46990
|
|
|
46499
46991
|
// src/commands/reset-session.ts
|
|
46500
46992
|
import * as fs19 from "fs";
|
|
46501
|
-
import * as
|
|
46993
|
+
import * as path33 from "path";
|
|
46502
46994
|
async function handleResetSessionCommand(directory, _args) {
|
|
46503
46995
|
const results = [];
|
|
46504
46996
|
try {
|
|
@@ -46513,13 +47005,13 @@ async function handleResetSessionCommand(directory, _args) {
|
|
|
46513
47005
|
results.push("\u274C Failed to delete state.json");
|
|
46514
47006
|
}
|
|
46515
47007
|
try {
|
|
46516
|
-
const sessionDir =
|
|
47008
|
+
const sessionDir = path33.dirname(validateSwarmPath(directory, "session/state.json"));
|
|
46517
47009
|
if (fs19.existsSync(sessionDir)) {
|
|
46518
47010
|
const files = fs19.readdirSync(sessionDir);
|
|
46519
47011
|
const otherFiles = files.filter((f) => f !== "state.json");
|
|
46520
47012
|
let deletedCount = 0;
|
|
46521
47013
|
for (const file3 of otherFiles) {
|
|
46522
|
-
const filePath =
|
|
47014
|
+
const filePath = path33.join(sessionDir, file3);
|
|
46523
47015
|
if (fs19.lstatSync(filePath).isFile()) {
|
|
46524
47016
|
fs19.unlinkSync(filePath);
|
|
46525
47017
|
deletedCount++;
|
|
@@ -46551,7 +47043,7 @@ var init_reset_session = __esm(() => {
|
|
|
46551
47043
|
});
|
|
46552
47044
|
|
|
46553
47045
|
// src/summaries/manager.ts
|
|
46554
|
-
import * as
|
|
47046
|
+
import * as path34 from "path";
|
|
46555
47047
|
function sanitizeSummaryId(id) {
|
|
46556
47048
|
if (!id || id.length === 0) {
|
|
46557
47049
|
throw new Error("Invalid summary ID: empty string");
|
|
@@ -46574,7 +47066,7 @@ function sanitizeSummaryId(id) {
|
|
|
46574
47066
|
}
|
|
46575
47067
|
async function loadFullOutput(directory, id) {
|
|
46576
47068
|
const sanitizedId = sanitizeSummaryId(id);
|
|
46577
|
-
const relativePath =
|
|
47069
|
+
const relativePath = path34.join("summaries", `${sanitizedId}.json`);
|
|
46578
47070
|
validateSwarmPath(directory, relativePath);
|
|
46579
47071
|
const content = await readSwarmFileAsync(directory, relativePath);
|
|
46580
47072
|
if (content === null) {
|
|
@@ -46637,7 +47129,7 @@ var init_retrieve = __esm(() => {
|
|
|
46637
47129
|
|
|
46638
47130
|
// src/commands/rollback.ts
|
|
46639
47131
|
import * as fs20 from "fs";
|
|
46640
|
-
import * as
|
|
47132
|
+
import * as path35 from "path";
|
|
46641
47133
|
async function handleRollbackCommand(directory, args) {
|
|
46642
47134
|
const phaseArg = args[0];
|
|
46643
47135
|
if (!phaseArg) {
|
|
@@ -46702,8 +47194,8 @@ async function handleRollbackCommand(directory, args) {
|
|
|
46702
47194
|
if (EXCLUDE_FILES.has(file3) || file3.startsWith("plan-ledger.archived-")) {
|
|
46703
47195
|
continue;
|
|
46704
47196
|
}
|
|
46705
|
-
const src =
|
|
46706
|
-
const dest =
|
|
47197
|
+
const src = path35.join(checkpointDir, file3);
|
|
47198
|
+
const dest = path35.join(swarmDir, file3);
|
|
46707
47199
|
try {
|
|
46708
47200
|
fs20.cpSync(src, dest, { recursive: true, force: true });
|
|
46709
47201
|
successes.push(file3);
|
|
@@ -46722,12 +47214,12 @@ async function handleRollbackCommand(directory, args) {
|
|
|
46722
47214
|
].join(`
|
|
46723
47215
|
`);
|
|
46724
47216
|
}
|
|
46725
|
-
const existingLedgerPath =
|
|
47217
|
+
const existingLedgerPath = path35.join(swarmDir, "plan-ledger.jsonl");
|
|
46726
47218
|
if (fs20.existsSync(existingLedgerPath)) {
|
|
46727
47219
|
fs20.unlinkSync(existingLedgerPath);
|
|
46728
47220
|
}
|
|
46729
47221
|
try {
|
|
46730
|
-
const planJsonPath =
|
|
47222
|
+
const planJsonPath = path35.join(swarmDir, "plan.json");
|
|
46731
47223
|
if (fs20.existsSync(planJsonPath)) {
|
|
46732
47224
|
const planRaw = fs20.readFileSync(planJsonPath, "utf-8");
|
|
46733
47225
|
const plan = PlanSchema.parse(JSON.parse(planRaw));
|
|
@@ -46805,9 +47297,9 @@ async function handleSimulateCommand(directory, args) {
|
|
|
46805
47297
|
const report = reportLines.filter(Boolean).join(`
|
|
46806
47298
|
`);
|
|
46807
47299
|
const fs21 = await import("fs/promises");
|
|
46808
|
-
const
|
|
46809
|
-
const reportPath =
|
|
46810
|
-
await fs21.mkdir(
|
|
47300
|
+
const path36 = await import("path");
|
|
47301
|
+
const reportPath = path36.join(directory, ".swarm", "simulate-report.md");
|
|
47302
|
+
await fs21.mkdir(path36.dirname(reportPath), { recursive: true });
|
|
46811
47303
|
await fs21.writeFile(reportPath, report, "utf-8");
|
|
46812
47304
|
return `${darkMatterPairs.length} hidden coupling pairs detected`;
|
|
46813
47305
|
}
|
|
@@ -46982,6 +47474,7 @@ async function handleStatusCommand(directory, agents) {
|
|
|
46982
47474
|
return formatStatusMarkdown(statusData);
|
|
46983
47475
|
}
|
|
46984
47476
|
var init_status_service = __esm(() => {
|
|
47477
|
+
init_extractors();
|
|
46985
47478
|
init_utils2();
|
|
46986
47479
|
init_manager();
|
|
46987
47480
|
init_state();
|
|
@@ -47161,7 +47654,7 @@ __export(exports_commands, {
|
|
|
47161
47654
|
COMMAND_REGISTRY: () => COMMAND_REGISTRY
|
|
47162
47655
|
});
|
|
47163
47656
|
import fs21 from "fs";
|
|
47164
|
-
import
|
|
47657
|
+
import path36 from "path";
|
|
47165
47658
|
function buildHelpText() {
|
|
47166
47659
|
const lines = ["## Swarm Commands", ""];
|
|
47167
47660
|
const CATEGORIES = [
|
|
@@ -47270,9 +47763,9 @@ function createSwarmCommandHandler(directory, agents) {
|
|
|
47270
47763
|
return;
|
|
47271
47764
|
}
|
|
47272
47765
|
let isFirstRun = false;
|
|
47273
|
-
const sentinelPath =
|
|
47766
|
+
const sentinelPath = path36.join(directory, ".swarm", ".first-run-complete");
|
|
47274
47767
|
try {
|
|
47275
|
-
const swarmDir =
|
|
47768
|
+
const swarmDir = path36.join(directory, ".swarm");
|
|
47276
47769
|
fs21.mkdirSync(swarmDir, { recursive: true });
|
|
47277
47770
|
fs21.writeFileSync(sentinelPath, `first-run-complete: ${new Date().toISOString()}
|
|
47278
47771
|
`, { flag: "wx" });
|
|
@@ -47387,7 +47880,7 @@ function findSimilarCommands(query) {
|
|
|
47387
47880
|
return cmd.toLowerCase().includes(q) || q.includes(cmd.toLowerCase());
|
|
47388
47881
|
}).map((cmd) => ({
|
|
47389
47882
|
cmd,
|
|
47390
|
-
score: cmd.length < q.length ? q.length - cmd.length : levenshteinDistance(q, cmd)
|
|
47883
|
+
score: cmd.length < q.length ? q.length - cmd.length : _internals19.levenshteinDistance(q, cmd)
|
|
47391
47884
|
}));
|
|
47392
47885
|
scored.sort((a, b) => a.score - b.score);
|
|
47393
47886
|
return scored.slice(0, 3).map((s) => s.cmd);
|
|
@@ -47417,11 +47910,11 @@ async function handleHelpCommand(ctx) {
|
|
|
47417
47910
|
return buildHelpText2();
|
|
47418
47911
|
}
|
|
47419
47912
|
const tokens = targetCommand.split(/\s+/);
|
|
47420
|
-
const resolved = resolveCommand(tokens);
|
|
47913
|
+
const resolved = _internals19.resolveCommand(tokens);
|
|
47421
47914
|
if (resolved) {
|
|
47422
|
-
return buildDetailedHelp(resolved.key, resolved.entry);
|
|
47915
|
+
return _internals19.buildDetailedHelp(resolved.key, resolved.entry);
|
|
47423
47916
|
}
|
|
47424
|
-
const similar = findSimilarCommands(targetCommand);
|
|
47917
|
+
const similar = _internals19.findSimilarCommands(targetCommand);
|
|
47425
47918
|
const { buildHelpText: fullHelp } = await Promise.resolve().then(() => (init_commands(), exports_commands));
|
|
47426
47919
|
if (similar.length > 0) {
|
|
47427
47920
|
return `Command '/swarm ${targetCommand}' not found.
|
|
@@ -47457,24 +47950,24 @@ function validateAliases() {
|
|
|
47457
47950
|
}
|
|
47458
47951
|
aliasTargets.get(target).push(name);
|
|
47459
47952
|
const visited = new Set;
|
|
47460
|
-
const
|
|
47953
|
+
const path37 = [];
|
|
47461
47954
|
let current = target;
|
|
47462
47955
|
while (current) {
|
|
47463
47956
|
const currentEntry = COMMAND_REGISTRY[current];
|
|
47464
47957
|
if (!currentEntry)
|
|
47465
47958
|
break;
|
|
47466
47959
|
if (visited.has(current)) {
|
|
47467
|
-
const cycleStart =
|
|
47960
|
+
const cycleStart = path37.indexOf(current);
|
|
47468
47961
|
const fullChain = [
|
|
47469
47962
|
name,
|
|
47470
|
-
...
|
|
47963
|
+
...path37.slice(0, cycleStart > 0 ? cycleStart : path37.length),
|
|
47471
47964
|
current
|
|
47472
47965
|
].join(" \u2192 ");
|
|
47473
47966
|
errors5.push(`Circular alias detected: ${fullChain}`);
|
|
47474
47967
|
break;
|
|
47475
47968
|
}
|
|
47476
47969
|
visited.add(current);
|
|
47477
|
-
|
|
47970
|
+
path37.push(current);
|
|
47478
47971
|
current = currentEntry.aliasOf || "";
|
|
47479
47972
|
}
|
|
47480
47973
|
}
|
|
@@ -47515,7 +48008,7 @@ function resolveCommand(tokens) {
|
|
|
47515
48008
|
}
|
|
47516
48009
|
return null;
|
|
47517
48010
|
}
|
|
47518
|
-
var COMMAND_REGISTRY, VALID_COMMANDS, validation;
|
|
48011
|
+
var COMMAND_REGISTRY, VALID_COMMANDS, _internals19, validation;
|
|
47519
48012
|
var init_registry = __esm(() => {
|
|
47520
48013
|
init_acknowledge_spec_drift();
|
|
47521
48014
|
init_agents();
|
|
@@ -47576,7 +48069,7 @@ var init_registry = __esm(() => {
|
|
|
47576
48069
|
clashesWithNativeCcCommand: "/agents"
|
|
47577
48070
|
},
|
|
47578
48071
|
help: {
|
|
47579
|
-
handler: (ctx) => handleHelpCommand(ctx),
|
|
48072
|
+
handler: (ctx) => _internals19.handleHelpCommand(ctx),
|
|
47580
48073
|
description: "Show help for swarm commands",
|
|
47581
48074
|
category: "core",
|
|
47582
48075
|
args: "[command]",
|
|
@@ -47906,7 +48399,15 @@ var init_registry = __esm(() => {
|
|
|
47906
48399
|
}
|
|
47907
48400
|
};
|
|
47908
48401
|
VALID_COMMANDS = Object.keys(COMMAND_REGISTRY);
|
|
47909
|
-
|
|
48402
|
+
_internals19 = {
|
|
48403
|
+
handleHelpCommand,
|
|
48404
|
+
validateAliases,
|
|
48405
|
+
resolveCommand,
|
|
48406
|
+
levenshteinDistance,
|
|
48407
|
+
findSimilarCommands,
|
|
48408
|
+
buildDetailedHelp
|
|
48409
|
+
};
|
|
48410
|
+
validation = _internals19.validateAliases();
|
|
47910
48411
|
if (!validation.valid) {
|
|
47911
48412
|
throw new Error(`COMMAND_REGISTRY alias validation failed:
|
|
47912
48413
|
${validation.errors.join(`
|
|
@@ -47926,53 +48427,53 @@ init_cache_paths();
|
|
|
47926
48427
|
init_constants();
|
|
47927
48428
|
import * as fs22 from "fs";
|
|
47928
48429
|
import * as os7 from "os";
|
|
47929
|
-
import * as
|
|
48430
|
+
import * as path37 from "path";
|
|
47930
48431
|
var { version: version4 } = package_default;
|
|
47931
48432
|
var CONFIG_DIR = getPluginConfigDir();
|
|
47932
|
-
var OPENCODE_CONFIG_PATH =
|
|
47933
|
-
var PLUGIN_CONFIG_PATH =
|
|
47934
|
-
var PROMPTS_DIR =
|
|
48433
|
+
var OPENCODE_CONFIG_PATH = path37.join(CONFIG_DIR, "opencode.json");
|
|
48434
|
+
var PLUGIN_CONFIG_PATH = path37.join(CONFIG_DIR, "opencode-swarm.json");
|
|
48435
|
+
var PROMPTS_DIR = path37.join(CONFIG_DIR, "opencode-swarm");
|
|
47935
48436
|
var OPENCODE_PLUGIN_CACHE_PATHS = getPluginCachePaths();
|
|
47936
48437
|
var OPENCODE_PLUGIN_LOCK_FILE_PATHS = getPluginLockFilePaths();
|
|
47937
48438
|
function isSafeCachePath(p) {
|
|
47938
|
-
const resolved =
|
|
47939
|
-
const home =
|
|
48439
|
+
const resolved = path37.resolve(p);
|
|
48440
|
+
const home = path37.resolve(os7.homedir());
|
|
47940
48441
|
if (resolved === "/" || resolved === home || resolved.length <= home.length) {
|
|
47941
48442
|
return false;
|
|
47942
48443
|
}
|
|
47943
|
-
const segments = resolved.split(
|
|
48444
|
+
const segments = resolved.split(path37.sep).filter((s) => s.length > 0);
|
|
47944
48445
|
if (segments.length < 4) {
|
|
47945
48446
|
return false;
|
|
47946
48447
|
}
|
|
47947
|
-
const leaf =
|
|
48448
|
+
const leaf = path37.basename(resolved);
|
|
47948
48449
|
if (leaf !== "opencode-swarm@latest" && leaf !== "opencode-swarm") {
|
|
47949
48450
|
return false;
|
|
47950
48451
|
}
|
|
47951
|
-
const parent =
|
|
48452
|
+
const parent = path37.basename(path37.dirname(resolved));
|
|
47952
48453
|
if (parent !== "packages" && parent !== "node_modules") {
|
|
47953
48454
|
return false;
|
|
47954
48455
|
}
|
|
47955
|
-
const grandparent =
|
|
48456
|
+
const grandparent = path37.basename(path37.dirname(path37.dirname(resolved)));
|
|
47956
48457
|
if (grandparent !== "opencode") {
|
|
47957
48458
|
return false;
|
|
47958
48459
|
}
|
|
47959
48460
|
return true;
|
|
47960
48461
|
}
|
|
47961
48462
|
function isSafeLockFilePath(p) {
|
|
47962
|
-
const resolved =
|
|
47963
|
-
const home =
|
|
48463
|
+
const resolved = path37.resolve(p);
|
|
48464
|
+
const home = path37.resolve(os7.homedir());
|
|
47964
48465
|
if (resolved === "/" || resolved === home || resolved.length <= home.length) {
|
|
47965
48466
|
return false;
|
|
47966
48467
|
}
|
|
47967
|
-
const segments = resolved.split(
|
|
48468
|
+
const segments = resolved.split(path37.sep).filter((s) => s.length > 0);
|
|
47968
48469
|
if (segments.length < 4) {
|
|
47969
48470
|
return false;
|
|
47970
48471
|
}
|
|
47971
|
-
const leaf =
|
|
48472
|
+
const leaf = path37.basename(resolved);
|
|
47972
48473
|
if (leaf !== "bun.lock" && leaf !== "bun.lockb" && leaf !== "package-lock.json") {
|
|
47973
48474
|
return false;
|
|
47974
48475
|
}
|
|
47975
|
-
const parent =
|
|
48476
|
+
const parent = path37.basename(path37.dirname(resolved));
|
|
47976
48477
|
if (parent !== "opencode") {
|
|
47977
48478
|
return false;
|
|
47978
48479
|
}
|
|
@@ -47998,8 +48499,8 @@ function saveJson(filepath, data) {
|
|
|
47998
48499
|
}
|
|
47999
48500
|
function writeProjectConfigIfMissing(cwd) {
|
|
48000
48501
|
try {
|
|
48001
|
-
const opencodeDir =
|
|
48002
|
-
const projectConfigPath =
|
|
48502
|
+
const opencodeDir = path37.join(cwd, ".opencode");
|
|
48503
|
+
const projectConfigPath = path37.join(opencodeDir, "opencode-swarm.json");
|
|
48003
48504
|
if (fs22.existsSync(projectConfigPath)) {
|
|
48004
48505
|
return;
|
|
48005
48506
|
}
|
|
@@ -48020,7 +48521,7 @@ async function install() {
|
|
|
48020
48521
|
`);
|
|
48021
48522
|
ensureDir(CONFIG_DIR);
|
|
48022
48523
|
ensureDir(PROMPTS_DIR);
|
|
48023
|
-
const LEGACY_CONFIG_PATH =
|
|
48524
|
+
const LEGACY_CONFIG_PATH = path37.join(CONFIG_DIR, "config.json");
|
|
48024
48525
|
let opencodeConfig = loadJson(OPENCODE_CONFIG_PATH);
|
|
48025
48526
|
if (!opencodeConfig) {
|
|
48026
48527
|
const legacyConfig = loadJson(LEGACY_CONFIG_PATH);
|