opencode-swarm 6.74.1 → 6.75.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/__tests__/evidence-lock.adversarial.test.d.ts +8 -0
- package/dist/__tests__/evidence-lock.test.d.ts +6 -0
- package/dist/__tests__/gate-evidence.adversarial.test.d.ts +7 -0
- package/dist/cli/index.js +1324 -1123
- package/dist/config/schema.d.ts +11 -0
- package/dist/evidence/lock.d.ts +36 -0
- package/dist/index.js +5137 -4981
- package/dist/parallel/dispatcher/index.d.ts +2 -0
- package/dist/parallel/dispatcher/noop-dispatcher.d.ts +18 -0
- package/dist/parallel/dispatcher/noop-dispatcher.test.d.ts +10 -0
- package/dist/parallel/dispatcher/types.d.ts +33 -0
- package/dist/parallel/index.d.ts +1 -0
- package/dist/plan/manager.cas-backoff.test.d.ts +10 -0
- package/dist/plan/manager.d.ts +17 -0
- package/dist/state/agent-run-context.d.ts +24 -0
- package/dist/state.agent-run-context.test.d.ts +10 -0
- package/dist/state.d.ts +16 -2
- package/dist/telemetry.d.ts +1 -1
- package/package.json +1 -1
package/dist/cli/index.js
CHANGED
|
@@ -14063,6 +14063,36 @@ var init_plan_schema = __esm(() => {
|
|
|
14063
14063
|
});
|
|
14064
14064
|
});
|
|
14065
14065
|
|
|
14066
|
+
// src/telemetry.ts
|
|
14067
|
+
import * as os from "os";
|
|
14068
|
+
function emit(event, data) {
|
|
14069
|
+
try {
|
|
14070
|
+
if (_disabled || _writeStream === null) {
|
|
14071
|
+
return;
|
|
14072
|
+
}
|
|
14073
|
+
const line = JSON.stringify({
|
|
14074
|
+
timestamp: new Date().toISOString(),
|
|
14075
|
+
event,
|
|
14076
|
+
...data
|
|
14077
|
+
}) + os.EOL;
|
|
14078
|
+
_writeStream.write(line, (err) => {
|
|
14079
|
+
if (err) {
|
|
14080
|
+
_disabled = true;
|
|
14081
|
+
_writeStream = null;
|
|
14082
|
+
}
|
|
14083
|
+
});
|
|
14084
|
+
for (const listener of _listeners) {
|
|
14085
|
+
try {
|
|
14086
|
+
listener(event, data);
|
|
14087
|
+
} catch {}
|
|
14088
|
+
}
|
|
14089
|
+
} catch {}
|
|
14090
|
+
}
|
|
14091
|
+
var _writeStream = null, _listeners, _disabled = false;
|
|
14092
|
+
var init_telemetry = __esm(() => {
|
|
14093
|
+
_listeners = [];
|
|
14094
|
+
});
|
|
14095
|
+
|
|
14066
14096
|
// src/utils/spec-hash.ts
|
|
14067
14097
|
import { createHash } from "crypto";
|
|
14068
14098
|
import { readFile } from "fs/promises";
|
|
@@ -14275,34 +14305,6 @@ async function appendLedgerEvent(directory, eventInput, options) {
|
|
|
14275
14305
|
fs.renameSync(tempPath, ledgerPath);
|
|
14276
14306
|
return event;
|
|
14277
14307
|
}
|
|
14278
|
-
async function appendLedgerEventWithRetry(directory, eventInput, options) {
|
|
14279
|
-
const maxRetries = options.maxRetries ?? 3;
|
|
14280
|
-
const backoffBase = options.backoffMs ?? 10;
|
|
14281
|
-
let currentExpected = options.expectedHash;
|
|
14282
|
-
let attempt = 0;
|
|
14283
|
-
while (true) {
|
|
14284
|
-
try {
|
|
14285
|
-
return await appendLedgerEvent(directory, eventInput, {
|
|
14286
|
-
expectedHash: currentExpected,
|
|
14287
|
-
planHashAfter: options.planHashAfter
|
|
14288
|
-
});
|
|
14289
|
-
} catch (error49) {
|
|
14290
|
-
if (!(error49 instanceof LedgerStaleWriterError) || attempt >= maxRetries) {
|
|
14291
|
-
throw error49;
|
|
14292
|
-
}
|
|
14293
|
-
attempt++;
|
|
14294
|
-
const delayMs = backoffBase * 2 ** (attempt - 1);
|
|
14295
|
-
await new Promise((resolve2) => setTimeout(resolve2, delayMs));
|
|
14296
|
-
if (options.verifyValid) {
|
|
14297
|
-
const stillValid = await options.verifyValid();
|
|
14298
|
-
if (!stillValid) {
|
|
14299
|
-
return null;
|
|
14300
|
-
}
|
|
14301
|
-
}
|
|
14302
|
-
currentExpected = computeCurrentPlanHash(directory);
|
|
14303
|
-
}
|
|
14304
|
-
}
|
|
14305
|
-
}
|
|
14306
14308
|
async function takeSnapshotEvent(directory, plan, options) {
|
|
14307
14309
|
const payloadHash = computePlanHash(plan);
|
|
14308
14310
|
const snapshotPayload = {
|
|
@@ -14481,6 +14483,39 @@ import {
|
|
|
14481
14483
|
} from "fs";
|
|
14482
14484
|
import * as fsPromises from "fs/promises";
|
|
14483
14485
|
import * as path3 from "path";
|
|
14486
|
+
async function retryCasWithBackoff(directory, eventInput, options) {
|
|
14487
|
+
const maxRetries = options.maxRetries ?? CAS_MAX_RETRIES;
|
|
14488
|
+
let currentExpected = options.expectedHash;
|
|
14489
|
+
let attempt = 0;
|
|
14490
|
+
while (true) {
|
|
14491
|
+
try {
|
|
14492
|
+
return await appendLedgerEvent(directory, eventInput, {
|
|
14493
|
+
expectedHash: currentExpected,
|
|
14494
|
+
planHashAfter: options.planHashAfter
|
|
14495
|
+
});
|
|
14496
|
+
} catch (error49) {
|
|
14497
|
+
if (!(error49 instanceof LedgerStaleWriterError) || attempt >= maxRetries) {
|
|
14498
|
+
throw error49;
|
|
14499
|
+
}
|
|
14500
|
+
attempt++;
|
|
14501
|
+
const base = Math.min(CAS_BACKOFF_START_MS * 2 ** (attempt - 1), CAS_BACKOFF_CAP_MS);
|
|
14502
|
+
const jitter = base * CAS_BACKOFF_JITTER * (Math.random() * 2 - 1);
|
|
14503
|
+
const delayMs = Math.max(1, Math.round(base + jitter));
|
|
14504
|
+
emit("plan_ledger_cas_retry", {
|
|
14505
|
+
attempt,
|
|
14506
|
+
expectedHashPrefix: currentExpected.slice(0, 8),
|
|
14507
|
+
delayMs
|
|
14508
|
+
});
|
|
14509
|
+
await new Promise((resolve3) => setTimeout(resolve3, delayMs));
|
|
14510
|
+
if (options.verifyValid) {
|
|
14511
|
+
const stillValid = await options.verifyValid();
|
|
14512
|
+
if (!stillValid)
|
|
14513
|
+
return null;
|
|
14514
|
+
}
|
|
14515
|
+
currentExpected = computeCurrentPlanHash(directory);
|
|
14516
|
+
}
|
|
14517
|
+
}
|
|
14518
|
+
}
|
|
14484
14519
|
async function loadPlanJsonOnly(directory) {
|
|
14485
14520
|
const planJsonContent = await readSwarmFileAsync(directory, "plan.json");
|
|
14486
14521
|
if (planJsonContent !== null) {
|
|
@@ -14933,10 +14968,9 @@ async function savePlan(directory, plan, options) {
|
|
|
14933
14968
|
};
|
|
14934
14969
|
const capturedFromStatus = oldTask.status;
|
|
14935
14970
|
const capturedTaskId = task.id;
|
|
14936
|
-
await
|
|
14971
|
+
await retryCasWithBackoff(directory, eventInput, {
|
|
14937
14972
|
expectedHash: currentHash,
|
|
14938
14973
|
planHashAfter: hashAfter,
|
|
14939
|
-
maxRetries: 3,
|
|
14940
14974
|
verifyValid: async () => {
|
|
14941
14975
|
const onDisk = await loadPlanJsonOnly(directory);
|
|
14942
14976
|
if (!onDisk)
|
|
@@ -15308,10 +15342,11 @@ function migrateLegacyPlan(planContent, swarmId) {
|
|
|
15308
15342
|
};
|
|
15309
15343
|
return plan;
|
|
15310
15344
|
}
|
|
15311
|
-
var PlanConcurrentModificationError, startupLedgerCheckedWorkspaces, recoveryMutexes;
|
|
15345
|
+
var PlanConcurrentModificationError, startupLedgerCheckedWorkspaces, recoveryMutexes, CAS_BACKOFF_START_MS = 5, CAS_BACKOFF_CAP_MS = 250, CAS_BACKOFF_JITTER = 0.25, CAS_MAX_RETRIES = 3;
|
|
15312
15346
|
var init_manager = __esm(() => {
|
|
15313
15347
|
init_plan_schema();
|
|
15314
15348
|
init_utils2();
|
|
15349
|
+
init_telemetry();
|
|
15315
15350
|
init_utils();
|
|
15316
15351
|
init_spec_hash();
|
|
15317
15352
|
init_ledger();
|
|
@@ -15579,378 +15614,79 @@ var init_evidence_schema = __esm(() => {
|
|
|
15579
15614
|
});
|
|
15580
15615
|
});
|
|
15581
15616
|
|
|
15582
|
-
//
|
|
15583
|
-
|
|
15584
|
-
|
|
15585
|
-
|
|
15586
|
-
|
|
15587
|
-
|
|
15588
|
-
|
|
15589
|
-
|
|
15590
|
-
|
|
15591
|
-
|
|
15592
|
-
return "Invalid task ID: contains control characters";
|
|
15593
|
-
}
|
|
15594
|
-
}
|
|
15595
|
-
if (taskId.includes("..") || taskId.includes("/") || taskId.includes("\\")) {
|
|
15596
|
-
return "Invalid task ID: path traversal detected";
|
|
15597
|
-
}
|
|
15598
|
-
return;
|
|
15599
|
-
}
|
|
15600
|
-
function sanitizeTaskId(taskId) {
|
|
15601
|
-
const unsafeMsg = checkUnsafeChars(taskId);
|
|
15602
|
-
if (unsafeMsg) {
|
|
15603
|
-
throw new Error(unsafeMsg);
|
|
15604
|
-
}
|
|
15605
|
-
if (STRICT_TASK_ID_PATTERN.test(taskId) || RETRO_TASK_ID_REGEX.test(taskId) || INTERNAL_TOOL_ID_REGEX.test(taskId) || GENERAL_TASK_ID_REGEX.test(taskId)) {
|
|
15606
|
-
return taskId;
|
|
15607
|
-
}
|
|
15608
|
-
throw new Error(`Invalid task ID: must be alphanumeric (ASCII) with optional hyphens, underscores, or dots, got "${taskId}"`);
|
|
15609
|
-
}
|
|
15610
|
-
var STRICT_TASK_ID_PATTERN, RETRO_TASK_ID_REGEX, INTERNAL_TOOL_ID_REGEX, GENERAL_TASK_ID_REGEX;
|
|
15611
|
-
var init_task_id = __esm(() => {
|
|
15612
|
-
STRICT_TASK_ID_PATTERN = /^\d+\.\d+(\.\d+)*$/;
|
|
15613
|
-
RETRO_TASK_ID_REGEX = /^retro-\d+$/;
|
|
15614
|
-
INTERNAL_TOOL_ID_REGEX = /^(?:sast_scan|quality_budget|syntax_check|placeholder_scan|sbom_generate|build|secretscan)$/;
|
|
15615
|
-
GENERAL_TASK_ID_REGEX = /^[a-zA-Z0-9][a-zA-Z0-9._-]*$/;
|
|
15616
|
-
});
|
|
15617
|
-
|
|
15618
|
-
// src/evidence/manager.ts
|
|
15619
|
-
import { mkdirSync as mkdirSync2, readdirSync as readdirSync2, rmSync, statSync as statSync2 } from "fs";
|
|
15620
|
-
import * as fs3 from "fs/promises";
|
|
15621
|
-
import * as path5 from "path";
|
|
15622
|
-
function isValidEvidenceType(type) {
|
|
15623
|
-
return VALID_EVIDENCE_TYPES.includes(type);
|
|
15624
|
-
}
|
|
15625
|
-
async function saveEvidence(directory, taskId, evidence) {
|
|
15626
|
-
const sanitizedTaskId = sanitizeTaskId2(taskId);
|
|
15627
|
-
const relativePath = path5.join("evidence", sanitizedTaskId, "evidence.json");
|
|
15628
|
-
const evidencePath = validateSwarmPath(directory, relativePath);
|
|
15629
|
-
const evidenceDir = path5.dirname(evidencePath);
|
|
15630
|
-
let bundle;
|
|
15631
|
-
const existingContent = await readSwarmFileAsync(directory, relativePath);
|
|
15632
|
-
if (existingContent !== null) {
|
|
15633
|
-
try {
|
|
15634
|
-
const parsed = JSON.parse(existingContent);
|
|
15635
|
-
bundle = EvidenceBundleSchema.parse(parsed);
|
|
15636
|
-
} catch (error49) {
|
|
15637
|
-
warn(`Existing evidence bundle invalid for task ${sanitizedTaskId}, creating new: ${error49 instanceof Error ? error49.message : String(error49)}`);
|
|
15638
|
-
const now = new Date().toISOString();
|
|
15639
|
-
bundle = {
|
|
15640
|
-
schema_version: "1.0.0",
|
|
15641
|
-
task_id: sanitizedTaskId,
|
|
15642
|
-
entries: [],
|
|
15643
|
-
created_at: now,
|
|
15644
|
-
updated_at: now
|
|
15645
|
-
};
|
|
15646
|
-
}
|
|
15647
|
-
} else {
|
|
15648
|
-
const now = new Date().toISOString();
|
|
15649
|
-
bundle = {
|
|
15650
|
-
schema_version: "1.0.0",
|
|
15651
|
-
task_id: sanitizedTaskId,
|
|
15652
|
-
entries: [],
|
|
15653
|
-
created_at: now,
|
|
15654
|
-
updated_at: now
|
|
15655
|
-
};
|
|
15656
|
-
}
|
|
15657
|
-
const MAX_BUNDLE_ENTRIES = 100;
|
|
15658
|
-
let entries = [...bundle.entries, evidence];
|
|
15659
|
-
if (entries.length > MAX_BUNDLE_ENTRIES) {
|
|
15660
|
-
entries = entries.slice(entries.length - MAX_BUNDLE_ENTRIES);
|
|
15661
|
-
}
|
|
15662
|
-
const updatedBundle = {
|
|
15663
|
-
...bundle,
|
|
15664
|
-
entries,
|
|
15665
|
-
updated_at: new Date().toISOString()
|
|
15617
|
+
// node_modules/graceful-fs/polyfills.js
|
|
15618
|
+
var require_polyfills = __commonJS((exports, module) => {
|
|
15619
|
+
var constants = __require("constants");
|
|
15620
|
+
var origCwd = process.cwd;
|
|
15621
|
+
var cwd = null;
|
|
15622
|
+
var platform = process.env.GRACEFUL_FS_PLATFORM || process.platform;
|
|
15623
|
+
process.cwd = function() {
|
|
15624
|
+
if (!cwd)
|
|
15625
|
+
cwd = origCwd.call(process);
|
|
15626
|
+
return cwd;
|
|
15666
15627
|
};
|
|
15667
|
-
const bundleJson = JSON.stringify(updatedBundle);
|
|
15668
|
-
if (bundleJson.length > EVIDENCE_MAX_JSON_BYTES) {
|
|
15669
|
-
throw new Error(`Evidence bundle size (${bundleJson.length} bytes) exceeds maximum (${EVIDENCE_MAX_JSON_BYTES} bytes)`);
|
|
15670
|
-
}
|
|
15671
|
-
mkdirSync2(evidenceDir, { recursive: true });
|
|
15672
|
-
const tempPath = path5.join(evidenceDir, `evidence.json.tmp.${Date.now()}.${process.pid}`);
|
|
15673
15628
|
try {
|
|
15674
|
-
|
|
15675
|
-
|
|
15676
|
-
|
|
15677
|
-
|
|
15678
|
-
|
|
15679
|
-
|
|
15680
|
-
|
|
15681
|
-
}
|
|
15682
|
-
return updatedBundle;
|
|
15683
|
-
}
|
|
15684
|
-
function isFlatRetrospective(parsed) {
|
|
15685
|
-
return parsed !== null && typeof parsed === "object" && !Array.isArray(parsed) && parsed.type === "retrospective" && !parsed.schema_version;
|
|
15686
|
-
}
|
|
15687
|
-
function remapLegacyTaskComplexity(entry) {
|
|
15688
|
-
const taskComplexity = entry.task_complexity;
|
|
15689
|
-
if (typeof taskComplexity === "string" && taskComplexity in LEGACY_TASK_COMPLEXITY_MAP) {
|
|
15690
|
-
return {
|
|
15691
|
-
...entry,
|
|
15692
|
-
task_complexity: LEGACY_TASK_COMPLEXITY_MAP[taskComplexity]
|
|
15629
|
+
process.cwd();
|
|
15630
|
+
} catch (er) {}
|
|
15631
|
+
if (typeof process.chdir === "function") {
|
|
15632
|
+
chdir = process.chdir;
|
|
15633
|
+
process.chdir = function(d) {
|
|
15634
|
+
cwd = null;
|
|
15635
|
+
chdir.call(process, d);
|
|
15693
15636
|
};
|
|
15637
|
+
if (Object.setPrototypeOf)
|
|
15638
|
+
Object.setPrototypeOf(process.chdir, chdir);
|
|
15694
15639
|
}
|
|
15695
|
-
|
|
15696
|
-
|
|
15697
|
-
function
|
|
15698
|
-
|
|
15699
|
-
|
|
15700
|
-
|
|
15701
|
-
|
|
15702
|
-
|
|
15703
|
-
|
|
15704
|
-
|
|
15705
|
-
|
|
15706
|
-
|
|
15707
|
-
|
|
15708
|
-
|
|
15709
|
-
|
|
15710
|
-
|
|
15711
|
-
|
|
15712
|
-
|
|
15713
|
-
|
|
15714
|
-
|
|
15715
|
-
|
|
15716
|
-
|
|
15717
|
-
|
|
15718
|
-
|
|
15719
|
-
|
|
15720
|
-
|
|
15721
|
-
|
|
15722
|
-
|
|
15723
|
-
|
|
15724
|
-
|
|
15725
|
-
|
|
15726
|
-
|
|
15727
|
-
|
|
15728
|
-
const tempPath = path5.join(evidenceDir, `evidence.json.tmp.${Date.now()}.${process.pid}`);
|
|
15729
|
-
try {
|
|
15730
|
-
await Bun.write(tempPath, bundleJson);
|
|
15731
|
-
await fs3.rename(tempPath, evidencePath);
|
|
15732
|
-
} catch (writeError) {
|
|
15733
|
-
try {
|
|
15734
|
-
rmSync(tempPath, { force: true });
|
|
15735
|
-
} catch {}
|
|
15736
|
-
warn(`Failed to persist repaired flat retrospective for task ${sanitizedTaskId}: ${writeError instanceof Error ? writeError.message : String(writeError)}`);
|
|
15737
|
-
}
|
|
15738
|
-
return { status: "found", bundle: validated };
|
|
15739
|
-
} catch (error49) {
|
|
15740
|
-
warn(`Wrapped flat retrospective failed validation for task ${sanitizedTaskId}: ${error49 instanceof Error ? error49.message : String(error49)}`);
|
|
15741
|
-
const errors3 = error49 instanceof ZodError ? error49.issues.map((e) => `${e.path.join(".")}: ${e.message}`) : [error49 instanceof Error ? error49.message : String(error49)];
|
|
15742
|
-
return { status: "invalid_schema", errors: errors3 };
|
|
15640
|
+
var chdir;
|
|
15641
|
+
module.exports = patch;
|
|
15642
|
+
function patch(fs3) {
|
|
15643
|
+
if (constants.hasOwnProperty("O_SYMLINK") && process.version.match(/^v0\.6\.[0-2]|^v0\.5\./)) {
|
|
15644
|
+
patchLchmod(fs3);
|
|
15645
|
+
}
|
|
15646
|
+
if (!fs3.lutimes) {
|
|
15647
|
+
patchLutimes(fs3);
|
|
15648
|
+
}
|
|
15649
|
+
fs3.chown = chownFix(fs3.chown);
|
|
15650
|
+
fs3.fchown = chownFix(fs3.fchown);
|
|
15651
|
+
fs3.lchown = chownFix(fs3.lchown);
|
|
15652
|
+
fs3.chmod = chmodFix(fs3.chmod);
|
|
15653
|
+
fs3.fchmod = chmodFix(fs3.fchmod);
|
|
15654
|
+
fs3.lchmod = chmodFix(fs3.lchmod);
|
|
15655
|
+
fs3.chownSync = chownFixSync(fs3.chownSync);
|
|
15656
|
+
fs3.fchownSync = chownFixSync(fs3.fchownSync);
|
|
15657
|
+
fs3.lchownSync = chownFixSync(fs3.lchownSync);
|
|
15658
|
+
fs3.chmodSync = chmodFixSync(fs3.chmodSync);
|
|
15659
|
+
fs3.fchmodSync = chmodFixSync(fs3.fchmodSync);
|
|
15660
|
+
fs3.lchmodSync = chmodFixSync(fs3.lchmodSync);
|
|
15661
|
+
fs3.stat = statFix(fs3.stat);
|
|
15662
|
+
fs3.fstat = statFix(fs3.fstat);
|
|
15663
|
+
fs3.lstat = statFix(fs3.lstat);
|
|
15664
|
+
fs3.statSync = statFixSync(fs3.statSync);
|
|
15665
|
+
fs3.fstatSync = statFixSync(fs3.fstatSync);
|
|
15666
|
+
fs3.lstatSync = statFixSync(fs3.lstatSync);
|
|
15667
|
+
if (fs3.chmod && !fs3.lchmod) {
|
|
15668
|
+
fs3.lchmod = function(path5, mode, cb) {
|
|
15669
|
+
if (cb)
|
|
15670
|
+
process.nextTick(cb);
|
|
15671
|
+
};
|
|
15672
|
+
fs3.lchmodSync = function() {};
|
|
15743
15673
|
}
|
|
15744
|
-
|
|
15745
|
-
|
|
15746
|
-
|
|
15747
|
-
|
|
15748
|
-
|
|
15749
|
-
|
|
15750
|
-
const errors3 = error49 instanceof ZodError ? error49.issues.map((e) => `${e.path.join(".")}: ${e.message}`) : [error49 instanceof Error ? error49.message : String(error49)];
|
|
15751
|
-
return { status: "invalid_schema", errors: errors3 };
|
|
15752
|
-
}
|
|
15753
|
-
}
|
|
15754
|
-
async function listEvidenceTaskIds(directory) {
|
|
15755
|
-
const evidenceBasePath = validateSwarmPath(directory, "evidence");
|
|
15756
|
-
try {
|
|
15757
|
-
statSync2(evidenceBasePath);
|
|
15758
|
-
} catch {
|
|
15759
|
-
return [];
|
|
15760
|
-
}
|
|
15761
|
-
let entries;
|
|
15762
|
-
try {
|
|
15763
|
-
entries = readdirSync2(evidenceBasePath);
|
|
15764
|
-
} catch {
|
|
15765
|
-
return [];
|
|
15766
|
-
}
|
|
15767
|
-
const taskIds = [];
|
|
15768
|
-
for (const entry of entries) {
|
|
15769
|
-
const entryPath = path5.join(evidenceBasePath, entry);
|
|
15770
|
-
try {
|
|
15771
|
-
const stats = statSync2(entryPath);
|
|
15772
|
-
if (!stats.isDirectory()) {
|
|
15773
|
-
continue;
|
|
15774
|
-
}
|
|
15775
|
-
sanitizeTaskId2(entry);
|
|
15776
|
-
taskIds.push(entry);
|
|
15777
|
-
} catch (error49) {
|
|
15778
|
-
if (error49 instanceof Error && !error49.message.startsWith("Invalid task ID")) {
|
|
15779
|
-
warn(`Error reading evidence entry '${entry}': ${error49.message}`);
|
|
15780
|
-
}
|
|
15781
|
-
}
|
|
15782
|
-
}
|
|
15783
|
-
return taskIds.sort();
|
|
15784
|
-
}
|
|
15785
|
-
async function deleteEvidence(directory, taskId) {
|
|
15786
|
-
const sanitizedTaskId = sanitizeTaskId2(taskId);
|
|
15787
|
-
const relativePath = path5.join("evidence", sanitizedTaskId);
|
|
15788
|
-
const evidenceDir = validateSwarmPath(directory, relativePath);
|
|
15789
|
-
try {
|
|
15790
|
-
statSync2(evidenceDir);
|
|
15791
|
-
} catch {
|
|
15792
|
-
return false;
|
|
15793
|
-
}
|
|
15794
|
-
try {
|
|
15795
|
-
rmSync(evidenceDir, { recursive: true, force: true });
|
|
15796
|
-
return true;
|
|
15797
|
-
} catch (error49) {
|
|
15798
|
-
warn(`Failed to delete evidence for task ${sanitizedTaskId}: ${error49 instanceof Error ? error49.message : String(error49)}`);
|
|
15799
|
-
return false;
|
|
15800
|
-
}
|
|
15801
|
-
}
|
|
15802
|
-
async function checkRequirementCoverage(phase, directory) {
|
|
15803
|
-
const relativePath = path5.join("evidence", `req-coverage-phase-${phase}.json`);
|
|
15804
|
-
const absolutePath = path5.resolve(directory, ".swarm", relativePath);
|
|
15805
|
-
try {
|
|
15806
|
-
await fs3.access(absolutePath);
|
|
15807
|
-
return { exists: true, path: absolutePath };
|
|
15808
|
-
} catch {
|
|
15809
|
-
return { exists: false, path: absolutePath };
|
|
15810
|
-
}
|
|
15811
|
-
}
|
|
15812
|
-
async function archiveEvidence(directory, maxAgeDays, maxBundles) {
|
|
15813
|
-
const taskIds = await listEvidenceTaskIds(directory);
|
|
15814
|
-
const cutoffDate = new Date;
|
|
15815
|
-
cutoffDate.setDate(cutoffDate.getDate() - maxAgeDays);
|
|
15816
|
-
const cutoffIso = cutoffDate.toISOString();
|
|
15817
|
-
const archived = [];
|
|
15818
|
-
const remainingBundles = [];
|
|
15819
|
-
for (const taskId of taskIds) {
|
|
15820
|
-
const result = await loadEvidence(directory, taskId);
|
|
15821
|
-
if (result.status !== "found") {
|
|
15822
|
-
continue;
|
|
15823
|
-
}
|
|
15824
|
-
if (result.bundle.updated_at < cutoffIso) {
|
|
15825
|
-
const deleted = await deleteEvidence(directory, taskId);
|
|
15826
|
-
if (deleted) {
|
|
15827
|
-
archived.push(taskId);
|
|
15828
|
-
}
|
|
15829
|
-
} else {
|
|
15830
|
-
remainingBundles.push({
|
|
15831
|
-
taskId,
|
|
15832
|
-
updatedAt: result.bundle.updated_at
|
|
15833
|
-
});
|
|
15834
|
-
}
|
|
15835
|
-
}
|
|
15836
|
-
if (maxBundles !== undefined && remainingBundles.length > maxBundles) {
|
|
15837
|
-
remainingBundles.sort((a, b) => a.updatedAt.localeCompare(b.updatedAt));
|
|
15838
|
-
const toDelete = remainingBundles.length - maxBundles;
|
|
15839
|
-
for (let i = 0;i < toDelete; i++) {
|
|
15840
|
-
const deleted = await deleteEvidence(directory, remainingBundles[i].taskId);
|
|
15841
|
-
if (deleted) {
|
|
15842
|
-
archived.push(remainingBundles[i].taskId);
|
|
15843
|
-
}
|
|
15844
|
-
}
|
|
15845
|
-
}
|
|
15846
|
-
return archived;
|
|
15847
|
-
}
|
|
15848
|
-
var VALID_EVIDENCE_TYPES, sanitizeTaskId2, LEGACY_TASK_COMPLEXITY_MAP;
|
|
15849
|
-
var init_manager2 = __esm(() => {
|
|
15850
|
-
init_zod();
|
|
15851
|
-
init_evidence_schema();
|
|
15852
|
-
init_utils2();
|
|
15853
|
-
init_utils();
|
|
15854
|
-
init_task_id();
|
|
15855
|
-
VALID_EVIDENCE_TYPES = [
|
|
15856
|
-
"review",
|
|
15857
|
-
"test",
|
|
15858
|
-
"diff",
|
|
15859
|
-
"approval",
|
|
15860
|
-
"note",
|
|
15861
|
-
"retrospective",
|
|
15862
|
-
"syntax",
|
|
15863
|
-
"placeholder",
|
|
15864
|
-
"sast",
|
|
15865
|
-
"sbom",
|
|
15866
|
-
"build",
|
|
15867
|
-
"quality_budget",
|
|
15868
|
-
"secretscan"
|
|
15869
|
-
];
|
|
15870
|
-
sanitizeTaskId2 = sanitizeTaskId;
|
|
15871
|
-
LEGACY_TASK_COMPLEXITY_MAP = {
|
|
15872
|
-
low: "simple",
|
|
15873
|
-
medium: "moderate",
|
|
15874
|
-
high: "complex"
|
|
15875
|
-
};
|
|
15876
|
-
});
|
|
15877
|
-
|
|
15878
|
-
// src/telemetry.ts
|
|
15879
|
-
var init_telemetry = () => {};
|
|
15880
|
-
|
|
15881
|
-
// node_modules/graceful-fs/polyfills.js
|
|
15882
|
-
var require_polyfills = __commonJS((exports, module) => {
|
|
15883
|
-
var constants = __require("constants");
|
|
15884
|
-
var origCwd = process.cwd;
|
|
15885
|
-
var cwd = null;
|
|
15886
|
-
var platform = process.env.GRACEFUL_FS_PLATFORM || process.platform;
|
|
15887
|
-
process.cwd = function() {
|
|
15888
|
-
if (!cwd)
|
|
15889
|
-
cwd = origCwd.call(process);
|
|
15890
|
-
return cwd;
|
|
15891
|
-
};
|
|
15892
|
-
try {
|
|
15893
|
-
process.cwd();
|
|
15894
|
-
} catch (er) {}
|
|
15895
|
-
if (typeof process.chdir === "function") {
|
|
15896
|
-
chdir = process.chdir;
|
|
15897
|
-
process.chdir = function(d) {
|
|
15898
|
-
cwd = null;
|
|
15899
|
-
chdir.call(process, d);
|
|
15900
|
-
};
|
|
15901
|
-
if (Object.setPrototypeOf)
|
|
15902
|
-
Object.setPrototypeOf(process.chdir, chdir);
|
|
15903
|
-
}
|
|
15904
|
-
var chdir;
|
|
15905
|
-
module.exports = patch;
|
|
15906
|
-
function patch(fs4) {
|
|
15907
|
-
if (constants.hasOwnProperty("O_SYMLINK") && process.version.match(/^v0\.6\.[0-2]|^v0\.5\./)) {
|
|
15908
|
-
patchLchmod(fs4);
|
|
15909
|
-
}
|
|
15910
|
-
if (!fs4.lutimes) {
|
|
15911
|
-
patchLutimes(fs4);
|
|
15912
|
-
}
|
|
15913
|
-
fs4.chown = chownFix(fs4.chown);
|
|
15914
|
-
fs4.fchown = chownFix(fs4.fchown);
|
|
15915
|
-
fs4.lchown = chownFix(fs4.lchown);
|
|
15916
|
-
fs4.chmod = chmodFix(fs4.chmod);
|
|
15917
|
-
fs4.fchmod = chmodFix(fs4.fchmod);
|
|
15918
|
-
fs4.lchmod = chmodFix(fs4.lchmod);
|
|
15919
|
-
fs4.chownSync = chownFixSync(fs4.chownSync);
|
|
15920
|
-
fs4.fchownSync = chownFixSync(fs4.fchownSync);
|
|
15921
|
-
fs4.lchownSync = chownFixSync(fs4.lchownSync);
|
|
15922
|
-
fs4.chmodSync = chmodFixSync(fs4.chmodSync);
|
|
15923
|
-
fs4.fchmodSync = chmodFixSync(fs4.fchmodSync);
|
|
15924
|
-
fs4.lchmodSync = chmodFixSync(fs4.lchmodSync);
|
|
15925
|
-
fs4.stat = statFix(fs4.stat);
|
|
15926
|
-
fs4.fstat = statFix(fs4.fstat);
|
|
15927
|
-
fs4.lstat = statFix(fs4.lstat);
|
|
15928
|
-
fs4.statSync = statFixSync(fs4.statSync);
|
|
15929
|
-
fs4.fstatSync = statFixSync(fs4.fstatSync);
|
|
15930
|
-
fs4.lstatSync = statFixSync(fs4.lstatSync);
|
|
15931
|
-
if (fs4.chmod && !fs4.lchmod) {
|
|
15932
|
-
fs4.lchmod = function(path6, mode, cb) {
|
|
15933
|
-
if (cb)
|
|
15934
|
-
process.nextTick(cb);
|
|
15935
|
-
};
|
|
15936
|
-
fs4.lchmodSync = function() {};
|
|
15937
|
-
}
|
|
15938
|
-
if (fs4.chown && !fs4.lchown) {
|
|
15939
|
-
fs4.lchown = function(path6, uid, gid, cb) {
|
|
15940
|
-
if (cb)
|
|
15941
|
-
process.nextTick(cb);
|
|
15942
|
-
};
|
|
15943
|
-
fs4.lchownSync = function() {};
|
|
15674
|
+
if (fs3.chown && !fs3.lchown) {
|
|
15675
|
+
fs3.lchown = function(path5, uid, gid, cb) {
|
|
15676
|
+
if (cb)
|
|
15677
|
+
process.nextTick(cb);
|
|
15678
|
+
};
|
|
15679
|
+
fs3.lchownSync = function() {};
|
|
15944
15680
|
}
|
|
15945
15681
|
if (platform === "win32") {
|
|
15946
|
-
|
|
15947
|
-
function
|
|
15682
|
+
fs3.rename = typeof fs3.rename !== "function" ? fs3.rename : function(fs$rename) {
|
|
15683
|
+
function rename(from, to, cb) {
|
|
15948
15684
|
var start = Date.now();
|
|
15949
15685
|
var backoff = 0;
|
|
15950
15686
|
fs$rename(from, to, function CB(er) {
|
|
15951
15687
|
if (er && (er.code === "EACCES" || er.code === "EPERM" || er.code === "EBUSY") && Date.now() - start < 60000) {
|
|
15952
15688
|
setTimeout(function() {
|
|
15953
|
-
|
|
15689
|
+
fs3.stat(to, function(stater, st) {
|
|
15954
15690
|
if (stater && stater.code === "ENOENT")
|
|
15955
15691
|
fs$rename(from, to, CB);
|
|
15956
15692
|
else
|
|
@@ -15966,11 +15702,11 @@ var require_polyfills = __commonJS((exports, module) => {
|
|
|
15966
15702
|
});
|
|
15967
15703
|
}
|
|
15968
15704
|
if (Object.setPrototypeOf)
|
|
15969
|
-
Object.setPrototypeOf(
|
|
15970
|
-
return
|
|
15971
|
-
}(
|
|
15705
|
+
Object.setPrototypeOf(rename, fs$rename);
|
|
15706
|
+
return rename;
|
|
15707
|
+
}(fs3.rename);
|
|
15972
15708
|
}
|
|
15973
|
-
|
|
15709
|
+
fs3.read = typeof fs3.read !== "function" ? fs3.read : function(fs$read) {
|
|
15974
15710
|
function read(fd, buffer, offset, length, position, callback_) {
|
|
15975
15711
|
var callback;
|
|
15976
15712
|
if (callback_ && typeof callback_ === "function") {
|
|
@@ -15978,23 +15714,23 @@ var require_polyfills = __commonJS((exports, module) => {
|
|
|
15978
15714
|
callback = function(er, _, __) {
|
|
15979
15715
|
if (er && er.code === "EAGAIN" && eagCounter < 10) {
|
|
15980
15716
|
eagCounter++;
|
|
15981
|
-
return fs$read.call(
|
|
15717
|
+
return fs$read.call(fs3, fd, buffer, offset, length, position, callback);
|
|
15982
15718
|
}
|
|
15983
15719
|
callback_.apply(this, arguments);
|
|
15984
15720
|
};
|
|
15985
15721
|
}
|
|
15986
|
-
return fs$read.call(
|
|
15722
|
+
return fs$read.call(fs3, fd, buffer, offset, length, position, callback);
|
|
15987
15723
|
}
|
|
15988
15724
|
if (Object.setPrototypeOf)
|
|
15989
15725
|
Object.setPrototypeOf(read, fs$read);
|
|
15990
15726
|
return read;
|
|
15991
|
-
}(
|
|
15992
|
-
|
|
15727
|
+
}(fs3.read);
|
|
15728
|
+
fs3.readSync = typeof fs3.readSync !== "function" ? fs3.readSync : function(fs$readSync) {
|
|
15993
15729
|
return function(fd, buffer, offset, length, position) {
|
|
15994
15730
|
var eagCounter = 0;
|
|
15995
15731
|
while (true) {
|
|
15996
15732
|
try {
|
|
15997
|
-
return fs$readSync.call(
|
|
15733
|
+
return fs$readSync.call(fs3, fd, buffer, offset, length, position);
|
|
15998
15734
|
} catch (er) {
|
|
15999
15735
|
if (er.code === "EAGAIN" && eagCounter < 10) {
|
|
16000
15736
|
eagCounter++;
|
|
@@ -16004,90 +15740,90 @@ var require_polyfills = __commonJS((exports, module) => {
|
|
|
16004
15740
|
}
|
|
16005
15741
|
}
|
|
16006
15742
|
};
|
|
16007
|
-
}(
|
|
16008
|
-
function patchLchmod(
|
|
16009
|
-
|
|
16010
|
-
|
|
15743
|
+
}(fs3.readSync);
|
|
15744
|
+
function patchLchmod(fs4) {
|
|
15745
|
+
fs4.lchmod = function(path5, mode, callback) {
|
|
15746
|
+
fs4.open(path5, constants.O_WRONLY | constants.O_SYMLINK, mode, function(err, fd) {
|
|
16011
15747
|
if (err) {
|
|
16012
15748
|
if (callback)
|
|
16013
15749
|
callback(err);
|
|
16014
15750
|
return;
|
|
16015
15751
|
}
|
|
16016
|
-
|
|
16017
|
-
|
|
15752
|
+
fs4.fchmod(fd, mode, function(err2) {
|
|
15753
|
+
fs4.close(fd, function(err22) {
|
|
16018
15754
|
if (callback)
|
|
16019
15755
|
callback(err2 || err22);
|
|
16020
15756
|
});
|
|
16021
15757
|
});
|
|
16022
15758
|
});
|
|
16023
15759
|
};
|
|
16024
|
-
|
|
16025
|
-
var fd =
|
|
15760
|
+
fs4.lchmodSync = function(path5, mode) {
|
|
15761
|
+
var fd = fs4.openSync(path5, constants.O_WRONLY | constants.O_SYMLINK, mode);
|
|
16026
15762
|
var threw = true;
|
|
16027
15763
|
var ret;
|
|
16028
15764
|
try {
|
|
16029
|
-
ret =
|
|
15765
|
+
ret = fs4.fchmodSync(fd, mode);
|
|
16030
15766
|
threw = false;
|
|
16031
15767
|
} finally {
|
|
16032
15768
|
if (threw) {
|
|
16033
15769
|
try {
|
|
16034
|
-
|
|
15770
|
+
fs4.closeSync(fd);
|
|
16035
15771
|
} catch (er) {}
|
|
16036
15772
|
} else {
|
|
16037
|
-
|
|
15773
|
+
fs4.closeSync(fd);
|
|
16038
15774
|
}
|
|
16039
15775
|
}
|
|
16040
15776
|
return ret;
|
|
16041
15777
|
};
|
|
16042
15778
|
}
|
|
16043
|
-
function patchLutimes(
|
|
16044
|
-
if (constants.hasOwnProperty("O_SYMLINK") &&
|
|
16045
|
-
|
|
16046
|
-
|
|
15779
|
+
function patchLutimes(fs4) {
|
|
15780
|
+
if (constants.hasOwnProperty("O_SYMLINK") && fs4.futimes) {
|
|
15781
|
+
fs4.lutimes = function(path5, at, mt, cb) {
|
|
15782
|
+
fs4.open(path5, constants.O_SYMLINK, function(er, fd) {
|
|
16047
15783
|
if (er) {
|
|
16048
15784
|
if (cb)
|
|
16049
15785
|
cb(er);
|
|
16050
15786
|
return;
|
|
16051
15787
|
}
|
|
16052
|
-
|
|
16053
|
-
|
|
15788
|
+
fs4.futimes(fd, at, mt, function(er2) {
|
|
15789
|
+
fs4.close(fd, function(er22) {
|
|
16054
15790
|
if (cb)
|
|
16055
15791
|
cb(er2 || er22);
|
|
16056
15792
|
});
|
|
16057
15793
|
});
|
|
16058
15794
|
});
|
|
16059
15795
|
};
|
|
16060
|
-
|
|
16061
|
-
var fd =
|
|
15796
|
+
fs4.lutimesSync = function(path5, at, mt) {
|
|
15797
|
+
var fd = fs4.openSync(path5, constants.O_SYMLINK);
|
|
16062
15798
|
var ret;
|
|
16063
15799
|
var threw = true;
|
|
16064
15800
|
try {
|
|
16065
|
-
ret =
|
|
15801
|
+
ret = fs4.futimesSync(fd, at, mt);
|
|
16066
15802
|
threw = false;
|
|
16067
15803
|
} finally {
|
|
16068
15804
|
if (threw) {
|
|
16069
15805
|
try {
|
|
16070
|
-
|
|
15806
|
+
fs4.closeSync(fd);
|
|
16071
15807
|
} catch (er) {}
|
|
16072
15808
|
} else {
|
|
16073
|
-
|
|
15809
|
+
fs4.closeSync(fd);
|
|
16074
15810
|
}
|
|
16075
15811
|
}
|
|
16076
15812
|
return ret;
|
|
16077
15813
|
};
|
|
16078
|
-
} else if (
|
|
16079
|
-
|
|
15814
|
+
} else if (fs4.futimes) {
|
|
15815
|
+
fs4.lutimes = function(_a2, _b, _c, cb) {
|
|
16080
15816
|
if (cb)
|
|
16081
15817
|
process.nextTick(cb);
|
|
16082
15818
|
};
|
|
16083
|
-
|
|
15819
|
+
fs4.lutimesSync = function() {};
|
|
16084
15820
|
}
|
|
16085
15821
|
}
|
|
16086
15822
|
function chmodFix(orig) {
|
|
16087
15823
|
if (!orig)
|
|
16088
15824
|
return orig;
|
|
16089
15825
|
return function(target, mode, cb) {
|
|
16090
|
-
return orig.call(
|
|
15826
|
+
return orig.call(fs3, target, mode, function(er) {
|
|
16091
15827
|
if (chownErOk(er))
|
|
16092
15828
|
er = null;
|
|
16093
15829
|
if (cb)
|
|
@@ -16100,7 +15836,7 @@ var require_polyfills = __commonJS((exports, module) => {
|
|
|
16100
15836
|
return orig;
|
|
16101
15837
|
return function(target, mode) {
|
|
16102
15838
|
try {
|
|
16103
|
-
return orig.call(
|
|
15839
|
+
return orig.call(fs3, target, mode);
|
|
16104
15840
|
} catch (er) {
|
|
16105
15841
|
if (!chownErOk(er))
|
|
16106
15842
|
throw er;
|
|
@@ -16111,7 +15847,7 @@ var require_polyfills = __commonJS((exports, module) => {
|
|
|
16111
15847
|
if (!orig)
|
|
16112
15848
|
return orig;
|
|
16113
15849
|
return function(target, uid, gid, cb) {
|
|
16114
|
-
return orig.call(
|
|
15850
|
+
return orig.call(fs3, target, uid, gid, function(er) {
|
|
16115
15851
|
if (chownErOk(er))
|
|
16116
15852
|
er = null;
|
|
16117
15853
|
if (cb)
|
|
@@ -16124,7 +15860,7 @@ var require_polyfills = __commonJS((exports, module) => {
|
|
|
16124
15860
|
return orig;
|
|
16125
15861
|
return function(target, uid, gid) {
|
|
16126
15862
|
try {
|
|
16127
|
-
return orig.call(
|
|
15863
|
+
return orig.call(fs3, target, uid, gid);
|
|
16128
15864
|
} catch (er) {
|
|
16129
15865
|
if (!chownErOk(er))
|
|
16130
15866
|
throw er;
|
|
@@ -16149,14 +15885,14 @@ var require_polyfills = __commonJS((exports, module) => {
|
|
|
16149
15885
|
if (cb)
|
|
16150
15886
|
cb.apply(this, arguments);
|
|
16151
15887
|
}
|
|
16152
|
-
return options ? orig.call(
|
|
15888
|
+
return options ? orig.call(fs3, target, options, callback) : orig.call(fs3, target, callback);
|
|
16153
15889
|
};
|
|
16154
15890
|
}
|
|
16155
15891
|
function statFixSync(orig) {
|
|
16156
15892
|
if (!orig)
|
|
16157
15893
|
return orig;
|
|
16158
15894
|
return function(target, options) {
|
|
16159
|
-
var stats = options ? orig.call(
|
|
15895
|
+
var stats = options ? orig.call(fs3, target, options) : orig.call(fs3, target);
|
|
16160
15896
|
if (stats) {
|
|
16161
15897
|
if (stats.uid < 0)
|
|
16162
15898
|
stats.uid += 4294967296;
|
|
@@ -16185,17 +15921,17 @@ var require_polyfills = __commonJS((exports, module) => {
|
|
|
16185
15921
|
var require_legacy_streams = __commonJS((exports, module) => {
|
|
16186
15922
|
var Stream = __require("stream").Stream;
|
|
16187
15923
|
module.exports = legacy;
|
|
16188
|
-
function legacy(
|
|
15924
|
+
function legacy(fs3) {
|
|
16189
15925
|
return {
|
|
16190
15926
|
ReadStream,
|
|
16191
15927
|
WriteStream
|
|
16192
15928
|
};
|
|
16193
|
-
function ReadStream(
|
|
15929
|
+
function ReadStream(path5, options) {
|
|
16194
15930
|
if (!(this instanceof ReadStream))
|
|
16195
|
-
return new ReadStream(
|
|
15931
|
+
return new ReadStream(path5, options);
|
|
16196
15932
|
Stream.call(this);
|
|
16197
15933
|
var self = this;
|
|
16198
|
-
this.path =
|
|
15934
|
+
this.path = path5;
|
|
16199
15935
|
this.fd = null;
|
|
16200
15936
|
this.readable = true;
|
|
16201
15937
|
this.paused = false;
|
|
@@ -16230,7 +15966,7 @@ var require_legacy_streams = __commonJS((exports, module) => {
|
|
|
16230
15966
|
});
|
|
16231
15967
|
return;
|
|
16232
15968
|
}
|
|
16233
|
-
|
|
15969
|
+
fs3.open(this.path, this.flags, this.mode, function(err, fd) {
|
|
16234
15970
|
if (err) {
|
|
16235
15971
|
self.emit("error", err);
|
|
16236
15972
|
self.readable = false;
|
|
@@ -16241,11 +15977,11 @@ var require_legacy_streams = __commonJS((exports, module) => {
|
|
|
16241
15977
|
self._read();
|
|
16242
15978
|
});
|
|
16243
15979
|
}
|
|
16244
|
-
function WriteStream(
|
|
15980
|
+
function WriteStream(path5, options) {
|
|
16245
15981
|
if (!(this instanceof WriteStream))
|
|
16246
|
-
return new WriteStream(
|
|
15982
|
+
return new WriteStream(path5, options);
|
|
16247
15983
|
Stream.call(this);
|
|
16248
|
-
this.path =
|
|
15984
|
+
this.path = path5;
|
|
16249
15985
|
this.fd = null;
|
|
16250
15986
|
this.writable = true;
|
|
16251
15987
|
this.flags = "w";
|
|
@@ -16270,7 +16006,7 @@ var require_legacy_streams = __commonJS((exports, module) => {
|
|
|
16270
16006
|
this.busy = false;
|
|
16271
16007
|
this._queue = [];
|
|
16272
16008
|
if (this.fd === null) {
|
|
16273
|
-
this._open =
|
|
16009
|
+
this._open = fs3.open;
|
|
16274
16010
|
this._queue.push([this._open, this.path, this.flags, this.mode, undefined]);
|
|
16275
16011
|
this.flush();
|
|
16276
16012
|
}
|
|
@@ -16300,7 +16036,7 @@ var require_clone = __commonJS((exports, module) => {
|
|
|
16300
16036
|
|
|
16301
16037
|
// node_modules/graceful-fs/graceful-fs.js
|
|
16302
16038
|
var require_graceful_fs = __commonJS((exports, module) => {
|
|
16303
|
-
var
|
|
16039
|
+
var fs3 = __require("fs");
|
|
16304
16040
|
var polyfills = require_polyfills();
|
|
16305
16041
|
var legacy = require_legacy_streams();
|
|
16306
16042
|
var clone2 = require_clone();
|
|
@@ -16332,12 +16068,12 @@ var require_graceful_fs = __commonJS((exports, module) => {
|
|
|
16332
16068
|
GFS4: `);
|
|
16333
16069
|
console.error(m);
|
|
16334
16070
|
};
|
|
16335
|
-
if (!
|
|
16071
|
+
if (!fs3[gracefulQueue]) {
|
|
16336
16072
|
queue = global[gracefulQueue] || [];
|
|
16337
|
-
publishQueue(
|
|
16338
|
-
|
|
16073
|
+
publishQueue(fs3, queue);
|
|
16074
|
+
fs3.close = function(fs$close) {
|
|
16339
16075
|
function close(fd, cb) {
|
|
16340
|
-
return fs$close.call(
|
|
16076
|
+
return fs$close.call(fs3, fd, function(err) {
|
|
16341
16077
|
if (!err) {
|
|
16342
16078
|
resetQueue();
|
|
16343
16079
|
}
|
|
@@ -16349,48 +16085,48 @@ GFS4: `);
|
|
|
16349
16085
|
value: fs$close
|
|
16350
16086
|
});
|
|
16351
16087
|
return close;
|
|
16352
|
-
}(
|
|
16353
|
-
|
|
16088
|
+
}(fs3.close);
|
|
16089
|
+
fs3.closeSync = function(fs$closeSync) {
|
|
16354
16090
|
function closeSync(fd) {
|
|
16355
|
-
fs$closeSync.apply(
|
|
16091
|
+
fs$closeSync.apply(fs3, arguments);
|
|
16356
16092
|
resetQueue();
|
|
16357
16093
|
}
|
|
16358
16094
|
Object.defineProperty(closeSync, previousSymbol, {
|
|
16359
16095
|
value: fs$closeSync
|
|
16360
16096
|
});
|
|
16361
16097
|
return closeSync;
|
|
16362
|
-
}(
|
|
16098
|
+
}(fs3.closeSync);
|
|
16363
16099
|
if (/\bgfs4\b/i.test(process.env.NODE_DEBUG || "")) {
|
|
16364
16100
|
process.on("exit", function() {
|
|
16365
|
-
debug(
|
|
16366
|
-
__require("assert").equal(
|
|
16101
|
+
debug(fs3[gracefulQueue]);
|
|
16102
|
+
__require("assert").equal(fs3[gracefulQueue].length, 0);
|
|
16367
16103
|
});
|
|
16368
16104
|
}
|
|
16369
16105
|
}
|
|
16370
16106
|
var queue;
|
|
16371
16107
|
if (!global[gracefulQueue]) {
|
|
16372
|
-
publishQueue(global,
|
|
16373
|
-
}
|
|
16374
|
-
module.exports = patch(clone2(
|
|
16375
|
-
if (process.env.TEST_GRACEFUL_FS_GLOBAL_PATCH && !
|
|
16376
|
-
module.exports = patch(
|
|
16377
|
-
|
|
16378
|
-
}
|
|
16379
|
-
function patch(
|
|
16380
|
-
polyfills(
|
|
16381
|
-
|
|
16382
|
-
|
|
16383
|
-
|
|
16384
|
-
var fs$readFile =
|
|
16385
|
-
|
|
16386
|
-
function readFile2(
|
|
16108
|
+
publishQueue(global, fs3[gracefulQueue]);
|
|
16109
|
+
}
|
|
16110
|
+
module.exports = patch(clone2(fs3));
|
|
16111
|
+
if (process.env.TEST_GRACEFUL_FS_GLOBAL_PATCH && !fs3.__patched) {
|
|
16112
|
+
module.exports = patch(fs3);
|
|
16113
|
+
fs3.__patched = true;
|
|
16114
|
+
}
|
|
16115
|
+
function patch(fs4) {
|
|
16116
|
+
polyfills(fs4);
|
|
16117
|
+
fs4.gracefulify = patch;
|
|
16118
|
+
fs4.createReadStream = createReadStream;
|
|
16119
|
+
fs4.createWriteStream = createWriteStream;
|
|
16120
|
+
var fs$readFile = fs4.readFile;
|
|
16121
|
+
fs4.readFile = readFile2;
|
|
16122
|
+
function readFile2(path5, options, cb) {
|
|
16387
16123
|
if (typeof options === "function")
|
|
16388
16124
|
cb = options, options = null;
|
|
16389
|
-
return go$readFile(
|
|
16390
|
-
function go$readFile(
|
|
16391
|
-
return fs$readFile(
|
|
16125
|
+
return go$readFile(path5, options, cb);
|
|
16126
|
+
function go$readFile(path6, options2, cb2, startTime) {
|
|
16127
|
+
return fs$readFile(path6, options2, function(err) {
|
|
16392
16128
|
if (err && (err.code === "EMFILE" || err.code === "ENFILE"))
|
|
16393
|
-
enqueue([go$readFile, [
|
|
16129
|
+
enqueue([go$readFile, [path6, options2, cb2], err, startTime || Date.now(), Date.now()]);
|
|
16394
16130
|
else {
|
|
16395
16131
|
if (typeof cb2 === "function")
|
|
16396
16132
|
cb2.apply(this, arguments);
|
|
@@ -16398,16 +16134,16 @@ GFS4: `);
|
|
|
16398
16134
|
});
|
|
16399
16135
|
}
|
|
16400
16136
|
}
|
|
16401
|
-
var fs$writeFile =
|
|
16402
|
-
|
|
16403
|
-
function writeFile2(
|
|
16137
|
+
var fs$writeFile = fs4.writeFile;
|
|
16138
|
+
fs4.writeFile = writeFile2;
|
|
16139
|
+
function writeFile2(path5, data, options, cb) {
|
|
16404
16140
|
if (typeof options === "function")
|
|
16405
16141
|
cb = options, options = null;
|
|
16406
|
-
return go$writeFile(
|
|
16407
|
-
function go$writeFile(
|
|
16408
|
-
return fs$writeFile(
|
|
16142
|
+
return go$writeFile(path5, data, options, cb);
|
|
16143
|
+
function go$writeFile(path6, data2, options2, cb2, startTime) {
|
|
16144
|
+
return fs$writeFile(path6, data2, options2, function(err) {
|
|
16409
16145
|
if (err && (err.code === "EMFILE" || err.code === "ENFILE"))
|
|
16410
|
-
enqueue([go$writeFile, [
|
|
16146
|
+
enqueue([go$writeFile, [path6, data2, options2, cb2], err, startTime || Date.now(), Date.now()]);
|
|
16411
16147
|
else {
|
|
16412
16148
|
if (typeof cb2 === "function")
|
|
16413
16149
|
cb2.apply(this, arguments);
|
|
@@ -16415,17 +16151,17 @@ GFS4: `);
|
|
|
16415
16151
|
});
|
|
16416
16152
|
}
|
|
16417
16153
|
}
|
|
16418
|
-
var fs$appendFile =
|
|
16154
|
+
var fs$appendFile = fs4.appendFile;
|
|
16419
16155
|
if (fs$appendFile)
|
|
16420
|
-
|
|
16421
|
-
function appendFile2(
|
|
16156
|
+
fs4.appendFile = appendFile2;
|
|
16157
|
+
function appendFile2(path5, data, options, cb) {
|
|
16422
16158
|
if (typeof options === "function")
|
|
16423
16159
|
cb = options, options = null;
|
|
16424
|
-
return go$appendFile(
|
|
16425
|
-
function go$appendFile(
|
|
16426
|
-
return fs$appendFile(
|
|
16160
|
+
return go$appendFile(path5, data, options, cb);
|
|
16161
|
+
function go$appendFile(path6, data2, options2, cb2, startTime) {
|
|
16162
|
+
return fs$appendFile(path6, data2, options2, function(err) {
|
|
16427
16163
|
if (err && (err.code === "EMFILE" || err.code === "ENFILE"))
|
|
16428
|
-
enqueue([go$appendFile, [
|
|
16164
|
+
enqueue([go$appendFile, [path6, data2, options2, cb2], err, startTime || Date.now(), Date.now()]);
|
|
16429
16165
|
else {
|
|
16430
16166
|
if (typeof cb2 === "function")
|
|
16431
16167
|
cb2.apply(this, arguments);
|
|
@@ -16433,9 +16169,9 @@ GFS4: `);
|
|
|
16433
16169
|
});
|
|
16434
16170
|
}
|
|
16435
16171
|
}
|
|
16436
|
-
var fs$copyFile =
|
|
16172
|
+
var fs$copyFile = fs4.copyFile;
|
|
16437
16173
|
if (fs$copyFile)
|
|
16438
|
-
|
|
16174
|
+
fs4.copyFile = copyFile;
|
|
16439
16175
|
function copyFile(src, dest, flags, cb) {
|
|
16440
16176
|
if (typeof flags === "function") {
|
|
16441
16177
|
cb = flags;
|
|
@@ -16453,24 +16189,24 @@ GFS4: `);
|
|
|
16453
16189
|
});
|
|
16454
16190
|
}
|
|
16455
16191
|
}
|
|
16456
|
-
var fs$readdir =
|
|
16457
|
-
|
|
16192
|
+
var fs$readdir = fs4.readdir;
|
|
16193
|
+
fs4.readdir = readdir;
|
|
16458
16194
|
var noReaddirOptionVersions = /^v[0-5]\./;
|
|
16459
|
-
function readdir(
|
|
16195
|
+
function readdir(path5, options, cb) {
|
|
16460
16196
|
if (typeof options === "function")
|
|
16461
16197
|
cb = options, options = null;
|
|
16462
|
-
var go$readdir = noReaddirOptionVersions.test(process.version) ? function go$readdir2(
|
|
16463
|
-
return fs$readdir(
|
|
16464
|
-
} : function go$readdir2(
|
|
16465
|
-
return fs$readdir(
|
|
16198
|
+
var go$readdir = noReaddirOptionVersions.test(process.version) ? function go$readdir2(path6, options2, cb2, startTime) {
|
|
16199
|
+
return fs$readdir(path6, fs$readdirCallback(path6, options2, cb2, startTime));
|
|
16200
|
+
} : function go$readdir2(path6, options2, cb2, startTime) {
|
|
16201
|
+
return fs$readdir(path6, options2, fs$readdirCallback(path6, options2, cb2, startTime));
|
|
16466
16202
|
};
|
|
16467
|
-
return go$readdir(
|
|
16468
|
-
function fs$readdirCallback(
|
|
16203
|
+
return go$readdir(path5, options, cb);
|
|
16204
|
+
function fs$readdirCallback(path6, options2, cb2, startTime) {
|
|
16469
16205
|
return function(err, files) {
|
|
16470
16206
|
if (err && (err.code === "EMFILE" || err.code === "ENFILE"))
|
|
16471
16207
|
enqueue([
|
|
16472
16208
|
go$readdir,
|
|
16473
|
-
[
|
|
16209
|
+
[path6, options2, cb2],
|
|
16474
16210
|
err,
|
|
16475
16211
|
startTime || Date.now(),
|
|
16476
16212
|
Date.now()
|
|
@@ -16485,21 +16221,21 @@ GFS4: `);
|
|
|
16485
16221
|
}
|
|
16486
16222
|
}
|
|
16487
16223
|
if (process.version.substr(0, 4) === "v0.8") {
|
|
16488
|
-
var legStreams = legacy(
|
|
16224
|
+
var legStreams = legacy(fs4);
|
|
16489
16225
|
ReadStream = legStreams.ReadStream;
|
|
16490
16226
|
WriteStream = legStreams.WriteStream;
|
|
16491
16227
|
}
|
|
16492
|
-
var fs$ReadStream =
|
|
16228
|
+
var fs$ReadStream = fs4.ReadStream;
|
|
16493
16229
|
if (fs$ReadStream) {
|
|
16494
16230
|
ReadStream.prototype = Object.create(fs$ReadStream.prototype);
|
|
16495
16231
|
ReadStream.prototype.open = ReadStream$open;
|
|
16496
16232
|
}
|
|
16497
|
-
var fs$WriteStream =
|
|
16233
|
+
var fs$WriteStream = fs4.WriteStream;
|
|
16498
16234
|
if (fs$WriteStream) {
|
|
16499
16235
|
WriteStream.prototype = Object.create(fs$WriteStream.prototype);
|
|
16500
16236
|
WriteStream.prototype.open = WriteStream$open;
|
|
16501
16237
|
}
|
|
16502
|
-
Object.defineProperty(
|
|
16238
|
+
Object.defineProperty(fs4, "ReadStream", {
|
|
16503
16239
|
get: function() {
|
|
16504
16240
|
return ReadStream;
|
|
16505
16241
|
},
|
|
@@ -16509,7 +16245,7 @@ GFS4: `);
|
|
|
16509
16245
|
enumerable: true,
|
|
16510
16246
|
configurable: true
|
|
16511
16247
|
});
|
|
16512
|
-
Object.defineProperty(
|
|
16248
|
+
Object.defineProperty(fs4, "WriteStream", {
|
|
16513
16249
|
get: function() {
|
|
16514
16250
|
return WriteStream;
|
|
16515
16251
|
},
|
|
@@ -16520,7 +16256,7 @@ GFS4: `);
|
|
|
16520
16256
|
configurable: true
|
|
16521
16257
|
});
|
|
16522
16258
|
var FileReadStream = ReadStream;
|
|
16523
|
-
Object.defineProperty(
|
|
16259
|
+
Object.defineProperty(fs4, "FileReadStream", {
|
|
16524
16260
|
get: function() {
|
|
16525
16261
|
return FileReadStream;
|
|
16526
16262
|
},
|
|
@@ -16531,7 +16267,7 @@ GFS4: `);
|
|
|
16531
16267
|
configurable: true
|
|
16532
16268
|
});
|
|
16533
16269
|
var FileWriteStream = WriteStream;
|
|
16534
|
-
Object.defineProperty(
|
|
16270
|
+
Object.defineProperty(fs4, "FileWriteStream", {
|
|
16535
16271
|
get: function() {
|
|
16536
16272
|
return FileWriteStream;
|
|
16537
16273
|
},
|
|
@@ -16541,7 +16277,7 @@ GFS4: `);
|
|
|
16541
16277
|
enumerable: true,
|
|
16542
16278
|
configurable: true
|
|
16543
16279
|
});
|
|
16544
|
-
function ReadStream(
|
|
16280
|
+
function ReadStream(path5, options) {
|
|
16545
16281
|
if (this instanceof ReadStream)
|
|
16546
16282
|
return fs$ReadStream.apply(this, arguments), this;
|
|
16547
16283
|
else
|
|
@@ -16561,7 +16297,7 @@ GFS4: `);
|
|
|
16561
16297
|
}
|
|
16562
16298
|
});
|
|
16563
16299
|
}
|
|
16564
|
-
function WriteStream(
|
|
16300
|
+
function WriteStream(path5, options) {
|
|
16565
16301
|
if (this instanceof WriteStream)
|
|
16566
16302
|
return fs$WriteStream.apply(this, arguments), this;
|
|
16567
16303
|
else
|
|
@@ -16579,22 +16315,22 @@ GFS4: `);
|
|
|
16579
16315
|
}
|
|
16580
16316
|
});
|
|
16581
16317
|
}
|
|
16582
|
-
function createReadStream(
|
|
16583
|
-
return new
|
|
16318
|
+
function createReadStream(path5, options) {
|
|
16319
|
+
return new fs4.ReadStream(path5, options);
|
|
16584
16320
|
}
|
|
16585
|
-
function createWriteStream(
|
|
16586
|
-
return new
|
|
16321
|
+
function createWriteStream(path5, options) {
|
|
16322
|
+
return new fs4.WriteStream(path5, options);
|
|
16587
16323
|
}
|
|
16588
|
-
var fs$open =
|
|
16589
|
-
|
|
16590
|
-
function open(
|
|
16324
|
+
var fs$open = fs4.open;
|
|
16325
|
+
fs4.open = open;
|
|
16326
|
+
function open(path5, flags, mode, cb) {
|
|
16591
16327
|
if (typeof mode === "function")
|
|
16592
16328
|
cb = mode, mode = null;
|
|
16593
|
-
return go$open(
|
|
16594
|
-
function go$open(
|
|
16595
|
-
return fs$open(
|
|
16329
|
+
return go$open(path5, flags, mode, cb);
|
|
16330
|
+
function go$open(path6, flags2, mode2, cb2, startTime) {
|
|
16331
|
+
return fs$open(path6, flags2, mode2, function(err, fd) {
|
|
16596
16332
|
if (err && (err.code === "EMFILE" || err.code === "ENFILE"))
|
|
16597
|
-
enqueue([go$open, [
|
|
16333
|
+
enqueue([go$open, [path6, flags2, mode2, cb2], err, startTime || Date.now(), Date.now()]);
|
|
16598
16334
|
else {
|
|
16599
16335
|
if (typeof cb2 === "function")
|
|
16600
16336
|
cb2.apply(this, arguments);
|
|
@@ -16602,20 +16338,20 @@ GFS4: `);
|
|
|
16602
16338
|
});
|
|
16603
16339
|
}
|
|
16604
16340
|
}
|
|
16605
|
-
return
|
|
16341
|
+
return fs4;
|
|
16606
16342
|
}
|
|
16607
16343
|
function enqueue(elem) {
|
|
16608
16344
|
debug("ENQUEUE", elem[0].name, elem[1]);
|
|
16609
|
-
|
|
16345
|
+
fs3[gracefulQueue].push(elem);
|
|
16610
16346
|
retry();
|
|
16611
16347
|
}
|
|
16612
16348
|
var retryTimer;
|
|
16613
16349
|
function resetQueue() {
|
|
16614
16350
|
var now = Date.now();
|
|
16615
|
-
for (var i = 0;i <
|
|
16616
|
-
if (
|
|
16617
|
-
|
|
16618
|
-
|
|
16351
|
+
for (var i = 0;i < fs3[gracefulQueue].length; ++i) {
|
|
16352
|
+
if (fs3[gracefulQueue][i].length > 2) {
|
|
16353
|
+
fs3[gracefulQueue][i][3] = now;
|
|
16354
|
+
fs3[gracefulQueue][i][4] = now;
|
|
16619
16355
|
}
|
|
16620
16356
|
}
|
|
16621
16357
|
retry();
|
|
@@ -16623,9 +16359,9 @@ GFS4: `);
|
|
|
16623
16359
|
function retry() {
|
|
16624
16360
|
clearTimeout(retryTimer);
|
|
16625
16361
|
retryTimer = undefined;
|
|
16626
|
-
if (
|
|
16362
|
+
if (fs3[gracefulQueue].length === 0)
|
|
16627
16363
|
return;
|
|
16628
|
-
var elem =
|
|
16364
|
+
var elem = fs3[gracefulQueue].shift();
|
|
16629
16365
|
var fn = elem[0];
|
|
16630
16366
|
var args = elem[1];
|
|
16631
16367
|
var err = elem[2];
|
|
@@ -16647,7 +16383,7 @@ GFS4: `);
|
|
|
16647
16383
|
debug("RETRY", fn.name, args);
|
|
16648
16384
|
fn.apply(null, args.concat([startTime]));
|
|
16649
16385
|
} else {
|
|
16650
|
-
|
|
16386
|
+
fs3[gracefulQueue].push(elem);
|
|
16651
16387
|
}
|
|
16652
16388
|
}
|
|
16653
16389
|
if (retryTimer === undefined) {
|
|
@@ -16951,7 +16687,7 @@ var require_signal_exit = __commonJS((exports, module) => {
|
|
|
16951
16687
|
emitter.count -= 1;
|
|
16952
16688
|
};
|
|
16953
16689
|
module.exports.unload = unload;
|
|
16954
|
-
|
|
16690
|
+
emit2 = function emit3(event, code, signal) {
|
|
16955
16691
|
if (emitter.emitted[event]) {
|
|
16956
16692
|
return;
|
|
16957
16693
|
}
|
|
@@ -16967,8 +16703,8 @@ var require_signal_exit = __commonJS((exports, module) => {
|
|
|
16967
16703
|
var listeners = process3.listeners(sig);
|
|
16968
16704
|
if (listeners.length === emitter.count) {
|
|
16969
16705
|
unload();
|
|
16970
|
-
|
|
16971
|
-
|
|
16706
|
+
emit2("exit", null, sig);
|
|
16707
|
+
emit2("afterexit", null, sig);
|
|
16972
16708
|
if (isWin && sig === "SIGHUP") {
|
|
16973
16709
|
sig = "SIGINT";
|
|
16974
16710
|
}
|
|
@@ -17004,8 +16740,8 @@ var require_signal_exit = __commonJS((exports, module) => {
|
|
|
17004
16740
|
return;
|
|
17005
16741
|
}
|
|
17006
16742
|
process3.exitCode = code || 0;
|
|
17007
|
-
|
|
17008
|
-
|
|
16743
|
+
emit2("exit", process3.exitCode, null);
|
|
16744
|
+
emit2("afterexit", process3.exitCode, null);
|
|
17009
16745
|
originalProcessReallyExit.call(process3, process3.exitCode);
|
|
17010
16746
|
};
|
|
17011
16747
|
originalProcessEmit = process3.emit;
|
|
@@ -17015,8 +16751,8 @@ var require_signal_exit = __commonJS((exports, module) => {
|
|
|
17015
16751
|
process3.exitCode = arg;
|
|
17016
16752
|
}
|
|
17017
16753
|
var ret = originalProcessEmit.apply(this, arguments);
|
|
17018
|
-
|
|
17019
|
-
|
|
16754
|
+
emit2("exit", process3.exitCode, null);
|
|
16755
|
+
emit2("afterexit", process3.exitCode, null);
|
|
17020
16756
|
return ret;
|
|
17021
16757
|
} else {
|
|
17022
16758
|
return originalProcessEmit.apply(this, arguments);
|
|
@@ -17029,7 +16765,7 @@ var require_signal_exit = __commonJS((exports, module) => {
|
|
|
17029
16765
|
var EE;
|
|
17030
16766
|
var emitter;
|
|
17031
16767
|
var unload;
|
|
17032
|
-
var
|
|
16768
|
+
var emit2;
|
|
17033
16769
|
var sigListeners;
|
|
17034
16770
|
var loaded;
|
|
17035
16771
|
var load;
|
|
@@ -17042,10 +16778,10 @@ var require_signal_exit = __commonJS((exports, module) => {
|
|
|
17042
16778
|
// node_modules/proper-lockfile/lib/mtime-precision.js
|
|
17043
16779
|
var require_mtime_precision = __commonJS((exports, module) => {
|
|
17044
16780
|
var cacheSymbol = Symbol();
|
|
17045
|
-
function probe(file2,
|
|
17046
|
-
const cachedPrecision =
|
|
16781
|
+
function probe(file2, fs3, callback) {
|
|
16782
|
+
const cachedPrecision = fs3[cacheSymbol];
|
|
17047
16783
|
if (cachedPrecision) {
|
|
17048
|
-
return
|
|
16784
|
+
return fs3.stat(file2, (err, stat) => {
|
|
17049
16785
|
if (err) {
|
|
17050
16786
|
return callback(err);
|
|
17051
16787
|
}
|
|
@@ -17053,16 +16789,16 @@ var require_mtime_precision = __commonJS((exports, module) => {
|
|
|
17053
16789
|
});
|
|
17054
16790
|
}
|
|
17055
16791
|
const mtime = new Date(Math.ceil(Date.now() / 1000) * 1000 + 5);
|
|
17056
|
-
|
|
16792
|
+
fs3.utimes(file2, mtime, mtime, (err) => {
|
|
17057
16793
|
if (err) {
|
|
17058
16794
|
return callback(err);
|
|
17059
16795
|
}
|
|
17060
|
-
|
|
16796
|
+
fs3.stat(file2, (err2, stat) => {
|
|
17061
16797
|
if (err2) {
|
|
17062
16798
|
return callback(err2);
|
|
17063
16799
|
}
|
|
17064
16800
|
const precision = stat.mtime.getTime() % 1000 === 0 ? "s" : "ms";
|
|
17065
|
-
Object.defineProperty(
|
|
16801
|
+
Object.defineProperty(fs3, cacheSymbol, { value: precision });
|
|
17066
16802
|
callback(null, stat.mtime, precision);
|
|
17067
16803
|
});
|
|
17068
16804
|
});
|
|
@@ -17080,8 +16816,8 @@ var require_mtime_precision = __commonJS((exports, module) => {
|
|
|
17080
16816
|
|
|
17081
16817
|
// node_modules/proper-lockfile/lib/lockfile.js
|
|
17082
16818
|
var require_lockfile = __commonJS((exports, module) => {
|
|
17083
|
-
var
|
|
17084
|
-
var
|
|
16819
|
+
var path5 = __require("path");
|
|
16820
|
+
var fs3 = require_graceful_fs();
|
|
17085
16821
|
var retry = require_retry();
|
|
17086
16822
|
var onExit = require_signal_exit();
|
|
17087
16823
|
var mtimePrecision = require_mtime_precision();
|
|
@@ -17091,7 +16827,7 @@ var require_lockfile = __commonJS((exports, module) => {
|
|
|
17091
16827
|
}
|
|
17092
16828
|
function resolveCanonicalPath(file2, options, callback) {
|
|
17093
16829
|
if (!options.realpath) {
|
|
17094
|
-
return callback(null,
|
|
16830
|
+
return callback(null, path5.resolve(file2));
|
|
17095
16831
|
}
|
|
17096
16832
|
options.fs.realpath(file2, callback);
|
|
17097
16833
|
}
|
|
@@ -17204,7 +16940,7 @@ var require_lockfile = __commonJS((exports, module) => {
|
|
|
17204
16940
|
update: null,
|
|
17205
16941
|
realpath: true,
|
|
17206
16942
|
retries: 0,
|
|
17207
|
-
fs:
|
|
16943
|
+
fs: fs3,
|
|
17208
16944
|
onCompromised: (err) => {
|
|
17209
16945
|
throw err;
|
|
17210
16946
|
},
|
|
@@ -17248,7 +16984,7 @@ var require_lockfile = __commonJS((exports, module) => {
|
|
|
17248
16984
|
}
|
|
17249
16985
|
function unlock(file2, options, callback) {
|
|
17250
16986
|
options = {
|
|
17251
|
-
fs:
|
|
16987
|
+
fs: fs3,
|
|
17252
16988
|
realpath: true,
|
|
17253
16989
|
...options
|
|
17254
16990
|
};
|
|
@@ -17270,7 +17006,7 @@ var require_lockfile = __commonJS((exports, module) => {
|
|
|
17270
17006
|
options = {
|
|
17271
17007
|
stale: 1e4,
|
|
17272
17008
|
realpath: true,
|
|
17273
|
-
fs:
|
|
17009
|
+
fs: fs3,
|
|
17274
17010
|
...options
|
|
17275
17011
|
};
|
|
17276
17012
|
options.stale = Math.max(options.stale || 0, 2000);
|
|
@@ -17305,16 +17041,16 @@ var require_lockfile = __commonJS((exports, module) => {
|
|
|
17305
17041
|
|
|
17306
17042
|
// node_modules/proper-lockfile/lib/adapter.js
|
|
17307
17043
|
var require_adapter = __commonJS((exports, module) => {
|
|
17308
|
-
var
|
|
17309
|
-
function createSyncFs(
|
|
17044
|
+
var fs3 = require_graceful_fs();
|
|
17045
|
+
function createSyncFs(fs4) {
|
|
17310
17046
|
const methods = ["mkdir", "realpath", "stat", "rmdir", "utimes"];
|
|
17311
|
-
const newFs = { ...
|
|
17047
|
+
const newFs = { ...fs4 };
|
|
17312
17048
|
methods.forEach((method) => {
|
|
17313
17049
|
newFs[method] = (...args) => {
|
|
17314
17050
|
const callback = args.pop();
|
|
17315
17051
|
let ret;
|
|
17316
17052
|
try {
|
|
17317
|
-
ret =
|
|
17053
|
+
ret = fs4[`${method}Sync`](...args);
|
|
17318
17054
|
} catch (err) {
|
|
17319
17055
|
return callback(err);
|
|
17320
17056
|
}
|
|
@@ -17323,79 +17059,513 @@ var require_adapter = __commonJS((exports, module) => {
|
|
|
17323
17059
|
});
|
|
17324
17060
|
return newFs;
|
|
17325
17061
|
}
|
|
17326
|
-
function toPromise(method) {
|
|
17327
|
-
return (...args) => new Promise((
|
|
17328
|
-
args.push((err, result) => {
|
|
17329
|
-
if (err) {
|
|
17330
|
-
reject(err);
|
|
17331
|
-
} else {
|
|
17332
|
-
|
|
17333
|
-
}
|
|
17334
|
-
});
|
|
17335
|
-
method(...args);
|
|
17336
|
-
});
|
|
17062
|
+
function toPromise(method) {
|
|
17063
|
+
return (...args) => new Promise((resolve3, reject) => {
|
|
17064
|
+
args.push((err, result) => {
|
|
17065
|
+
if (err) {
|
|
17066
|
+
reject(err);
|
|
17067
|
+
} else {
|
|
17068
|
+
resolve3(result);
|
|
17069
|
+
}
|
|
17070
|
+
});
|
|
17071
|
+
method(...args);
|
|
17072
|
+
});
|
|
17073
|
+
}
|
|
17074
|
+
function toSync(method) {
|
|
17075
|
+
return (...args) => {
|
|
17076
|
+
let err;
|
|
17077
|
+
let result;
|
|
17078
|
+
args.push((_err, _result) => {
|
|
17079
|
+
err = _err;
|
|
17080
|
+
result = _result;
|
|
17081
|
+
});
|
|
17082
|
+
method(...args);
|
|
17083
|
+
if (err) {
|
|
17084
|
+
throw err;
|
|
17085
|
+
}
|
|
17086
|
+
return result;
|
|
17087
|
+
};
|
|
17088
|
+
}
|
|
17089
|
+
function toSyncOptions(options) {
|
|
17090
|
+
options = { ...options };
|
|
17091
|
+
options.fs = createSyncFs(options.fs || fs3);
|
|
17092
|
+
if (typeof options.retries === "number" && options.retries > 0 || options.retries && typeof options.retries.retries === "number" && options.retries.retries > 0) {
|
|
17093
|
+
throw Object.assign(new Error("Cannot use retries with the sync api"), { code: "ESYNC" });
|
|
17094
|
+
}
|
|
17095
|
+
return options;
|
|
17096
|
+
}
|
|
17097
|
+
module.exports = {
|
|
17098
|
+
toPromise,
|
|
17099
|
+
toSync,
|
|
17100
|
+
toSyncOptions
|
|
17101
|
+
};
|
|
17102
|
+
});
|
|
17103
|
+
|
|
17104
|
+
// node_modules/proper-lockfile/index.js
|
|
17105
|
+
var require_proper_lockfile = __commonJS((exports, module) => {
|
|
17106
|
+
var lockfile = require_lockfile();
|
|
17107
|
+
var { toPromise, toSync, toSyncOptions } = require_adapter();
|
|
17108
|
+
async function lock(file2, options) {
|
|
17109
|
+
const release = await toPromise(lockfile.lock)(file2, options);
|
|
17110
|
+
return toPromise(release);
|
|
17111
|
+
}
|
|
17112
|
+
function lockSync(file2, options) {
|
|
17113
|
+
const release = toSync(lockfile.lock)(file2, toSyncOptions(options));
|
|
17114
|
+
return toSync(release);
|
|
17115
|
+
}
|
|
17116
|
+
function unlock(file2, options) {
|
|
17117
|
+
return toPromise(lockfile.unlock)(file2, options);
|
|
17118
|
+
}
|
|
17119
|
+
function unlockSync(file2, options) {
|
|
17120
|
+
return toSync(lockfile.unlock)(file2, toSyncOptions(options));
|
|
17121
|
+
}
|
|
17122
|
+
function check2(file2, options) {
|
|
17123
|
+
return toPromise(lockfile.check)(file2, options);
|
|
17124
|
+
}
|
|
17125
|
+
function checkSync(file2, options) {
|
|
17126
|
+
return toSync(lockfile.check)(file2, toSyncOptions(options));
|
|
17127
|
+
}
|
|
17128
|
+
module.exports = lock;
|
|
17129
|
+
module.exports.lock = lock;
|
|
17130
|
+
module.exports.unlock = unlock;
|
|
17131
|
+
module.exports.lockSync = lockSync;
|
|
17132
|
+
module.exports.unlockSync = unlockSync;
|
|
17133
|
+
module.exports.check = check2;
|
|
17134
|
+
module.exports.checkSync = checkSync;
|
|
17135
|
+
});
|
|
17136
|
+
|
|
17137
|
+
// src/parallel/file-locks.ts
|
|
17138
|
+
import * as fs3 from "fs";
|
|
17139
|
+
import * as path5 from "path";
|
|
17140
|
+
function getLockFilePath(directory, filePath) {
|
|
17141
|
+
const normalized = path5.resolve(directory, filePath);
|
|
17142
|
+
const baseDir = path5.resolve(directory) + path5.sep;
|
|
17143
|
+
const pathOk = process.platform === "win32" ? normalized.toLowerCase().startsWith(baseDir.toLowerCase()) : normalized.startsWith(baseDir);
|
|
17144
|
+
if (!pathOk) {
|
|
17145
|
+
throw new Error("Invalid file path: path traversal not allowed");
|
|
17146
|
+
}
|
|
17147
|
+
const hash2 = Buffer.from(normalized).toString("base64").replace(/[/+=]/g, "_");
|
|
17148
|
+
return path5.join(directory, LOCKS_DIR, `${hash2}.lock`);
|
|
17149
|
+
}
|
|
17150
|
+
async function tryAcquireLock(directory, filePath, agent, taskId) {
|
|
17151
|
+
const lockPath = getLockFilePath(directory, filePath);
|
|
17152
|
+
const locksDir = path5.dirname(lockPath);
|
|
17153
|
+
if (!fs3.existsSync(locksDir)) {
|
|
17154
|
+
fs3.mkdirSync(locksDir, { recursive: true });
|
|
17155
|
+
}
|
|
17156
|
+
if (!fs3.existsSync(lockPath)) {
|
|
17157
|
+
fs3.writeFileSync(lockPath, "", "utf-8");
|
|
17158
|
+
}
|
|
17159
|
+
let release;
|
|
17160
|
+
try {
|
|
17161
|
+
release = await import_proper_lockfile.default.lock(lockPath, {
|
|
17162
|
+
stale: LOCK_TIMEOUT_MS,
|
|
17163
|
+
retries: { retries: 0 },
|
|
17164
|
+
realpath: false
|
|
17165
|
+
});
|
|
17166
|
+
} catch (err) {
|
|
17167
|
+
const code = err.code;
|
|
17168
|
+
if (code === "ELOCKED" || code === "EEXIST") {
|
|
17169
|
+
return { acquired: false };
|
|
17170
|
+
}
|
|
17171
|
+
throw err;
|
|
17172
|
+
}
|
|
17173
|
+
const lock = {
|
|
17174
|
+
filePath,
|
|
17175
|
+
agent,
|
|
17176
|
+
taskId,
|
|
17177
|
+
timestamp: new Date().toISOString(),
|
|
17178
|
+
expiresAt: Date.now() + LOCK_TIMEOUT_MS,
|
|
17179
|
+
_release: release
|
|
17180
|
+
};
|
|
17181
|
+
return { acquired: true, lock };
|
|
17182
|
+
}
|
|
17183
|
+
var import_proper_lockfile, LOCKS_DIR = ".swarm/locks", LOCK_TIMEOUT_MS;
|
|
17184
|
+
var init_file_locks = __esm(() => {
|
|
17185
|
+
import_proper_lockfile = __toESM(require_proper_lockfile(), 1);
|
|
17186
|
+
LOCK_TIMEOUT_MS = 5 * 60 * 1000;
|
|
17187
|
+
});
|
|
17188
|
+
|
|
17189
|
+
// src/evidence/lock.ts
|
|
17190
|
+
function backoffMs(attempt) {
|
|
17191
|
+
const base = Math.min(BACKOFF_START_MS * 2 ** attempt, BACKOFF_MAX_MS);
|
|
17192
|
+
const jitter = base * BACKOFF_JITTER_RATIO * (Math.random() * 2 - 1);
|
|
17193
|
+
return Math.max(1, Math.round(base + jitter));
|
|
17194
|
+
}
|
|
17195
|
+
async function withEvidenceLock(directory, evidencePath, agent, taskId, fn, timeoutMs = 60000) {
|
|
17196
|
+
const deadline = Date.now() + timeoutMs;
|
|
17197
|
+
let attempt = 0;
|
|
17198
|
+
while (true) {
|
|
17199
|
+
const result = await tryAcquireLock(directory, evidencePath, agent, taskId);
|
|
17200
|
+
if (result.acquired) {
|
|
17201
|
+
const lock = result.lock;
|
|
17202
|
+
if (attempt > 0) {
|
|
17203
|
+
emit("evidence_lock_stale_recovered", {
|
|
17204
|
+
directory,
|
|
17205
|
+
evidencePath,
|
|
17206
|
+
agent,
|
|
17207
|
+
taskId,
|
|
17208
|
+
attempt
|
|
17209
|
+
});
|
|
17210
|
+
}
|
|
17211
|
+
emit("evidence_lock_acquired", {
|
|
17212
|
+
directory,
|
|
17213
|
+
evidencePath,
|
|
17214
|
+
agent,
|
|
17215
|
+
taskId,
|
|
17216
|
+
attempt
|
|
17217
|
+
});
|
|
17218
|
+
try {
|
|
17219
|
+
return await fn();
|
|
17220
|
+
} finally {
|
|
17221
|
+
if (lock._release) {
|
|
17222
|
+
try {
|
|
17223
|
+
await lock._release();
|
|
17224
|
+
} catch {}
|
|
17225
|
+
}
|
|
17226
|
+
}
|
|
17227
|
+
}
|
|
17228
|
+
if (Date.now() >= deadline) {
|
|
17229
|
+
throw new EvidenceLockTimeoutError(directory, evidencePath, agent, taskId, timeoutMs);
|
|
17230
|
+
}
|
|
17231
|
+
emit("evidence_lock_contended", {
|
|
17232
|
+
directory,
|
|
17233
|
+
evidencePath,
|
|
17234
|
+
agent,
|
|
17235
|
+
taskId,
|
|
17236
|
+
attempt
|
|
17237
|
+
});
|
|
17238
|
+
const delay = Math.min(backoffMs(attempt), deadline - Date.now());
|
|
17239
|
+
if (delay > 0) {
|
|
17240
|
+
await new Promise((resolve4) => setTimeout(resolve4, delay));
|
|
17241
|
+
}
|
|
17242
|
+
attempt++;
|
|
17243
|
+
}
|
|
17244
|
+
}
|
|
17245
|
+
var EvidenceLockTimeoutError, BACKOFF_START_MS = 50, BACKOFF_MAX_MS = 2000, BACKOFF_JITTER_RATIO = 0.25;
|
|
17246
|
+
var init_lock = __esm(() => {
|
|
17247
|
+
init_file_locks();
|
|
17248
|
+
init_telemetry();
|
|
17249
|
+
EvidenceLockTimeoutError = class EvidenceLockTimeoutError extends Error {
|
|
17250
|
+
directory;
|
|
17251
|
+
evidencePath;
|
|
17252
|
+
agent;
|
|
17253
|
+
taskId;
|
|
17254
|
+
constructor(directory, evidencePath, agent, taskId, timeoutMs) {
|
|
17255
|
+
super(`Evidence lock timeout after ${timeoutMs}ms for ${evidencePath} (agent=${agent}, task=${taskId})`);
|
|
17256
|
+
this.name = "EvidenceLockTimeoutError";
|
|
17257
|
+
this.directory = directory;
|
|
17258
|
+
this.evidencePath = evidencePath;
|
|
17259
|
+
this.agent = agent;
|
|
17260
|
+
this.taskId = taskId;
|
|
17261
|
+
}
|
|
17262
|
+
};
|
|
17263
|
+
});
|
|
17264
|
+
|
|
17265
|
+
// src/validation/task-id.ts
|
|
17266
|
+
function checkUnsafeChars(taskId) {
|
|
17267
|
+
if (!taskId || taskId.length === 0) {
|
|
17268
|
+
return "Invalid task ID: empty string";
|
|
17269
|
+
}
|
|
17270
|
+
if (/\0/.test(taskId)) {
|
|
17271
|
+
return "Invalid task ID: contains null bytes";
|
|
17272
|
+
}
|
|
17273
|
+
for (let i = 0;i < taskId.length; i++) {
|
|
17274
|
+
if (taskId.charCodeAt(i) < 32) {
|
|
17275
|
+
return "Invalid task ID: contains control characters";
|
|
17276
|
+
}
|
|
17277
|
+
}
|
|
17278
|
+
if (taskId.includes("..") || taskId.includes("/") || taskId.includes("\\")) {
|
|
17279
|
+
return "Invalid task ID: path traversal detected";
|
|
17280
|
+
}
|
|
17281
|
+
return;
|
|
17282
|
+
}
|
|
17283
|
+
function sanitizeTaskId(taskId) {
|
|
17284
|
+
const unsafeMsg = checkUnsafeChars(taskId);
|
|
17285
|
+
if (unsafeMsg) {
|
|
17286
|
+
throw new Error(unsafeMsg);
|
|
17287
|
+
}
|
|
17288
|
+
if (STRICT_TASK_ID_PATTERN.test(taskId) || RETRO_TASK_ID_REGEX.test(taskId) || INTERNAL_TOOL_ID_REGEX.test(taskId) || GENERAL_TASK_ID_REGEX.test(taskId)) {
|
|
17289
|
+
return taskId;
|
|
17290
|
+
}
|
|
17291
|
+
throw new Error(`Invalid task ID: must be alphanumeric (ASCII) with optional hyphens, underscores, or dots, got "${taskId}"`);
|
|
17292
|
+
}
|
|
17293
|
+
var STRICT_TASK_ID_PATTERN, RETRO_TASK_ID_REGEX, INTERNAL_TOOL_ID_REGEX, GENERAL_TASK_ID_REGEX;
|
|
17294
|
+
var init_task_id = __esm(() => {
|
|
17295
|
+
STRICT_TASK_ID_PATTERN = /^\d+\.\d+(\.\d+)*$/;
|
|
17296
|
+
RETRO_TASK_ID_REGEX = /^retro-\d+$/;
|
|
17297
|
+
INTERNAL_TOOL_ID_REGEX = /^(?:sast_scan|quality_budget|syntax_check|placeholder_scan|sbom_generate|build|secretscan)$/;
|
|
17298
|
+
GENERAL_TASK_ID_REGEX = /^[a-zA-Z0-9][a-zA-Z0-9._-]*$/;
|
|
17299
|
+
});
|
|
17300
|
+
|
|
17301
|
+
// src/evidence/manager.ts
|
|
17302
|
+
import { mkdirSync as mkdirSync3, readdirSync as readdirSync3, rmSync, statSync as statSync3 } from "fs";
|
|
17303
|
+
import * as fs4 from "fs/promises";
|
|
17304
|
+
import * as path6 from "path";
|
|
17305
|
+
function isValidEvidenceType(type) {
|
|
17306
|
+
return VALID_EVIDENCE_TYPES.includes(type);
|
|
17307
|
+
}
|
|
17308
|
+
async function saveEvidence(directory, taskId, evidence) {
|
|
17309
|
+
const sanitizedTaskId = sanitizeTaskId2(taskId);
|
|
17310
|
+
const relativePath = path6.join("evidence", sanitizedTaskId, "evidence.json");
|
|
17311
|
+
validateSwarmPath(directory, relativePath);
|
|
17312
|
+
return withEvidenceLock(directory, relativePath, "evidence-manager", sanitizedTaskId, async () => {
|
|
17313
|
+
const evidencePath = validateSwarmPath(directory, relativePath);
|
|
17314
|
+
const evidenceDir = path6.dirname(evidencePath);
|
|
17315
|
+
let bundle;
|
|
17316
|
+
const existingContent = await readSwarmFileAsync(directory, relativePath);
|
|
17317
|
+
if (existingContent !== null) {
|
|
17318
|
+
try {
|
|
17319
|
+
const parsed = JSON.parse(existingContent);
|
|
17320
|
+
bundle = EvidenceBundleSchema.parse(parsed);
|
|
17321
|
+
} catch (error49) {
|
|
17322
|
+
warn(`Existing evidence bundle invalid for task ${sanitizedTaskId}, creating new: ${error49 instanceof Error ? error49.message : String(error49)}`);
|
|
17323
|
+
const now = new Date().toISOString();
|
|
17324
|
+
bundle = {
|
|
17325
|
+
schema_version: "1.0.0",
|
|
17326
|
+
task_id: sanitizedTaskId,
|
|
17327
|
+
entries: [],
|
|
17328
|
+
created_at: now,
|
|
17329
|
+
updated_at: now
|
|
17330
|
+
};
|
|
17331
|
+
}
|
|
17332
|
+
} else {
|
|
17333
|
+
const now = new Date().toISOString();
|
|
17334
|
+
bundle = {
|
|
17335
|
+
schema_version: "1.0.0",
|
|
17336
|
+
task_id: sanitizedTaskId,
|
|
17337
|
+
entries: [],
|
|
17338
|
+
created_at: now,
|
|
17339
|
+
updated_at: now
|
|
17340
|
+
};
|
|
17341
|
+
}
|
|
17342
|
+
const MAX_BUNDLE_ENTRIES = 100;
|
|
17343
|
+
let entries = [...bundle.entries, evidence];
|
|
17344
|
+
if (entries.length > MAX_BUNDLE_ENTRIES) {
|
|
17345
|
+
entries = entries.slice(entries.length - MAX_BUNDLE_ENTRIES);
|
|
17346
|
+
}
|
|
17347
|
+
const updatedBundle = {
|
|
17348
|
+
...bundle,
|
|
17349
|
+
entries,
|
|
17350
|
+
updated_at: new Date().toISOString()
|
|
17351
|
+
};
|
|
17352
|
+
const bundleJson = JSON.stringify(updatedBundle);
|
|
17353
|
+
if (bundleJson.length > EVIDENCE_MAX_JSON_BYTES) {
|
|
17354
|
+
throw new Error(`Evidence bundle size (${bundleJson.length} bytes) exceeds maximum (${EVIDENCE_MAX_JSON_BYTES} bytes)`);
|
|
17355
|
+
}
|
|
17356
|
+
mkdirSync3(evidenceDir, { recursive: true });
|
|
17357
|
+
const tempPath = path6.join(evidenceDir, `evidence.json.tmp.${Date.now()}.${process.pid}`);
|
|
17358
|
+
try {
|
|
17359
|
+
await Bun.write(tempPath, bundleJson);
|
|
17360
|
+
await fs4.rename(tempPath, evidencePath);
|
|
17361
|
+
} catch (error49) {
|
|
17362
|
+
try {
|
|
17363
|
+
rmSync(tempPath, { force: true });
|
|
17364
|
+
} catch {}
|
|
17365
|
+
throw error49;
|
|
17366
|
+
}
|
|
17367
|
+
return updatedBundle;
|
|
17368
|
+
});
|
|
17369
|
+
}
|
|
17370
|
+
function isFlatRetrospective(parsed) {
|
|
17371
|
+
return parsed !== null && typeof parsed === "object" && !Array.isArray(parsed) && parsed.type === "retrospective" && !parsed.schema_version;
|
|
17372
|
+
}
|
|
17373
|
+
function remapLegacyTaskComplexity(entry) {
|
|
17374
|
+
const taskComplexity = entry.task_complexity;
|
|
17375
|
+
if (typeof taskComplexity === "string" && taskComplexity in LEGACY_TASK_COMPLEXITY_MAP) {
|
|
17376
|
+
return {
|
|
17377
|
+
...entry,
|
|
17378
|
+
task_complexity: LEGACY_TASK_COMPLEXITY_MAP[taskComplexity]
|
|
17379
|
+
};
|
|
17380
|
+
}
|
|
17381
|
+
return entry;
|
|
17382
|
+
}
|
|
17383
|
+
function wrapFlatRetrospective(flatEntry, taskId) {
|
|
17384
|
+
const now = new Date().toISOString();
|
|
17385
|
+
const remappedEntry = remapLegacyTaskComplexity(flatEntry);
|
|
17386
|
+
return {
|
|
17387
|
+
schema_version: "1.0.0",
|
|
17388
|
+
task_id: remappedEntry.task_id ?? taskId,
|
|
17389
|
+
created_at: remappedEntry.timestamp ?? now,
|
|
17390
|
+
updated_at: remappedEntry.timestamp ?? now,
|
|
17391
|
+
entries: [remappedEntry]
|
|
17392
|
+
};
|
|
17393
|
+
}
|
|
17394
|
+
async function loadEvidence(directory, taskId) {
|
|
17395
|
+
const sanitizedTaskId = sanitizeTaskId2(taskId);
|
|
17396
|
+
const relativePath = path6.join("evidence", sanitizedTaskId, "evidence.json");
|
|
17397
|
+
const evidencePath = validateSwarmPath(directory, relativePath);
|
|
17398
|
+
const content = await readSwarmFileAsync(directory, relativePath);
|
|
17399
|
+
if (content === null) {
|
|
17400
|
+
return { status: "not_found" };
|
|
17401
|
+
}
|
|
17402
|
+
let parsed;
|
|
17403
|
+
try {
|
|
17404
|
+
parsed = JSON.parse(content);
|
|
17405
|
+
} catch {
|
|
17406
|
+
return { status: "invalid_schema", errors: ["Invalid JSON"] };
|
|
17407
|
+
}
|
|
17408
|
+
if (isFlatRetrospective(parsed)) {
|
|
17409
|
+
const wrappedBundle = wrapFlatRetrospective(parsed, sanitizedTaskId);
|
|
17410
|
+
try {
|
|
17411
|
+
const validated = EvidenceBundleSchema.parse(wrappedBundle);
|
|
17412
|
+
try {
|
|
17413
|
+
await withEvidenceLock(directory, relativePath, "evidence-loader", sanitizedTaskId, async () => {
|
|
17414
|
+
const evidenceDir = path6.dirname(evidencePath);
|
|
17415
|
+
const bundleJson = JSON.stringify(validated);
|
|
17416
|
+
const tempPath = path6.join(evidenceDir, `evidence.json.tmp.${Date.now()}.${process.pid}`);
|
|
17417
|
+
try {
|
|
17418
|
+
await Bun.write(tempPath, bundleJson);
|
|
17419
|
+
await fs4.rename(tempPath, evidencePath);
|
|
17420
|
+
} catch (writeError) {
|
|
17421
|
+
try {
|
|
17422
|
+
rmSync(tempPath, { force: true });
|
|
17423
|
+
} catch {}
|
|
17424
|
+
warn(`Failed to persist repaired flat retrospective for task ${sanitizedTaskId}: ${writeError instanceof Error ? writeError.message : String(writeError)}`);
|
|
17425
|
+
}
|
|
17426
|
+
});
|
|
17427
|
+
} catch (lockErr) {
|
|
17428
|
+
warn(`Evidence lock failed during flat-retrospective write-back for task ${sanitizedTaskId}: ${lockErr instanceof Error ? lockErr.message : String(lockErr)}`);
|
|
17429
|
+
}
|
|
17430
|
+
return { status: "found", bundle: validated };
|
|
17431
|
+
} catch (error49) {
|
|
17432
|
+
warn(`Wrapped flat retrospective failed validation for task ${sanitizedTaskId}: ${error49 instanceof Error ? error49.message : String(error49)}`);
|
|
17433
|
+
const errors3 = error49 instanceof ZodError ? error49.issues.map((e) => `${e.path.join(".")}: ${e.message}`) : [error49 instanceof Error ? error49.message : String(error49)];
|
|
17434
|
+
return { status: "invalid_schema", errors: errors3 };
|
|
17435
|
+
}
|
|
17436
|
+
}
|
|
17437
|
+
try {
|
|
17438
|
+
const validated = EvidenceBundleSchema.parse(parsed);
|
|
17439
|
+
return { status: "found", bundle: validated };
|
|
17440
|
+
} catch (error49) {
|
|
17441
|
+
warn(`Evidence bundle validation failed for task ${sanitizedTaskId}: ${error49 instanceof Error ? error49.message : String(error49)}`);
|
|
17442
|
+
const errors3 = error49 instanceof ZodError ? error49.issues.map((e) => `${e.path.join(".")}: ${e.message}`) : [error49 instanceof Error ? error49.message : String(error49)];
|
|
17443
|
+
return { status: "invalid_schema", errors: errors3 };
|
|
17444
|
+
}
|
|
17445
|
+
}
|
|
17446
|
+
async function listEvidenceTaskIds(directory) {
|
|
17447
|
+
const evidenceBasePath = validateSwarmPath(directory, "evidence");
|
|
17448
|
+
try {
|
|
17449
|
+
statSync3(evidenceBasePath);
|
|
17450
|
+
} catch {
|
|
17451
|
+
return [];
|
|
17452
|
+
}
|
|
17453
|
+
let entries;
|
|
17454
|
+
try {
|
|
17455
|
+
entries = readdirSync3(evidenceBasePath);
|
|
17456
|
+
} catch {
|
|
17457
|
+
return [];
|
|
17337
17458
|
}
|
|
17338
|
-
|
|
17339
|
-
|
|
17340
|
-
|
|
17341
|
-
|
|
17342
|
-
|
|
17343
|
-
|
|
17344
|
-
|
|
17345
|
-
}
|
|
17346
|
-
|
|
17347
|
-
|
|
17348
|
-
|
|
17459
|
+
const taskIds = [];
|
|
17460
|
+
for (const entry of entries) {
|
|
17461
|
+
const entryPath = path6.join(evidenceBasePath, entry);
|
|
17462
|
+
try {
|
|
17463
|
+
const stats = statSync3(entryPath);
|
|
17464
|
+
if (!stats.isDirectory()) {
|
|
17465
|
+
continue;
|
|
17466
|
+
}
|
|
17467
|
+
sanitizeTaskId2(entry);
|
|
17468
|
+
taskIds.push(entry);
|
|
17469
|
+
} catch (error49) {
|
|
17470
|
+
if (error49 instanceof Error && !error49.message.startsWith("Invalid task ID")) {
|
|
17471
|
+
warn(`Error reading evidence entry '${entry}': ${error49.message}`);
|
|
17349
17472
|
}
|
|
17350
|
-
return result;
|
|
17351
|
-
};
|
|
17352
|
-
}
|
|
17353
|
-
function toSyncOptions(options) {
|
|
17354
|
-
options = { ...options };
|
|
17355
|
-
options.fs = createSyncFs(options.fs || fs4);
|
|
17356
|
-
if (typeof options.retries === "number" && options.retries > 0 || options.retries && typeof options.retries.retries === "number" && options.retries.retries > 0) {
|
|
17357
|
-
throw Object.assign(new Error("Cannot use retries with the sync api"), { code: "ESYNC" });
|
|
17358
17473
|
}
|
|
17359
|
-
return options;
|
|
17360
|
-
}
|
|
17361
|
-
module.exports = {
|
|
17362
|
-
toPromise,
|
|
17363
|
-
toSync,
|
|
17364
|
-
toSyncOptions
|
|
17365
|
-
};
|
|
17366
|
-
});
|
|
17367
|
-
|
|
17368
|
-
// node_modules/proper-lockfile/index.js
|
|
17369
|
-
var require_proper_lockfile = __commonJS((exports, module) => {
|
|
17370
|
-
var lockfile = require_lockfile();
|
|
17371
|
-
var { toPromise, toSync, toSyncOptions } = require_adapter();
|
|
17372
|
-
async function lock(file2, options) {
|
|
17373
|
-
const release = await toPromise(lockfile.lock)(file2, options);
|
|
17374
|
-
return toPromise(release);
|
|
17375
17474
|
}
|
|
17376
|
-
|
|
17377
|
-
|
|
17378
|
-
|
|
17475
|
+
return taskIds.sort();
|
|
17476
|
+
}
|
|
17477
|
+
async function deleteEvidence(directory, taskId) {
|
|
17478
|
+
const sanitizedTaskId = sanitizeTaskId2(taskId);
|
|
17479
|
+
const relativePath = path6.join("evidence", sanitizedTaskId);
|
|
17480
|
+
const evidenceDir = validateSwarmPath(directory, relativePath);
|
|
17481
|
+
try {
|
|
17482
|
+
statSync3(evidenceDir);
|
|
17483
|
+
} catch {
|
|
17484
|
+
return false;
|
|
17379
17485
|
}
|
|
17380
|
-
|
|
17381
|
-
|
|
17486
|
+
try {
|
|
17487
|
+
rmSync(evidenceDir, { recursive: true, force: true });
|
|
17488
|
+
return true;
|
|
17489
|
+
} catch (error49) {
|
|
17490
|
+
warn(`Failed to delete evidence for task ${sanitizedTaskId}: ${error49 instanceof Error ? error49.message : String(error49)}`);
|
|
17491
|
+
return false;
|
|
17382
17492
|
}
|
|
17383
|
-
|
|
17384
|
-
|
|
17493
|
+
}
|
|
17494
|
+
async function checkRequirementCoverage(phase, directory) {
|
|
17495
|
+
const relativePath = path6.join("evidence", `req-coverage-phase-${phase}.json`);
|
|
17496
|
+
const absolutePath = path6.resolve(directory, ".swarm", relativePath);
|
|
17497
|
+
try {
|
|
17498
|
+
await fs4.access(absolutePath);
|
|
17499
|
+
return { exists: true, path: absolutePath };
|
|
17500
|
+
} catch {
|
|
17501
|
+
return { exists: false, path: absolutePath };
|
|
17385
17502
|
}
|
|
17386
|
-
|
|
17387
|
-
|
|
17503
|
+
}
|
|
17504
|
+
async function archiveEvidence(directory, maxAgeDays, maxBundles) {
|
|
17505
|
+
const taskIds = await listEvidenceTaskIds(directory);
|
|
17506
|
+
const cutoffDate = new Date;
|
|
17507
|
+
cutoffDate.setDate(cutoffDate.getDate() - maxAgeDays);
|
|
17508
|
+
const cutoffIso = cutoffDate.toISOString();
|
|
17509
|
+
const archived = [];
|
|
17510
|
+
const remainingBundles = [];
|
|
17511
|
+
for (const taskId of taskIds) {
|
|
17512
|
+
const result = await loadEvidence(directory, taskId);
|
|
17513
|
+
if (result.status !== "found") {
|
|
17514
|
+
continue;
|
|
17515
|
+
}
|
|
17516
|
+
if (result.bundle.updated_at < cutoffIso) {
|
|
17517
|
+
const deleted = await deleteEvidence(directory, taskId);
|
|
17518
|
+
if (deleted) {
|
|
17519
|
+
archived.push(taskId);
|
|
17520
|
+
}
|
|
17521
|
+
} else {
|
|
17522
|
+
remainingBundles.push({
|
|
17523
|
+
taskId,
|
|
17524
|
+
updatedAt: result.bundle.updated_at
|
|
17525
|
+
});
|
|
17526
|
+
}
|
|
17388
17527
|
}
|
|
17389
|
-
|
|
17390
|
-
|
|
17528
|
+
if (maxBundles !== undefined && remainingBundles.length > maxBundles) {
|
|
17529
|
+
remainingBundles.sort((a, b) => a.updatedAt.localeCompare(b.updatedAt));
|
|
17530
|
+
const toDelete = remainingBundles.length - maxBundles;
|
|
17531
|
+
for (let i = 0;i < toDelete; i++) {
|
|
17532
|
+
const deleted = await deleteEvidence(directory, remainingBundles[i].taskId);
|
|
17533
|
+
if (deleted) {
|
|
17534
|
+
archived.push(remainingBundles[i].taskId);
|
|
17535
|
+
}
|
|
17536
|
+
}
|
|
17391
17537
|
}
|
|
17392
|
-
|
|
17393
|
-
|
|
17394
|
-
|
|
17395
|
-
|
|
17396
|
-
|
|
17397
|
-
|
|
17398
|
-
|
|
17538
|
+
return archived;
|
|
17539
|
+
}
|
|
17540
|
+
var VALID_EVIDENCE_TYPES, sanitizeTaskId2, LEGACY_TASK_COMPLEXITY_MAP;
|
|
17541
|
+
var init_manager2 = __esm(() => {
|
|
17542
|
+
init_zod();
|
|
17543
|
+
init_evidence_schema();
|
|
17544
|
+
init_utils2();
|
|
17545
|
+
init_utils();
|
|
17546
|
+
init_lock();
|
|
17547
|
+
init_task_id();
|
|
17548
|
+
VALID_EVIDENCE_TYPES = [
|
|
17549
|
+
"review",
|
|
17550
|
+
"test",
|
|
17551
|
+
"diff",
|
|
17552
|
+
"approval",
|
|
17553
|
+
"note",
|
|
17554
|
+
"retrospective",
|
|
17555
|
+
"syntax",
|
|
17556
|
+
"placeholder",
|
|
17557
|
+
"sast",
|
|
17558
|
+
"sbom",
|
|
17559
|
+
"build",
|
|
17560
|
+
"quality_budget",
|
|
17561
|
+
"secretscan"
|
|
17562
|
+
];
|
|
17563
|
+
sanitizeTaskId2 = sanitizeTaskId;
|
|
17564
|
+
LEGACY_TASK_COMPLEXITY_MAP = {
|
|
17565
|
+
low: "simple",
|
|
17566
|
+
medium: "moderate",
|
|
17567
|
+
high: "complex"
|
|
17568
|
+
};
|
|
17399
17569
|
});
|
|
17400
17570
|
|
|
17401
17571
|
// src/services/config-doctor.ts
|
|
@@ -17412,15 +17582,15 @@ __export(exports_config_doctor, {
|
|
|
17412
17582
|
applySafeAutoFixes: () => applySafeAutoFixes
|
|
17413
17583
|
});
|
|
17414
17584
|
import * as crypto3 from "crypto";
|
|
17415
|
-
import * as
|
|
17416
|
-
import * as
|
|
17417
|
-
import * as
|
|
17585
|
+
import * as fs9 from "fs";
|
|
17586
|
+
import * as os5 from "os";
|
|
17587
|
+
import * as path18 from "path";
|
|
17418
17588
|
function getUserConfigDir3() {
|
|
17419
|
-
return process.env.XDG_CONFIG_HOME ||
|
|
17589
|
+
return process.env.XDG_CONFIG_HOME || path18.join(os5.homedir(), ".config");
|
|
17420
17590
|
}
|
|
17421
17591
|
function getConfigPaths(directory) {
|
|
17422
|
-
const userConfigPath =
|
|
17423
|
-
const projectConfigPath =
|
|
17592
|
+
const userConfigPath = path18.join(getUserConfigDir3(), "opencode", "opencode-swarm.json");
|
|
17593
|
+
const projectConfigPath = path18.join(directory, ".opencode", "opencode-swarm.json");
|
|
17424
17594
|
return { userConfigPath, projectConfigPath };
|
|
17425
17595
|
}
|
|
17426
17596
|
function computeHash(content) {
|
|
@@ -17445,9 +17615,9 @@ function isValidConfigPath(configPath, directory) {
|
|
|
17445
17615
|
const normalizedUser = userConfigPath.replace(/\\/g, "/");
|
|
17446
17616
|
const normalizedProject = projectConfigPath.replace(/\\/g, "/");
|
|
17447
17617
|
try {
|
|
17448
|
-
const resolvedConfig =
|
|
17449
|
-
const resolvedUser =
|
|
17450
|
-
const resolvedProject =
|
|
17618
|
+
const resolvedConfig = path18.resolve(configPath);
|
|
17619
|
+
const resolvedUser = path18.resolve(normalizedUser);
|
|
17620
|
+
const resolvedProject = path18.resolve(normalizedProject);
|
|
17451
17621
|
return resolvedConfig === resolvedUser || resolvedConfig === resolvedProject;
|
|
17452
17622
|
} catch {
|
|
17453
17623
|
return false;
|
|
@@ -17457,19 +17627,19 @@ function createConfigBackup(directory) {
|
|
|
17457
17627
|
const { userConfigPath, projectConfigPath } = getConfigPaths(directory);
|
|
17458
17628
|
let configPath = projectConfigPath;
|
|
17459
17629
|
let content = null;
|
|
17460
|
-
if (
|
|
17630
|
+
if (fs9.existsSync(projectConfigPath)) {
|
|
17461
17631
|
try {
|
|
17462
|
-
content =
|
|
17632
|
+
content = fs9.readFileSync(projectConfigPath, "utf-8");
|
|
17463
17633
|
} catch (error93) {
|
|
17464
17634
|
log("[ConfigDoctor] project config read failed", {
|
|
17465
17635
|
error: error93 instanceof Error ? error93.message : String(error93)
|
|
17466
17636
|
});
|
|
17467
17637
|
}
|
|
17468
17638
|
}
|
|
17469
|
-
if (content === null &&
|
|
17639
|
+
if (content === null && fs9.existsSync(userConfigPath)) {
|
|
17470
17640
|
configPath = userConfigPath;
|
|
17471
17641
|
try {
|
|
17472
|
-
content =
|
|
17642
|
+
content = fs9.readFileSync(userConfigPath, "utf-8");
|
|
17473
17643
|
} catch (error93) {
|
|
17474
17644
|
log("[ConfigDoctor] user config read failed", {
|
|
17475
17645
|
error: error93 instanceof Error ? error93.message : String(error93)
|
|
@@ -17487,12 +17657,12 @@ function createConfigBackup(directory) {
|
|
|
17487
17657
|
};
|
|
17488
17658
|
}
|
|
17489
17659
|
function writeBackupArtifact(directory, backup) {
|
|
17490
|
-
const swarmDir =
|
|
17491
|
-
if (!
|
|
17492
|
-
|
|
17660
|
+
const swarmDir = path18.join(directory, ".swarm");
|
|
17661
|
+
if (!fs9.existsSync(swarmDir)) {
|
|
17662
|
+
fs9.mkdirSync(swarmDir, { recursive: true });
|
|
17493
17663
|
}
|
|
17494
17664
|
const backupFilename = `config-backup-${backup.createdAt}.json`;
|
|
17495
|
-
const backupPath =
|
|
17665
|
+
const backupPath = path18.join(swarmDir, backupFilename);
|
|
17496
17666
|
const artifact = {
|
|
17497
17667
|
createdAt: backup.createdAt,
|
|
17498
17668
|
configPath: backup.configPath,
|
|
@@ -17500,15 +17670,15 @@ function writeBackupArtifact(directory, backup) {
|
|
|
17500
17670
|
content: backup.content,
|
|
17501
17671
|
preview: backup.content.substring(0, 500) + (backup.content.length > 500 ? "..." : "")
|
|
17502
17672
|
};
|
|
17503
|
-
|
|
17673
|
+
fs9.writeFileSync(backupPath, JSON.stringify(artifact, null, 2), "utf-8");
|
|
17504
17674
|
return backupPath;
|
|
17505
17675
|
}
|
|
17506
17676
|
function restoreFromBackup(backupPath, directory) {
|
|
17507
|
-
if (!
|
|
17677
|
+
if (!fs9.existsSync(backupPath)) {
|
|
17508
17678
|
return null;
|
|
17509
17679
|
}
|
|
17510
17680
|
try {
|
|
17511
|
-
const artifact = JSON.parse(
|
|
17681
|
+
const artifact = JSON.parse(fs9.readFileSync(backupPath, "utf-8"));
|
|
17512
17682
|
if (!artifact.content || !artifact.configPath || !artifact.contentHash) {
|
|
17513
17683
|
return null;
|
|
17514
17684
|
}
|
|
@@ -17522,11 +17692,11 @@ function restoreFromBackup(backupPath, directory) {
|
|
|
17522
17692
|
return null;
|
|
17523
17693
|
}
|
|
17524
17694
|
const targetPath = artifact.configPath;
|
|
17525
|
-
const targetDir =
|
|
17526
|
-
if (!
|
|
17527
|
-
|
|
17695
|
+
const targetDir = path18.dirname(targetPath);
|
|
17696
|
+
if (!fs9.existsSync(targetDir)) {
|
|
17697
|
+
fs9.mkdirSync(targetDir, { recursive: true });
|
|
17528
17698
|
}
|
|
17529
|
-
|
|
17699
|
+
fs9.writeFileSync(targetPath, artifact.content, "utf-8");
|
|
17530
17700
|
return targetPath;
|
|
17531
17701
|
} catch {
|
|
17532
17702
|
return null;
|
|
@@ -17536,12 +17706,12 @@ function readConfigFromFile(directory) {
|
|
|
17536
17706
|
const { userConfigPath, projectConfigPath } = getConfigPaths(directory);
|
|
17537
17707
|
let configPath = projectConfigPath;
|
|
17538
17708
|
let configContent = null;
|
|
17539
|
-
if (
|
|
17709
|
+
if (fs9.existsSync(projectConfigPath)) {
|
|
17540
17710
|
configPath = projectConfigPath;
|
|
17541
|
-
configContent =
|
|
17542
|
-
} else if (
|
|
17711
|
+
configContent = fs9.readFileSync(projectConfigPath, "utf-8");
|
|
17712
|
+
} else if (fs9.existsSync(userConfigPath)) {
|
|
17543
17713
|
configPath = userConfigPath;
|
|
17544
|
-
configContent =
|
|
17714
|
+
configContent = fs9.readFileSync(userConfigPath, "utf-8");
|
|
17545
17715
|
}
|
|
17546
17716
|
if (configContent === null) {
|
|
17547
17717
|
return null;
|
|
@@ -17553,9 +17723,9 @@ function readConfigFromFile(directory) {
|
|
|
17553
17723
|
return null;
|
|
17554
17724
|
}
|
|
17555
17725
|
}
|
|
17556
|
-
function validateConfigKey(
|
|
17726
|
+
function validateConfigKey(path19, value, _config) {
|
|
17557
17727
|
const findings = [];
|
|
17558
|
-
switch (
|
|
17728
|
+
switch (path19) {
|
|
17559
17729
|
case "agents": {
|
|
17560
17730
|
if (value !== undefined) {
|
|
17561
17731
|
findings.push({
|
|
@@ -17802,27 +17972,27 @@ function validateConfigKey(path18, value, _config) {
|
|
|
17802
17972
|
}
|
|
17803
17973
|
return findings;
|
|
17804
17974
|
}
|
|
17805
|
-
function walkConfigAndValidate(obj,
|
|
17975
|
+
function walkConfigAndValidate(obj, path19, config3, findings) {
|
|
17806
17976
|
if (obj === null || obj === undefined) {
|
|
17807
17977
|
return;
|
|
17808
17978
|
}
|
|
17809
|
-
if (
|
|
17810
|
-
const keyFindings = validateConfigKey(
|
|
17979
|
+
if (path19 && typeof obj === "object" && !Array.isArray(obj)) {
|
|
17980
|
+
const keyFindings = validateConfigKey(path19, obj, config3);
|
|
17811
17981
|
findings.push(...keyFindings);
|
|
17812
17982
|
}
|
|
17813
17983
|
if (typeof obj !== "object") {
|
|
17814
|
-
const keyFindings = validateConfigKey(
|
|
17984
|
+
const keyFindings = validateConfigKey(path19, obj, config3);
|
|
17815
17985
|
findings.push(...keyFindings);
|
|
17816
17986
|
return;
|
|
17817
17987
|
}
|
|
17818
17988
|
if (Array.isArray(obj)) {
|
|
17819
17989
|
obj.forEach((item, index) => {
|
|
17820
|
-
walkConfigAndValidate(item, `${
|
|
17990
|
+
walkConfigAndValidate(item, `${path19}[${index}]`, config3, findings);
|
|
17821
17991
|
});
|
|
17822
17992
|
return;
|
|
17823
17993
|
}
|
|
17824
17994
|
for (const [key, value] of Object.entries(obj)) {
|
|
17825
|
-
const newPath =
|
|
17995
|
+
const newPath = path19 ? `${path19}.${key}` : key;
|
|
17826
17996
|
walkConfigAndValidate(value, newPath, config3, findings);
|
|
17827
17997
|
}
|
|
17828
17998
|
}
|
|
@@ -17837,9 +18007,9 @@ function runConfigDoctor(config3, directory) {
|
|
|
17837
18007
|
const hasAutoFixableIssues = findings.some((f) => f.autoFixable && f.proposedFix?.risk === "low");
|
|
17838
18008
|
const { userConfigPath, projectConfigPath } = getConfigPaths(directory);
|
|
17839
18009
|
let configSource = "defaults";
|
|
17840
|
-
if (
|
|
18010
|
+
if (fs9.existsSync(projectConfigPath)) {
|
|
17841
18011
|
configSource = projectConfigPath;
|
|
17842
|
-
} else if (
|
|
18012
|
+
} else if (fs9.existsSync(userConfigPath)) {
|
|
17843
18013
|
configSource = userConfigPath;
|
|
17844
18014
|
}
|
|
17845
18015
|
return {
|
|
@@ -17868,12 +18038,12 @@ function applySafeAutoFixes(directory, result) {
|
|
|
17868
18038
|
const { userConfigPath, projectConfigPath } = getConfigPaths(directory);
|
|
17869
18039
|
let configPath = projectConfigPath;
|
|
17870
18040
|
let configContent;
|
|
17871
|
-
if (
|
|
18041
|
+
if (fs9.existsSync(projectConfigPath)) {
|
|
17872
18042
|
configPath = projectConfigPath;
|
|
17873
|
-
configContent =
|
|
17874
|
-
} else if (
|
|
18043
|
+
configContent = fs9.readFileSync(projectConfigPath, "utf-8");
|
|
18044
|
+
} else if (fs9.existsSync(userConfigPath)) {
|
|
17875
18045
|
configPath = userConfigPath;
|
|
17876
|
-
configContent =
|
|
18046
|
+
configContent = fs9.readFileSync(userConfigPath, "utf-8");
|
|
17877
18047
|
} else {
|
|
17878
18048
|
return { appliedFixes, updatedConfigPath: null };
|
|
17879
18049
|
}
|
|
@@ -17942,22 +18112,22 @@ function applySafeAutoFixes(directory, result) {
|
|
|
17942
18112
|
}
|
|
17943
18113
|
}
|
|
17944
18114
|
if (appliedFixes.length > 0) {
|
|
17945
|
-
const configDir =
|
|
17946
|
-
if (!
|
|
17947
|
-
|
|
18115
|
+
const configDir = path18.dirname(configPath);
|
|
18116
|
+
if (!fs9.existsSync(configDir)) {
|
|
18117
|
+
fs9.mkdirSync(configDir, { recursive: true });
|
|
17948
18118
|
}
|
|
17949
|
-
|
|
18119
|
+
fs9.writeFileSync(configPath, JSON.stringify(config3, null, 2), "utf-8");
|
|
17950
18120
|
updatedConfigPath = configPath;
|
|
17951
18121
|
}
|
|
17952
18122
|
return { appliedFixes, updatedConfigPath };
|
|
17953
18123
|
}
|
|
17954
18124
|
function writeDoctorArtifact(directory, result) {
|
|
17955
|
-
const swarmDir =
|
|
17956
|
-
if (!
|
|
17957
|
-
|
|
18125
|
+
const swarmDir = path18.join(directory, ".swarm");
|
|
18126
|
+
if (!fs9.existsSync(swarmDir)) {
|
|
18127
|
+
fs9.mkdirSync(swarmDir, { recursive: true });
|
|
17958
18128
|
}
|
|
17959
18129
|
const artifactFilename = "config-doctor.json";
|
|
17960
|
-
const artifactPath =
|
|
18130
|
+
const artifactPath = path18.join(swarmDir, artifactFilename);
|
|
17961
18131
|
const guiOutput = {
|
|
17962
18132
|
timestamp: result.timestamp,
|
|
17963
18133
|
summary: result.summary,
|
|
@@ -17978,7 +18148,7 @@ function writeDoctorArtifact(directory, result) {
|
|
|
17978
18148
|
} : null
|
|
17979
18149
|
}))
|
|
17980
18150
|
};
|
|
17981
|
-
|
|
18151
|
+
fs9.writeFileSync(artifactPath, JSON.stringify(guiOutput, null, 2), "utf-8");
|
|
17982
18152
|
return artifactPath;
|
|
17983
18153
|
}
|
|
17984
18154
|
function shouldRunOnStartup(automationConfig) {
|
|
@@ -18318,9 +18488,9 @@ var init_evidence_summary_service = __esm(() => {
|
|
|
18318
18488
|
});
|
|
18319
18489
|
|
|
18320
18490
|
// src/cli/index.ts
|
|
18321
|
-
import * as
|
|
18322
|
-
import * as
|
|
18323
|
-
import * as
|
|
18491
|
+
import * as fs23 from "fs";
|
|
18492
|
+
import * as os7 from "os";
|
|
18493
|
+
import * as path33 from "path";
|
|
18324
18494
|
|
|
18325
18495
|
// src/commands/acknowledge-spec-drift.ts
|
|
18326
18496
|
init_utils2();
|
|
@@ -18456,7 +18626,7 @@ async function handleAnalyzeCommand(_directory, args) {
|
|
|
18456
18626
|
|
|
18457
18627
|
// src/config/loader.ts
|
|
18458
18628
|
import * as fs2 from "fs";
|
|
18459
|
-
import * as
|
|
18629
|
+
import * as os2 from "os";
|
|
18460
18630
|
import * as path4 from "path";
|
|
18461
18631
|
|
|
18462
18632
|
// src/config/schema.ts
|
|
@@ -19241,6 +19411,11 @@ var CouncilConfigSchema = exports_external.object({
|
|
|
19241
19411
|
requireAllMembers: exports_external.boolean().default(false).describe("When true, convene_council rejects if fewer than 5 member verdicts are provided."),
|
|
19242
19412
|
escalateOnMaxRounds: exports_external.string().optional().describe("Optional webhook URL or handler name invoked when maxRounds is reached without APPROVE. Declared for forward compatibility; no behavior is implemented yet.")
|
|
19243
19413
|
}).strict();
|
|
19414
|
+
var ParallelizationConfigSchema = exports_external.object({
|
|
19415
|
+
enabled: exports_external.boolean().default(false),
|
|
19416
|
+
maxConcurrentTasks: exports_external.number().int().min(1).max(64).default(1),
|
|
19417
|
+
evidenceLockTimeoutMs: exports_external.number().int().min(1000).max(300000).default(60000)
|
|
19418
|
+
});
|
|
19244
19419
|
var PluginConfigSchema = exports_external.object({
|
|
19245
19420
|
agents: exports_external.record(exports_external.string(), AgentOverrideConfigSchema).optional(),
|
|
19246
19421
|
swarms: exports_external.record(exports_external.string(), SwarmConfigSchema).optional(),
|
|
@@ -19289,6 +19464,7 @@ var PluginConfigSchema = exports_external.object({
|
|
|
19289
19464
|
incremental_verify: IncrementalVerifyConfigSchema.optional(),
|
|
19290
19465
|
compaction_service: CompactionConfigSchema.optional(),
|
|
19291
19466
|
council: CouncilConfigSchema.optional(),
|
|
19467
|
+
parallelization: ParallelizationConfigSchema.optional(),
|
|
19292
19468
|
turbo_mode: exports_external.boolean().default(false).optional(),
|
|
19293
19469
|
full_auto: exports_external.object({
|
|
19294
19470
|
enabled: exports_external.boolean().default(false),
|
|
@@ -19308,7 +19484,7 @@ var PluginConfigSchema = exports_external.object({
|
|
|
19308
19484
|
var CONFIG_FILENAME = "opencode-swarm.json";
|
|
19309
19485
|
var MAX_CONFIG_FILE_BYTES = 102400;
|
|
19310
19486
|
function getUserConfigDir() {
|
|
19311
|
-
return process.env.XDG_CONFIG_HOME || path4.join(
|
|
19487
|
+
return process.env.XDG_CONFIG_HOME || path4.join(os2.homedir(), ".config");
|
|
19312
19488
|
}
|
|
19313
19489
|
function loadRawConfigFromPath(configPath) {
|
|
19314
19490
|
try {
|
|
@@ -19496,8 +19672,8 @@ import { createHash as createHash3 } from "crypto";
|
|
|
19496
19672
|
|
|
19497
19673
|
// src/db/project-db.ts
|
|
19498
19674
|
import { Database } from "bun:sqlite";
|
|
19499
|
-
import { existsSync as
|
|
19500
|
-
import { join as
|
|
19675
|
+
import { existsSync as existsSync5, mkdirSync as mkdirSync4 } from "fs";
|
|
19676
|
+
import { join as join7, resolve as resolve5 } from "path";
|
|
19501
19677
|
var MIGRATIONS = [
|
|
19502
19678
|
{
|
|
19503
19679
|
version: 1,
|
|
@@ -19556,19 +19732,19 @@ function runProjectMigrations(db) {
|
|
|
19556
19732
|
}
|
|
19557
19733
|
}
|
|
19558
19734
|
function projectDbPath(directory) {
|
|
19559
|
-
return
|
|
19735
|
+
return join7(resolve5(directory), ".swarm", "swarm.db");
|
|
19560
19736
|
}
|
|
19561
19737
|
function projectDbExists(directory) {
|
|
19562
|
-
return
|
|
19738
|
+
return existsSync5(projectDbPath(directory));
|
|
19563
19739
|
}
|
|
19564
19740
|
function getProjectDb(directory) {
|
|
19565
|
-
const key =
|
|
19741
|
+
const key = resolve5(directory);
|
|
19566
19742
|
const existing = _projectDbs.get(key);
|
|
19567
19743
|
if (existing)
|
|
19568
19744
|
return existing;
|
|
19569
|
-
const swarmDir =
|
|
19570
|
-
|
|
19571
|
-
const db = new Database(
|
|
19745
|
+
const swarmDir = join7(key, ".swarm");
|
|
19746
|
+
mkdirSync4(swarmDir, { recursive: true });
|
|
19747
|
+
const db = new Database(join7(swarmDir, "swarm.db"));
|
|
19572
19748
|
db.run("PRAGMA journal_mode = WAL;");
|
|
19573
19749
|
db.run("PRAGMA synchronous = NORMAL;");
|
|
19574
19750
|
db.run("PRAGMA busy_timeout = 5000;");
|
|
@@ -20002,9 +20178,9 @@ var warnedAgents = new Set;
|
|
|
20002
20178
|
init_manager();
|
|
20003
20179
|
|
|
20004
20180
|
// src/scope/scope-persistence.ts
|
|
20005
|
-
var
|
|
20006
|
-
import * as
|
|
20007
|
-
import * as
|
|
20181
|
+
var import_proper_lockfile2 = __toESM(require_proper_lockfile(), 1);
|
|
20182
|
+
import * as fs5 from "fs";
|
|
20183
|
+
import * as path7 from "path";
|
|
20008
20184
|
var DEFAULT_TTL_MS = 24 * 60 * 60 * 1000;
|
|
20009
20185
|
var LOCK_STALE_MS = 30 * 1000;
|
|
20010
20186
|
var SCOPES_DIR = ".swarm/scopes";
|
|
@@ -20035,11 +20211,11 @@ var WINDOWS_RESERVED = new Set([
|
|
|
20035
20211
|
"LPT9"
|
|
20036
20212
|
]);
|
|
20037
20213
|
function getScopesDir(directory) {
|
|
20038
|
-
return
|
|
20214
|
+
return path7.join(directory, SCOPES_DIR);
|
|
20039
20215
|
}
|
|
20040
20216
|
function clearAllScopes(directory) {
|
|
20041
20217
|
try {
|
|
20042
|
-
|
|
20218
|
+
fs5.rmSync(getScopesDir(directory), { recursive: true, force: true });
|
|
20043
20219
|
} catch {}
|
|
20044
20220
|
}
|
|
20045
20221
|
|
|
@@ -20138,23 +20314,48 @@ function clearPendingCoderScope() {
|
|
|
20138
20314
|
|
|
20139
20315
|
// src/state.ts
|
|
20140
20316
|
init_manager();
|
|
20317
|
+
|
|
20318
|
+
// src/state/agent-run-context.ts
|
|
20319
|
+
class AgentRunContext {
|
|
20320
|
+
runId;
|
|
20321
|
+
activeToolCalls;
|
|
20322
|
+
activeAgent;
|
|
20323
|
+
delegationChains;
|
|
20324
|
+
agentSessions;
|
|
20325
|
+
environmentProfiles;
|
|
20326
|
+
toolAggregates;
|
|
20327
|
+
constructor(runId, toolAggregates) {
|
|
20328
|
+
this.runId = runId;
|
|
20329
|
+
this.activeToolCalls = new Map;
|
|
20330
|
+
this.activeAgent = new Map;
|
|
20331
|
+
this.delegationChains = new Map;
|
|
20332
|
+
this.agentSessions = new Map;
|
|
20333
|
+
this.environmentProfiles = new Map;
|
|
20334
|
+
this.toolAggregates = toolAggregates;
|
|
20335
|
+
}
|
|
20336
|
+
}
|
|
20337
|
+
|
|
20338
|
+
// src/state.ts
|
|
20141
20339
|
init_telemetry();
|
|
20142
20340
|
var _rehydrationCache = null;
|
|
20143
20341
|
var _councilDisagreementWarned = new Set;
|
|
20342
|
+
var _toolAggregates = new Map;
|
|
20343
|
+
var defaultRunContext = new AgentRunContext("default", _toolAggregates);
|
|
20344
|
+
var _runContexts = new Map;
|
|
20144
20345
|
var swarmState = {
|
|
20145
|
-
activeToolCalls:
|
|
20146
|
-
toolAggregates:
|
|
20147
|
-
activeAgent:
|
|
20148
|
-
delegationChains:
|
|
20346
|
+
activeToolCalls: defaultRunContext.activeToolCalls,
|
|
20347
|
+
toolAggregates: defaultRunContext.toolAggregates,
|
|
20348
|
+
activeAgent: defaultRunContext.activeAgent,
|
|
20349
|
+
delegationChains: defaultRunContext.delegationChains,
|
|
20149
20350
|
pendingEvents: 0,
|
|
20150
20351
|
opencodeClient: null,
|
|
20151
20352
|
curatorInitAgentNames: [],
|
|
20152
20353
|
curatorPhaseAgentNames: [],
|
|
20153
20354
|
lastBudgetPct: 0,
|
|
20154
|
-
agentSessions:
|
|
20355
|
+
agentSessions: defaultRunContext.agentSessions,
|
|
20155
20356
|
pendingRehydrations: new Set,
|
|
20156
20357
|
fullAutoEnabledInConfig: false,
|
|
20157
|
-
environmentProfiles:
|
|
20358
|
+
environmentProfiles: defaultRunContext.environmentProfiles
|
|
20158
20359
|
};
|
|
20159
20360
|
function resetSwarmState() {
|
|
20160
20361
|
swarmState.activeToolCalls.clear();
|
|
@@ -20532,8 +20733,8 @@ init_zod();
|
|
|
20532
20733
|
|
|
20533
20734
|
// src/tools/checkpoint.ts
|
|
20534
20735
|
import * as child_process from "child_process";
|
|
20535
|
-
import * as
|
|
20536
|
-
import * as
|
|
20736
|
+
import * as fs6 from "fs";
|
|
20737
|
+
import * as path8 from "path";
|
|
20537
20738
|
|
|
20538
20739
|
// node_modules/@opencode-ai/plugin/node_modules/zod/v4/classic/external.js
|
|
20539
20740
|
var exports_external2 = {};
|
|
@@ -21264,10 +21465,10 @@ function mergeDefs2(...defs) {
|
|
|
21264
21465
|
function cloneDef2(schema) {
|
|
21265
21466
|
return mergeDefs2(schema._zod.def);
|
|
21266
21467
|
}
|
|
21267
|
-
function getElementAtPath2(obj,
|
|
21268
|
-
if (!
|
|
21468
|
+
function getElementAtPath2(obj, path8) {
|
|
21469
|
+
if (!path8)
|
|
21269
21470
|
return obj;
|
|
21270
|
-
return
|
|
21471
|
+
return path8.reduce((acc, key) => acc?.[key], obj);
|
|
21271
21472
|
}
|
|
21272
21473
|
function promiseAllObject2(promisesObj) {
|
|
21273
21474
|
const keys = Object.keys(promisesObj);
|
|
@@ -21626,11 +21827,11 @@ function aborted2(x, startIndex = 0) {
|
|
|
21626
21827
|
}
|
|
21627
21828
|
return false;
|
|
21628
21829
|
}
|
|
21629
|
-
function prefixIssues2(
|
|
21830
|
+
function prefixIssues2(path8, issues) {
|
|
21630
21831
|
return issues.map((iss) => {
|
|
21631
21832
|
var _a2;
|
|
21632
21833
|
(_a2 = iss).path ?? (_a2.path = []);
|
|
21633
|
-
iss.path.unshift(
|
|
21834
|
+
iss.path.unshift(path8);
|
|
21634
21835
|
return iss;
|
|
21635
21836
|
});
|
|
21636
21837
|
}
|
|
@@ -21798,7 +21999,7 @@ function treeifyError2(error49, _mapper) {
|
|
|
21798
21999
|
return issue3.message;
|
|
21799
22000
|
};
|
|
21800
22001
|
const result = { errors: [] };
|
|
21801
|
-
const processError = (error50,
|
|
22002
|
+
const processError = (error50, path8 = []) => {
|
|
21802
22003
|
var _a2, _b;
|
|
21803
22004
|
for (const issue3 of error50.issues) {
|
|
21804
22005
|
if (issue3.code === "invalid_union" && issue3.errors.length) {
|
|
@@ -21808,7 +22009,7 @@ function treeifyError2(error49, _mapper) {
|
|
|
21808
22009
|
} else if (issue3.code === "invalid_element") {
|
|
21809
22010
|
processError({ issues: issue3.issues }, issue3.path);
|
|
21810
22011
|
} else {
|
|
21811
|
-
const fullpath = [...
|
|
22012
|
+
const fullpath = [...path8, ...issue3.path];
|
|
21812
22013
|
if (fullpath.length === 0) {
|
|
21813
22014
|
result.errors.push(mapper(issue3));
|
|
21814
22015
|
continue;
|
|
@@ -21840,8 +22041,8 @@ function treeifyError2(error49, _mapper) {
|
|
|
21840
22041
|
}
|
|
21841
22042
|
function toDotPath2(_path) {
|
|
21842
22043
|
const segs = [];
|
|
21843
|
-
const
|
|
21844
|
-
for (const seg of
|
|
22044
|
+
const path8 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
|
|
22045
|
+
for (const seg of path8) {
|
|
21845
22046
|
if (typeof seg === "number")
|
|
21846
22047
|
segs.push(`[${seg}]`);
|
|
21847
22048
|
else if (typeof seg === "symbol")
|
|
@@ -32938,13 +33139,13 @@ function validateLabel(label) {
|
|
|
32938
33139
|
return null;
|
|
32939
33140
|
}
|
|
32940
33141
|
function getCheckpointLogPath(directory) {
|
|
32941
|
-
return
|
|
33142
|
+
return path8.join(directory, CHECKPOINT_LOG_PATH);
|
|
32942
33143
|
}
|
|
32943
33144
|
function readCheckpointLog(directory) {
|
|
32944
33145
|
const logPath = getCheckpointLogPath(directory);
|
|
32945
33146
|
try {
|
|
32946
|
-
if (
|
|
32947
|
-
const content =
|
|
33147
|
+
if (fs6.existsSync(logPath)) {
|
|
33148
|
+
const content = fs6.readFileSync(logPath, "utf-8");
|
|
32948
33149
|
const parsed = JSON.parse(content);
|
|
32949
33150
|
if (!parsed.checkpoints || !Array.isArray(parsed.checkpoints)) {
|
|
32950
33151
|
return { version: 1, checkpoints: [] };
|
|
@@ -32956,13 +33157,13 @@ function readCheckpointLog(directory) {
|
|
|
32956
33157
|
}
|
|
32957
33158
|
function writeCheckpointLog(log2, directory) {
|
|
32958
33159
|
const logPath = getCheckpointLogPath(directory);
|
|
32959
|
-
const dir =
|
|
32960
|
-
if (!
|
|
32961
|
-
|
|
33160
|
+
const dir = path8.dirname(logPath);
|
|
33161
|
+
if (!fs6.existsSync(dir)) {
|
|
33162
|
+
fs6.mkdirSync(dir, { recursive: true });
|
|
32962
33163
|
}
|
|
32963
33164
|
const tempPath = `${logPath}.tmp`;
|
|
32964
|
-
|
|
32965
|
-
|
|
33165
|
+
fs6.writeFileSync(tempPath, JSON.stringify(log2, null, 2), "utf-8");
|
|
33166
|
+
fs6.renameSync(tempPath, logPath);
|
|
32966
33167
|
}
|
|
32967
33168
|
function gitExec(args) {
|
|
32968
33169
|
const result = child_process.spawnSync("git", args, {
|
|
@@ -33296,8 +33497,8 @@ async function handleClarifyCommand(_directory, args) {
|
|
|
33296
33497
|
|
|
33297
33498
|
// src/commands/close.ts
|
|
33298
33499
|
import { execFileSync } from "child_process";
|
|
33299
|
-
import { promises as
|
|
33300
|
-
import
|
|
33500
|
+
import { promises as fs8 } from "fs";
|
|
33501
|
+
import path13 from "path";
|
|
33301
33502
|
init_manager2();
|
|
33302
33503
|
|
|
33303
33504
|
// src/git/branch.ts
|
|
@@ -33347,36 +33548,36 @@ function hasUncommittedChanges(cwd) {
|
|
|
33347
33548
|
}
|
|
33348
33549
|
|
|
33349
33550
|
// src/hooks/knowledge-store.ts
|
|
33350
|
-
var
|
|
33351
|
-
import { existsSync as
|
|
33551
|
+
var import_proper_lockfile3 = __toESM(require_proper_lockfile(), 1);
|
|
33552
|
+
import { existsSync as existsSync7 } from "fs";
|
|
33352
33553
|
import { appendFile as appendFile2, mkdir, readFile as readFile2, writeFile as writeFile2 } from "fs/promises";
|
|
33353
|
-
import * as
|
|
33354
|
-
import * as
|
|
33554
|
+
import * as os3 from "os";
|
|
33555
|
+
import * as path9 from "path";
|
|
33355
33556
|
function resolveSwarmKnowledgePath(directory) {
|
|
33356
|
-
return
|
|
33557
|
+
return path9.join(directory, ".swarm", "knowledge.jsonl");
|
|
33357
33558
|
}
|
|
33358
33559
|
function resolveSwarmRejectedPath(directory) {
|
|
33359
|
-
return
|
|
33560
|
+
return path9.join(directory, ".swarm", "knowledge-rejected.jsonl");
|
|
33360
33561
|
}
|
|
33361
33562
|
function resolveHiveKnowledgePath() {
|
|
33362
33563
|
const platform = process.platform;
|
|
33363
|
-
const home =
|
|
33564
|
+
const home = os3.homedir();
|
|
33364
33565
|
let dataDir;
|
|
33365
33566
|
if (platform === "win32") {
|
|
33366
|
-
dataDir =
|
|
33567
|
+
dataDir = path9.join(process.env.LOCALAPPDATA || path9.join(home, "AppData", "Local"), "opencode-swarm", "Data");
|
|
33367
33568
|
} else if (platform === "darwin") {
|
|
33368
|
-
dataDir =
|
|
33569
|
+
dataDir = path9.join(home, "Library", "Application Support", "opencode-swarm");
|
|
33369
33570
|
} else {
|
|
33370
|
-
dataDir =
|
|
33571
|
+
dataDir = path9.join(process.env.XDG_DATA_HOME || path9.join(home, ".local", "share"), "opencode-swarm");
|
|
33371
33572
|
}
|
|
33372
|
-
return
|
|
33573
|
+
return path9.join(dataDir, "shared-learnings.jsonl");
|
|
33373
33574
|
}
|
|
33374
33575
|
function resolveHiveRejectedPath() {
|
|
33375
33576
|
const hivePath = resolveHiveKnowledgePath();
|
|
33376
|
-
return
|
|
33577
|
+
return path9.join(path9.dirname(hivePath), "shared-learnings-rejected.jsonl");
|
|
33377
33578
|
}
|
|
33378
33579
|
async function readKnowledge(filePath) {
|
|
33379
|
-
if (!
|
|
33580
|
+
if (!existsSync7(filePath))
|
|
33380
33581
|
return [];
|
|
33381
33582
|
const content = await readFile2(filePath, "utf-8");
|
|
33382
33583
|
const results = [];
|
|
@@ -33397,16 +33598,16 @@ async function readRejectedLessons(directory) {
|
|
|
33397
33598
|
return readKnowledge(resolveSwarmRejectedPath(directory));
|
|
33398
33599
|
}
|
|
33399
33600
|
async function appendKnowledge(filePath, entry) {
|
|
33400
|
-
await mkdir(
|
|
33601
|
+
await mkdir(path9.dirname(filePath), { recursive: true });
|
|
33401
33602
|
await appendFile2(filePath, `${JSON.stringify(entry)}
|
|
33402
33603
|
`, "utf-8");
|
|
33403
33604
|
}
|
|
33404
33605
|
async function rewriteKnowledge(filePath, entries) {
|
|
33405
|
-
const dir =
|
|
33606
|
+
const dir = path9.dirname(filePath);
|
|
33406
33607
|
await mkdir(dir, { recursive: true });
|
|
33407
33608
|
let release = null;
|
|
33408
33609
|
try {
|
|
33409
|
-
release = await
|
|
33610
|
+
release = await import_proper_lockfile3.default.lock(dir, {
|
|
33410
33611
|
retries: { retries: 5, minTimeout: 100, maxTimeout: 500 },
|
|
33411
33612
|
stale: 5000
|
|
33412
33613
|
});
|
|
@@ -33511,9 +33712,9 @@ function inferTags(lesson) {
|
|
|
33511
33712
|
}
|
|
33512
33713
|
|
|
33513
33714
|
// src/hooks/knowledge-validator.ts
|
|
33514
|
-
var
|
|
33715
|
+
var import_proper_lockfile4 = __toESM(require_proper_lockfile(), 1);
|
|
33515
33716
|
import { appendFile as appendFile3, mkdir as mkdir2, writeFile as writeFile3 } from "fs/promises";
|
|
33516
|
-
import * as
|
|
33717
|
+
import * as path10 from "path";
|
|
33517
33718
|
var DANGEROUS_COMMAND_PATTERNS = [
|
|
33518
33719
|
/\brm\s+-rf\b/,
|
|
33519
33720
|
/\bsudo\s+rm\b/,
|
|
@@ -33768,14 +33969,14 @@ async function quarantineEntry(directory, entryId, reason, reportedBy) {
|
|
|
33768
33969
|
return;
|
|
33769
33970
|
}
|
|
33770
33971
|
const sanitizedReason = reason.slice(0, 500).replace(/[\x00-\x08\x0b-\x0c\x0e-\x1f\x7f\x0d]/g, "");
|
|
33771
|
-
const knowledgePath =
|
|
33772
|
-
const quarantinePath =
|
|
33773
|
-
const rejectedPath =
|
|
33774
|
-
const swarmDir =
|
|
33972
|
+
const knowledgePath = path10.join(directory, ".swarm", "knowledge.jsonl");
|
|
33973
|
+
const quarantinePath = path10.join(directory, ".swarm", "knowledge-quarantined.jsonl");
|
|
33974
|
+
const rejectedPath = path10.join(directory, ".swarm", "knowledge-rejected.jsonl");
|
|
33975
|
+
const swarmDir = path10.join(directory, ".swarm");
|
|
33775
33976
|
await mkdir2(swarmDir, { recursive: true });
|
|
33776
33977
|
let release;
|
|
33777
33978
|
try {
|
|
33778
|
-
release = await
|
|
33979
|
+
release = await import_proper_lockfile4.default.lock(swarmDir, {
|
|
33779
33980
|
retries: { retries: 3, minTimeout: 100 }
|
|
33780
33981
|
});
|
|
33781
33982
|
const entries = await readKnowledge(knowledgePath);
|
|
@@ -33828,14 +34029,14 @@ async function restoreEntry(directory, entryId) {
|
|
|
33828
34029
|
console.warn("[knowledge-validator] restoreEntry: invalid entryId rejected");
|
|
33829
34030
|
return;
|
|
33830
34031
|
}
|
|
33831
|
-
const knowledgePath =
|
|
33832
|
-
const quarantinePath =
|
|
33833
|
-
const rejectedPath =
|
|
33834
|
-
const swarmDir =
|
|
34032
|
+
const knowledgePath = path10.join(directory, ".swarm", "knowledge.jsonl");
|
|
34033
|
+
const quarantinePath = path10.join(directory, ".swarm", "knowledge-quarantined.jsonl");
|
|
34034
|
+
const rejectedPath = path10.join(directory, ".swarm", "knowledge-rejected.jsonl");
|
|
34035
|
+
const swarmDir = path10.join(directory, ".swarm");
|
|
33835
34036
|
await mkdir2(swarmDir, { recursive: true });
|
|
33836
34037
|
let release;
|
|
33837
34038
|
try {
|
|
33838
|
-
release = await
|
|
34039
|
+
release = await import_proper_lockfile4.default.lock(swarmDir, {
|
|
33839
34040
|
retries: { retries: 3, minTimeout: 100 }
|
|
33840
34041
|
});
|
|
33841
34042
|
const quarantinedEntries = await readKnowledge(quarantinePath);
|
|
@@ -33990,18 +34191,18 @@ init_utils2();
|
|
|
33990
34191
|
init_plan_schema();
|
|
33991
34192
|
init_ledger();
|
|
33992
34193
|
init_manager();
|
|
33993
|
-
import * as
|
|
33994
|
-
import * as
|
|
34194
|
+
import * as fs7 from "fs";
|
|
34195
|
+
import * as path11 from "path";
|
|
33995
34196
|
async function writeCheckpoint(directory) {
|
|
33996
34197
|
try {
|
|
33997
34198
|
const plan = await loadPlan(directory);
|
|
33998
34199
|
if (!plan)
|
|
33999
34200
|
return;
|
|
34000
|
-
const jsonPath =
|
|
34001
|
-
const mdPath =
|
|
34002
|
-
|
|
34201
|
+
const jsonPath = path11.join(directory, "SWARM_PLAN.json");
|
|
34202
|
+
const mdPath = path11.join(directory, "SWARM_PLAN.md");
|
|
34203
|
+
fs7.writeFileSync(jsonPath, JSON.stringify(plan, null, 2), "utf8");
|
|
34003
34204
|
const md = derivePlanMarkdown(plan);
|
|
34004
|
-
|
|
34205
|
+
fs7.writeFileSync(mdPath, md, "utf8");
|
|
34005
34206
|
} catch (error93) {
|
|
34006
34207
|
console.warn(`[checkpoint] Failed to write SWARM_PLAN checkpoint: ${error93 instanceof Error ? error93.message : String(error93)}`);
|
|
34007
34208
|
}
|
|
@@ -34009,8 +34210,8 @@ async function writeCheckpoint(directory) {
|
|
|
34009
34210
|
|
|
34010
34211
|
// src/session/snapshot-writer.ts
|
|
34011
34212
|
init_utils2();
|
|
34012
|
-
import { mkdirSync as
|
|
34013
|
-
import * as
|
|
34213
|
+
import { mkdirSync as mkdirSync7, renameSync as renameSync5 } from "fs";
|
|
34214
|
+
import * as path12 from "path";
|
|
34014
34215
|
init_utils();
|
|
34015
34216
|
var _writeInFlight = Promise.resolve();
|
|
34016
34217
|
function serializeAgentSession(s) {
|
|
@@ -34101,8 +34302,8 @@ async function writeSnapshot(directory, state) {
|
|
|
34101
34302
|
}
|
|
34102
34303
|
const content = JSON.stringify(snapshot, null, 2);
|
|
34103
34304
|
const resolvedPath = validateSwarmPath(directory, "session/state.json");
|
|
34104
|
-
const dir =
|
|
34105
|
-
|
|
34305
|
+
const dir = path12.dirname(resolvedPath);
|
|
34306
|
+
mkdirSync7(dir, { recursive: true });
|
|
34106
34307
|
const tempPath = `${resolvedPath}.tmp.${Date.now()}.${Math.random().toString(36).slice(2)}`;
|
|
34107
34308
|
await Bun.write(tempPath, content);
|
|
34108
34309
|
renameSync5(tempPath, resolvedPath);
|
|
@@ -34493,21 +34694,21 @@ var ACTIVE_STATE_TO_CLEAN = [
|
|
|
34493
34694
|
];
|
|
34494
34695
|
async function handleCloseCommand(directory, args) {
|
|
34495
34696
|
const planPath = validateSwarmPath(directory, "plan.json");
|
|
34496
|
-
const swarmDir =
|
|
34697
|
+
const swarmDir = path13.join(directory, ".swarm");
|
|
34497
34698
|
let planExists = false;
|
|
34498
34699
|
let planData = {
|
|
34499
|
-
title:
|
|
34700
|
+
title: path13.basename(directory) || "Ad-hoc session",
|
|
34500
34701
|
phases: []
|
|
34501
34702
|
};
|
|
34502
34703
|
try {
|
|
34503
|
-
const content = await
|
|
34704
|
+
const content = await fs8.readFile(planPath, "utf-8");
|
|
34504
34705
|
planData = JSON.parse(content);
|
|
34505
34706
|
planExists = true;
|
|
34506
34707
|
} catch (error93) {
|
|
34507
34708
|
if (error93?.code !== "ENOENT") {
|
|
34508
34709
|
return `\u274C Failed to read plan.json: ${error93 instanceof Error ? error93.message : String(error93)}`;
|
|
34509
34710
|
}
|
|
34510
|
-
const swarmDirExists = await
|
|
34711
|
+
const swarmDirExists = await fs8.access(swarmDir).then(() => true).catch(() => false);
|
|
34511
34712
|
if (!swarmDirExists) {
|
|
34512
34713
|
return `\u274C No .swarm/ directory found in ${directory}. Run /swarm close from the project root, or run /swarm plan first.`;
|
|
34513
34714
|
}
|
|
@@ -34601,10 +34802,10 @@ async function handleCloseCommand(directory, args) {
|
|
|
34601
34802
|
warnings.push(`Session retrospective write threw: ${retroError instanceof Error ? retroError.message : String(retroError)}`);
|
|
34602
34803
|
}
|
|
34603
34804
|
}
|
|
34604
|
-
const lessonsFilePath =
|
|
34805
|
+
const lessonsFilePath = path13.join(swarmDir, "close-lessons.md");
|
|
34605
34806
|
let explicitLessons = [];
|
|
34606
34807
|
try {
|
|
34607
|
-
const lessonsText = await
|
|
34808
|
+
const lessonsText = await fs8.readFile(lessonsFilePath, "utf-8");
|
|
34608
34809
|
explicitLessons = lessonsText.split(`
|
|
34609
34810
|
`).map((line) => line.trim()).filter((line) => line.length > 0 && !line.startsWith("#"));
|
|
34610
34811
|
} catch {}
|
|
@@ -34618,7 +34819,7 @@ async function handleCloseCommand(directory, args) {
|
|
|
34618
34819
|
console.warn("[close-command] curateAndStoreSwarm error:", error93);
|
|
34619
34820
|
}
|
|
34620
34821
|
if (curationSucceeded && explicitLessons.length > 0) {
|
|
34621
|
-
await
|
|
34822
|
+
await fs8.unlink(lessonsFilePath).catch(() => {});
|
|
34622
34823
|
}
|
|
34623
34824
|
if (planExists && !planAlreadyDone) {
|
|
34624
34825
|
for (const phase of phases) {
|
|
@@ -34638,7 +34839,7 @@ async function handleCloseCommand(directory, args) {
|
|
|
34638
34839
|
}
|
|
34639
34840
|
}
|
|
34640
34841
|
try {
|
|
34641
|
-
await
|
|
34842
|
+
await fs8.writeFile(planPath, JSON.stringify(planData, null, 2), "utf-8");
|
|
34642
34843
|
} catch (error93) {
|
|
34643
34844
|
const msg = error93 instanceof Error ? error93.message : String(error93);
|
|
34644
34845
|
warnings.push(`Failed to persist terminal plan.json state: ${msg}`);
|
|
@@ -34647,53 +34848,53 @@ async function handleCloseCommand(directory, args) {
|
|
|
34647
34848
|
}
|
|
34648
34849
|
const timestamp = new Date().toISOString().replace(/[:.]/g, "-");
|
|
34649
34850
|
const suffix = Math.random().toString(36).slice(2, 8);
|
|
34650
|
-
const archiveDir =
|
|
34851
|
+
const archiveDir = path13.join(swarmDir, "archive", `swarm-${timestamp}-${suffix}`);
|
|
34651
34852
|
let archiveResult = "";
|
|
34652
34853
|
let archivedFileCount = 0;
|
|
34653
34854
|
const archivedActiveStateFiles = new Set;
|
|
34654
34855
|
try {
|
|
34655
|
-
await
|
|
34856
|
+
await fs8.mkdir(archiveDir, { recursive: true });
|
|
34656
34857
|
for (const artifact of ARCHIVE_ARTIFACTS) {
|
|
34657
|
-
const srcPath =
|
|
34658
|
-
const destPath =
|
|
34858
|
+
const srcPath = path13.join(swarmDir, artifact);
|
|
34859
|
+
const destPath = path13.join(archiveDir, artifact);
|
|
34659
34860
|
try {
|
|
34660
|
-
await
|
|
34861
|
+
await fs8.copyFile(srcPath, destPath);
|
|
34661
34862
|
archivedFileCount++;
|
|
34662
34863
|
if (ACTIVE_STATE_TO_CLEAN.includes(artifact)) {
|
|
34663
34864
|
archivedActiveStateFiles.add(artifact);
|
|
34664
34865
|
}
|
|
34665
34866
|
} catch {}
|
|
34666
34867
|
}
|
|
34667
|
-
const evidenceDir =
|
|
34668
|
-
const archiveEvidenceDir =
|
|
34868
|
+
const evidenceDir = path13.join(swarmDir, "evidence");
|
|
34869
|
+
const archiveEvidenceDir = path13.join(archiveDir, "evidence");
|
|
34669
34870
|
try {
|
|
34670
|
-
const evidenceEntries = await
|
|
34871
|
+
const evidenceEntries = await fs8.readdir(evidenceDir);
|
|
34671
34872
|
if (evidenceEntries.length > 0) {
|
|
34672
|
-
await
|
|
34873
|
+
await fs8.mkdir(archiveEvidenceDir, { recursive: true });
|
|
34673
34874
|
for (const entry of evidenceEntries) {
|
|
34674
|
-
const srcEntry =
|
|
34675
|
-
const destEntry =
|
|
34875
|
+
const srcEntry = path13.join(evidenceDir, entry);
|
|
34876
|
+
const destEntry = path13.join(archiveEvidenceDir, entry);
|
|
34676
34877
|
try {
|
|
34677
|
-
const stat = await
|
|
34878
|
+
const stat = await fs8.stat(srcEntry);
|
|
34678
34879
|
if (stat.isDirectory()) {
|
|
34679
|
-
await
|
|
34680
|
-
const subEntries = await
|
|
34880
|
+
await fs8.mkdir(destEntry, { recursive: true });
|
|
34881
|
+
const subEntries = await fs8.readdir(srcEntry);
|
|
34681
34882
|
for (const sub of subEntries) {
|
|
34682
|
-
await
|
|
34883
|
+
await fs8.copyFile(path13.join(srcEntry, sub), path13.join(destEntry, sub)).catch(() => {});
|
|
34683
34884
|
}
|
|
34684
34885
|
} else {
|
|
34685
|
-
await
|
|
34886
|
+
await fs8.copyFile(srcEntry, destEntry);
|
|
34686
34887
|
}
|
|
34687
34888
|
archivedFileCount++;
|
|
34688
34889
|
} catch {}
|
|
34689
34890
|
}
|
|
34690
34891
|
}
|
|
34691
34892
|
} catch {}
|
|
34692
|
-
const sessionStatePath =
|
|
34893
|
+
const sessionStatePath = path13.join(swarmDir, "session", "state.json");
|
|
34693
34894
|
try {
|
|
34694
|
-
const archiveSessionDir =
|
|
34695
|
-
await
|
|
34696
|
-
await
|
|
34895
|
+
const archiveSessionDir = path13.join(archiveDir, "session");
|
|
34896
|
+
await fs8.mkdir(archiveSessionDir, { recursive: true });
|
|
34897
|
+
await fs8.copyFile(sessionStatePath, path13.join(archiveSessionDir, "state.json"));
|
|
34697
34898
|
archivedFileCount++;
|
|
34698
34899
|
} catch {}
|
|
34699
34900
|
archiveResult = `Archived ${archivedFileCount} artifact(s) to .swarm/archive/swarm-${timestamp}/`;
|
|
@@ -34716,9 +34917,9 @@ async function handleCloseCommand(directory, args) {
|
|
|
34716
34917
|
warnings.push(`Preserved ${artifact} because it was not successfully archived.`);
|
|
34717
34918
|
continue;
|
|
34718
34919
|
}
|
|
34719
|
-
const filePath =
|
|
34920
|
+
const filePath = path13.join(swarmDir, artifact);
|
|
34720
34921
|
try {
|
|
34721
|
-
await
|
|
34922
|
+
await fs8.unlink(filePath);
|
|
34722
34923
|
cleanedFiles.push(artifact);
|
|
34723
34924
|
} catch {}
|
|
34724
34925
|
}
|
|
@@ -34726,23 +34927,23 @@ async function handleCloseCommand(directory, args) {
|
|
|
34726
34927
|
warnings.push("Skipped active-state cleanup because no active-state files were archived. Files preserved to prevent data loss.");
|
|
34727
34928
|
}
|
|
34728
34929
|
try {
|
|
34729
|
-
const swarmFiles = await
|
|
34930
|
+
const swarmFiles = await fs8.readdir(swarmDir);
|
|
34730
34931
|
const configBackups = swarmFiles.filter((f) => f.startsWith("config-backup-") && f.endsWith(".json"));
|
|
34731
34932
|
for (const backup of configBackups) {
|
|
34732
34933
|
try {
|
|
34733
|
-
await
|
|
34934
|
+
await fs8.unlink(path13.join(swarmDir, backup));
|
|
34734
34935
|
configBackupsRemoved++;
|
|
34735
34936
|
} catch {}
|
|
34736
34937
|
}
|
|
34737
34938
|
const ledgerSiblings = swarmFiles.filter((f) => (f.startsWith("plan-ledger.archived-") || f.startsWith("plan-ledger.backup-")) && f.endsWith(".jsonl"));
|
|
34738
34939
|
for (const sibling of ledgerSiblings) {
|
|
34739
34940
|
try {
|
|
34740
|
-
await
|
|
34941
|
+
await fs8.unlink(path13.join(swarmDir, sibling));
|
|
34741
34942
|
} catch {}
|
|
34742
34943
|
}
|
|
34743
34944
|
} catch {}
|
|
34744
34945
|
clearAllScopes(directory);
|
|
34745
|
-
const contextPath =
|
|
34946
|
+
const contextPath = path13.join(swarmDir, "context.md");
|
|
34746
34947
|
const contextContent = [
|
|
34747
34948
|
"# Context",
|
|
34748
34949
|
"",
|
|
@@ -34755,7 +34956,7 @@ async function handleCloseCommand(directory, args) {
|
|
|
34755
34956
|
].join(`
|
|
34756
34957
|
`);
|
|
34757
34958
|
try {
|
|
34758
|
-
await
|
|
34959
|
+
await fs8.writeFile(contextPath, contextContent, "utf-8");
|
|
34759
34960
|
} catch (error93) {
|
|
34760
34961
|
const msg = error93 instanceof Error ? error93.message : String(error93);
|
|
34761
34962
|
warnings.push(`Failed to reset context.md: ${msg}`);
|
|
@@ -34886,7 +35087,7 @@ async function handleCloseCommand(directory, args) {
|
|
|
34886
35087
|
].join(`
|
|
34887
35088
|
`);
|
|
34888
35089
|
try {
|
|
34889
|
-
await
|
|
35090
|
+
await fs8.writeFile(closeSummaryPath, summaryContent, "utf-8");
|
|
34890
35091
|
} catch (error93) {
|
|
34891
35092
|
const msg = error93 instanceof Error ? error93.message : String(error93);
|
|
34892
35093
|
warnings.push(`Failed to write close-summary.md: ${msg}`);
|
|
@@ -34942,15 +35143,15 @@ ${otherWarnings.map((w) => `- ${w}`).join(`
|
|
|
34942
35143
|
}
|
|
34943
35144
|
|
|
34944
35145
|
// src/commands/config.ts
|
|
34945
|
-
import * as
|
|
34946
|
-
import * as
|
|
35146
|
+
import * as os4 from "os";
|
|
35147
|
+
import * as path14 from "path";
|
|
34947
35148
|
function getUserConfigDir2() {
|
|
34948
|
-
return process.env.XDG_CONFIG_HOME ||
|
|
35149
|
+
return process.env.XDG_CONFIG_HOME || path14.join(os4.homedir(), ".config");
|
|
34949
35150
|
}
|
|
34950
35151
|
async function handleConfigCommand(directory, _args) {
|
|
34951
35152
|
const config3 = loadPluginConfig(directory);
|
|
34952
|
-
const userConfigPath =
|
|
34953
|
-
const projectConfigPath =
|
|
35153
|
+
const userConfigPath = path14.join(getUserConfigDir2(), "opencode", "opencode-swarm.json");
|
|
35154
|
+
const projectConfigPath = path14.join(directory, ".opencode", "opencode-swarm.json");
|
|
34954
35155
|
const lines = [
|
|
34955
35156
|
"## Swarm Configuration",
|
|
34956
35157
|
"",
|
|
@@ -35218,13 +35419,13 @@ function formatCurationSummary(summary) {
|
|
|
35218
35419
|
}
|
|
35219
35420
|
|
|
35220
35421
|
// src/commands/dark-matter.ts
|
|
35221
|
-
import
|
|
35422
|
+
import path16 from "path";
|
|
35222
35423
|
|
|
35223
35424
|
// src/tools/co-change-analyzer.ts
|
|
35224
35425
|
import * as child_process3 from "child_process";
|
|
35225
35426
|
import { randomUUID } from "crypto";
|
|
35226
35427
|
import { readdir, readFile as readFile3, stat } from "fs/promises";
|
|
35227
|
-
import * as
|
|
35428
|
+
import * as path15 from "path";
|
|
35228
35429
|
import { promisify } from "util";
|
|
35229
35430
|
function getExecFileAsync() {
|
|
35230
35431
|
return promisify(child_process3.execFile);
|
|
@@ -35326,7 +35527,7 @@ async function scanSourceFiles(dir) {
|
|
|
35326
35527
|
try {
|
|
35327
35528
|
const entries = await readdir(dir, { withFileTypes: true });
|
|
35328
35529
|
for (const entry of entries) {
|
|
35329
|
-
const fullPath =
|
|
35530
|
+
const fullPath = path15.join(dir, entry.name);
|
|
35330
35531
|
if (entry.isDirectory()) {
|
|
35331
35532
|
if (skipDirs.has(entry.name)) {
|
|
35332
35533
|
continue;
|
|
@@ -35334,7 +35535,7 @@ async function scanSourceFiles(dir) {
|
|
|
35334
35535
|
const subFiles = await scanSourceFiles(fullPath);
|
|
35335
35536
|
results.push(...subFiles);
|
|
35336
35537
|
} else if (entry.isFile()) {
|
|
35337
|
-
const ext =
|
|
35538
|
+
const ext = path15.extname(entry.name);
|
|
35338
35539
|
if ([".ts", ".tsx", ".js", ".jsx", ".mjs"].includes(ext)) {
|
|
35339
35540
|
results.push(fullPath);
|
|
35340
35541
|
}
|
|
@@ -35356,8 +35557,8 @@ async function getStaticEdges(directory) {
|
|
|
35356
35557
|
continue;
|
|
35357
35558
|
}
|
|
35358
35559
|
try {
|
|
35359
|
-
const sourceDir =
|
|
35360
|
-
const resolvedPath =
|
|
35560
|
+
const sourceDir = path15.dirname(sourceFile);
|
|
35561
|
+
const resolvedPath = path15.resolve(sourceDir, importPath);
|
|
35361
35562
|
const extensions = [
|
|
35362
35563
|
"",
|
|
35363
35564
|
".ts",
|
|
@@ -35382,8 +35583,8 @@ async function getStaticEdges(directory) {
|
|
|
35382
35583
|
if (!targetFile) {
|
|
35383
35584
|
continue;
|
|
35384
35585
|
}
|
|
35385
|
-
const relSource =
|
|
35386
|
-
const relTarget =
|
|
35586
|
+
const relSource = path15.relative(directory, sourceFile).replace(/\\/g, "/");
|
|
35587
|
+
const relTarget = path15.relative(directory, targetFile).replace(/\\/g, "/");
|
|
35387
35588
|
const [key] = relSource < relTarget ? [`${relSource}::${relTarget}`, relSource, relTarget] : [`${relTarget}::${relSource}`, relTarget, relSource];
|
|
35388
35589
|
edges.add(key);
|
|
35389
35590
|
} catch {}
|
|
@@ -35395,7 +35596,7 @@ async function getStaticEdges(directory) {
|
|
|
35395
35596
|
function isTestImplementationPair(fileA, fileB) {
|
|
35396
35597
|
const testPatterns = [".test.ts", ".test.js", ".spec.ts", ".spec.js"];
|
|
35397
35598
|
const getBaseName = (filePath) => {
|
|
35398
|
-
const base =
|
|
35599
|
+
const base = path15.basename(filePath);
|
|
35399
35600
|
for (const pattern of testPatterns) {
|
|
35400
35601
|
if (base.endsWith(pattern)) {
|
|
35401
35602
|
return base.slice(0, -pattern.length);
|
|
@@ -35405,16 +35606,16 @@ function isTestImplementationPair(fileA, fileB) {
|
|
|
35405
35606
|
};
|
|
35406
35607
|
const baseA = getBaseName(fileA);
|
|
35407
35608
|
const baseB = getBaseName(fileB);
|
|
35408
|
-
return baseA === baseB && baseA !==
|
|
35609
|
+
return baseA === baseB && baseA !== path15.basename(fileA) && baseA !== path15.basename(fileB);
|
|
35409
35610
|
}
|
|
35410
35611
|
function hasSharedPrefix(fileA, fileB) {
|
|
35411
|
-
const dirA =
|
|
35412
|
-
const dirB =
|
|
35612
|
+
const dirA = path15.dirname(fileA);
|
|
35613
|
+
const dirB = path15.dirname(fileB);
|
|
35413
35614
|
if (dirA !== dirB) {
|
|
35414
35615
|
return false;
|
|
35415
35616
|
}
|
|
35416
|
-
const baseA =
|
|
35417
|
-
const baseB =
|
|
35617
|
+
const baseA = path15.basename(fileA).replace(/\.(ts|js|tsx|jsx|mjs)$/, "");
|
|
35618
|
+
const baseB = path15.basename(fileB).replace(/\.(ts|js|tsx|jsx|mjs)$/, "");
|
|
35418
35619
|
if (baseA.startsWith(baseB) || baseB.startsWith(baseA)) {
|
|
35419
35620
|
return true;
|
|
35420
35621
|
}
|
|
@@ -35468,8 +35669,8 @@ function darkMatterToKnowledgeEntries(pairs, projectName) {
|
|
|
35468
35669
|
const entries = [];
|
|
35469
35670
|
const now = new Date().toISOString();
|
|
35470
35671
|
for (const pair of pairs.slice(0, 10)) {
|
|
35471
|
-
const baseA =
|
|
35472
|
-
const baseB =
|
|
35672
|
+
const baseA = path15.basename(pair.fileA);
|
|
35673
|
+
const baseB = path15.basename(pair.fileB);
|
|
35473
35674
|
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.`;
|
|
35474
35675
|
if (lesson.length > 280) {
|
|
35475
35676
|
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.`;
|
|
@@ -35579,7 +35780,7 @@ async function handleDarkMatterCommand(directory, args) {
|
|
|
35579
35780
|
const output = formatDarkMatterOutput(pairs);
|
|
35580
35781
|
if (pairs.length > 0) {
|
|
35581
35782
|
try {
|
|
35582
|
-
const projectName =
|
|
35783
|
+
const projectName = path16.basename(path16.resolve(directory));
|
|
35583
35784
|
const entries = darkMatterToKnowledgeEntries(pairs, projectName);
|
|
35584
35785
|
if (entries.length > 0) {
|
|
35585
35786
|
const knowledgePath = resolveSwarmKnowledgePath(directory);
|
|
@@ -35600,8 +35801,8 @@ async function handleDarkMatterCommand(directory, args) {
|
|
|
35600
35801
|
|
|
35601
35802
|
// src/services/diagnose-service.ts
|
|
35602
35803
|
import * as child_process4 from "child_process";
|
|
35603
|
-
import { existsSync as
|
|
35604
|
-
import
|
|
35804
|
+
import { existsSync as existsSync8, readdirSync as readdirSync4, readFileSync as readFileSync6, statSync as statSync5 } from "fs";
|
|
35805
|
+
import path17 from "path";
|
|
35605
35806
|
import { fileURLToPath } from "url";
|
|
35606
35807
|
init_manager2();
|
|
35607
35808
|
init_utils2();
|
|
@@ -35806,7 +36007,7 @@ async function checkPlanSync(directory, plan) {
|
|
|
35806
36007
|
}
|
|
35807
36008
|
async function checkConfigBackups(directory) {
|
|
35808
36009
|
try {
|
|
35809
|
-
const files =
|
|
36010
|
+
const files = readdirSync4(directory);
|
|
35810
36011
|
const backupCount = files.filter((f) => /\.opencode-swarm\.yaml\.bak/.test(f)).length;
|
|
35811
36012
|
if (backupCount <= 5) {
|
|
35812
36013
|
return {
|
|
@@ -35837,7 +36038,7 @@ async function checkConfigBackups(directory) {
|
|
|
35837
36038
|
}
|
|
35838
36039
|
async function checkGitRepository(directory) {
|
|
35839
36040
|
try {
|
|
35840
|
-
if (!
|
|
36041
|
+
if (!existsSync8(directory) || !statSync5(directory).isDirectory()) {
|
|
35841
36042
|
return {
|
|
35842
36043
|
name: "Git Repository",
|
|
35843
36044
|
status: "\u274C",
|
|
@@ -35901,8 +36102,8 @@ async function checkSpecStaleness(directory, plan) {
|
|
|
35901
36102
|
};
|
|
35902
36103
|
}
|
|
35903
36104
|
async function checkConfigParseability(directory) {
|
|
35904
|
-
const configPath =
|
|
35905
|
-
if (!
|
|
36105
|
+
const configPath = path17.join(directory, ".opencode/opencode-swarm.json");
|
|
36106
|
+
if (!existsSync8(configPath)) {
|
|
35906
36107
|
return {
|
|
35907
36108
|
name: "Config Parseability",
|
|
35908
36109
|
status: "\u2705",
|
|
@@ -35948,15 +36149,15 @@ async function checkGrammarWasmFiles() {
|
|
|
35948
36149
|
"tree-sitter-ini.wasm",
|
|
35949
36150
|
"tree-sitter-regex.wasm"
|
|
35950
36151
|
];
|
|
35951
|
-
const thisDir =
|
|
36152
|
+
const thisDir = path17.dirname(fileURLToPath(import.meta.url));
|
|
35952
36153
|
const isSource = thisDir.replace(/\\/g, "/").endsWith("/src/services");
|
|
35953
|
-
const grammarDir = isSource ?
|
|
36154
|
+
const grammarDir = isSource ? path17.join(thisDir, "..", "lang", "grammars") : path17.join(thisDir, "lang", "grammars");
|
|
35954
36155
|
const missing = [];
|
|
35955
|
-
if (!
|
|
36156
|
+
if (!existsSync8(path17.join(grammarDir, "tree-sitter.wasm"))) {
|
|
35956
36157
|
missing.push("tree-sitter.wasm (core runtime)");
|
|
35957
36158
|
}
|
|
35958
36159
|
for (const file3 of grammarFiles) {
|
|
35959
|
-
if (!
|
|
36160
|
+
if (!existsSync8(path17.join(grammarDir, file3))) {
|
|
35960
36161
|
missing.push(file3);
|
|
35961
36162
|
}
|
|
35962
36163
|
}
|
|
@@ -35974,8 +36175,8 @@ async function checkGrammarWasmFiles() {
|
|
|
35974
36175
|
};
|
|
35975
36176
|
}
|
|
35976
36177
|
async function checkCheckpointManifest(directory) {
|
|
35977
|
-
const manifestPath =
|
|
35978
|
-
if (!
|
|
36178
|
+
const manifestPath = path17.join(directory, ".swarm/checkpoints.json");
|
|
36179
|
+
if (!existsSync8(manifestPath)) {
|
|
35979
36180
|
return {
|
|
35980
36181
|
name: "Checkpoint Manifest",
|
|
35981
36182
|
status: "\u2705",
|
|
@@ -36026,8 +36227,8 @@ async function checkCheckpointManifest(directory) {
|
|
|
36026
36227
|
}
|
|
36027
36228
|
}
|
|
36028
36229
|
async function checkEventStreamIntegrity(directory) {
|
|
36029
|
-
const eventsPath =
|
|
36030
|
-
if (!
|
|
36230
|
+
const eventsPath = path17.join(directory, ".swarm/events.jsonl");
|
|
36231
|
+
if (!existsSync8(eventsPath)) {
|
|
36031
36232
|
return {
|
|
36032
36233
|
name: "Event Stream",
|
|
36033
36234
|
status: "\u2705",
|
|
@@ -36067,8 +36268,8 @@ async function checkEventStreamIntegrity(directory) {
|
|
|
36067
36268
|
}
|
|
36068
36269
|
}
|
|
36069
36270
|
async function checkSteeringDirectives(directory) {
|
|
36070
|
-
const eventsPath =
|
|
36071
|
-
if (!
|
|
36271
|
+
const eventsPath = path17.join(directory, ".swarm/events.jsonl");
|
|
36272
|
+
if (!existsSync8(eventsPath)) {
|
|
36072
36273
|
return {
|
|
36073
36274
|
name: "Steering Directives",
|
|
36074
36275
|
status: "\u2705",
|
|
@@ -36123,8 +36324,8 @@ async function checkCurator(directory) {
|
|
|
36123
36324
|
detail: "Disabled (enable via curator.enabled)"
|
|
36124
36325
|
};
|
|
36125
36326
|
}
|
|
36126
|
-
const summaryPath =
|
|
36127
|
-
if (!
|
|
36327
|
+
const summaryPath = path17.join(directory, ".swarm/curator-summary.json");
|
|
36328
|
+
if (!existsSync8(summaryPath)) {
|
|
36128
36329
|
return {
|
|
36129
36330
|
name: "Curator",
|
|
36130
36331
|
status: "\u2705",
|
|
@@ -36271,8 +36472,8 @@ async function getDiagnoseData(directory) {
|
|
|
36271
36472
|
checks5.push(await checkSteeringDirectives(directory));
|
|
36272
36473
|
checks5.push(await checkCurator(directory));
|
|
36273
36474
|
try {
|
|
36274
|
-
const evidenceDir =
|
|
36275
|
-
const snapshotFiles =
|
|
36475
|
+
const evidenceDir = path17.join(directory, ".swarm", "evidence");
|
|
36476
|
+
const snapshotFiles = existsSync8(evidenceDir) ? readdirSync4(evidenceDir).filter((f) => f.startsWith("agent-tools-") && f.endsWith(".json")) : [];
|
|
36276
36477
|
if (snapshotFiles.length > 0) {
|
|
36277
36478
|
const latest = snapshotFiles.sort().pop();
|
|
36278
36479
|
checks5.push({
|
|
@@ -36323,16 +36524,16 @@ async function handleDiagnoseCommand(directory, _args) {
|
|
|
36323
36524
|
init_config_doctor();
|
|
36324
36525
|
|
|
36325
36526
|
// src/services/tool-doctor.ts
|
|
36326
|
-
import * as
|
|
36327
|
-
import * as
|
|
36527
|
+
import * as fs11 from "fs";
|
|
36528
|
+
import * as path20 from "path";
|
|
36328
36529
|
|
|
36329
36530
|
// src/build/discovery.ts
|
|
36330
|
-
import * as
|
|
36331
|
-
import * as
|
|
36531
|
+
import * as fs10 from "fs";
|
|
36532
|
+
import * as path19 from "path";
|
|
36332
36533
|
|
|
36333
36534
|
// src/lang/detector.ts
|
|
36334
36535
|
import { access as access2, readdir as readdir2 } from "fs/promises";
|
|
36335
|
-
import { extname as extname2, join as
|
|
36536
|
+
import { extname as extname2, join as join16 } from "path";
|
|
36336
36537
|
|
|
36337
36538
|
// src/lang/profiles.ts
|
|
36338
36539
|
class LanguageRegistry {
|
|
@@ -37312,7 +37513,7 @@ async function detectProjectLanguages(projectDir) {
|
|
|
37312
37513
|
if (detectFile.includes("*") || detectFile.includes("?"))
|
|
37313
37514
|
continue;
|
|
37314
37515
|
try {
|
|
37315
|
-
await access2(
|
|
37516
|
+
await access2(join16(dir, detectFile));
|
|
37316
37517
|
detected.add(profile.id);
|
|
37317
37518
|
break;
|
|
37318
37519
|
} catch {}
|
|
@@ -37333,7 +37534,7 @@ async function detectProjectLanguages(projectDir) {
|
|
|
37333
37534
|
const topEntries = await readdir2(projectDir, { withFileTypes: true });
|
|
37334
37535
|
for (const entry of topEntries) {
|
|
37335
37536
|
if (entry.isDirectory() && !entry.name.startsWith(".") && entry.name !== "node_modules") {
|
|
37336
|
-
await scanDir(
|
|
37537
|
+
await scanDir(join16(projectDir, entry.name));
|
|
37337
37538
|
}
|
|
37338
37539
|
}
|
|
37339
37540
|
} catch {}
|
|
@@ -37488,16 +37689,16 @@ function findBuildFiles(workingDir, patterns) {
|
|
|
37488
37689
|
if (pattern.includes("*")) {
|
|
37489
37690
|
const dir = workingDir;
|
|
37490
37691
|
try {
|
|
37491
|
-
const files =
|
|
37692
|
+
const files = fs10.readdirSync(dir);
|
|
37492
37693
|
const regex = simpleGlobToRegex(pattern);
|
|
37493
37694
|
const matches = files.filter((f) => regex.test(f));
|
|
37494
37695
|
if (matches.length > 0) {
|
|
37495
|
-
return
|
|
37696
|
+
return path19.join(dir, matches[0]);
|
|
37496
37697
|
}
|
|
37497
37698
|
} catch {}
|
|
37498
37699
|
} else {
|
|
37499
|
-
const filePath =
|
|
37500
|
-
if (
|
|
37700
|
+
const filePath = path19.join(workingDir, pattern);
|
|
37701
|
+
if (fs10.existsSync(filePath)) {
|
|
37501
37702
|
return filePath;
|
|
37502
37703
|
}
|
|
37503
37704
|
}
|
|
@@ -37505,12 +37706,12 @@ function findBuildFiles(workingDir, patterns) {
|
|
|
37505
37706
|
return null;
|
|
37506
37707
|
}
|
|
37507
37708
|
function getRepoDefinedScripts(workingDir, scripts) {
|
|
37508
|
-
const packageJsonPath =
|
|
37509
|
-
if (!
|
|
37709
|
+
const packageJsonPath = path19.join(workingDir, "package.json");
|
|
37710
|
+
if (!fs10.existsSync(packageJsonPath)) {
|
|
37510
37711
|
return [];
|
|
37511
37712
|
}
|
|
37512
37713
|
try {
|
|
37513
|
-
const content =
|
|
37714
|
+
const content = fs10.readFileSync(packageJsonPath, "utf-8");
|
|
37514
37715
|
const pkg = JSON.parse(content);
|
|
37515
37716
|
if (!pkg.scripts || typeof pkg.scripts !== "object") {
|
|
37516
37717
|
return [];
|
|
@@ -37546,8 +37747,8 @@ function findAllBuildFiles(workingDir) {
|
|
|
37546
37747
|
const regex = simpleGlobToRegex(pattern);
|
|
37547
37748
|
findFilesRecursive(workingDir, regex, allBuildFiles);
|
|
37548
37749
|
} else {
|
|
37549
|
-
const filePath =
|
|
37550
|
-
if (
|
|
37750
|
+
const filePath = path19.join(workingDir, pattern);
|
|
37751
|
+
if (fs10.existsSync(filePath)) {
|
|
37551
37752
|
allBuildFiles.add(filePath);
|
|
37552
37753
|
}
|
|
37553
37754
|
}
|
|
@@ -37557,9 +37758,9 @@ function findAllBuildFiles(workingDir) {
|
|
|
37557
37758
|
}
|
|
37558
37759
|
function findFilesRecursive(dir, regex, results) {
|
|
37559
37760
|
try {
|
|
37560
|
-
const entries =
|
|
37761
|
+
const entries = fs10.readdirSync(dir, { withFileTypes: true });
|
|
37561
37762
|
for (const entry of entries) {
|
|
37562
|
-
const fullPath =
|
|
37763
|
+
const fullPath = path19.join(dir, entry.name);
|
|
37563
37764
|
if (entry.isDirectory() && !["node_modules", ".git", "dist", "build", "target"].includes(entry.name)) {
|
|
37564
37765
|
findFilesRecursive(fullPath, regex, results);
|
|
37565
37766
|
} else if (entry.isFile() && regex.test(entry.name)) {
|
|
@@ -37582,8 +37783,8 @@ async function discoverBuildCommandsFromProfiles(workingDir) {
|
|
|
37582
37783
|
let foundCommand = false;
|
|
37583
37784
|
for (const cmd of sortedCommands) {
|
|
37584
37785
|
if (cmd.detectFile) {
|
|
37585
|
-
const detectFilePath =
|
|
37586
|
-
if (!
|
|
37786
|
+
const detectFilePath = path19.join(workingDir, cmd.detectFile);
|
|
37787
|
+
if (!fs10.existsSync(detectFilePath)) {
|
|
37587
37788
|
continue;
|
|
37588
37789
|
}
|
|
37589
37790
|
}
|
|
@@ -37706,7 +37907,7 @@ var BINARY_CHECKLIST = [
|
|
|
37706
37907
|
function extractRegisteredToolKeys(indexPath) {
|
|
37707
37908
|
const registeredKeys = new Set;
|
|
37708
37909
|
try {
|
|
37709
|
-
const content =
|
|
37910
|
+
const content = fs11.readFileSync(indexPath, "utf-8");
|
|
37710
37911
|
const toolBlockMatch = content.match(/tool:\s*\{([^}]+(?:\{[^}]*\}[^}]*)*)\}/s);
|
|
37711
37912
|
if (!toolBlockMatch) {
|
|
37712
37913
|
return registeredKeys;
|
|
@@ -37757,9 +37958,9 @@ function checkBinaryReadiness() {
|
|
|
37757
37958
|
}
|
|
37758
37959
|
function runToolDoctor(_directory, pluginRoot) {
|
|
37759
37960
|
const findings = [];
|
|
37760
|
-
const resolvedPluginRoot = pluginRoot ??
|
|
37761
|
-
const indexPath =
|
|
37762
|
-
if (!
|
|
37961
|
+
const resolvedPluginRoot = pluginRoot ?? path20.resolve(import.meta.dir, "..", "..");
|
|
37962
|
+
const indexPath = path20.join(resolvedPluginRoot, "src", "index.ts");
|
|
37963
|
+
if (!fs11.existsSync(indexPath)) {
|
|
37763
37964
|
return {
|
|
37764
37965
|
findings: [
|
|
37765
37966
|
{
|
|
@@ -38669,14 +38870,14 @@ async function handleHistoryCommand(directory, _args) {
|
|
|
38669
38870
|
}
|
|
38670
38871
|
// src/hooks/knowledge-migrator.ts
|
|
38671
38872
|
import { randomUUID as randomUUID2 } from "crypto";
|
|
38672
|
-
import { existsSync as
|
|
38873
|
+
import { existsSync as existsSync12, readFileSync as readFileSync10 } from "fs";
|
|
38673
38874
|
import { mkdir as mkdir3, readFile as readFile4, writeFile as writeFile4 } from "fs/promises";
|
|
38674
|
-
import * as
|
|
38875
|
+
import * as path21 from "path";
|
|
38675
38876
|
async function migrateContextToKnowledge(directory, config3) {
|
|
38676
|
-
const sentinelPath =
|
|
38677
|
-
const contextPath =
|
|
38877
|
+
const sentinelPath = path21.join(directory, ".swarm", ".knowledge-migrated");
|
|
38878
|
+
const contextPath = path21.join(directory, ".swarm", "context.md");
|
|
38678
38879
|
const knowledgePath = resolveSwarmKnowledgePath(directory);
|
|
38679
|
-
if (
|
|
38880
|
+
if (existsSync12(sentinelPath)) {
|
|
38680
38881
|
return {
|
|
38681
38882
|
migrated: false,
|
|
38682
38883
|
entriesMigrated: 0,
|
|
@@ -38685,7 +38886,7 @@ async function migrateContextToKnowledge(directory, config3) {
|
|
|
38685
38886
|
skippedReason: "sentinel-exists"
|
|
38686
38887
|
};
|
|
38687
38888
|
}
|
|
38688
|
-
if (!
|
|
38889
|
+
if (!existsSync12(contextPath)) {
|
|
38689
38890
|
return {
|
|
38690
38891
|
migrated: false,
|
|
38691
38892
|
entriesMigrated: 0,
|
|
@@ -38870,8 +39071,8 @@ function truncateLesson(text) {
|
|
|
38870
39071
|
return `${text.slice(0, 277)}...`;
|
|
38871
39072
|
}
|
|
38872
39073
|
function inferProjectName(directory) {
|
|
38873
|
-
const packageJsonPath =
|
|
38874
|
-
if (
|
|
39074
|
+
const packageJsonPath = path21.join(directory, "package.json");
|
|
39075
|
+
if (existsSync12(packageJsonPath)) {
|
|
38875
39076
|
try {
|
|
38876
39077
|
const pkg = JSON.parse(readFileSync10(packageJsonPath, "utf-8"));
|
|
38877
39078
|
if (pkg.name && typeof pkg.name === "string") {
|
|
@@ -38879,7 +39080,7 @@ function inferProjectName(directory) {
|
|
|
38879
39080
|
}
|
|
38880
39081
|
} catch {}
|
|
38881
39082
|
}
|
|
38882
|
-
return
|
|
39083
|
+
return path21.basename(directory);
|
|
38883
39084
|
}
|
|
38884
39085
|
async function writeSentinel(sentinelPath, migrated, dropped) {
|
|
38885
39086
|
const sentinel = {
|
|
@@ -38891,7 +39092,7 @@ async function writeSentinel(sentinelPath, migrated, dropped) {
|
|
|
38891
39092
|
schema_version: 1,
|
|
38892
39093
|
migration_tool: "knowledge-migrator.ts"
|
|
38893
39094
|
};
|
|
38894
|
-
await mkdir3(
|
|
39095
|
+
await mkdir3(path21.dirname(sentinelPath), { recursive: true });
|
|
38895
39096
|
await writeFile4(sentinelPath, JSON.stringify(sentinel, null, 2), "utf-8");
|
|
38896
39097
|
}
|
|
38897
39098
|
|
|
@@ -39127,12 +39328,12 @@ async function handlePlanCommand(directory, args) {
|
|
|
39127
39328
|
// src/services/preflight-service.ts
|
|
39128
39329
|
init_manager2();
|
|
39129
39330
|
init_manager();
|
|
39130
|
-
import * as
|
|
39131
|
-
import * as
|
|
39331
|
+
import * as fs18 from "fs";
|
|
39332
|
+
import * as path28 from "path";
|
|
39132
39333
|
|
|
39133
39334
|
// src/tools/lint.ts
|
|
39134
|
-
import * as
|
|
39135
|
-
import * as
|
|
39335
|
+
import * as fs12 from "fs";
|
|
39336
|
+
import * as path22 from "path";
|
|
39136
39337
|
init_utils();
|
|
39137
39338
|
|
|
39138
39339
|
// src/utils/path-security.ts
|
|
@@ -39178,9 +39379,9 @@ function validateArgs(args) {
|
|
|
39178
39379
|
}
|
|
39179
39380
|
function getLinterCommand(linter, mode, projectDir) {
|
|
39180
39381
|
const isWindows = process.platform === "win32";
|
|
39181
|
-
const binDir =
|
|
39182
|
-
const biomeBin = isWindows ?
|
|
39183
|
-
const eslintBin = isWindows ?
|
|
39382
|
+
const binDir = path22.join(projectDir, "node_modules", ".bin");
|
|
39383
|
+
const biomeBin = isWindows ? path22.join(binDir, "biome.EXE") : path22.join(binDir, "biome");
|
|
39384
|
+
const eslintBin = isWindows ? path22.join(binDir, "eslint.cmd") : path22.join(binDir, "eslint");
|
|
39184
39385
|
switch (linter) {
|
|
39185
39386
|
case "biome":
|
|
39186
39387
|
if (mode === "fix") {
|
|
@@ -39196,7 +39397,7 @@ function getLinterCommand(linter, mode, projectDir) {
|
|
|
39196
39397
|
}
|
|
39197
39398
|
function getAdditionalLinterCommand(linter, mode, cwd) {
|
|
39198
39399
|
const gradlewName = process.platform === "win32" ? "gradlew.bat" : "gradlew";
|
|
39199
|
-
const gradlew =
|
|
39400
|
+
const gradlew = fs12.existsSync(path22.join(cwd, gradlewName)) ? path22.join(cwd, gradlewName) : null;
|
|
39200
39401
|
switch (linter) {
|
|
39201
39402
|
case "ruff":
|
|
39202
39403
|
return mode === "fix" ? ["ruff", "check", "--fix", "."] : ["ruff", "check", "."];
|
|
@@ -39230,12 +39431,12 @@ function getAdditionalLinterCommand(linter, mode, cwd) {
|
|
|
39230
39431
|
}
|
|
39231
39432
|
}
|
|
39232
39433
|
function detectRuff(cwd) {
|
|
39233
|
-
if (
|
|
39434
|
+
if (fs12.existsSync(path22.join(cwd, "ruff.toml")))
|
|
39234
39435
|
return isCommandAvailable("ruff");
|
|
39235
39436
|
try {
|
|
39236
|
-
const pyproject =
|
|
39237
|
-
if (
|
|
39238
|
-
const content =
|
|
39437
|
+
const pyproject = path22.join(cwd, "pyproject.toml");
|
|
39438
|
+
if (fs12.existsSync(pyproject)) {
|
|
39439
|
+
const content = fs12.readFileSync(pyproject, "utf-8");
|
|
39239
39440
|
if (content.includes("[tool.ruff]"))
|
|
39240
39441
|
return isCommandAvailable("ruff");
|
|
39241
39442
|
}
|
|
@@ -39243,21 +39444,21 @@ function detectRuff(cwd) {
|
|
|
39243
39444
|
return false;
|
|
39244
39445
|
}
|
|
39245
39446
|
function detectClippy(cwd) {
|
|
39246
|
-
return
|
|
39447
|
+
return fs12.existsSync(path22.join(cwd, "Cargo.toml")) && isCommandAvailable("cargo");
|
|
39247
39448
|
}
|
|
39248
39449
|
function detectGolangciLint(cwd) {
|
|
39249
|
-
return
|
|
39450
|
+
return fs12.existsSync(path22.join(cwd, "go.mod")) && isCommandAvailable("golangci-lint");
|
|
39250
39451
|
}
|
|
39251
39452
|
function detectCheckstyle(cwd) {
|
|
39252
|
-
const hasMaven =
|
|
39253
|
-
const hasGradle =
|
|
39254
|
-
const hasBinary = hasMaven && isCommandAvailable("mvn") || hasGradle && (
|
|
39453
|
+
const hasMaven = fs12.existsSync(path22.join(cwd, "pom.xml"));
|
|
39454
|
+
const hasGradle = fs12.existsSync(path22.join(cwd, "build.gradle")) || fs12.existsSync(path22.join(cwd, "build.gradle.kts"));
|
|
39455
|
+
const hasBinary = hasMaven && isCommandAvailable("mvn") || hasGradle && (fs12.existsSync(path22.join(cwd, "gradlew")) || isCommandAvailable("gradle"));
|
|
39255
39456
|
return (hasMaven || hasGradle) && hasBinary;
|
|
39256
39457
|
}
|
|
39257
39458
|
function detectKtlint(cwd) {
|
|
39258
|
-
const hasKotlin =
|
|
39459
|
+
const hasKotlin = fs12.existsSync(path22.join(cwd, "build.gradle.kts")) || fs12.existsSync(path22.join(cwd, "build.gradle")) || (() => {
|
|
39259
39460
|
try {
|
|
39260
|
-
return
|
|
39461
|
+
return fs12.readdirSync(cwd).some((f) => f.endsWith(".kt") || f.endsWith(".kts"));
|
|
39261
39462
|
} catch {
|
|
39262
39463
|
return false;
|
|
39263
39464
|
}
|
|
@@ -39266,7 +39467,7 @@ function detectKtlint(cwd) {
|
|
|
39266
39467
|
}
|
|
39267
39468
|
function detectDotnetFormat(cwd) {
|
|
39268
39469
|
try {
|
|
39269
|
-
const files =
|
|
39470
|
+
const files = fs12.readdirSync(cwd);
|
|
39270
39471
|
const hasCsproj = files.some((f) => f.endsWith(".csproj") || f.endsWith(".sln"));
|
|
39271
39472
|
return hasCsproj && isCommandAvailable("dotnet");
|
|
39272
39473
|
} catch {
|
|
@@ -39274,14 +39475,14 @@ function detectDotnetFormat(cwd) {
|
|
|
39274
39475
|
}
|
|
39275
39476
|
}
|
|
39276
39477
|
function detectCppcheck(cwd) {
|
|
39277
|
-
if (
|
|
39478
|
+
if (fs12.existsSync(path22.join(cwd, "CMakeLists.txt"))) {
|
|
39278
39479
|
return isCommandAvailable("cppcheck");
|
|
39279
39480
|
}
|
|
39280
39481
|
try {
|
|
39281
|
-
const dirsToCheck = [cwd,
|
|
39482
|
+
const dirsToCheck = [cwd, path22.join(cwd, "src")];
|
|
39282
39483
|
const hasCpp = dirsToCheck.some((dir) => {
|
|
39283
39484
|
try {
|
|
39284
|
-
return
|
|
39485
|
+
return fs12.readdirSync(dir).some((f) => /\.(c|cpp|cc|cxx|h|hpp)$/.test(f));
|
|
39285
39486
|
} catch {
|
|
39286
39487
|
return false;
|
|
39287
39488
|
}
|
|
@@ -39292,13 +39493,13 @@ function detectCppcheck(cwd) {
|
|
|
39292
39493
|
}
|
|
39293
39494
|
}
|
|
39294
39495
|
function detectSwiftlint(cwd) {
|
|
39295
|
-
return
|
|
39496
|
+
return fs12.existsSync(path22.join(cwd, "Package.swift")) && isCommandAvailable("swiftlint");
|
|
39296
39497
|
}
|
|
39297
39498
|
function detectDartAnalyze(cwd) {
|
|
39298
|
-
return
|
|
39499
|
+
return fs12.existsSync(path22.join(cwd, "pubspec.yaml")) && (isCommandAvailable("dart") || isCommandAvailable("flutter"));
|
|
39299
39500
|
}
|
|
39300
39501
|
function detectRubocop(cwd) {
|
|
39301
|
-
return (
|
|
39502
|
+
return (fs12.existsSync(path22.join(cwd, "Gemfile")) || fs12.existsSync(path22.join(cwd, "gems.rb")) || fs12.existsSync(path22.join(cwd, ".rubocop.yml"))) && (isCommandAvailable("rubocop") || isCommandAvailable("bundle"));
|
|
39302
39503
|
}
|
|
39303
39504
|
function detectAdditionalLinter(cwd) {
|
|
39304
39505
|
if (detectRuff(cwd))
|
|
@@ -39326,10 +39527,10 @@ function detectAdditionalLinter(cwd) {
|
|
|
39326
39527
|
function findBinInAncestors(startDir, binName) {
|
|
39327
39528
|
let dir = startDir;
|
|
39328
39529
|
while (true) {
|
|
39329
|
-
const candidate =
|
|
39330
|
-
if (
|
|
39530
|
+
const candidate = path22.join(dir, "node_modules", ".bin", binName);
|
|
39531
|
+
if (fs12.existsSync(candidate))
|
|
39331
39532
|
return candidate;
|
|
39332
|
-
const parent =
|
|
39533
|
+
const parent = path22.dirname(dir);
|
|
39333
39534
|
if (parent === dir)
|
|
39334
39535
|
break;
|
|
39335
39536
|
dir = parent;
|
|
@@ -39338,11 +39539,11 @@ function findBinInAncestors(startDir, binName) {
|
|
|
39338
39539
|
}
|
|
39339
39540
|
function findBinInEnvPath(binName) {
|
|
39340
39541
|
const searchPath = process.env.PATH ?? "";
|
|
39341
|
-
for (const dir of searchPath.split(
|
|
39542
|
+
for (const dir of searchPath.split(path22.delimiter)) {
|
|
39342
39543
|
if (!dir)
|
|
39343
39544
|
continue;
|
|
39344
|
-
const candidate =
|
|
39345
|
-
if (
|
|
39545
|
+
const candidate = path22.join(dir, binName);
|
|
39546
|
+
if (fs12.existsSync(candidate))
|
|
39346
39547
|
return candidate;
|
|
39347
39548
|
}
|
|
39348
39549
|
return null;
|
|
@@ -39350,17 +39551,17 @@ function findBinInEnvPath(binName) {
|
|
|
39350
39551
|
async function detectAvailableLinter(directory) {
|
|
39351
39552
|
if (!directory)
|
|
39352
39553
|
return null;
|
|
39353
|
-
if (!
|
|
39554
|
+
if (!fs12.existsSync(directory))
|
|
39354
39555
|
return null;
|
|
39355
39556
|
const projectDir = directory;
|
|
39356
39557
|
const isWindows = process.platform === "win32";
|
|
39357
|
-
const biomeBin = isWindows ?
|
|
39358
|
-
const eslintBin = isWindows ?
|
|
39558
|
+
const biomeBin = isWindows ? path22.join(projectDir, "node_modules", ".bin", "biome.EXE") : path22.join(projectDir, "node_modules", ".bin", "biome");
|
|
39559
|
+
const eslintBin = isWindows ? path22.join(projectDir, "node_modules", ".bin", "eslint.cmd") : path22.join(projectDir, "node_modules", ".bin", "eslint");
|
|
39359
39560
|
const localResult = await _detectAvailableLinter(projectDir, biomeBin, eslintBin);
|
|
39360
39561
|
if (localResult)
|
|
39361
39562
|
return localResult;
|
|
39362
|
-
const biomeAncestor = findBinInAncestors(
|
|
39363
|
-
const eslintAncestor = findBinInAncestors(
|
|
39563
|
+
const biomeAncestor = findBinInAncestors(path22.dirname(projectDir), isWindows ? "biome.EXE" : "biome");
|
|
39564
|
+
const eslintAncestor = findBinInAncestors(path22.dirname(projectDir), isWindows ? "eslint.cmd" : "eslint");
|
|
39364
39565
|
if (biomeAncestor || eslintAncestor) {
|
|
39365
39566
|
return _detectAvailableLinter(projectDir, biomeAncestor ?? biomeBin, eslintAncestor ?? eslintBin);
|
|
39366
39567
|
}
|
|
@@ -39379,11 +39580,11 @@ async function _detectAvailableLinter(_projectDir, biomeBin, eslintBin) {
|
|
|
39379
39580
|
stderr: "pipe"
|
|
39380
39581
|
});
|
|
39381
39582
|
const biomeExit = biomeProc.exited;
|
|
39382
|
-
const timeout = new Promise((
|
|
39583
|
+
const timeout = new Promise((resolve9) => setTimeout(() => resolve9("timeout"), DETECT_TIMEOUT));
|
|
39383
39584
|
const result = await Promise.race([biomeExit, timeout]);
|
|
39384
39585
|
if (result === "timeout") {
|
|
39385
39586
|
biomeProc.kill();
|
|
39386
|
-
} else if (biomeProc.exitCode === 0 &&
|
|
39587
|
+
} else if (biomeProc.exitCode === 0 && fs12.existsSync(biomeBin)) {
|
|
39387
39588
|
return "biome";
|
|
39388
39589
|
}
|
|
39389
39590
|
} catch {}
|
|
@@ -39393,11 +39594,11 @@ async function _detectAvailableLinter(_projectDir, biomeBin, eslintBin) {
|
|
|
39393
39594
|
stderr: "pipe"
|
|
39394
39595
|
});
|
|
39395
39596
|
const eslintExit = eslintProc.exited;
|
|
39396
|
-
const timeout = new Promise((
|
|
39597
|
+
const timeout = new Promise((resolve9) => setTimeout(() => resolve9("timeout"), DETECT_TIMEOUT));
|
|
39397
39598
|
const result = await Promise.race([eslintExit, timeout]);
|
|
39398
39599
|
if (result === "timeout") {
|
|
39399
39600
|
eslintProc.kill();
|
|
39400
|
-
} else if (eslintProc.exitCode === 0 &&
|
|
39601
|
+
} else if (eslintProc.exitCode === 0 && fs12.existsSync(eslintBin)) {
|
|
39401
39602
|
return "eslint";
|
|
39402
39603
|
}
|
|
39403
39604
|
} catch {}
|
|
@@ -39567,8 +39768,8 @@ For Rust: rustup component add clippy`
|
|
|
39567
39768
|
});
|
|
39568
39769
|
|
|
39569
39770
|
// src/tools/secretscan.ts
|
|
39570
|
-
import * as
|
|
39571
|
-
import * as
|
|
39771
|
+
import * as fs13 from "fs";
|
|
39772
|
+
import * as path23 from "path";
|
|
39572
39773
|
var MAX_FILE_PATH_LENGTH = 500;
|
|
39573
39774
|
var MAX_FILE_SIZE_BYTES = 512 * 1024;
|
|
39574
39775
|
var MAX_FILES_SCANNED = 1000;
|
|
@@ -39795,11 +39996,11 @@ function isGlobOrPathPattern(pattern) {
|
|
|
39795
39996
|
return pattern.includes("/") || pattern.includes("\\") || /[*?[\]{}]/.test(pattern);
|
|
39796
39997
|
}
|
|
39797
39998
|
function loadSecretScanIgnore(scanDir) {
|
|
39798
|
-
const ignorePath =
|
|
39999
|
+
const ignorePath = path23.join(scanDir, ".secretscanignore");
|
|
39799
40000
|
try {
|
|
39800
|
-
if (!
|
|
40001
|
+
if (!fs13.existsSync(ignorePath))
|
|
39801
40002
|
return [];
|
|
39802
|
-
const content =
|
|
40003
|
+
const content = fs13.readFileSync(ignorePath, "utf8");
|
|
39803
40004
|
const patterns = [];
|
|
39804
40005
|
for (const rawLine of content.split(/\r?\n/)) {
|
|
39805
40006
|
const line = rawLine.trim();
|
|
@@ -39818,7 +40019,7 @@ function isExcluded(entry, relPath, exactNames, globPatterns) {
|
|
|
39818
40019
|
if (exactNames.has(entry))
|
|
39819
40020
|
return true;
|
|
39820
40021
|
for (const pattern of globPatterns) {
|
|
39821
|
-
if (
|
|
40022
|
+
if (path23.matchesGlob(relPath, pattern))
|
|
39822
40023
|
return true;
|
|
39823
40024
|
}
|
|
39824
40025
|
return false;
|
|
@@ -39839,7 +40040,7 @@ function validateDirectoryInput(dir) {
|
|
|
39839
40040
|
return null;
|
|
39840
40041
|
}
|
|
39841
40042
|
function isBinaryFile(filePath, buffer) {
|
|
39842
|
-
const ext =
|
|
40043
|
+
const ext = path23.extname(filePath).toLowerCase();
|
|
39843
40044
|
if (DEFAULT_EXCLUDE_EXTENSIONS.has(ext)) {
|
|
39844
40045
|
return true;
|
|
39845
40046
|
}
|
|
@@ -39914,11 +40115,11 @@ function createRedactedContext(line, findings) {
|
|
|
39914
40115
|
result += line.slice(lastEnd);
|
|
39915
40116
|
return result;
|
|
39916
40117
|
}
|
|
39917
|
-
var O_NOFOLLOW = process.platform !== "win32" ?
|
|
40118
|
+
var O_NOFOLLOW = process.platform !== "win32" ? fs13.constants.O_NOFOLLOW : undefined;
|
|
39918
40119
|
function scanFileForSecrets(filePath) {
|
|
39919
40120
|
const findings = [];
|
|
39920
40121
|
try {
|
|
39921
|
-
const lstat =
|
|
40122
|
+
const lstat = fs13.lstatSync(filePath);
|
|
39922
40123
|
if (lstat.isSymbolicLink()) {
|
|
39923
40124
|
return findings;
|
|
39924
40125
|
}
|
|
@@ -39927,14 +40128,14 @@ function scanFileForSecrets(filePath) {
|
|
|
39927
40128
|
}
|
|
39928
40129
|
let buffer;
|
|
39929
40130
|
if (O_NOFOLLOW !== undefined) {
|
|
39930
|
-
const fd =
|
|
40131
|
+
const fd = fs13.openSync(filePath, "r", O_NOFOLLOW);
|
|
39931
40132
|
try {
|
|
39932
|
-
buffer =
|
|
40133
|
+
buffer = fs13.readFileSync(fd);
|
|
39933
40134
|
} finally {
|
|
39934
|
-
|
|
40135
|
+
fs13.closeSync(fd);
|
|
39935
40136
|
}
|
|
39936
40137
|
} else {
|
|
39937
|
-
buffer =
|
|
40138
|
+
buffer = fs13.readFileSync(filePath);
|
|
39938
40139
|
}
|
|
39939
40140
|
if (isBinaryFile(filePath, buffer)) {
|
|
39940
40141
|
return findings;
|
|
@@ -39976,9 +40177,9 @@ function isSymlinkLoop(realPath, visited) {
|
|
|
39976
40177
|
return false;
|
|
39977
40178
|
}
|
|
39978
40179
|
function isPathWithinScope(realPath, scanDir) {
|
|
39979
|
-
const resolvedScanDir =
|
|
39980
|
-
const resolvedRealPath =
|
|
39981
|
-
return resolvedRealPath === resolvedScanDir || resolvedRealPath.startsWith(resolvedScanDir +
|
|
40180
|
+
const resolvedScanDir = path23.resolve(scanDir);
|
|
40181
|
+
const resolvedRealPath = path23.resolve(realPath);
|
|
40182
|
+
return resolvedRealPath === resolvedScanDir || resolvedRealPath.startsWith(resolvedScanDir + path23.sep) || resolvedRealPath.startsWith(`${resolvedScanDir}/`) || resolvedRealPath.startsWith(`${resolvedScanDir}\\`);
|
|
39982
40183
|
}
|
|
39983
40184
|
function findScannableFiles(dir, excludeExact, excludeGlobs, scanDir, visited, stats = {
|
|
39984
40185
|
skippedDirs: 0,
|
|
@@ -39989,7 +40190,7 @@ function findScannableFiles(dir, excludeExact, excludeGlobs, scanDir, visited, s
|
|
|
39989
40190
|
const files = [];
|
|
39990
40191
|
let entries;
|
|
39991
40192
|
try {
|
|
39992
|
-
entries =
|
|
40193
|
+
entries = fs13.readdirSync(dir);
|
|
39993
40194
|
} catch {
|
|
39994
40195
|
stats.fileErrors++;
|
|
39995
40196
|
return files;
|
|
@@ -40004,15 +40205,15 @@ function findScannableFiles(dir, excludeExact, excludeGlobs, scanDir, visited, s
|
|
|
40004
40205
|
return a.localeCompare(b);
|
|
40005
40206
|
});
|
|
40006
40207
|
for (const entry of entries) {
|
|
40007
|
-
const fullPath =
|
|
40008
|
-
const relPath =
|
|
40208
|
+
const fullPath = path23.join(dir, entry);
|
|
40209
|
+
const relPath = path23.relative(scanDir, fullPath).replace(/\\/g, "/");
|
|
40009
40210
|
if (isExcluded(entry, relPath, excludeExact, excludeGlobs)) {
|
|
40010
40211
|
stats.skippedDirs++;
|
|
40011
40212
|
continue;
|
|
40012
40213
|
}
|
|
40013
40214
|
let lstat;
|
|
40014
40215
|
try {
|
|
40015
|
-
lstat =
|
|
40216
|
+
lstat = fs13.lstatSync(fullPath);
|
|
40016
40217
|
} catch {
|
|
40017
40218
|
stats.fileErrors++;
|
|
40018
40219
|
continue;
|
|
@@ -40024,7 +40225,7 @@ function findScannableFiles(dir, excludeExact, excludeGlobs, scanDir, visited, s
|
|
|
40024
40225
|
if (lstat.isDirectory()) {
|
|
40025
40226
|
let realPath;
|
|
40026
40227
|
try {
|
|
40027
|
-
realPath =
|
|
40228
|
+
realPath = fs13.realpathSync(fullPath);
|
|
40028
40229
|
} catch {
|
|
40029
40230
|
stats.fileErrors++;
|
|
40030
40231
|
continue;
|
|
@@ -40040,7 +40241,7 @@ function findScannableFiles(dir, excludeExact, excludeGlobs, scanDir, visited, s
|
|
|
40040
40241
|
const subFiles = findScannableFiles(fullPath, excludeExact, excludeGlobs, scanDir, visited, stats);
|
|
40041
40242
|
files.push(...subFiles);
|
|
40042
40243
|
} else if (lstat.isFile()) {
|
|
40043
|
-
const ext =
|
|
40244
|
+
const ext = path23.extname(fullPath).toLowerCase();
|
|
40044
40245
|
if (!DEFAULT_EXCLUDE_EXTENSIONS.has(ext)) {
|
|
40045
40246
|
files.push(fullPath);
|
|
40046
40247
|
} else {
|
|
@@ -40106,15 +40307,15 @@ var secretscan = createSwarmTool({
|
|
|
40106
40307
|
}
|
|
40107
40308
|
}
|
|
40108
40309
|
try {
|
|
40109
|
-
const _scanDirRaw =
|
|
40310
|
+
const _scanDirRaw = path23.resolve(directory);
|
|
40110
40311
|
const scanDir = (() => {
|
|
40111
40312
|
try {
|
|
40112
|
-
return
|
|
40313
|
+
return fs13.realpathSync(_scanDirRaw);
|
|
40113
40314
|
} catch {
|
|
40114
40315
|
return _scanDirRaw;
|
|
40115
40316
|
}
|
|
40116
40317
|
})();
|
|
40117
|
-
if (!
|
|
40318
|
+
if (!fs13.existsSync(scanDir)) {
|
|
40118
40319
|
const errorResult = {
|
|
40119
40320
|
error: "directory not found",
|
|
40120
40321
|
scan_dir: directory,
|
|
@@ -40125,7 +40326,7 @@ var secretscan = createSwarmTool({
|
|
|
40125
40326
|
};
|
|
40126
40327
|
return JSON.stringify(errorResult, null, 2);
|
|
40127
40328
|
}
|
|
40128
|
-
const dirStat =
|
|
40329
|
+
const dirStat = fs13.statSync(scanDir);
|
|
40129
40330
|
if (!dirStat.isDirectory()) {
|
|
40130
40331
|
const errorResult = {
|
|
40131
40332
|
error: "target must be a directory, not a file",
|
|
@@ -40176,7 +40377,7 @@ var secretscan = createSwarmTool({
|
|
|
40176
40377
|
break;
|
|
40177
40378
|
const fileFindings = scanFileForSecrets(filePath);
|
|
40178
40379
|
try {
|
|
40179
|
-
const stat2 =
|
|
40380
|
+
const stat2 = fs13.statSync(filePath);
|
|
40180
40381
|
if (stat2.size > MAX_FILE_SIZE_BYTES) {
|
|
40181
40382
|
skippedFiles++;
|
|
40182
40383
|
continue;
|
|
@@ -40263,12 +40464,12 @@ async function runSecretscan(directory) {
|
|
|
40263
40464
|
}
|
|
40264
40465
|
|
|
40265
40466
|
// src/tools/test-runner.ts
|
|
40266
|
-
import * as
|
|
40267
|
-
import * as
|
|
40467
|
+
import * as fs17 from "fs";
|
|
40468
|
+
import * as path27 from "path";
|
|
40268
40469
|
|
|
40269
40470
|
// src/test-impact/analyzer.ts
|
|
40270
|
-
import
|
|
40271
|
-
import
|
|
40471
|
+
import fs14 from "fs";
|
|
40472
|
+
import path24 from "path";
|
|
40272
40473
|
var IMPORT_REGEX_ES = /import\s+.*?\s+from\s+['"]([^'"]+)['"]/g;
|
|
40273
40474
|
var IMPORT_REGEX_REQUIRE = /require\s*\(\s*['"]([^'"]+)['"]\s*\)/g;
|
|
40274
40475
|
var IMPORT_REGEX_REEXPORT = /export\s+(?:\{[^}]*\}|\*)\s+from\s+['"]([^'"]+)['"]/g;
|
|
@@ -40279,7 +40480,7 @@ function normalizePath(p) {
|
|
|
40279
40480
|
function isCacheStale(impactMap, generatedAtMs) {
|
|
40280
40481
|
for (const sourcePath of Object.keys(impactMap)) {
|
|
40281
40482
|
try {
|
|
40282
|
-
const stat2 =
|
|
40483
|
+
const stat2 = fs14.statSync(sourcePath);
|
|
40283
40484
|
if (stat2.mtimeMs > generatedAtMs) {
|
|
40284
40485
|
return true;
|
|
40285
40486
|
}
|
|
@@ -40293,15 +40494,15 @@ function resolveRelativeImport(fromDir, importPath) {
|
|
|
40293
40494
|
if (!importPath.startsWith(".")) {
|
|
40294
40495
|
return null;
|
|
40295
40496
|
}
|
|
40296
|
-
const resolved =
|
|
40297
|
-
if (
|
|
40298
|
-
if (
|
|
40497
|
+
const resolved = path24.resolve(fromDir, importPath);
|
|
40498
|
+
if (path24.extname(resolved)) {
|
|
40499
|
+
if (fs14.existsSync(resolved) && fs14.statSync(resolved).isFile()) {
|
|
40299
40500
|
return normalizePath(resolved);
|
|
40300
40501
|
}
|
|
40301
40502
|
} else {
|
|
40302
40503
|
for (const ext of EXTENSIONS_TO_TRY) {
|
|
40303
40504
|
const withExt = resolved + ext;
|
|
40304
|
-
if (
|
|
40505
|
+
if (fs14.existsSync(withExt) && fs14.statSync(withExt).isFile()) {
|
|
40305
40506
|
return normalizePath(withExt);
|
|
40306
40507
|
}
|
|
40307
40508
|
}
|
|
@@ -40320,13 +40521,13 @@ function findTestFilesSync(cwd) {
|
|
|
40320
40521
|
function walk(dir, visitedInodes) {
|
|
40321
40522
|
let entries;
|
|
40322
40523
|
try {
|
|
40323
|
-
entries =
|
|
40524
|
+
entries = fs14.readdirSync(dir, { withFileTypes: true });
|
|
40324
40525
|
} catch {
|
|
40325
40526
|
return;
|
|
40326
40527
|
}
|
|
40327
40528
|
let dirInode;
|
|
40328
40529
|
try {
|
|
40329
|
-
dirInode =
|
|
40530
|
+
dirInode = fs14.statSync(dir).ino;
|
|
40330
40531
|
} catch {
|
|
40331
40532
|
return;
|
|
40332
40533
|
}
|
|
@@ -40339,12 +40540,12 @@ function findTestFilesSync(cwd) {
|
|
|
40339
40540
|
for (const entry of entries) {
|
|
40340
40541
|
if (entry.isDirectory()) {
|
|
40341
40542
|
if (!skipDirs.has(entry.name)) {
|
|
40342
|
-
walk(
|
|
40543
|
+
walk(path24.join(dir, entry.name), visitedInodes);
|
|
40343
40544
|
}
|
|
40344
40545
|
} else if (entry.isFile()) {
|
|
40345
40546
|
const name = entry.name;
|
|
40346
40547
|
if (/\.(test|spec)\.(ts|tsx|js|jsx)$/.test(name) || dir.includes("__tests__") && /\.(ts|tsx|js|jsx)$/.test(name)) {
|
|
40347
|
-
testFiles.push(normalizePath(
|
|
40548
|
+
testFiles.push(normalizePath(path24.join(dir, entry.name)));
|
|
40348
40549
|
}
|
|
40349
40550
|
}
|
|
40350
40551
|
}
|
|
@@ -40374,7 +40575,7 @@ async function buildImpactMapInternal(cwd) {
|
|
|
40374
40575
|
for (const testFile of testFiles) {
|
|
40375
40576
|
let content;
|
|
40376
40577
|
try {
|
|
40377
|
-
content =
|
|
40578
|
+
content = fs14.readFileSync(testFile, "utf-8");
|
|
40378
40579
|
} catch {
|
|
40379
40580
|
continue;
|
|
40380
40581
|
}
|
|
@@ -40382,7 +40583,7 @@ async function buildImpactMapInternal(cwd) {
|
|
|
40382
40583
|
continue;
|
|
40383
40584
|
}
|
|
40384
40585
|
const imports = extractImports(content);
|
|
40385
|
-
const testDir =
|
|
40586
|
+
const testDir = path24.dirname(testFile);
|
|
40386
40587
|
for (const importPath of imports) {
|
|
40387
40588
|
const resolvedSource = resolveRelativeImport(testDir, importPath);
|
|
40388
40589
|
if (resolvedSource === null) {
|
|
@@ -40404,10 +40605,10 @@ async function buildImpactMap(cwd) {
|
|
|
40404
40605
|
return impactMap;
|
|
40405
40606
|
}
|
|
40406
40607
|
async function loadImpactMap(cwd) {
|
|
40407
|
-
const cachePath =
|
|
40408
|
-
if (
|
|
40608
|
+
const cachePath = path24.join(cwd, ".swarm", "cache", "impact-map.json");
|
|
40609
|
+
if (fs14.existsSync(cachePath)) {
|
|
40409
40610
|
try {
|
|
40410
|
-
const content =
|
|
40611
|
+
const content = fs14.readFileSync(cachePath, "utf-8");
|
|
40411
40612
|
const data = JSON.parse(content);
|
|
40412
40613
|
const map3 = data.map;
|
|
40413
40614
|
const generatedAt = new Date(data.generatedAt).getTime();
|
|
@@ -40419,17 +40620,17 @@ async function loadImpactMap(cwd) {
|
|
|
40419
40620
|
return buildImpactMap(cwd);
|
|
40420
40621
|
}
|
|
40421
40622
|
async function saveImpactMap(cwd, impactMap) {
|
|
40422
|
-
const cacheDir =
|
|
40423
|
-
const cachePath =
|
|
40424
|
-
if (!
|
|
40425
|
-
|
|
40623
|
+
const cacheDir = path24.join(cwd, ".swarm", "cache");
|
|
40624
|
+
const cachePath = path24.join(cacheDir, "impact-map.json");
|
|
40625
|
+
if (!fs14.existsSync(cacheDir)) {
|
|
40626
|
+
fs14.mkdirSync(cacheDir, { recursive: true });
|
|
40426
40627
|
}
|
|
40427
40628
|
const data = {
|
|
40428
40629
|
generatedAt: new Date().toISOString(),
|
|
40429
40630
|
fileCount: Object.keys(impactMap).length,
|
|
40430
40631
|
map: impactMap
|
|
40431
40632
|
};
|
|
40432
|
-
|
|
40633
|
+
fs14.writeFileSync(cachePath, JSON.stringify(data, null, 2), "utf-8");
|
|
40433
40634
|
}
|
|
40434
40635
|
async function analyzeImpact(changedFiles, cwd) {
|
|
40435
40636
|
if (!Array.isArray(changedFiles)) {
|
|
@@ -40446,7 +40647,7 @@ async function analyzeImpact(changedFiles, cwd) {
|
|
|
40446
40647
|
const impactedTestsSet = new Set;
|
|
40447
40648
|
const untestedFiles = [];
|
|
40448
40649
|
for (const changedFile of validFiles) {
|
|
40449
|
-
const normalizedChanged = normalizePath(
|
|
40650
|
+
const normalizedChanged = normalizePath(path24.resolve(changedFile));
|
|
40450
40651
|
const tests = impactMap[normalizedChanged];
|
|
40451
40652
|
if (tests && tests.length > 0) {
|
|
40452
40653
|
for (const test of tests) {
|
|
@@ -40692,14 +40893,14 @@ function detectFlakyTests(allHistory) {
|
|
|
40692
40893
|
}
|
|
40693
40894
|
|
|
40694
40895
|
// src/test-impact/history-store.ts
|
|
40695
|
-
import
|
|
40696
|
-
import
|
|
40896
|
+
import fs15 from "fs";
|
|
40897
|
+
import path25 from "path";
|
|
40697
40898
|
var MAX_HISTORY_PER_TEST = 20;
|
|
40698
40899
|
var MAX_ERROR_LENGTH = 500;
|
|
40699
40900
|
var MAX_STACK_LENGTH = 200;
|
|
40700
40901
|
var MAX_CHANGED_FILES = 50;
|
|
40701
40902
|
function getHistoryPath(workingDir) {
|
|
40702
|
-
return
|
|
40903
|
+
return path25.join(workingDir || process.cwd(), ".swarm", "cache", "test-history.jsonl");
|
|
40703
40904
|
}
|
|
40704
40905
|
function sanitizeErrorMessage(errorMessage) {
|
|
40705
40906
|
if (errorMessage === undefined) {
|
|
@@ -40759,9 +40960,9 @@ function appendTestRun(record3, workingDir) {
|
|
|
40759
40960
|
changedFiles: sanitizeChangedFiles(record3.changedFiles || [])
|
|
40760
40961
|
};
|
|
40761
40962
|
const historyPath = getHistoryPath(workingDir);
|
|
40762
|
-
const historyDir =
|
|
40763
|
-
if (!
|
|
40764
|
-
|
|
40963
|
+
const historyDir = path25.dirname(historyPath);
|
|
40964
|
+
if (!fs15.existsSync(historyDir)) {
|
|
40965
|
+
fs15.mkdirSync(historyDir, { recursive: true });
|
|
40765
40966
|
}
|
|
40766
40967
|
const existingRecords = readAllRecords(historyPath);
|
|
40767
40968
|
existingRecords.push(sanitizedRecord);
|
|
@@ -40786,24 +40987,24 @@ function appendTestRun(record3, workingDir) {
|
|
|
40786
40987
|
`)}
|
|
40787
40988
|
`;
|
|
40788
40989
|
const tempPath = `${historyPath}.tmp`;
|
|
40789
|
-
|
|
40790
|
-
|
|
40990
|
+
fs15.writeFileSync(tempPath, content, "utf-8");
|
|
40991
|
+
fs15.renameSync(tempPath, historyPath);
|
|
40791
40992
|
} catch (err) {
|
|
40792
40993
|
try {
|
|
40793
40994
|
const tempPath = `${historyPath}.tmp`;
|
|
40794
|
-
if (
|
|
40795
|
-
|
|
40995
|
+
if (fs15.existsSync(tempPath)) {
|
|
40996
|
+
fs15.unlinkSync(tempPath);
|
|
40796
40997
|
}
|
|
40797
40998
|
} catch {}
|
|
40798
40999
|
throw new Error(`Failed to write test history: ${err instanceof Error ? err.message : String(err)}`);
|
|
40799
41000
|
}
|
|
40800
41001
|
}
|
|
40801
41002
|
function readAllRecords(historyPath) {
|
|
40802
|
-
if (!
|
|
41003
|
+
if (!fs15.existsSync(historyPath)) {
|
|
40803
41004
|
return [];
|
|
40804
41005
|
}
|
|
40805
41006
|
try {
|
|
40806
|
-
const content =
|
|
41007
|
+
const content = fs15.readFileSync(historyPath, "utf-8");
|
|
40807
41008
|
const lines = content.split(`
|
|
40808
41009
|
`);
|
|
40809
41010
|
const records = [];
|
|
@@ -40832,8 +41033,8 @@ function getAllHistory(workingDir) {
|
|
|
40832
41033
|
}
|
|
40833
41034
|
|
|
40834
41035
|
// src/tools/resolve-working-directory.ts
|
|
40835
|
-
import * as
|
|
40836
|
-
import * as
|
|
41036
|
+
import * as fs16 from "fs";
|
|
41037
|
+
import * as path26 from "path";
|
|
40837
41038
|
function resolveWorkingDirectory(workingDirectory, fallbackDirectory) {
|
|
40838
41039
|
if (workingDirectory == null || workingDirectory === "") {
|
|
40839
41040
|
return { success: true, directory: fallbackDirectory };
|
|
@@ -40853,17 +41054,17 @@ function resolveWorkingDirectory(workingDirectory, fallbackDirectory) {
|
|
|
40853
41054
|
};
|
|
40854
41055
|
}
|
|
40855
41056
|
}
|
|
40856
|
-
const normalizedDir =
|
|
40857
|
-
const pathParts = normalizedDir.split(
|
|
41057
|
+
const normalizedDir = path26.normalize(workingDirectory);
|
|
41058
|
+
const pathParts = normalizedDir.split(path26.sep);
|
|
40858
41059
|
if (pathParts.includes("..")) {
|
|
40859
41060
|
return {
|
|
40860
41061
|
success: false,
|
|
40861
41062
|
message: "Invalid working_directory: path traversal sequences (..) are not allowed"
|
|
40862
41063
|
};
|
|
40863
41064
|
}
|
|
40864
|
-
const resolvedDir =
|
|
41065
|
+
const resolvedDir = path26.resolve(normalizedDir);
|
|
40865
41066
|
try {
|
|
40866
|
-
const realPath =
|
|
41067
|
+
const realPath = fs16.realpathSync(resolvedDir);
|
|
40867
41068
|
return { success: true, directory: realPath };
|
|
40868
41069
|
} catch {
|
|
40869
41070
|
return {
|
|
@@ -40944,19 +41145,19 @@ function hasDevDependency(devDeps, ...patterns) {
|
|
|
40944
41145
|
return hasPackageJsonDependency(devDeps, ...patterns);
|
|
40945
41146
|
}
|
|
40946
41147
|
function detectGoTest(cwd) {
|
|
40947
|
-
return
|
|
41148
|
+
return fs17.existsSync(path27.join(cwd, "go.mod")) && isCommandAvailable("go");
|
|
40948
41149
|
}
|
|
40949
41150
|
function detectJavaMaven(cwd) {
|
|
40950
|
-
return
|
|
41151
|
+
return fs17.existsSync(path27.join(cwd, "pom.xml")) && isCommandAvailable("mvn");
|
|
40951
41152
|
}
|
|
40952
41153
|
function detectGradle(cwd) {
|
|
40953
|
-
const hasBuildFile =
|
|
40954
|
-
const hasGradlew =
|
|
41154
|
+
const hasBuildFile = fs17.existsSync(path27.join(cwd, "build.gradle")) || fs17.existsSync(path27.join(cwd, "build.gradle.kts"));
|
|
41155
|
+
const hasGradlew = fs17.existsSync(path27.join(cwd, "gradlew")) || fs17.existsSync(path27.join(cwd, "gradlew.bat"));
|
|
40955
41156
|
return hasBuildFile && (hasGradlew || isCommandAvailable("gradle"));
|
|
40956
41157
|
}
|
|
40957
41158
|
function detectDotnetTest(cwd) {
|
|
40958
41159
|
try {
|
|
40959
|
-
const files =
|
|
41160
|
+
const files = fs17.readdirSync(cwd);
|
|
40960
41161
|
const hasCsproj = files.some((f) => f.endsWith(".csproj"));
|
|
40961
41162
|
return hasCsproj && isCommandAvailable("dotnet");
|
|
40962
41163
|
} catch {
|
|
@@ -40964,32 +41165,32 @@ function detectDotnetTest(cwd) {
|
|
|
40964
41165
|
}
|
|
40965
41166
|
}
|
|
40966
41167
|
function detectCTest(cwd) {
|
|
40967
|
-
const hasSource =
|
|
40968
|
-
const hasBuildCache =
|
|
41168
|
+
const hasSource = fs17.existsSync(path27.join(cwd, "CMakeLists.txt"));
|
|
41169
|
+
const hasBuildCache = fs17.existsSync(path27.join(cwd, "CMakeCache.txt")) || fs17.existsSync(path27.join(cwd, "build", "CMakeCache.txt"));
|
|
40969
41170
|
return (hasSource || hasBuildCache) && isCommandAvailable("ctest");
|
|
40970
41171
|
}
|
|
40971
41172
|
function detectSwiftTest(cwd) {
|
|
40972
|
-
return
|
|
41173
|
+
return fs17.existsSync(path27.join(cwd, "Package.swift")) && isCommandAvailable("swift");
|
|
40973
41174
|
}
|
|
40974
41175
|
function detectDartTest(cwd) {
|
|
40975
|
-
return
|
|
41176
|
+
return fs17.existsSync(path27.join(cwd, "pubspec.yaml")) && (isCommandAvailable("dart") || isCommandAvailable("flutter"));
|
|
40976
41177
|
}
|
|
40977
41178
|
function detectRSpec(cwd) {
|
|
40978
|
-
const hasRSpecFile =
|
|
40979
|
-
const hasGemfile =
|
|
40980
|
-
const hasSpecDir =
|
|
41179
|
+
const hasRSpecFile = fs17.existsSync(path27.join(cwd, ".rspec"));
|
|
41180
|
+
const hasGemfile = fs17.existsSync(path27.join(cwd, "Gemfile"));
|
|
41181
|
+
const hasSpecDir = fs17.existsSync(path27.join(cwd, "spec"));
|
|
40981
41182
|
const hasRSpec = hasRSpecFile || hasGemfile && hasSpecDir;
|
|
40982
41183
|
return hasRSpec && (isCommandAvailable("bundle") || isCommandAvailable("rspec"));
|
|
40983
41184
|
}
|
|
40984
41185
|
function detectMinitest(cwd) {
|
|
40985
|
-
return
|
|
41186
|
+
return fs17.existsSync(path27.join(cwd, "test")) && (fs17.existsSync(path27.join(cwd, "Gemfile")) || fs17.existsSync(path27.join(cwd, "Rakefile"))) && isCommandAvailable("ruby");
|
|
40986
41187
|
}
|
|
40987
41188
|
async function detectTestFramework(cwd) {
|
|
40988
41189
|
const baseDir = cwd;
|
|
40989
41190
|
try {
|
|
40990
|
-
const packageJsonPath =
|
|
40991
|
-
if (
|
|
40992
|
-
const content =
|
|
41191
|
+
const packageJsonPath = path27.join(baseDir, "package.json");
|
|
41192
|
+
if (fs17.existsSync(packageJsonPath)) {
|
|
41193
|
+
const content = fs17.readFileSync(packageJsonPath, "utf-8");
|
|
40993
41194
|
const pkg = JSON.parse(content);
|
|
40994
41195
|
const _deps = pkg.dependencies || {};
|
|
40995
41196
|
const devDeps = pkg.devDependencies || {};
|
|
@@ -41008,38 +41209,38 @@ async function detectTestFramework(cwd) {
|
|
|
41008
41209
|
return "jest";
|
|
41009
41210
|
if (hasDevDependency(devDeps, "mocha", "@types/mocha"))
|
|
41010
41211
|
return "mocha";
|
|
41011
|
-
if (
|
|
41212
|
+
if (fs17.existsSync(path27.join(baseDir, "bun.lockb")) || fs17.existsSync(path27.join(baseDir, "bun.lock"))) {
|
|
41012
41213
|
if (scripts.test?.includes("bun"))
|
|
41013
41214
|
return "bun";
|
|
41014
41215
|
}
|
|
41015
41216
|
}
|
|
41016
41217
|
} catch {}
|
|
41017
41218
|
try {
|
|
41018
|
-
const pyprojectTomlPath =
|
|
41019
|
-
const setupCfgPath =
|
|
41020
|
-
const requirementsTxtPath =
|
|
41021
|
-
if (
|
|
41022
|
-
const content =
|
|
41219
|
+
const pyprojectTomlPath = path27.join(baseDir, "pyproject.toml");
|
|
41220
|
+
const setupCfgPath = path27.join(baseDir, "setup.cfg");
|
|
41221
|
+
const requirementsTxtPath = path27.join(baseDir, "requirements.txt");
|
|
41222
|
+
if (fs17.existsSync(pyprojectTomlPath)) {
|
|
41223
|
+
const content = fs17.readFileSync(pyprojectTomlPath, "utf-8");
|
|
41023
41224
|
if (content.includes("[tool.pytest"))
|
|
41024
41225
|
return "pytest";
|
|
41025
41226
|
if (content.includes("pytest"))
|
|
41026
41227
|
return "pytest";
|
|
41027
41228
|
}
|
|
41028
|
-
if (
|
|
41029
|
-
const content =
|
|
41229
|
+
if (fs17.existsSync(setupCfgPath)) {
|
|
41230
|
+
const content = fs17.readFileSync(setupCfgPath, "utf-8");
|
|
41030
41231
|
if (content.includes("[pytest]"))
|
|
41031
41232
|
return "pytest";
|
|
41032
41233
|
}
|
|
41033
|
-
if (
|
|
41034
|
-
const content =
|
|
41234
|
+
if (fs17.existsSync(requirementsTxtPath)) {
|
|
41235
|
+
const content = fs17.readFileSync(requirementsTxtPath, "utf-8");
|
|
41035
41236
|
if (content.includes("pytest"))
|
|
41036
41237
|
return "pytest";
|
|
41037
41238
|
}
|
|
41038
41239
|
} catch {}
|
|
41039
41240
|
try {
|
|
41040
|
-
const cargoTomlPath =
|
|
41041
|
-
if (
|
|
41042
|
-
const content =
|
|
41241
|
+
const cargoTomlPath = path27.join(baseDir, "Cargo.toml");
|
|
41242
|
+
if (fs17.existsSync(cargoTomlPath)) {
|
|
41243
|
+
const content = fs17.readFileSync(cargoTomlPath, "utf-8");
|
|
41043
41244
|
if (content.includes("[dev-dependencies]")) {
|
|
41044
41245
|
if (content.includes("tokio") || content.includes("mockall") || content.includes("pretty_assertions")) {
|
|
41045
41246
|
return "cargo";
|
|
@@ -41048,10 +41249,10 @@ async function detectTestFramework(cwd) {
|
|
|
41048
41249
|
}
|
|
41049
41250
|
} catch {}
|
|
41050
41251
|
try {
|
|
41051
|
-
const pesterConfigPath =
|
|
41052
|
-
const pesterConfigJsonPath =
|
|
41053
|
-
const pesterPs1Path =
|
|
41054
|
-
if (
|
|
41252
|
+
const pesterConfigPath = path27.join(baseDir, "pester.config.ps1");
|
|
41253
|
+
const pesterConfigJsonPath = path27.join(baseDir, "pester.config.ps1.json");
|
|
41254
|
+
const pesterPs1Path = path27.join(baseDir, "tests.ps1");
|
|
41255
|
+
if (fs17.existsSync(pesterConfigPath) || fs17.existsSync(pesterConfigJsonPath) || fs17.existsSync(pesterPs1Path)) {
|
|
41055
41256
|
return "pester";
|
|
41056
41257
|
}
|
|
41057
41258
|
} catch {}
|
|
@@ -41102,8 +41303,8 @@ function getTestFilesFromConvention(sourceFiles) {
|
|
|
41102
41303
|
const testFiles = [];
|
|
41103
41304
|
for (const file3 of sourceFiles) {
|
|
41104
41305
|
const normalizedPath = file3.replace(/\\/g, "/");
|
|
41105
|
-
const basename4 =
|
|
41106
|
-
const
|
|
41306
|
+
const basename4 = path27.basename(file3);
|
|
41307
|
+
const dirname11 = path27.dirname(file3);
|
|
41107
41308
|
if (hasCompoundTestExtension(basename4) || basename4.includes(".spec.") || basename4.includes(".test.") || normalizedPath.includes("/__tests__/") || normalizedPath.includes("/tests/") || normalizedPath.includes("/test/")) {
|
|
41108
41309
|
if (!testFiles.includes(file3)) {
|
|
41109
41310
|
testFiles.push(file3);
|
|
@@ -41112,16 +41313,16 @@ function getTestFilesFromConvention(sourceFiles) {
|
|
|
41112
41313
|
}
|
|
41113
41314
|
for (const _pattern of TEST_PATTERNS) {
|
|
41114
41315
|
const nameWithoutExt = basename4.replace(/\.[^.]+$/, "");
|
|
41115
|
-
const ext =
|
|
41316
|
+
const ext = path27.extname(basename4);
|
|
41116
41317
|
const possibleTestFiles = [
|
|
41117
|
-
|
|
41118
|
-
|
|
41119
|
-
|
|
41120
|
-
|
|
41121
|
-
|
|
41318
|
+
path27.join(dirname11, `${nameWithoutExt}.spec${ext}`),
|
|
41319
|
+
path27.join(dirname11, `${nameWithoutExt}.test${ext}`),
|
|
41320
|
+
path27.join(dirname11, "__tests__", `${nameWithoutExt}${ext}`),
|
|
41321
|
+
path27.join(dirname11, "tests", `${nameWithoutExt}${ext}`),
|
|
41322
|
+
path27.join(dirname11, "test", `${nameWithoutExt}${ext}`)
|
|
41122
41323
|
];
|
|
41123
41324
|
for (const testFile of possibleTestFiles) {
|
|
41124
|
-
if (
|
|
41325
|
+
if (fs17.existsSync(testFile) && !testFiles.includes(testFile)) {
|
|
41125
41326
|
testFiles.push(testFile);
|
|
41126
41327
|
}
|
|
41127
41328
|
}
|
|
@@ -41137,8 +41338,8 @@ async function getTestFilesFromGraph(sourceFiles) {
|
|
|
41137
41338
|
}
|
|
41138
41339
|
for (const testFile of candidateTestFiles) {
|
|
41139
41340
|
try {
|
|
41140
|
-
const content =
|
|
41141
|
-
const testDir =
|
|
41341
|
+
const content = fs17.readFileSync(testFile, "utf-8");
|
|
41342
|
+
const testDir = path27.dirname(testFile);
|
|
41142
41343
|
const importRegex = /import\s+.*?\s+from\s+['"]([^'"]+)['"]/g;
|
|
41143
41344
|
let match;
|
|
41144
41345
|
match = importRegex.exec(content);
|
|
@@ -41146,8 +41347,8 @@ async function getTestFilesFromGraph(sourceFiles) {
|
|
|
41146
41347
|
const importPath = match[1];
|
|
41147
41348
|
let resolvedImport;
|
|
41148
41349
|
if (importPath.startsWith(".")) {
|
|
41149
|
-
resolvedImport =
|
|
41150
|
-
const existingExt =
|
|
41350
|
+
resolvedImport = path27.resolve(testDir, importPath);
|
|
41351
|
+
const existingExt = path27.extname(resolvedImport);
|
|
41151
41352
|
if (!existingExt) {
|
|
41152
41353
|
for (const extToTry of [
|
|
41153
41354
|
".ts",
|
|
@@ -41158,7 +41359,7 @@ async function getTestFilesFromGraph(sourceFiles) {
|
|
|
41158
41359
|
".cjs"
|
|
41159
41360
|
]) {
|
|
41160
41361
|
const withExt = resolvedImport + extToTry;
|
|
41161
|
-
if (sourceFiles.includes(withExt) ||
|
|
41362
|
+
if (sourceFiles.includes(withExt) || fs17.existsSync(withExt)) {
|
|
41162
41363
|
resolvedImport = withExt;
|
|
41163
41364
|
break;
|
|
41164
41365
|
}
|
|
@@ -41167,12 +41368,12 @@ async function getTestFilesFromGraph(sourceFiles) {
|
|
|
41167
41368
|
} else {
|
|
41168
41369
|
continue;
|
|
41169
41370
|
}
|
|
41170
|
-
const importBasename =
|
|
41171
|
-
const importDir =
|
|
41371
|
+
const importBasename = path27.basename(resolvedImport, path27.extname(resolvedImport));
|
|
41372
|
+
const importDir = path27.dirname(resolvedImport);
|
|
41172
41373
|
for (const sourceFile of sourceFiles) {
|
|
41173
|
-
const sourceDir =
|
|
41174
|
-
const sourceBasename =
|
|
41175
|
-
const isRelatedDir = importDir === sourceDir || importDir ===
|
|
41374
|
+
const sourceDir = path27.dirname(sourceFile);
|
|
41375
|
+
const sourceBasename = path27.basename(sourceFile, path27.extname(sourceFile));
|
|
41376
|
+
const isRelatedDir = importDir === sourceDir || importDir === path27.join(sourceDir, "__tests__") || importDir === path27.join(sourceDir, "tests") || importDir === path27.join(sourceDir, "test");
|
|
41176
41377
|
if (resolvedImport === sourceFile || importBasename === sourceBasename && isRelatedDir) {
|
|
41177
41378
|
if (!testFiles.includes(testFile)) {
|
|
41178
41379
|
testFiles.push(testFile);
|
|
@@ -41187,8 +41388,8 @@ async function getTestFilesFromGraph(sourceFiles) {
|
|
|
41187
41388
|
while (match !== null) {
|
|
41188
41389
|
const importPath = match[1];
|
|
41189
41390
|
if (importPath.startsWith(".")) {
|
|
41190
|
-
let resolvedImport =
|
|
41191
|
-
const existingExt =
|
|
41391
|
+
let resolvedImport = path27.resolve(testDir, importPath);
|
|
41392
|
+
const existingExt = path27.extname(resolvedImport);
|
|
41192
41393
|
if (!existingExt) {
|
|
41193
41394
|
for (const extToTry of [
|
|
41194
41395
|
".ts",
|
|
@@ -41199,18 +41400,18 @@ async function getTestFilesFromGraph(sourceFiles) {
|
|
|
41199
41400
|
".cjs"
|
|
41200
41401
|
]) {
|
|
41201
41402
|
const withExt = resolvedImport + extToTry;
|
|
41202
|
-
if (sourceFiles.includes(withExt) ||
|
|
41403
|
+
if (sourceFiles.includes(withExt) || fs17.existsSync(withExt)) {
|
|
41203
41404
|
resolvedImport = withExt;
|
|
41204
41405
|
break;
|
|
41205
41406
|
}
|
|
41206
41407
|
}
|
|
41207
41408
|
}
|
|
41208
|
-
const importDir =
|
|
41209
|
-
const importBasename =
|
|
41409
|
+
const importDir = path27.dirname(resolvedImport);
|
|
41410
|
+
const importBasename = path27.basename(resolvedImport, path27.extname(resolvedImport));
|
|
41210
41411
|
for (const sourceFile of sourceFiles) {
|
|
41211
|
-
const sourceDir =
|
|
41212
|
-
const sourceBasename =
|
|
41213
|
-
const isRelatedDir = importDir === sourceDir || importDir ===
|
|
41412
|
+
const sourceDir = path27.dirname(sourceFile);
|
|
41413
|
+
const sourceBasename = path27.basename(sourceFile, path27.extname(sourceFile));
|
|
41414
|
+
const isRelatedDir = importDir === sourceDir || importDir === path27.join(sourceDir, "__tests__") || importDir === path27.join(sourceDir, "tests") || importDir === path27.join(sourceDir, "test");
|
|
41214
41415
|
if (resolvedImport === sourceFile || importBasename === sourceBasename && isRelatedDir) {
|
|
41215
41416
|
if (!testFiles.includes(testFile)) {
|
|
41216
41417
|
testFiles.push(testFile);
|
|
@@ -41295,8 +41496,8 @@ function buildTestCommand(framework, scope, files, coverage, baseDir) {
|
|
|
41295
41496
|
return ["mvn", "test"];
|
|
41296
41497
|
case "gradle": {
|
|
41297
41498
|
const isWindows = process.platform === "win32";
|
|
41298
|
-
const hasGradlewBat =
|
|
41299
|
-
const hasGradlew =
|
|
41499
|
+
const hasGradlewBat = fs17.existsSync(path27.join(baseDir, "gradlew.bat"));
|
|
41500
|
+
const hasGradlew = fs17.existsSync(path27.join(baseDir, "gradlew"));
|
|
41300
41501
|
if (hasGradlewBat && isWindows)
|
|
41301
41502
|
return ["gradlew.bat", "test"];
|
|
41302
41503
|
if (hasGradlew)
|
|
@@ -41313,7 +41514,7 @@ function buildTestCommand(framework, scope, files, coverage, baseDir) {
|
|
|
41313
41514
|
"cmake-build-release",
|
|
41314
41515
|
"out"
|
|
41315
41516
|
];
|
|
41316
|
-
const actualBuildDir = buildDirCandidates.find((d) =>
|
|
41517
|
+
const actualBuildDir = buildDirCandidates.find((d) => fs17.existsSync(path27.join(baseDir, d, "CMakeCache.txt"))) ?? "build";
|
|
41317
41518
|
return ["ctest", "--test-dir", actualBuildDir];
|
|
41318
41519
|
}
|
|
41319
41520
|
case "swift-test":
|
|
@@ -41612,9 +41813,9 @@ async function runTests(framework, scope, files, coverage, timeout_ms, cwd) {
|
|
|
41612
41813
|
stderr: "pipe",
|
|
41613
41814
|
cwd
|
|
41614
41815
|
});
|
|
41615
|
-
const timeoutPromise = new Promise((
|
|
41816
|
+
const timeoutPromise = new Promise((resolve12) => setTimeout(() => {
|
|
41616
41817
|
proc.kill();
|
|
41617
|
-
|
|
41818
|
+
resolve12(-1);
|
|
41618
41819
|
}, timeout_ms));
|
|
41619
41820
|
const [exitCode, stdoutResult, stderrResult] = await Promise.all([
|
|
41620
41821
|
Promise.race([proc.exited, timeoutPromise]),
|
|
@@ -41916,7 +42117,7 @@ var test_runner = createSwarmTool({
|
|
|
41916
42117
|
let effectiveScope = scope;
|
|
41917
42118
|
if (scope === "all") {} else if (scope === "convention") {
|
|
41918
42119
|
const sourceFiles = args.files.filter((f) => {
|
|
41919
|
-
const ext =
|
|
42120
|
+
const ext = path27.extname(f).toLowerCase();
|
|
41920
42121
|
return SOURCE_EXTENSIONS.has(ext);
|
|
41921
42122
|
});
|
|
41922
42123
|
if (sourceFiles.length === 0) {
|
|
@@ -41933,7 +42134,7 @@ var test_runner = createSwarmTool({
|
|
|
41933
42134
|
testFiles = getTestFilesFromConvention(sourceFiles);
|
|
41934
42135
|
} else if (scope === "graph") {
|
|
41935
42136
|
const sourceFiles = args.files.filter((f) => {
|
|
41936
|
-
const ext =
|
|
42137
|
+
const ext = path27.extname(f).toLowerCase();
|
|
41937
42138
|
return SOURCE_EXTENSIONS.has(ext);
|
|
41938
42139
|
});
|
|
41939
42140
|
if (sourceFiles.length === 0) {
|
|
@@ -41957,7 +42158,7 @@ var test_runner = createSwarmTool({
|
|
|
41957
42158
|
}
|
|
41958
42159
|
} else if (scope === "impact") {
|
|
41959
42160
|
const sourceFiles = args.files.filter((f) => {
|
|
41960
|
-
const ext =
|
|
42161
|
+
const ext = path27.extname(f).toLowerCase();
|
|
41961
42162
|
return SOURCE_EXTENSIONS.has(ext);
|
|
41962
42163
|
});
|
|
41963
42164
|
if (sourceFiles.length === 0) {
|
|
@@ -41975,8 +42176,8 @@ var test_runner = createSwarmTool({
|
|
|
41975
42176
|
const impactResult = await analyzeImpact(sourceFiles, workingDir);
|
|
41976
42177
|
if (impactResult.impactedTests.length > 0) {
|
|
41977
42178
|
testFiles = impactResult.impactedTests.map((absPath) => {
|
|
41978
|
-
const relativePath =
|
|
41979
|
-
return
|
|
42179
|
+
const relativePath = path27.relative(workingDir, absPath);
|
|
42180
|
+
return path27.isAbsolute(relativePath) ? absPath : relativePath;
|
|
41980
42181
|
});
|
|
41981
42182
|
} else {
|
|
41982
42183
|
graphFallbackReason = "no impacted tests found via impact analysis, falling back to graph";
|
|
@@ -42069,8 +42270,8 @@ function validateDirectoryPath(dir) {
|
|
|
42069
42270
|
if (dir.includes("..")) {
|
|
42070
42271
|
throw new Error("Directory path must not contain path traversal sequences");
|
|
42071
42272
|
}
|
|
42072
|
-
const normalized =
|
|
42073
|
-
const absolutePath =
|
|
42273
|
+
const normalized = path28.normalize(dir);
|
|
42274
|
+
const absolutePath = path28.isAbsolute(normalized) ? normalized : path28.resolve(normalized);
|
|
42074
42275
|
return absolutePath;
|
|
42075
42276
|
}
|
|
42076
42277
|
function validateTimeout(timeoutMs, defaultValue) {
|
|
@@ -42093,9 +42294,9 @@ function validateTimeout(timeoutMs, defaultValue) {
|
|
|
42093
42294
|
}
|
|
42094
42295
|
function getPackageVersion(dir) {
|
|
42095
42296
|
try {
|
|
42096
|
-
const packagePath =
|
|
42097
|
-
if (
|
|
42098
|
-
const content =
|
|
42297
|
+
const packagePath = path28.join(dir, "package.json");
|
|
42298
|
+
if (fs18.existsSync(packagePath)) {
|
|
42299
|
+
const content = fs18.readFileSync(packagePath, "utf-8");
|
|
42099
42300
|
const pkg = JSON.parse(content);
|
|
42100
42301
|
return pkg.version ?? null;
|
|
42101
42302
|
}
|
|
@@ -42104,9 +42305,9 @@ function getPackageVersion(dir) {
|
|
|
42104
42305
|
}
|
|
42105
42306
|
function getChangelogVersion(dir) {
|
|
42106
42307
|
try {
|
|
42107
|
-
const changelogPath =
|
|
42108
|
-
if (
|
|
42109
|
-
const content =
|
|
42308
|
+
const changelogPath = path28.join(dir, "CHANGELOG.md");
|
|
42309
|
+
if (fs18.existsSync(changelogPath)) {
|
|
42310
|
+
const content = fs18.readFileSync(changelogPath, "utf-8");
|
|
42110
42311
|
const match = content.match(/^##\s*\[?(\d+\.\d+\.\d+)\]?/m);
|
|
42111
42312
|
if (match) {
|
|
42112
42313
|
return match[1];
|
|
@@ -42118,10 +42319,10 @@ function getChangelogVersion(dir) {
|
|
|
42118
42319
|
function getVersionFileVersion(dir) {
|
|
42119
42320
|
const possibleFiles = ["VERSION.txt", "version.txt", "VERSION", "version"];
|
|
42120
42321
|
for (const file3 of possibleFiles) {
|
|
42121
|
-
const filePath =
|
|
42122
|
-
if (
|
|
42322
|
+
const filePath = path28.join(dir, file3);
|
|
42323
|
+
if (fs18.existsSync(filePath)) {
|
|
42123
42324
|
try {
|
|
42124
|
-
const content =
|
|
42325
|
+
const content = fs18.readFileSync(filePath, "utf-8").trim();
|
|
42125
42326
|
const match = content.match(/(\d+\.\d+\.\d+)/);
|
|
42126
42327
|
if (match) {
|
|
42127
42328
|
return match[1];
|
|
@@ -42445,8 +42646,8 @@ async function runEvidenceCheck(dir) {
|
|
|
42445
42646
|
async function runRequirementCoverageCheck(dir, currentPhase) {
|
|
42446
42647
|
const startTime = Date.now();
|
|
42447
42648
|
try {
|
|
42448
|
-
const specPath =
|
|
42449
|
-
if (!
|
|
42649
|
+
const specPath = path28.join(dir, ".swarm", "spec.md");
|
|
42650
|
+
if (!fs18.existsSync(specPath)) {
|
|
42450
42651
|
return {
|
|
42451
42652
|
type: "req_coverage",
|
|
42452
42653
|
status: "skip",
|
|
@@ -42659,9 +42860,9 @@ async function handlePreflightCommand(directory, _args) {
|
|
|
42659
42860
|
return formatPreflightMarkdown(report);
|
|
42660
42861
|
}
|
|
42661
42862
|
// src/knowledge/hive-promoter.ts
|
|
42662
|
-
import * as
|
|
42663
|
-
import * as
|
|
42664
|
-
import * as
|
|
42863
|
+
import * as fs19 from "fs";
|
|
42864
|
+
import * as os6 from "os";
|
|
42865
|
+
import * as path29 from "path";
|
|
42665
42866
|
var DANGEROUS_PATTERNS = [
|
|
42666
42867
|
[/rm\s+-rf/, "rm\\s+-rf"],
|
|
42667
42868
|
[/:\s*!\s*\|/, ":\\s*!\\s*\\|"],
|
|
@@ -42704,16 +42905,16 @@ function validateLesson2(text) {
|
|
|
42704
42905
|
}
|
|
42705
42906
|
function getHiveFilePath() {
|
|
42706
42907
|
const platform = process.platform;
|
|
42707
|
-
const home =
|
|
42908
|
+
const home = os6.homedir();
|
|
42708
42909
|
let dataDir;
|
|
42709
42910
|
if (platform === "win32") {
|
|
42710
|
-
dataDir =
|
|
42911
|
+
dataDir = path29.join(process.env.LOCALAPPDATA || path29.join(home, "AppData", "Local"), "opencode-swarm", "Data");
|
|
42711
42912
|
} else if (platform === "darwin") {
|
|
42712
|
-
dataDir =
|
|
42913
|
+
dataDir = path29.join(home, "Library", "Application Support", "opencode-swarm");
|
|
42713
42914
|
} else {
|
|
42714
|
-
dataDir =
|
|
42915
|
+
dataDir = path29.join(process.env.XDG_DATA_HOME || path29.join(home, ".local", "share"), "opencode-swarm");
|
|
42715
42916
|
}
|
|
42716
|
-
return
|
|
42917
|
+
return path29.join(dataDir, "hive-knowledge.jsonl");
|
|
42717
42918
|
}
|
|
42718
42919
|
async function promoteToHive(_directory, lesson, category) {
|
|
42719
42920
|
const trimmed = (lesson ?? "").trim();
|
|
@@ -42725,9 +42926,9 @@ async function promoteToHive(_directory, lesson, category) {
|
|
|
42725
42926
|
throw new Error(`Lesson rejected by validator: ${validation.reason}`);
|
|
42726
42927
|
}
|
|
42727
42928
|
const hivePath = getHiveFilePath();
|
|
42728
|
-
const hiveDir =
|
|
42729
|
-
if (!
|
|
42730
|
-
|
|
42929
|
+
const hiveDir = path29.dirname(hivePath);
|
|
42930
|
+
if (!fs19.existsSync(hiveDir)) {
|
|
42931
|
+
fs19.mkdirSync(hiveDir, { recursive: true });
|
|
42731
42932
|
}
|
|
42732
42933
|
const now = new Date;
|
|
42733
42934
|
const entry = {
|
|
@@ -42741,16 +42942,16 @@ async function promoteToHive(_directory, lesson, category) {
|
|
|
42741
42942
|
promotedAt: now.toISOString(),
|
|
42742
42943
|
retrievalOutcomes: { applied: 0, succeededAfter: 0, failedAfter: 0 }
|
|
42743
42944
|
};
|
|
42744
|
-
|
|
42945
|
+
fs19.appendFileSync(hivePath, `${JSON.stringify(entry)}
|
|
42745
42946
|
`, "utf-8");
|
|
42746
42947
|
const preview = `${trimmed.slice(0, 50)}${trimmed.length > 50 ? "..." : ""}`;
|
|
42747
42948
|
return `Promoted to hive: "${preview}" (confidence: 1.0, source: manual)`;
|
|
42748
42949
|
}
|
|
42749
42950
|
async function promoteFromSwarm(directory, lessonId) {
|
|
42750
|
-
const knowledgePath =
|
|
42951
|
+
const knowledgePath = path29.join(directory, ".swarm", "knowledge.jsonl");
|
|
42751
42952
|
const entries = [];
|
|
42752
|
-
if (
|
|
42753
|
-
const content =
|
|
42953
|
+
if (fs19.existsSync(knowledgePath)) {
|
|
42954
|
+
const content = fs19.readFileSync(knowledgePath, "utf-8");
|
|
42754
42955
|
for (const line of content.split(`
|
|
42755
42956
|
`)) {
|
|
42756
42957
|
const t = line.trim();
|
|
@@ -42774,9 +42975,9 @@ async function promoteFromSwarm(directory, lessonId) {
|
|
|
42774
42975
|
throw new Error(`Lesson rejected by validator: ${validation.reason}`);
|
|
42775
42976
|
}
|
|
42776
42977
|
const hivePath = getHiveFilePath();
|
|
42777
|
-
const hiveDir =
|
|
42778
|
-
if (!
|
|
42779
|
-
|
|
42978
|
+
const hiveDir = path29.dirname(hivePath);
|
|
42979
|
+
if (!fs19.existsSync(hiveDir)) {
|
|
42980
|
+
fs19.mkdirSync(hiveDir, { recursive: true });
|
|
42780
42981
|
}
|
|
42781
42982
|
const now = new Date;
|
|
42782
42983
|
const hiveEntry = {
|
|
@@ -42790,7 +42991,7 @@ async function promoteFromSwarm(directory, lessonId) {
|
|
|
42790
42991
|
promotedAt: now.toISOString(),
|
|
42791
42992
|
retrievalOutcomes: { applied: 0, succeededAfter: 0, failedAfter: 0 }
|
|
42792
42993
|
};
|
|
42793
|
-
|
|
42994
|
+
fs19.appendFileSync(hivePath, `${JSON.stringify(hiveEntry)}
|
|
42794
42995
|
`, "utf-8");
|
|
42795
42996
|
const preview = `${lessonText.slice(0, 50)}${lessonText.length > 50 ? "..." : ""}`;
|
|
42796
42997
|
return `Promoted to hive: "${preview}" (confidence: 1.0, source: manual)`;
|
|
@@ -42969,7 +43170,7 @@ async function handleQaGatesCommand(directory, args, sessionID) {
|
|
|
42969
43170
|
}
|
|
42970
43171
|
|
|
42971
43172
|
// src/commands/reset.ts
|
|
42972
|
-
import * as
|
|
43173
|
+
import * as fs20 from "fs";
|
|
42973
43174
|
|
|
42974
43175
|
// src/background/manager.ts
|
|
42975
43176
|
init_utils();
|
|
@@ -43024,13 +43225,13 @@ class CircuitBreaker {
|
|
|
43024
43225
|
if (this.config.callTimeoutMs <= 0) {
|
|
43025
43226
|
return fn();
|
|
43026
43227
|
}
|
|
43027
|
-
return new Promise((
|
|
43228
|
+
return new Promise((resolve13, reject) => {
|
|
43028
43229
|
const timeout = setTimeout(() => {
|
|
43029
43230
|
reject(new Error(`Call timeout after ${this.config.callTimeoutMs}ms`));
|
|
43030
43231
|
}, this.config.callTimeoutMs);
|
|
43031
43232
|
fn().then((result) => {
|
|
43032
43233
|
clearTimeout(timeout);
|
|
43033
|
-
|
|
43234
|
+
resolve13(result);
|
|
43034
43235
|
}).catch((error93) => {
|
|
43035
43236
|
clearTimeout(timeout);
|
|
43036
43237
|
reject(error93);
|
|
@@ -43314,7 +43515,7 @@ class AutomationQueue {
|
|
|
43314
43515
|
|
|
43315
43516
|
// src/background/worker.ts
|
|
43316
43517
|
function sleep(ms) {
|
|
43317
|
-
return new Promise((
|
|
43518
|
+
return new Promise((resolve13) => setTimeout(resolve13, ms));
|
|
43318
43519
|
}
|
|
43319
43520
|
|
|
43320
43521
|
class WorkerManager {
|
|
@@ -43670,8 +43871,8 @@ async function handleResetCommand(directory, args) {
|
|
|
43670
43871
|
for (const filename of filesToReset) {
|
|
43671
43872
|
try {
|
|
43672
43873
|
const resolvedPath = validateSwarmPath(directory, filename);
|
|
43673
|
-
if (
|
|
43674
|
-
|
|
43874
|
+
if (fs20.existsSync(resolvedPath)) {
|
|
43875
|
+
fs20.unlinkSync(resolvedPath);
|
|
43675
43876
|
results.push(`- \u2705 Deleted ${filename}`);
|
|
43676
43877
|
} else {
|
|
43677
43878
|
results.push(`- \u23ED\uFE0F ${filename} not found (skipped)`);
|
|
@@ -43688,8 +43889,8 @@ async function handleResetCommand(directory, args) {
|
|
|
43688
43889
|
}
|
|
43689
43890
|
try {
|
|
43690
43891
|
const summariesPath = validateSwarmPath(directory, "summaries");
|
|
43691
|
-
if (
|
|
43692
|
-
|
|
43892
|
+
if (fs20.existsSync(summariesPath)) {
|
|
43893
|
+
fs20.rmSync(summariesPath, { recursive: true, force: true });
|
|
43693
43894
|
results.push("- \u2705 Deleted summaries/ directory");
|
|
43694
43895
|
} else {
|
|
43695
43896
|
results.push("- \u23ED\uFE0F summaries/ not found (skipped)");
|
|
@@ -43709,14 +43910,14 @@ async function handleResetCommand(directory, args) {
|
|
|
43709
43910
|
|
|
43710
43911
|
// src/commands/reset-session.ts
|
|
43711
43912
|
init_utils2();
|
|
43712
|
-
import * as
|
|
43713
|
-
import * as
|
|
43913
|
+
import * as fs21 from "fs";
|
|
43914
|
+
import * as path30 from "path";
|
|
43714
43915
|
async function handleResetSessionCommand(directory, _args) {
|
|
43715
43916
|
const results = [];
|
|
43716
43917
|
try {
|
|
43717
43918
|
const statePath = validateSwarmPath(directory, "session/state.json");
|
|
43718
|
-
if (
|
|
43719
|
-
|
|
43919
|
+
if (fs21.existsSync(statePath)) {
|
|
43920
|
+
fs21.unlinkSync(statePath);
|
|
43720
43921
|
results.push("\u2705 Deleted .swarm/session/state.json");
|
|
43721
43922
|
} else {
|
|
43722
43923
|
results.push("\u23ED\uFE0F state.json not found (already clean)");
|
|
@@ -43725,15 +43926,15 @@ async function handleResetSessionCommand(directory, _args) {
|
|
|
43725
43926
|
results.push("\u274C Failed to delete state.json");
|
|
43726
43927
|
}
|
|
43727
43928
|
try {
|
|
43728
|
-
const sessionDir =
|
|
43729
|
-
if (
|
|
43730
|
-
const files =
|
|
43929
|
+
const sessionDir = path30.dirname(validateSwarmPath(directory, "session/state.json"));
|
|
43930
|
+
if (fs21.existsSync(sessionDir)) {
|
|
43931
|
+
const files = fs21.readdirSync(sessionDir);
|
|
43731
43932
|
const otherFiles = files.filter((f) => f !== "state.json");
|
|
43732
43933
|
let deletedCount = 0;
|
|
43733
43934
|
for (const file3 of otherFiles) {
|
|
43734
|
-
const filePath =
|
|
43735
|
-
if (
|
|
43736
|
-
|
|
43935
|
+
const filePath = path30.join(sessionDir, file3);
|
|
43936
|
+
if (fs21.lstatSync(filePath).isFile()) {
|
|
43937
|
+
fs21.unlinkSync(filePath);
|
|
43737
43938
|
deletedCount++;
|
|
43738
43939
|
}
|
|
43739
43940
|
}
|
|
@@ -43761,7 +43962,7 @@ async function handleResetSessionCommand(directory, _args) {
|
|
|
43761
43962
|
// src/summaries/manager.ts
|
|
43762
43963
|
init_utils2();
|
|
43763
43964
|
init_utils();
|
|
43764
|
-
import * as
|
|
43965
|
+
import * as path31 from "path";
|
|
43765
43966
|
var SUMMARY_ID_REGEX = /^S\d+$/;
|
|
43766
43967
|
function sanitizeSummaryId(id) {
|
|
43767
43968
|
if (!id || id.length === 0) {
|
|
@@ -43785,7 +43986,7 @@ function sanitizeSummaryId(id) {
|
|
|
43785
43986
|
}
|
|
43786
43987
|
async function loadFullOutput(directory, id) {
|
|
43787
43988
|
const sanitizedId = sanitizeSummaryId(id);
|
|
43788
|
-
const relativePath =
|
|
43989
|
+
const relativePath = path31.join("summaries", `${sanitizedId}.json`);
|
|
43789
43990
|
validateSwarmPath(directory, relativePath);
|
|
43790
43991
|
const content = await readSwarmFileAsync(directory, relativePath);
|
|
43791
43992
|
if (content === null) {
|
|
@@ -43838,18 +44039,18 @@ ${error93 instanceof Error ? error93.message : String(error93)}`;
|
|
|
43838
44039
|
|
|
43839
44040
|
// src/commands/rollback.ts
|
|
43840
44041
|
init_utils2();
|
|
43841
|
-
import * as
|
|
43842
|
-
import * as
|
|
44042
|
+
import * as fs22 from "fs";
|
|
44043
|
+
import * as path32 from "path";
|
|
43843
44044
|
async function handleRollbackCommand(directory, args) {
|
|
43844
44045
|
const phaseArg = args[0];
|
|
43845
44046
|
if (!phaseArg) {
|
|
43846
44047
|
const manifestPath2 = validateSwarmPath(directory, "checkpoints/manifest.json");
|
|
43847
|
-
if (!
|
|
44048
|
+
if (!fs22.existsSync(manifestPath2)) {
|
|
43848
44049
|
return "No checkpoints found. Use `/swarm checkpoint` to create checkpoints.";
|
|
43849
44050
|
}
|
|
43850
44051
|
let manifest2;
|
|
43851
44052
|
try {
|
|
43852
|
-
manifest2 = JSON.parse(
|
|
44053
|
+
manifest2 = JSON.parse(fs22.readFileSync(manifestPath2, "utf-8"));
|
|
43853
44054
|
} catch {
|
|
43854
44055
|
return "Error: Checkpoint manifest is corrupted. Delete .swarm/checkpoints/manifest.json and re-checkpoint.";
|
|
43855
44056
|
}
|
|
@@ -43871,12 +44072,12 @@ async function handleRollbackCommand(directory, args) {
|
|
|
43871
44072
|
return "Error: Phase number must be a positive integer.";
|
|
43872
44073
|
}
|
|
43873
44074
|
const manifestPath = validateSwarmPath(directory, "checkpoints/manifest.json");
|
|
43874
|
-
if (!
|
|
44075
|
+
if (!fs22.existsSync(manifestPath)) {
|
|
43875
44076
|
return `Error: No checkpoints found. Cannot rollback to phase ${targetPhase}.`;
|
|
43876
44077
|
}
|
|
43877
44078
|
let manifest;
|
|
43878
44079
|
try {
|
|
43879
|
-
manifest = JSON.parse(
|
|
44080
|
+
manifest = JSON.parse(fs22.readFileSync(manifestPath, "utf-8"));
|
|
43880
44081
|
} catch {
|
|
43881
44082
|
return `Error: Checkpoint manifest is corrupted. Delete .swarm/checkpoints/manifest.json and re-checkpoint.`;
|
|
43882
44083
|
}
|
|
@@ -43886,10 +44087,10 @@ async function handleRollbackCommand(directory, args) {
|
|
|
43886
44087
|
return `Error: Checkpoint for phase ${targetPhase} not found. Available phases: ${available}`;
|
|
43887
44088
|
}
|
|
43888
44089
|
const checkpointDir = validateSwarmPath(directory, `checkpoints/phase-${targetPhase}`);
|
|
43889
|
-
if (!
|
|
44090
|
+
if (!fs22.existsSync(checkpointDir)) {
|
|
43890
44091
|
return `Error: Checkpoint directory for phase ${targetPhase} does not exist.`;
|
|
43891
44092
|
}
|
|
43892
|
-
const checkpointFiles =
|
|
44093
|
+
const checkpointFiles = fs22.readdirSync(checkpointDir);
|
|
43893
44094
|
if (checkpointFiles.length === 0) {
|
|
43894
44095
|
return `Error: Checkpoint for phase ${targetPhase} is empty. Cannot rollback.`;
|
|
43895
44096
|
}
|
|
@@ -43897,10 +44098,10 @@ async function handleRollbackCommand(directory, args) {
|
|
|
43897
44098
|
const successes = [];
|
|
43898
44099
|
const failures = [];
|
|
43899
44100
|
for (const file3 of checkpointFiles) {
|
|
43900
|
-
const src =
|
|
43901
|
-
const dest =
|
|
44101
|
+
const src = path32.join(checkpointDir, file3);
|
|
44102
|
+
const dest = path32.join(swarmDir, file3);
|
|
43902
44103
|
try {
|
|
43903
|
-
|
|
44104
|
+
fs22.cpSync(src, dest, { recursive: true, force: true });
|
|
43904
44105
|
successes.push(file3);
|
|
43905
44106
|
} catch (error93) {
|
|
43906
44107
|
failures.push({ file: file3, error: error93.message });
|
|
@@ -43917,7 +44118,7 @@ async function handleRollbackCommand(directory, args) {
|
|
|
43917
44118
|
timestamp: new Date().toISOString()
|
|
43918
44119
|
};
|
|
43919
44120
|
try {
|
|
43920
|
-
|
|
44121
|
+
fs22.appendFileSync(eventsPath, `${JSON.stringify(rollbackEvent)}
|
|
43921
44122
|
`);
|
|
43922
44123
|
} catch (error93) {
|
|
43923
44124
|
console.error("Failed to write rollback event:", error93 instanceof Error ? error93.message : String(error93));
|
|
@@ -43960,11 +44161,11 @@ async function handleSimulateCommand(directory, args) {
|
|
|
43960
44161
|
];
|
|
43961
44162
|
const report = reportLines.filter(Boolean).join(`
|
|
43962
44163
|
`);
|
|
43963
|
-
const
|
|
43964
|
-
const
|
|
43965
|
-
const reportPath =
|
|
43966
|
-
await
|
|
43967
|
-
await
|
|
44164
|
+
const fs23 = await import("fs/promises");
|
|
44165
|
+
const path33 = await import("path");
|
|
44166
|
+
const reportPath = path33.join(directory, ".swarm", "simulate-report.md");
|
|
44167
|
+
await fs23.mkdir(path33.dirname(reportPath), { recursive: true });
|
|
44168
|
+
await fs23.writeFile(reportPath, report, "utf-8");
|
|
43968
44169
|
return `${darkMatterPairs.length} hidden coupling pairs detected`;
|
|
43969
44170
|
}
|
|
43970
44171
|
|
|
@@ -44487,18 +44688,18 @@ function resolveCommand(tokens) {
|
|
|
44487
44688
|
}
|
|
44488
44689
|
|
|
44489
44690
|
// src/cli/index.ts
|
|
44490
|
-
var CONFIG_DIR =
|
|
44491
|
-
var OPENCODE_CONFIG_PATH =
|
|
44492
|
-
var PLUGIN_CONFIG_PATH =
|
|
44493
|
-
var PROMPTS_DIR =
|
|
44691
|
+
var CONFIG_DIR = path33.join(process.env.XDG_CONFIG_HOME || path33.join(os7.homedir(), ".config"), "opencode");
|
|
44692
|
+
var OPENCODE_CONFIG_PATH = path33.join(CONFIG_DIR, "opencode.json");
|
|
44693
|
+
var PLUGIN_CONFIG_PATH = path33.join(CONFIG_DIR, "opencode-swarm.json");
|
|
44694
|
+
var PROMPTS_DIR = path33.join(CONFIG_DIR, "opencode-swarm");
|
|
44494
44695
|
function ensureDir(dir) {
|
|
44495
|
-
if (!
|
|
44496
|
-
|
|
44696
|
+
if (!fs23.existsSync(dir)) {
|
|
44697
|
+
fs23.mkdirSync(dir, { recursive: true });
|
|
44497
44698
|
}
|
|
44498
44699
|
}
|
|
44499
44700
|
function loadJson(filepath) {
|
|
44500
44701
|
try {
|
|
44501
|
-
const content =
|
|
44702
|
+
const content = fs23.readFileSync(filepath, "utf-8");
|
|
44502
44703
|
const stripped = content.replace(/\\"|"(?:\\"|[^"])*"|(\/\/.*|\/\*[\s\S]*?\*\/)/g, (match, comment) => comment ? "" : match).replace(/,(\s*[}\]])/g, "$1");
|
|
44503
44704
|
return JSON.parse(stripped);
|
|
44504
44705
|
} catch {
|
|
@@ -44506,7 +44707,7 @@ function loadJson(filepath) {
|
|
|
44506
44707
|
}
|
|
44507
44708
|
}
|
|
44508
44709
|
function saveJson(filepath, data) {
|
|
44509
|
-
|
|
44710
|
+
fs23.writeFileSync(filepath, `${JSON.stringify(data, null, 2)}
|
|
44510
44711
|
`, "utf-8");
|
|
44511
44712
|
}
|
|
44512
44713
|
async function install() {
|
|
@@ -44514,7 +44715,7 @@ async function install() {
|
|
|
44514
44715
|
`);
|
|
44515
44716
|
ensureDir(CONFIG_DIR);
|
|
44516
44717
|
ensureDir(PROMPTS_DIR);
|
|
44517
|
-
const LEGACY_CONFIG_PATH =
|
|
44718
|
+
const LEGACY_CONFIG_PATH = path33.join(CONFIG_DIR, "config.json");
|
|
44518
44719
|
let opencodeConfig = loadJson(OPENCODE_CONFIG_PATH);
|
|
44519
44720
|
if (!opencodeConfig) {
|
|
44520
44721
|
const legacyConfig = loadJson(LEGACY_CONFIG_PATH);
|
|
@@ -44539,7 +44740,7 @@ async function install() {
|
|
|
44539
44740
|
saveJson(OPENCODE_CONFIG_PATH, opencodeConfig);
|
|
44540
44741
|
console.log("\u2713 Added opencode-swarm to OpenCode plugins");
|
|
44541
44742
|
console.log("\u2713 Disabled default OpenCode agents (explore, general)");
|
|
44542
|
-
if (!
|
|
44743
|
+
if (!fs23.existsSync(PLUGIN_CONFIG_PATH)) {
|
|
44543
44744
|
const defaultConfig = {
|
|
44544
44745
|
agents: {
|
|
44545
44746
|
coder: { model: "opencode/minimax-m2.5-free" },
|
|
@@ -44582,7 +44783,7 @@ async function uninstall() {
|
|
|
44582
44783
|
`);
|
|
44583
44784
|
const opencodeConfig = loadJson(OPENCODE_CONFIG_PATH);
|
|
44584
44785
|
if (!opencodeConfig) {
|
|
44585
|
-
if (
|
|
44786
|
+
if (fs23.existsSync(OPENCODE_CONFIG_PATH)) {
|
|
44586
44787
|
console.log(`\u2717 Could not parse opencode config at: ${OPENCODE_CONFIG_PATH}`);
|
|
44587
44788
|
return 1;
|
|
44588
44789
|
} else {
|
|
@@ -44614,13 +44815,13 @@ async function uninstall() {
|
|
|
44614
44815
|
console.log("\u2713 Re-enabled default OpenCode agents (explore, general)");
|
|
44615
44816
|
if (process.argv.includes("--clean")) {
|
|
44616
44817
|
let cleaned = false;
|
|
44617
|
-
if (
|
|
44618
|
-
|
|
44818
|
+
if (fs23.existsSync(PLUGIN_CONFIG_PATH)) {
|
|
44819
|
+
fs23.unlinkSync(PLUGIN_CONFIG_PATH);
|
|
44619
44820
|
console.log(`\u2713 Removed plugin config: ${PLUGIN_CONFIG_PATH}`);
|
|
44620
44821
|
cleaned = true;
|
|
44621
44822
|
}
|
|
44622
|
-
if (
|
|
44623
|
-
|
|
44823
|
+
if (fs23.existsSync(PROMPTS_DIR)) {
|
|
44824
|
+
fs23.rmSync(PROMPTS_DIR, { recursive: true });
|
|
44624
44825
|
console.log(`\u2713 Removed custom prompts: ${PROMPTS_DIR}`);
|
|
44625
44826
|
cleaned = true;
|
|
44626
44827
|
}
|