opencode-swarm 7.33.2 → 7.35.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli/index.js CHANGED
@@ -34,7 +34,7 @@ var package_default;
34
34
  var init_package = __esm(() => {
35
35
  package_default = {
36
36
  name: "opencode-swarm",
37
- version: "7.33.2",
37
+ version: "7.35.0",
38
38
  description: "Architect-centric agentic swarm plugin for OpenCode - hub-and-spoke orchestration with SME consultation, code generation, and QA review",
39
39
  main: "dist/index.js",
40
40
  types: "dist/index.d.ts",
@@ -17601,7 +17601,7 @@ var init_schema = __esm(() => {
17601
17601
  });
17602
17602
  MemoryConfigSchema = exports_external.object({
17603
17603
  enabled: exports_external.boolean().default(false),
17604
- provider: exports_external.enum(["local-jsonl", "sqlite"]).default("local-jsonl"),
17604
+ provider: exports_external.enum(["local-jsonl", "sqlite"]).default("sqlite"),
17605
17605
  storageDir: exports_external.string().default(".swarm/memory"),
17606
17606
  sqlite: exports_external.object({
17607
17607
  path: exports_external.string().default(".swarm/memory/memory.db"),
@@ -45268,6 +45268,1604 @@ var init_knowledge = __esm(() => {
45268
45268
  init_knowledge_validator();
45269
45269
  });
45270
45270
 
45271
+ // src/memory/config.ts
45272
+ function resolveMemoryConfig(input) {
45273
+ return {
45274
+ ...DEFAULT_MEMORY_CONFIG,
45275
+ ...input ?? {},
45276
+ sqlite: {
45277
+ ...DEFAULT_MEMORY_CONFIG.sqlite,
45278
+ ...input?.sqlite ?? {}
45279
+ },
45280
+ recall: {
45281
+ ...DEFAULT_MEMORY_CONFIG.recall,
45282
+ ...input?.recall ?? {},
45283
+ injection: {
45284
+ ...DEFAULT_MEMORY_CONFIG.recall.injection,
45285
+ ...input?.recall?.injection ?? {}
45286
+ }
45287
+ },
45288
+ writes: {
45289
+ ...DEFAULT_MEMORY_CONFIG.writes,
45290
+ ...input?.writes ?? {}
45291
+ },
45292
+ redaction: {
45293
+ ...DEFAULT_MEMORY_CONFIG.redaction,
45294
+ ...input?.redaction ?? {}
45295
+ }
45296
+ };
45297
+ }
45298
+ var DEFAULT_MEMORY_CONFIG, DURABLE_MEMORY_KINDS, EVIDENCE_REQUIRED_KINDS;
45299
+ var init_config3 = __esm(() => {
45300
+ DEFAULT_MEMORY_CONFIG = {
45301
+ enabled: false,
45302
+ provider: "sqlite",
45303
+ storageDir: ".swarm/memory",
45304
+ sqlite: {
45305
+ path: ".swarm/memory/memory.db",
45306
+ busyTimeoutMs: 5000
45307
+ },
45308
+ recall: {
45309
+ defaultMaxItems: 8,
45310
+ defaultTokenBudget: 1200,
45311
+ minScore: 0.05,
45312
+ injection: {
45313
+ enabled: true,
45314
+ minScore: 0.25,
45315
+ requireQuerySignal: true,
45316
+ maxItems: 6,
45317
+ tokenBudget: 1000
45318
+ }
45319
+ },
45320
+ writes: {
45321
+ mode: "propose"
45322
+ },
45323
+ redaction: {
45324
+ rejectDurableSecrets: true
45325
+ },
45326
+ hardDelete: false
45327
+ };
45328
+ DURABLE_MEMORY_KINDS = new Set([
45329
+ "user_preference",
45330
+ "project_fact",
45331
+ "architecture_decision",
45332
+ "repo_convention",
45333
+ "code_pattern",
45334
+ "test_pattern",
45335
+ "failure_pattern",
45336
+ "security_note"
45337
+ ]);
45338
+ EVIDENCE_REQUIRED_KINDS = new Set([
45339
+ "api_finding",
45340
+ "evidence",
45341
+ "security_note"
45342
+ ]);
45343
+ });
45344
+
45345
+ // src/memory/errors.ts
45346
+ var MemoryValidationError;
45347
+ var init_errors6 = __esm(() => {
45348
+ MemoryValidationError = class MemoryValidationError extends Error {
45349
+ code;
45350
+ constructor(message, code = "memory_validation_error") {
45351
+ super(message);
45352
+ this.name = "MemoryValidationError";
45353
+ this.code = code;
45354
+ }
45355
+ };
45356
+ });
45357
+
45358
+ // src/memory/redaction.ts
45359
+ function findSecrets(text) {
45360
+ const findings = [];
45361
+ for (const { type, pattern } of SECRET_PATTERNS) {
45362
+ pattern.lastIndex = 0;
45363
+ for (const match of text.matchAll(pattern)) {
45364
+ if (match[0])
45365
+ findings.push({ type, match: match[0] });
45366
+ }
45367
+ }
45368
+ return findings;
45369
+ }
45370
+ function containsSecret(text) {
45371
+ return findSecrets(text).length > 0;
45372
+ }
45373
+ var SECRET_PATTERNS;
45374
+ var init_redaction = __esm(() => {
45375
+ SECRET_PATTERNS = [
45376
+ { type: "openai_api_key", pattern: /\bsk-[A-Za-z0-9_-]{20,}\b/g },
45377
+ {
45378
+ type: "github_token",
45379
+ pattern: /\b(?:ghp|gho|ghu|ghs|ghr|github_pat)_[A-Za-z0-9_]{20,}\b/g
45380
+ },
45381
+ { type: "aws_access_key_id", pattern: /\bAKIA[0-9A-Z]{16}\b/g },
45382
+ {
45383
+ type: "private_key_block",
45384
+ pattern: /-----BEGIN [A-Z ]*PRIVATE KEY-----[\s\S]*?-----END [A-Z ]*PRIVATE KEY-----/g
45385
+ },
45386
+ {
45387
+ type: "authorization_bearer",
45388
+ pattern: /\bAuthorization\s*:\s*Bearer\s+[A-Za-z0-9._~+/=-]{12,}/gi
45389
+ },
45390
+ {
45391
+ type: "env_secret",
45392
+ pattern: /\b(?:[A-Z0-9]+_)*(?:KEY|TOKEN|SECRET|PASSWORD)\b\s*=\s*["']?[^\s"'`]{8,}["']?/gi
45393
+ }
45394
+ ];
45395
+ });
45396
+
45397
+ // src/memory/schema.ts
45398
+ import { createHash as createHash5 } from "crypto";
45399
+ function normalizeMemoryText(text) {
45400
+ return text.replace(/\s+/g, " ").trim();
45401
+ }
45402
+ function stableScopeKey(scope) {
45403
+ const ordered = { type: scope.type };
45404
+ const keys = scope.type === "repository" ? ["repoId"] : [
45405
+ "userId",
45406
+ "workspaceId",
45407
+ "projectId",
45408
+ "repoId",
45409
+ "repoRoot",
45410
+ "runId",
45411
+ "agentId"
45412
+ ];
45413
+ for (const key of keys) {
45414
+ const value = scope[key];
45415
+ if (value)
45416
+ ordered[key] = value;
45417
+ }
45418
+ return JSON.stringify(ordered);
45419
+ }
45420
+ function computeMemoryContentHash(recordLike) {
45421
+ const normalized = normalizeMemoryText(recordLike.text).toLowerCase();
45422
+ return createHash5("sha256").update(`${stableScopeKey(recordLike.scope)}
45423
+ ${recordLike.kind}
45424
+ ${normalized}`).digest("hex");
45425
+ }
45426
+ function createMemoryId(recordLike) {
45427
+ return `mem_${computeMemoryContentHash(recordLike).slice(0, 16)}`;
45428
+ }
45429
+ function isExpired(record3, now = new Date) {
45430
+ if (!record3.expiresAt)
45431
+ return false;
45432
+ const expires = Date.parse(record3.expiresAt);
45433
+ return Number.isFinite(expires) && expires <= now.getTime();
45434
+ }
45435
+ function hasEvidenceSource(record3) {
45436
+ return Boolean(record3.source.url || record3.source.filePath || record3.source.commitSha || record3.source.ref);
45437
+ }
45438
+ function validateMemoryRecordRules(record3, options) {
45439
+ const parsed = MemoryRecordSchema.parse(record3);
45440
+ const expectedHash = computeMemoryContentHash(parsed);
45441
+ const expectedId = createMemoryId(parsed);
45442
+ if (parsed.contentHash !== expectedHash) {
45443
+ throw new MemoryValidationError("contentHash does not match memory content");
45444
+ }
45445
+ if (parsed.id !== expectedId) {
45446
+ throw new MemoryValidationError("id does not match memory content");
45447
+ }
45448
+ if (parsed.stability === "durable" && (parsed.scope.type === "run" || parsed.scope.type === "agent")) {
45449
+ throw new MemoryValidationError("durable memories cannot use run or agent scope");
45450
+ }
45451
+ if (parsed.stability === "durable" && (DURABLE_MEMORY_KINDS.has(parsed.kind) || parsed.kind === "api_finding" || parsed.kind === "evidence") && !hasEvidenceSource(parsed)) {
45452
+ throw new MemoryValidationError("durable project, repository, API, evidence, and security memories require source evidence");
45453
+ }
45454
+ if (EVIDENCE_REQUIRED_KINDS.has(parsed.kind) && !hasEvidenceSource(parsed)) {
45455
+ throw new MemoryValidationError(`${parsed.kind} memories require source evidence`);
45456
+ }
45457
+ if (parsed.kind === "scratch" && (!parsed.expiresAt || Date.parse(parsed.expiresAt) - Date.parse(parsed.createdAt) > 7 * 24 * 60 * 60 * 1000)) {
45458
+ throw new MemoryValidationError("scratch memories must expire within 7 days");
45459
+ }
45460
+ if (options.rejectDurableSecrets && parsed.stability === "durable" && containsSecret(parsed.text)) {
45461
+ throw new MemoryValidationError("durable memory contains a likely secret");
45462
+ }
45463
+ return parsed;
45464
+ }
45465
+ function validateMemoryProposal(proposal) {
45466
+ return MemoryProposalSchema.parse(proposal);
45467
+ }
45468
+ var MemoryScopeTypeSchema, MemoryScopeRefSchema, MemoryKindSchema, MemorySourceSchema, MemoryRecordSchema, MemoryProposalSchema;
45469
+ var init_schema2 = __esm(() => {
45470
+ init_zod();
45471
+ init_config3();
45472
+ init_errors6();
45473
+ init_redaction();
45474
+ MemoryScopeTypeSchema = exports_external.enum([
45475
+ "global_user",
45476
+ "workspace",
45477
+ "project",
45478
+ "repository",
45479
+ "run",
45480
+ "agent"
45481
+ ]);
45482
+ MemoryScopeRefSchema = exports_external.object({
45483
+ type: MemoryScopeTypeSchema,
45484
+ userId: exports_external.string().optional(),
45485
+ workspaceId: exports_external.string().optional(),
45486
+ projectId: exports_external.string().optional(),
45487
+ repoId: exports_external.string().optional(),
45488
+ repoRoot: exports_external.string().optional(),
45489
+ runId: exports_external.string().optional(),
45490
+ agentId: exports_external.string().optional()
45491
+ }).strict();
45492
+ MemoryKindSchema = exports_external.enum([
45493
+ "user_preference",
45494
+ "project_fact",
45495
+ "architecture_decision",
45496
+ "repo_convention",
45497
+ "api_finding",
45498
+ "code_pattern",
45499
+ "test_pattern",
45500
+ "failure_pattern",
45501
+ "security_note",
45502
+ "evidence",
45503
+ "todo",
45504
+ "scratch"
45505
+ ]);
45506
+ MemorySourceSchema = exports_external.object({
45507
+ type: exports_external.enum([
45508
+ "user",
45509
+ "agent",
45510
+ "tool",
45511
+ "file",
45512
+ "repo",
45513
+ "commit",
45514
+ "test",
45515
+ "web",
45516
+ "manual"
45517
+ ]),
45518
+ ref: exports_external.string().optional(),
45519
+ url: exports_external.string().optional(),
45520
+ filePath: exports_external.string().optional(),
45521
+ commitSha: exports_external.string().optional(),
45522
+ createdBy: exports_external.string().optional()
45523
+ }).strict();
45524
+ MemoryRecordSchema = exports_external.object({
45525
+ id: exports_external.string().regex(/^mem_[a-f0-9]{16}$/),
45526
+ scope: MemoryScopeRefSchema,
45527
+ kind: MemoryKindSchema,
45528
+ text: exports_external.string().min(1).max(2000),
45529
+ tags: exports_external.array(exports_external.string().min(1).max(64)).max(32),
45530
+ confidence: exports_external.number().min(0).max(1),
45531
+ stability: exports_external.enum(["ephemeral", "session", "durable"]),
45532
+ source: MemorySourceSchema,
45533
+ createdAt: exports_external.string().datetime(),
45534
+ updatedAt: exports_external.string().datetime(),
45535
+ lastAccessedAt: exports_external.string().datetime().optional(),
45536
+ expiresAt: exports_external.string().datetime().optional(),
45537
+ supersedes: exports_external.array(exports_external.string()).optional(),
45538
+ supersededBy: exports_external.string().optional(),
45539
+ contentHash: exports_external.string().regex(/^[a-f0-9]{64}$/),
45540
+ metadata: exports_external.record(exports_external.string(), exports_external.unknown())
45541
+ }).strict();
45542
+ MemoryProposalSchema = exports_external.object({
45543
+ id: exports_external.string().regex(/^prop_[a-f0-9]{16}$/),
45544
+ operation: exports_external.enum([
45545
+ "add",
45546
+ "update",
45547
+ "delete",
45548
+ "ignore",
45549
+ "merge",
45550
+ "supersede"
45551
+ ]),
45552
+ proposedRecord: MemoryRecordSchema.optional(),
45553
+ targetMemoryId: exports_external.string().optional(),
45554
+ relatedMemoryIds: exports_external.array(exports_external.string()).optional(),
45555
+ proposedBy: exports_external.object({
45556
+ agentRole: exports_external.string().optional(),
45557
+ agentId: exports_external.string().optional(),
45558
+ runId: exports_external.string().optional()
45559
+ }).strict(),
45560
+ rationale: exports_external.string().min(1).max(2000),
45561
+ evidenceRefs: exports_external.array(exports_external.string().min(1).max(500)).max(20),
45562
+ status: exports_external.enum([
45563
+ "pending",
45564
+ "approved",
45565
+ "rejected",
45566
+ "superseded",
45567
+ "applied"
45568
+ ]),
45569
+ reviewer: exports_external.enum(["user", "controller", "curator_agent", "auto_policy"]).optional(),
45570
+ reviewedAt: exports_external.string().datetime().optional(),
45571
+ rejectionReason: exports_external.string().optional(),
45572
+ createdAt: exports_external.string().datetime(),
45573
+ metadata: exports_external.record(exports_external.string(), exports_external.unknown())
45574
+ }).strict();
45575
+ });
45576
+
45577
+ // src/memory/scoring.ts
45578
+ function tokenize(text) {
45579
+ return new Set(text.toLowerCase().replace(/[^\w\s-]/g, " ").split(/\s+/).map((token) => token.trim()).filter(Boolean));
45580
+ }
45581
+ function normalizeKindText(kind) {
45582
+ return kind.replace(/_/g, " ");
45583
+ }
45584
+ function collectMetadataStrings(metadata, keys) {
45585
+ const values = [];
45586
+ for (const key of keys) {
45587
+ const value = metadata[key];
45588
+ if (typeof value === "string")
45589
+ values.push(value);
45590
+ if (Array.isArray(value)) {
45591
+ for (const item of value) {
45592
+ if (typeof item === "string")
45593
+ values.push(item);
45594
+ }
45595
+ }
45596
+ }
45597
+ return values;
45598
+ }
45599
+ function overlap(a, b) {
45600
+ if (a.size === 0 || b.size === 0)
45601
+ return 0;
45602
+ let hits = 0;
45603
+ for (const token of a) {
45604
+ if (b.has(token))
45605
+ hits++;
45606
+ }
45607
+ return hits / Math.max(a.size, 1);
45608
+ }
45609
+ function scopeSpecificityBoost(scope) {
45610
+ switch (scope.type) {
45611
+ case "agent":
45612
+ return 1;
45613
+ case "run":
45614
+ return 0.9;
45615
+ case "repository":
45616
+ return 0.8;
45617
+ case "project":
45618
+ return 0.65;
45619
+ case "workspace":
45620
+ return 0.45;
45621
+ case "global_user":
45622
+ return 0.3;
45623
+ }
45624
+ }
45625
+ function kindProfileBoost(kind, request) {
45626
+ if (!request.kinds || request.kinds.length === 0)
45627
+ return 0.5;
45628
+ return request.kinds.includes(kind) ? 1 : 0;
45629
+ }
45630
+ function sameScope(a, b) {
45631
+ return stableScopeKey(a) === stableScopeKey(b);
45632
+ }
45633
+ function scopeAllowed(recordScope, allowedScopes) {
45634
+ return allowedScopes.some((scope) => sameScope(recordScope, scope));
45635
+ }
45636
+ function scoreMemoryRecordDetailed(record3, request) {
45637
+ if (!request.includeExpired && isExpired(record3)) {
45638
+ return { item: null, skipReason: "filtered" };
45639
+ }
45640
+ if (record3.supersededBy)
45641
+ return { item: null, skipReason: "filtered" };
45642
+ if (record3.metadata.deleted === true) {
45643
+ return { item: null, skipReason: "filtered" };
45644
+ }
45645
+ if (!scopeAllowed(record3.scope, request.scopes)) {
45646
+ return { item: null, skipReason: "filtered" };
45647
+ }
45648
+ if (request.kinds && !request.kinds.includes(record3.kind)) {
45649
+ return { item: null, skipReason: "filtered" };
45650
+ }
45651
+ const queryTokens = request.mode === "injection" && request.task ? tokenize(request.task) : tokenize(request.query);
45652
+ const textTokens = tokenize(record3.text);
45653
+ const tagTokens = tokenize(record3.tags.join(" "));
45654
+ const fileTokens = tokenize([
45655
+ record3.source.filePath,
45656
+ ...collectMetadataStrings(record3.metadata, [
45657
+ "file",
45658
+ "filePath",
45659
+ "files",
45660
+ "touchedFiles"
45661
+ ])
45662
+ ].filter((value) => typeof value === "string").join(" "));
45663
+ const symbolTokens = tokenize(collectMetadataStrings(record3.metadata, ["symbol", "symbols"]).join(" "));
45664
+ const kindQueryOverlap = overlap(queryTokens, tokenize(normalizeKindText(record3.kind)));
45665
+ const textOverlap = overlap(queryTokens, textTokens);
45666
+ const tagOverlap = overlap(queryTokens, tagTokens);
45667
+ const fileOverlap = overlap(queryTokens, fileTokens);
45668
+ const symbolOverlap = overlap(queryTokens, symbolTokens);
45669
+ const kindMatch = request.kinds?.includes(record3.kind) ?? false;
45670
+ const scopeMatch = scopeAllowed(record3.scope, request.scopes);
45671
+ const hasQuerySignal = textOverlap > 0 || tagOverlap > 0 || fileOverlap > 0 || symbolOverlap > 0 || kindQueryOverlap > 0;
45672
+ if (request.mode === "injection" && request.requireQuerySignal !== false && !hasQuerySignal) {
45673
+ return { item: null, skipReason: "no_signal" };
45674
+ }
45675
+ const score = textOverlap * 0.45 + tagOverlap * 0.2 + fileOverlap * 0.05 + symbolOverlap * 0.05 + scopeSpecificityBoost(record3.scope) * 0.15 + kindProfileBoost(record3.kind, request) * 0.1 + record3.confidence * 0.1;
45676
+ const reasonParts = [
45677
+ textOverlap > 0 ? `text_overlap=${textOverlap.toFixed(2)}` : null,
45678
+ tagOverlap > 0 ? `tag_overlap=${tagOverlap.toFixed(2)}` : null,
45679
+ fileOverlap > 0 ? `file_overlap=${fileOverlap.toFixed(2)}` : null,
45680
+ symbolOverlap > 0 ? `symbol_overlap=${symbolOverlap.toFixed(2)}` : null,
45681
+ kindQueryOverlap > 0 ? `kind_query=${kindQueryOverlap.toFixed(2)}` : null,
45682
+ `scope=${record3.scope.type}`,
45683
+ `confidence=${record3.confidence.toFixed(2)}`
45684
+ ].filter(Boolean);
45685
+ return {
45686
+ item: {
45687
+ record: record3,
45688
+ score,
45689
+ reason: reasonParts.join(", "),
45690
+ signals: {
45691
+ textOverlap,
45692
+ tagOverlap,
45693
+ fileOverlap,
45694
+ symbolOverlap,
45695
+ kindMatch,
45696
+ scopeMatch
45697
+ }
45698
+ }
45699
+ };
45700
+ }
45701
+ function scoreMemoryRecordsWithDiagnostics(records, request) {
45702
+ const minScore = request.minScore ?? 0;
45703
+ const diagnostics = {
45704
+ candidateCount: records.length,
45705
+ preScoredFilteredCount: 0,
45706
+ scoredCount: 0,
45707
+ returnedCount: 0,
45708
+ noSignalCount: 0,
45709
+ belowThresholdCount: 0
45710
+ };
45711
+ const items = [];
45712
+ for (const record3 of records) {
45713
+ const result = scoreMemoryRecordDetailed(record3, request);
45714
+ if (!result.item) {
45715
+ if (result.skipReason === "filtered")
45716
+ diagnostics.preScoredFilteredCount++;
45717
+ if (result.skipReason === "no_signal")
45718
+ diagnostics.noSignalCount++;
45719
+ continue;
45720
+ }
45721
+ diagnostics.scoredCount++;
45722
+ if (result.item.score < minScore) {
45723
+ diagnostics.belowThresholdCount++;
45724
+ continue;
45725
+ }
45726
+ items.push(result.item);
45727
+ }
45728
+ items.sort((a, b) => b.score - a.score || a.record.id.localeCompare(b.record.id));
45729
+ diagnostics.returnedCount = items.length;
45730
+ return { items, diagnostics };
45731
+ }
45732
+ var init_scoring = __esm(() => {
45733
+ init_schema2();
45734
+ });
45735
+
45736
+ // src/memory/local-jsonl-provider.ts
45737
+ import { randomUUID as randomUUID3 } from "crypto";
45738
+ import { existsSync as existsSync18 } from "fs";
45739
+ import {
45740
+ appendFile as appendFile4,
45741
+ mkdir as mkdir8,
45742
+ readFile as readFile8,
45743
+ rename as rename6,
45744
+ writeFile as writeFile9
45745
+ } from "fs/promises";
45746
+ import * as path29 from "path";
45747
+
45748
+ class LocalJsonlMemoryProvider {
45749
+ name = "local-jsonl";
45750
+ rootDirectory;
45751
+ config;
45752
+ initialized = false;
45753
+ memories = new Map;
45754
+ proposals = new Map;
45755
+ constructor(rootDirectory, config3 = {}) {
45756
+ this.rootDirectory = rootDirectory;
45757
+ this.config = { ...DEFAULT_MEMORY_CONFIG, ...config3 };
45758
+ }
45759
+ pathFor(file3) {
45760
+ const storageDir = this.config.storageDir.replace(/^\.swarm[/\\]?/, "");
45761
+ const filename = file3 === "memories" ? "memories.jsonl" : file3 === "proposals" ? "proposals.jsonl" : "audit.jsonl";
45762
+ return validateSwarmPath(this.rootDirectory, path29.join(storageDir, filename));
45763
+ }
45764
+ async initialize() {
45765
+ if (this.initialized)
45766
+ return;
45767
+ const memoryPath = this.pathFor("memories");
45768
+ const proposalPath2 = this.pathFor("proposals");
45769
+ const memoryLoad = validateLoadedMemories(await readJsonl(memoryPath), this.config);
45770
+ const proposalLoad = validateLoadedProposals(await readJsonl(proposalPath2), this.config);
45771
+ this.memories = new Map(memoryLoad.records.map((record3) => [record3.id, record3]));
45772
+ this.proposals = new Map(proposalLoad.records.map((proposal) => [proposal.id, proposal]));
45773
+ this.initialized = true;
45774
+ if (memoryLoad.invalidCount > 0) {
45775
+ await this.audit("invalid_load", "memories", `${memoryLoad.invalidCount} invalid memory JSONL row(s) skipped`);
45776
+ }
45777
+ if (proposalLoad.invalidCount > 0) {
45778
+ await this.audit("invalid_load", "proposals", `${proposalLoad.invalidCount} invalid proposal JSONL row(s) skipped`);
45779
+ }
45780
+ }
45781
+ async upsert(record3) {
45782
+ await this.initialize();
45783
+ const existing = this.memories.get(record3.id);
45784
+ if (existing?.metadata.deleted === true) {
45785
+ throw new MemoryValidationError("memory is tombstoned and cannot be upserted");
45786
+ }
45787
+ const next = validateMemoryRecordRules({
45788
+ ...record3,
45789
+ createdAt: existing?.createdAt ?? record3.createdAt
45790
+ }, { rejectDurableSecrets: this.config.redaction.rejectDurableSecrets });
45791
+ this.memories.set(next.id, next);
45792
+ await appendJsonl(this.pathFor("memories"), next);
45793
+ await this.audit("upsert", next.id);
45794
+ return next;
45795
+ }
45796
+ async get(id) {
45797
+ await this.initialize();
45798
+ return this.memories.get(id) ?? null;
45799
+ }
45800
+ async delete(id, reason) {
45801
+ await this.initialize();
45802
+ const existing = this.memories.get(id);
45803
+ if (!existing)
45804
+ return;
45805
+ if (this.config.hardDelete) {
45806
+ this.memories.delete(id);
45807
+ await this.compact();
45808
+ } else {
45809
+ const tombstone = {
45810
+ ...existing,
45811
+ updatedAt: new Date().toISOString(),
45812
+ metadata: { ...existing.metadata, deleted: true, deleteReason: reason }
45813
+ };
45814
+ this.memories.set(id, tombstone);
45815
+ await appendJsonl(this.pathFor("memories"), tombstone);
45816
+ }
45817
+ await this.audit("delete", id, reason);
45818
+ }
45819
+ async recall(request) {
45820
+ return (await this.recallWithDiagnostics(request)).items;
45821
+ }
45822
+ async recallWithDiagnostics(request) {
45823
+ await this.initialize();
45824
+ const records = await this.list({
45825
+ scopes: request.scopes,
45826
+ kinds: request.kinds,
45827
+ includeExpired: request.includeExpired
45828
+ });
45829
+ const result = scoreMemoryRecordsWithDiagnostics(records, request);
45830
+ return {
45831
+ items: result.items.slice(0, request.maxItems),
45832
+ diagnostics: {
45833
+ ...result.diagnostics,
45834
+ returnedCount: Math.min(result.diagnostics.returnedCount, request.maxItems)
45835
+ }
45836
+ };
45837
+ }
45838
+ async recordRecallUsage(event) {
45839
+ await this.initialize();
45840
+ await this.audit("recall", event.bundleId, JSON.stringify({
45841
+ query: event.query,
45842
+ scopes: event.scopes,
45843
+ kinds: event.kinds,
45844
+ memoryIds: event.memoryIds,
45845
+ scores: event.scores,
45846
+ tokenEstimate: event.tokenEstimate,
45847
+ agentRole: event.agentRole,
45848
+ runId: event.runId
45849
+ }));
45850
+ }
45851
+ async list(filter = {}) {
45852
+ await this.initialize();
45853
+ let records = Array.from(this.memories.values());
45854
+ if (filter.scopes && filter.scopes.length > 0) {
45855
+ records = records.filter((record3) => scopeAllowed(record3.scope, filter.scopes ?? []));
45856
+ }
45857
+ if (filter.kinds && filter.kinds.length > 0) {
45858
+ records = records.filter((record3) => filter.kinds?.includes(record3.kind));
45859
+ }
45860
+ if (!filter.includeExpired) {
45861
+ const now = Date.now();
45862
+ records = records.filter((record3) => {
45863
+ if (!record3.expiresAt)
45864
+ return true;
45865
+ const expires = Date.parse(record3.expiresAt);
45866
+ return !Number.isFinite(expires) || expires > now;
45867
+ });
45868
+ }
45869
+ records = records.filter((record3) => !record3.supersededBy && record3.metadata.deleted !== true);
45870
+ records.sort((a, b) => b.updatedAt.localeCompare(a.updatedAt));
45871
+ return records.slice(0, filter.limit ?? records.length);
45872
+ }
45873
+ async createProposal(proposal) {
45874
+ await this.initialize();
45875
+ const next = validateMemoryProposal(proposal);
45876
+ this.proposals.set(next.id, next);
45877
+ await appendJsonl(this.pathFor("proposals"), next);
45878
+ await this.audit("proposal", next.id);
45879
+ return next;
45880
+ }
45881
+ async listProposals(filter = {}) {
45882
+ await this.initialize();
45883
+ let proposals = Array.from(this.proposals.values());
45884
+ if (filter.status) {
45885
+ proposals = proposals.filter((proposal) => proposal.status === filter.status);
45886
+ }
45887
+ proposals.sort((a, b) => b.createdAt.localeCompare(a.createdAt));
45888
+ return proposals.slice(0, filter.limit ?? proposals.length);
45889
+ }
45890
+ async compact() {
45891
+ await this.initialize();
45892
+ await writeJsonlAtomic(this.pathFor("memories"), Array.from(this.memories.values()));
45893
+ await this.audit("compact", "memories");
45894
+ }
45895
+ async audit(operation, targetId, reason) {
45896
+ const event = {
45897
+ id: randomUUID3(),
45898
+ operation,
45899
+ targetId,
45900
+ reason,
45901
+ timestamp: new Date().toISOString()
45902
+ };
45903
+ await appendJsonl(this.pathFor("audit"), event);
45904
+ }
45905
+ }
45906
+ function validateLoadedMemories(values, config3) {
45907
+ const records = [];
45908
+ let invalidCount = 0;
45909
+ for (const value of values) {
45910
+ try {
45911
+ records.push(validateMemoryRecordRules(value, {
45912
+ rejectDurableSecrets: config3.redaction.rejectDurableSecrets
45913
+ }));
45914
+ } catch {
45915
+ invalidCount++;
45916
+ }
45917
+ }
45918
+ return { records, invalidCount };
45919
+ }
45920
+ function validateLoadedProposals(values, config3) {
45921
+ const records = [];
45922
+ let invalidCount = 0;
45923
+ for (const value of values) {
45924
+ try {
45925
+ const proposal = validateMemoryProposal(value);
45926
+ if (proposal.proposedRecord) {
45927
+ validateMemoryRecordRules(proposal.proposedRecord, {
45928
+ rejectDurableSecrets: config3.redaction.rejectDurableSecrets
45929
+ });
45930
+ }
45931
+ records.push(proposal);
45932
+ } catch {
45933
+ invalidCount++;
45934
+ }
45935
+ }
45936
+ return { records, invalidCount };
45937
+ }
45938
+ async function readJsonl(filePath) {
45939
+ if (!existsSync18(filePath))
45940
+ return [];
45941
+ const content = await readFile8(filePath, "utf-8");
45942
+ const records = [];
45943
+ for (const line of content.split(`
45944
+ `)) {
45945
+ const trimmed = line.trim();
45946
+ if (!trimmed)
45947
+ continue;
45948
+ try {
45949
+ records.push(JSON.parse(trimmed));
45950
+ } catch {}
45951
+ }
45952
+ return records;
45953
+ }
45954
+ async function appendJsonl(filePath, value) {
45955
+ await mkdir8(path29.dirname(filePath), { recursive: true });
45956
+ await appendFile4(filePath, `${JSON.stringify(value)}
45957
+ `, "utf-8");
45958
+ }
45959
+ async function writeJsonlAtomic(filePath, values) {
45960
+ await mkdir8(path29.dirname(filePath), { recursive: true });
45961
+ const tmp = `${filePath}.tmp.${randomUUID3()}`;
45962
+ const content = values.map((value) => JSON.stringify(value)).join(`
45963
+ `) + (values.length > 0 ? `
45964
+ ` : "");
45965
+ await writeFile9(tmp, content, "utf-8");
45966
+ await rename6(tmp, filePath);
45967
+ }
45968
+ var init_local_jsonl_provider = __esm(() => {
45969
+ init_utils2();
45970
+ init_config3();
45971
+ init_errors6();
45972
+ init_schema2();
45973
+ init_scoring();
45974
+ });
45975
+
45976
+ // src/memory/prompt-block.ts
45977
+ var init_prompt_block = __esm(() => {
45978
+ init_utils2();
45979
+ init_redaction();
45980
+ });
45981
+
45982
+ // src/memory/jsonl-migration.ts
45983
+ import { existsSync as existsSync19 } from "fs";
45984
+ import { copyFile, mkdir as mkdir9, readFile as readFile9, stat as stat3, writeFile as writeFile10 } from "fs/promises";
45985
+ import * as path30 from "path";
45986
+ function resolveMemoryStorageDir(rootDirectory, config3 = {}) {
45987
+ const resolved = resolveConfig(config3);
45988
+ const storageDir = resolved.storageDir.replace(/^\.swarm[/\\]?/, "");
45989
+ return validateSwarmPath(rootDirectory, storageDir);
45990
+ }
45991
+ function resolveSqliteDatabasePath(rootDirectory, config3 = {}) {
45992
+ const resolved = resolveConfig(config3);
45993
+ const relativePath = resolved.sqlite.path.replace(/^\.swarm[/\\]?/, "");
45994
+ return validateSwarmPath(rootDirectory, relativePath);
45995
+ }
45996
+ async function readLegacyJsonl(rootDirectory, config3 = {}) {
45997
+ const resolved = resolveConfig(config3);
45998
+ const storageDir = resolveMemoryStorageDir(rootDirectory, resolved);
45999
+ const memoryLoad = await readMemoryJsonl(path30.join(storageDir, "memories.jsonl"), resolved);
46000
+ const proposalLoad = await readProposalJsonl(path30.join(storageDir, "proposals.jsonl"), resolved);
46001
+ return {
46002
+ memories: memoryLoad.records,
46003
+ proposals: proposalLoad.records,
46004
+ invalidRows: [...memoryLoad.invalidRows, ...proposalLoad.invalidRows],
46005
+ totalRows: memoryLoad.totalRows + proposalLoad.totalRows
46006
+ };
46007
+ }
46008
+ async function backupLegacyJsonl(rootDirectory, config3 = {}) {
46009
+ const storageDir = resolveMemoryStorageDir(rootDirectory, config3);
46010
+ const backupDir = path30.join(storageDir, "backups");
46011
+ await mkdir9(backupDir, { recursive: true });
46012
+ const results = [];
46013
+ for (const filename of ["memories.jsonl", "proposals.jsonl"]) {
46014
+ const source = path30.join(storageDir, filename);
46015
+ if (!existsSync19(source))
46016
+ continue;
46017
+ const backup = path30.join(backupDir, `${filename}.pre-sqlite-migration`);
46018
+ if (existsSync19(backup)) {
46019
+ results.push({ source, backup, created: false });
46020
+ continue;
46021
+ }
46022
+ await copyFile(source, backup);
46023
+ results.push({ source, backup, created: true });
46024
+ }
46025
+ return results;
46026
+ }
46027
+ async function writeJsonlExport(rootDirectory, config3, memories, proposals) {
46028
+ const exportDir = path30.join(resolveMemoryStorageDir(rootDirectory, config3), "export");
46029
+ await mkdir9(exportDir, { recursive: true });
46030
+ const memoriesPath = path30.join(exportDir, "memories.jsonl");
46031
+ const proposalsPath = path30.join(exportDir, "proposals.jsonl");
46032
+ await writeFile10(memoriesPath, toJsonl(memories), "utf-8");
46033
+ await writeFile10(proposalsPath, toJsonl(proposals), "utf-8");
46034
+ return { directory: exportDir, memoriesPath, proposalsPath };
46035
+ }
46036
+ async function writeMigrationReport(rootDirectory, report, config3 = {}) {
46037
+ const reportPath = path30.join(resolveMemoryStorageDir(rootDirectory, config3), "migration-report.json");
46038
+ await mkdir9(path30.dirname(reportPath), { recursive: true });
46039
+ await writeFile10(reportPath, `${JSON.stringify(report, null, 2)}
46040
+ `, "utf-8");
46041
+ return reportPath;
46042
+ }
46043
+ async function readMigrationReport(rootDirectory, config3 = {}) {
46044
+ const reportPath = path30.join(resolveMemoryStorageDir(rootDirectory, config3), "migration-report.json");
46045
+ if (!existsSync19(reportPath))
46046
+ return null;
46047
+ try {
46048
+ return JSON.parse(await readFile9(reportPath, "utf-8"));
46049
+ } catch {
46050
+ return null;
46051
+ }
46052
+ }
46053
+ async function getLegacyJsonlFileStatus(rootDirectory, config3 = {}) {
46054
+ const storageDir = resolveMemoryStorageDir(rootDirectory, config3);
46055
+ const statuses = [];
46056
+ for (const file3 of ["memories.jsonl", "proposals.jsonl"]) {
46057
+ const filePath = path30.join(storageDir, file3);
46058
+ let sizeBytes = 0;
46059
+ if (existsSync19(filePath)) {
46060
+ sizeBytes = (await stat3(filePath)).size;
46061
+ }
46062
+ statuses.push({
46063
+ file: file3,
46064
+ path: filePath,
46065
+ exists: existsSync19(filePath),
46066
+ sizeBytes
46067
+ });
46068
+ }
46069
+ return statuses;
46070
+ }
46071
+ function resolveConfig(config3) {
46072
+ return {
46073
+ ...DEFAULT_MEMORY_CONFIG,
46074
+ ...config3,
46075
+ sqlite: {
46076
+ ...DEFAULT_MEMORY_CONFIG.sqlite,
46077
+ ...config3.sqlite ?? {}
46078
+ },
46079
+ recall: {
46080
+ ...DEFAULT_MEMORY_CONFIG.recall,
46081
+ ...config3.recall ?? {},
46082
+ injection: {
46083
+ ...DEFAULT_MEMORY_CONFIG.recall.injection,
46084
+ ...config3.recall?.injection ?? {}
46085
+ }
46086
+ },
46087
+ writes: {
46088
+ ...DEFAULT_MEMORY_CONFIG.writes,
46089
+ ...config3.writes ?? {}
46090
+ },
46091
+ redaction: {
46092
+ ...DEFAULT_MEMORY_CONFIG.redaction,
46093
+ ...config3.redaction ?? {}
46094
+ }
46095
+ };
46096
+ }
46097
+ async function readMemoryJsonl(filePath, config3) {
46098
+ const rows = await readJsonlRows(filePath);
46099
+ const records = [];
46100
+ const invalidRows = [];
46101
+ for (const row of rows.rows) {
46102
+ try {
46103
+ records.push(validateMemoryRecordRules(row.value, {
46104
+ rejectDurableSecrets: config3.redaction.rejectDurableSecrets
46105
+ }));
46106
+ } catch (err) {
46107
+ invalidRows.push({
46108
+ file: "memories.jsonl",
46109
+ line: row.line,
46110
+ error: err instanceof Error ? err.message : String(err)
46111
+ });
46112
+ }
46113
+ }
46114
+ for (const row of rows.invalidRows) {
46115
+ invalidRows.push({ file: "memories.jsonl", ...row });
46116
+ }
46117
+ return { records, invalidRows, totalRows: rows.totalRows };
46118
+ }
46119
+ async function readProposalJsonl(filePath, config3) {
46120
+ const rows = await readJsonlRows(filePath);
46121
+ const records = [];
46122
+ const invalidRows = [];
46123
+ for (const row of rows.rows) {
46124
+ try {
46125
+ const proposal = validateMemoryProposal(row.value);
46126
+ if (proposal.proposedRecord) {
46127
+ validateMemoryRecordRules(proposal.proposedRecord, {
46128
+ rejectDurableSecrets: config3.redaction.rejectDurableSecrets
46129
+ });
46130
+ }
46131
+ records.push(proposal);
46132
+ } catch (err) {
46133
+ invalidRows.push({
46134
+ file: "proposals.jsonl",
46135
+ line: row.line,
46136
+ error: err instanceof Error ? err.message : String(err)
46137
+ });
46138
+ }
46139
+ }
46140
+ for (const row of rows.invalidRows) {
46141
+ invalidRows.push({ file: "proposals.jsonl", ...row });
46142
+ }
46143
+ return { records, invalidRows, totalRows: rows.totalRows };
46144
+ }
46145
+ async function readJsonlRows(filePath) {
46146
+ if (!existsSync19(filePath)) {
46147
+ return { rows: [], invalidRows: [], totalRows: 0 };
46148
+ }
46149
+ const content = await readFile9(filePath, "utf-8");
46150
+ const rows = [];
46151
+ const invalidRows = [];
46152
+ let totalRows = 0;
46153
+ const lines = content.split(/\r?\n/);
46154
+ for (let index = 0;index < lines.length; index++) {
46155
+ const trimmed = lines[index].trim();
46156
+ if (!trimmed)
46157
+ continue;
46158
+ totalRows++;
46159
+ try {
46160
+ rows.push({ line: index + 1, value: JSON.parse(trimmed) });
46161
+ } catch (err) {
46162
+ invalidRows.push({
46163
+ line: index + 1,
46164
+ error: err instanceof Error ? err.message : String(err)
46165
+ });
46166
+ }
46167
+ }
46168
+ return { rows, invalidRows, totalRows };
46169
+ }
46170
+ function toJsonl(values) {
46171
+ return values.map((value) => JSON.stringify(value)).join(`
46172
+ `) + (values.length > 0 ? `
46173
+ ` : "");
46174
+ }
46175
+ var LEGACY_JSONL_MIGRATION_VERSION = 2, LEGACY_JSONL_MIGRATION_NAME = "legacy_jsonl_import_complete";
46176
+ var init_jsonl_migration = __esm(() => {
46177
+ init_utils2();
46178
+ init_config3();
46179
+ init_schema2();
46180
+ });
46181
+
46182
+ // src/memory/sqlite-provider.ts
46183
+ import { randomUUID as randomUUID4 } from "crypto";
46184
+ import { mkdirSync as mkdirSync12 } from "fs";
46185
+ import { createRequire as createRequire2 } from "module";
46186
+ import * as path31 from "path";
46187
+ function loadDatabaseCtor2() {
46188
+ if (_DatabaseCtor2)
46189
+ return _DatabaseCtor2;
46190
+ const req = createRequire2(import.meta.url);
46191
+ _DatabaseCtor2 = req("bun:sqlite").Database;
46192
+ return _DatabaseCtor2;
46193
+ }
46194
+
46195
+ class SQLiteMemoryProvider {
46196
+ name = "sqlite";
46197
+ rootDirectory;
46198
+ config;
46199
+ initialized = false;
46200
+ db = null;
46201
+ memories = new Map;
46202
+ proposals = new Map;
46203
+ lastAutomaticJsonlMigration = null;
46204
+ constructor(rootDirectory, config3 = {}) {
46205
+ this.rootDirectory = rootDirectory;
46206
+ this.config = {
46207
+ ...DEFAULT_MEMORY_CONFIG,
46208
+ ...config3,
46209
+ sqlite: {
46210
+ ...DEFAULT_MEMORY_CONFIG.sqlite,
46211
+ ...config3.sqlite ?? {}
46212
+ },
46213
+ recall: {
46214
+ ...DEFAULT_MEMORY_CONFIG.recall,
46215
+ ...config3.recall ?? {},
46216
+ injection: {
46217
+ ...DEFAULT_MEMORY_CONFIG.recall.injection,
46218
+ ...config3.recall?.injection ?? {}
46219
+ }
46220
+ },
46221
+ writes: {
46222
+ ...DEFAULT_MEMORY_CONFIG.writes,
46223
+ ...config3.writes ?? {}
46224
+ },
46225
+ redaction: {
46226
+ ...DEFAULT_MEMORY_CONFIG.redaction,
46227
+ ...config3.redaction ?? {}
46228
+ }
46229
+ };
46230
+ }
46231
+ databasePath() {
46232
+ const relativePath = this.config.sqlite.path.replace(/^\.swarm[/\\]?/, "");
46233
+ return validateSwarmPath(this.rootDirectory, relativePath);
46234
+ }
46235
+ async initialize() {
46236
+ if (this.initialized)
46237
+ return;
46238
+ const dbPath = this.databasePath();
46239
+ mkdirSync12(path31.dirname(dbPath), { recursive: true });
46240
+ const Db = loadDatabaseCtor2();
46241
+ this.db = new Db(dbPath);
46242
+ this.db.run("PRAGMA journal_mode = WAL;");
46243
+ this.db.run("PRAGMA synchronous = NORMAL;");
46244
+ const busyTimeoutMs = Math.min(60000, Math.max(0, Math.trunc(this.config.sqlite.busyTimeoutMs)));
46245
+ this.db.run(`PRAGMA busy_timeout = ${busyTimeoutMs};`);
46246
+ this.db.run("PRAGMA foreign_keys = ON;");
46247
+ this.runMigrations();
46248
+ this.lastAutomaticJsonlMigration = null;
46249
+ await this.migrateLegacyJsonlIfNeeded();
46250
+ const memoryLoad = this.loadMemories();
46251
+ const proposalLoad = this.loadProposals();
46252
+ this.memories = new Map(memoryLoad.records.map((record3) => [record3.id, record3]));
46253
+ this.proposals = new Map(proposalLoad.records.map((proposal) => [proposal.id, proposal]));
46254
+ this.initialized = true;
46255
+ if (memoryLoad.invalidCount > 0) {
46256
+ await this.event("invalid_load", "memory_items", `${memoryLoad.invalidCount} invalid SQLite memory row(s) skipped`);
46257
+ }
46258
+ if (proposalLoad.invalidCount > 0) {
46259
+ await this.event("invalid_load", "memory_proposals", `${proposalLoad.invalidCount} invalid SQLite proposal row(s) skipped`);
46260
+ }
46261
+ }
46262
+ async upsert(record3) {
46263
+ await this.initialize();
46264
+ const existing = this.memories.get(record3.id);
46265
+ if (existing?.metadata.deleted === true) {
46266
+ throw new MemoryValidationError("memory is tombstoned and cannot be upserted");
46267
+ }
46268
+ const next = validateMemoryRecordRules({
46269
+ ...record3,
46270
+ createdAt: existing?.createdAt ?? record3.createdAt
46271
+ }, { rejectDurableSecrets: this.config.redaction.rejectDurableSecrets });
46272
+ this.memories.set(next.id, next);
46273
+ this.writeMemory(next);
46274
+ await this.event("upsert", next.id);
46275
+ return next;
46276
+ }
46277
+ async get(id) {
46278
+ await this.initialize();
46279
+ return this.memories.get(id) ?? null;
46280
+ }
46281
+ async delete(id, reason) {
46282
+ await this.initialize();
46283
+ const existing = this.memories.get(id);
46284
+ if (!existing)
46285
+ return;
46286
+ if (this.config.hardDelete) {
46287
+ this.memories.delete(id);
46288
+ this.requireDb().run("DELETE FROM memory_items WHERE id = ?", [id]);
46289
+ } else {
46290
+ const tombstone = {
46291
+ ...existing,
46292
+ updatedAt: new Date().toISOString(),
46293
+ metadata: { ...existing.metadata, deleted: true, deleteReason: reason }
46294
+ };
46295
+ this.memories.set(id, tombstone);
46296
+ this.writeMemory(tombstone);
46297
+ }
46298
+ await this.event("delete", id, reason);
46299
+ }
46300
+ async recall(request) {
46301
+ return (await this.recallWithDiagnostics(request)).items;
46302
+ }
46303
+ async recallWithDiagnostics(request) {
46304
+ await this.initialize();
46305
+ const records = await this.list({
46306
+ scopes: request.scopes,
46307
+ kinds: request.kinds,
46308
+ includeExpired: request.includeExpired
46309
+ });
46310
+ const result = scoreMemoryRecordsWithDiagnostics(records, request);
46311
+ return {
46312
+ items: result.items.slice(0, request.maxItems),
46313
+ diagnostics: {
46314
+ ...result.diagnostics,
46315
+ returnedCount: Math.min(result.diagnostics.returnedCount, request.maxItems)
46316
+ }
46317
+ };
46318
+ }
46319
+ async recordRecallUsage(event) {
46320
+ await this.initialize();
46321
+ this.requireDb().run(`INSERT INTO memory_recall_usage (
46322
+ id,
46323
+ bundle_id,
46324
+ timestamp,
46325
+ usage_json
46326
+ ) VALUES (?, ?, ?, ?)`, [randomUUID4(), event.bundleId, event.timestamp, JSON.stringify(event)]);
46327
+ await this.event("recall", event.bundleId, JSON.stringify(event));
46328
+ }
46329
+ async list(filter = {}) {
46330
+ await this.initialize();
46331
+ let records = Array.from(this.memories.values());
46332
+ if (filter.scopes && filter.scopes.length > 0) {
46333
+ records = records.filter((record3) => scopeAllowed(record3.scope, filter.scopes ?? []));
46334
+ }
46335
+ if (filter.kinds && filter.kinds.length > 0) {
46336
+ records = records.filter((record3) => filter.kinds?.includes(record3.kind));
46337
+ }
46338
+ if (!filter.includeExpired) {
46339
+ const now = Date.now();
46340
+ records = records.filter((record3) => {
46341
+ if (!record3.expiresAt)
46342
+ return true;
46343
+ const expires = Date.parse(record3.expiresAt);
46344
+ return !Number.isFinite(expires) || expires > now;
46345
+ });
46346
+ }
46347
+ records = records.filter((record3) => !record3.supersededBy && record3.metadata.deleted !== true);
46348
+ records.sort((a, b) => b.updatedAt.localeCompare(a.updatedAt));
46349
+ return records.slice(0, filter.limit ?? records.length);
46350
+ }
46351
+ async createProposal(proposal) {
46352
+ await this.initialize();
46353
+ const next = validateMemoryProposal(proposal);
46354
+ if (next.proposedRecord) {
46355
+ validateMemoryRecordRules(next.proposedRecord, {
46356
+ rejectDurableSecrets: this.config.redaction.rejectDurableSecrets
46357
+ });
46358
+ }
46359
+ this.proposals.set(next.id, next);
46360
+ this.writeProposal(next);
46361
+ await this.event("proposal", next.id);
46362
+ return next;
46363
+ }
46364
+ async listProposals(filter = {}) {
46365
+ await this.initialize();
46366
+ let proposals = Array.from(this.proposals.values());
46367
+ if (filter.status) {
46368
+ proposals = proposals.filter((proposal) => proposal.status === filter.status);
46369
+ }
46370
+ proposals.sort((a, b) => b.createdAt.localeCompare(a.createdAt));
46371
+ return proposals.slice(0, filter.limit ?? proposals.length);
46372
+ }
46373
+ close() {
46374
+ if (!this.db)
46375
+ return;
46376
+ this.db.close();
46377
+ this.db = null;
46378
+ this.initialized = false;
46379
+ this.lastAutomaticJsonlMigration = null;
46380
+ }
46381
+ async importJsonl() {
46382
+ const wasInitialized = this.initialized;
46383
+ await this.initialize();
46384
+ if (!wasInitialized && this.lastAutomaticJsonlMigration) {
46385
+ return this.lastAutomaticJsonlMigration;
46386
+ }
46387
+ return this.importLegacyJsonlRows();
46388
+ }
46389
+ async exportJsonl() {
46390
+ await this.initialize();
46391
+ const memories = await this.list({ includeExpired: true });
46392
+ const proposals = await this.listProposals();
46393
+ const output = await writeJsonlExport(this.rootDirectory, this.config, memories, proposals);
46394
+ return {
46395
+ ...output,
46396
+ memories: memories.length,
46397
+ proposals: proposals.length
46398
+ };
46399
+ }
46400
+ hasMigration(name) {
46401
+ const row = this.requireDb().query("SELECT version, name FROM schema_migrations WHERE name = ? LIMIT 1").get(name);
46402
+ return Boolean(row);
46403
+ }
46404
+ markMigration(version4, name) {
46405
+ this.requireDb().run("INSERT OR IGNORE INTO schema_migrations (version, name) VALUES (?, ?)", [version4, name]);
46406
+ }
46407
+ runMigrations() {
46408
+ const db = this.requireDb();
46409
+ db.run(`CREATE TABLE IF NOT EXISTS schema_migrations (
46410
+ version INTEGER PRIMARY KEY,
46411
+ name TEXT NOT NULL,
46412
+ applied_at TEXT NOT NULL DEFAULT (datetime('now'))
46413
+ )`);
46414
+ const row = db.query("SELECT MAX(version) as version FROM schema_migrations").get();
46415
+ const currentVersion = row?.version ?? 0;
46416
+ for (const migration of MIGRATIONS2) {
46417
+ if (migration.version <= currentVersion)
46418
+ continue;
46419
+ const apply = db.transaction(() => {
46420
+ for (const statement of splitSql(migration.sql)) {
46421
+ db.run(statement);
46422
+ }
46423
+ db.run("INSERT INTO schema_migrations (version, name) VALUES (?, ?)", [
46424
+ migration.version,
46425
+ migration.name
46426
+ ]);
46427
+ this.insertEvent("migration", String(migration.version), migration.name);
46428
+ });
46429
+ apply();
46430
+ }
46431
+ }
46432
+ loadMemories() {
46433
+ const rows = this.requireDb().query("SELECT id, record_json FROM memory_items ORDER BY updated_at ASC").all();
46434
+ const records = [];
46435
+ let invalidCount = 0;
46436
+ for (const row of rows) {
46437
+ try {
46438
+ records.push(validateMemoryRecordRules(JSON.parse(row.record_json), {
46439
+ rejectDurableSecrets: this.config.redaction.rejectDurableSecrets
46440
+ }));
46441
+ } catch {
46442
+ invalidCount++;
46443
+ }
46444
+ }
46445
+ return { records, invalidCount };
46446
+ }
46447
+ loadProposals() {
46448
+ const rows = this.requireDb().query("SELECT id, proposal_json FROM memory_proposals ORDER BY created_at ASC").all();
46449
+ const records = [];
46450
+ let invalidCount = 0;
46451
+ for (const row of rows) {
46452
+ try {
46453
+ const proposal = validateMemoryProposal(JSON.parse(row.proposal_json));
46454
+ if (proposal.proposedRecord) {
46455
+ validateMemoryRecordRules(proposal.proposedRecord, {
46456
+ rejectDurableSecrets: this.config.redaction.rejectDurableSecrets
46457
+ });
46458
+ }
46459
+ records.push(proposal);
46460
+ } catch {
46461
+ invalidCount++;
46462
+ }
46463
+ }
46464
+ return { records, invalidCount };
46465
+ }
46466
+ writeMemory(record3) {
46467
+ this.requireDb().run(`INSERT OR REPLACE INTO memory_items (
46468
+ id,
46469
+ scope_key,
46470
+ kind,
46471
+ updated_at,
46472
+ expires_at,
46473
+ superseded_by,
46474
+ deleted,
46475
+ record_json
46476
+ ) VALUES (?, ?, ?, ?, ?, ?, ?, ?)`, [
46477
+ record3.id,
46478
+ JSON.stringify(record3.scope),
46479
+ record3.kind,
46480
+ record3.updatedAt,
46481
+ record3.expiresAt ?? null,
46482
+ record3.supersededBy ?? null,
46483
+ record3.metadata.deleted === true ? 1 : 0,
46484
+ JSON.stringify(record3)
46485
+ ]);
46486
+ }
46487
+ writeProposal(proposal) {
46488
+ this.requireDb().run(`INSERT OR REPLACE INTO memory_proposals (
46489
+ id,
46490
+ status,
46491
+ created_at,
46492
+ proposal_json
46493
+ ) VALUES (?, ?, ?, ?)`, [
46494
+ proposal.id,
46495
+ proposal.status,
46496
+ proposal.createdAt,
46497
+ JSON.stringify(proposal)
46498
+ ]);
46499
+ }
46500
+ async migrateLegacyJsonlIfNeeded() {
46501
+ if (this.hasMigration(LEGACY_JSONL_MIGRATION_NAME))
46502
+ return;
46503
+ const backups = await backupLegacyJsonl(this.rootDirectory, this.config);
46504
+ const result = await this.importLegacyJsonlRows();
46505
+ this.lastAutomaticJsonlMigration = result;
46506
+ this.markMigration(LEGACY_JSONL_MIGRATION_VERSION, LEGACY_JSONL_MIGRATION_NAME);
46507
+ const report = {
46508
+ migration: LEGACY_JSONL_MIGRATION_NAME,
46509
+ completedAt: new Date().toISOString(),
46510
+ skipped: false,
46511
+ importedMemories: result.importedMemories,
46512
+ importedProposals: result.importedProposals,
46513
+ invalidRows: result.invalidRows,
46514
+ backups
46515
+ };
46516
+ await writeMigrationReport(this.rootDirectory, report, this.config);
46517
+ this.insertEvent("migration", LEGACY_JSONL_MIGRATION_NAME, JSON.stringify({
46518
+ importedMemories: result.importedMemories,
46519
+ importedProposals: result.importedProposals,
46520
+ invalidRows: result.invalidRows.length
46521
+ }));
46522
+ }
46523
+ async importLegacyJsonlRows() {
46524
+ const payload = await readLegacyJsonl(this.rootDirectory, this.config);
46525
+ for (const record3 of payload.memories) {
46526
+ this.writeMemory(record3);
46527
+ }
46528
+ for (const proposal of payload.proposals) {
46529
+ this.writeProposal(proposal);
46530
+ }
46531
+ return {
46532
+ importedMemories: payload.memories.length,
46533
+ importedProposals: payload.proposals.length,
46534
+ invalidRows: payload.invalidRows,
46535
+ totalRows: payload.totalRows
46536
+ };
46537
+ }
46538
+ async event(operation, targetId, reason) {
46539
+ this.insertEvent(operation, targetId, reason);
46540
+ }
46541
+ insertEvent(operation, targetId, reason) {
46542
+ this.requireDb().run(`INSERT INTO memory_events (
46543
+ id,
46544
+ operation,
46545
+ target_id,
46546
+ reason,
46547
+ timestamp,
46548
+ event_json
46549
+ ) VALUES (?, ?, ?, ?, ?, ?)`, [
46550
+ randomUUID4(),
46551
+ operation,
46552
+ targetId,
46553
+ reason ?? null,
46554
+ new Date().toISOString(),
46555
+ reason ? JSON.stringify({ reason }) : null
46556
+ ]);
46557
+ }
46558
+ requireDb() {
46559
+ if (!this.db)
46560
+ throw new Error("SQLite memory provider is not initialized");
46561
+ return this.db;
46562
+ }
46563
+ }
46564
+ function splitSql(sql) {
46565
+ return sql.split(";").map((statement) => statement.trim()).filter(Boolean);
46566
+ }
46567
+ var _DatabaseCtor2 = null, MIGRATIONS2;
46568
+ var init_sqlite_provider = __esm(() => {
46569
+ init_utils2();
46570
+ init_config3();
46571
+ init_errors6();
46572
+ init_jsonl_migration();
46573
+ init_schema2();
46574
+ init_scoring();
46575
+ MIGRATIONS2 = [
46576
+ {
46577
+ version: 1,
46578
+ name: "create_memory_provider_tables",
46579
+ sql: `
46580
+ CREATE TABLE IF NOT EXISTS memory_items (
46581
+ id TEXT PRIMARY KEY,
46582
+ scope_key TEXT NOT NULL,
46583
+ kind TEXT NOT NULL,
46584
+ updated_at TEXT NOT NULL,
46585
+ expires_at TEXT,
46586
+ superseded_by TEXT,
46587
+ deleted INTEGER NOT NULL DEFAULT 0,
46588
+ record_json TEXT NOT NULL
46589
+ );
46590
+ CREATE INDEX IF NOT EXISTS idx_memory_items_scope_kind
46591
+ ON memory_items(scope_key, kind);
46592
+ CREATE INDEX IF NOT EXISTS idx_memory_items_updated_at
46593
+ ON memory_items(updated_at);
46594
+
46595
+ CREATE TABLE IF NOT EXISTS memory_proposals (
46596
+ id TEXT PRIMARY KEY,
46597
+ status TEXT NOT NULL,
46598
+ created_at TEXT NOT NULL,
46599
+ proposal_json TEXT NOT NULL
46600
+ );
46601
+ CREATE INDEX IF NOT EXISTS idx_memory_proposals_status_created
46602
+ ON memory_proposals(status, created_at);
46603
+
46604
+ CREATE TABLE IF NOT EXISTS memory_events (
46605
+ id TEXT PRIMARY KEY,
46606
+ operation TEXT NOT NULL,
46607
+ target_id TEXT NOT NULL,
46608
+ reason TEXT,
46609
+ timestamp TEXT NOT NULL,
46610
+ event_json TEXT
46611
+ );
46612
+
46613
+ CREATE TABLE IF NOT EXISTS memory_recall_usage (
46614
+ id TEXT PRIMARY KEY,
46615
+ bundle_id TEXT NOT NULL,
46616
+ timestamp TEXT NOT NULL,
46617
+ usage_json TEXT NOT NULL
46618
+ );
46619
+ CREATE INDEX IF NOT EXISTS idx_memory_recall_usage_bundle
46620
+ ON memory_recall_usage(bundle_id);
46621
+ `
46622
+ }
46623
+ ];
46624
+ });
46625
+
46626
+ // src/memory/gateway.ts
46627
+ function createConfiguredMemoryProvider(directory, config3) {
46628
+ if (config3.provider === "sqlite") {
46629
+ return new SQLiteMemoryProvider(directory, config3);
46630
+ }
46631
+ return new LocalJsonlMemoryProvider(directory, config3);
46632
+ }
46633
+ var gitRemoteUrlCache;
46634
+ var init_gateway = __esm(() => {
46635
+ init_config3();
46636
+ init_errors6();
46637
+ init_local_jsonl_provider();
46638
+ init_prompt_block();
46639
+ init_redaction();
46640
+ init_schema2();
46641
+ init_sqlite_provider();
46642
+ gitRemoteUrlCache = new Map;
46643
+ });
46644
+
46645
+ // src/agents/agent-output-schema.ts
46646
+ var AgentMemoryProposalSchema, AgentOutputMemorySchema;
46647
+ var init_agent_output_schema = __esm(() => {
46648
+ init_zod();
46649
+ init_schema2();
46650
+ AgentMemoryProposalSchema = exports_external.object({
46651
+ operation: exports_external.enum([
46652
+ "add",
46653
+ "update",
46654
+ "delete",
46655
+ "ignore",
46656
+ "merge",
46657
+ "supersede"
46658
+ ]),
46659
+ kind: MemoryKindSchema.optional(),
46660
+ text: exports_external.string().min(1).max(2000).optional(),
46661
+ targetMemoryId: exports_external.string().optional(),
46662
+ relatedMemoryIds: exports_external.array(exports_external.string()).optional(),
46663
+ rationale: exports_external.string().min(1).max(2000),
46664
+ evidenceRefs: exports_external.array(exports_external.string().min(1).max(500)).max(20).optional()
46665
+ }).strict();
46666
+ AgentOutputMemorySchema = exports_external.object({
46667
+ memoryProposals: exports_external.array(AgentMemoryProposalSchema).max(20).optional()
46668
+ }).passthrough();
46669
+ });
46670
+
46671
+ // src/memory/role-profiles.ts
46672
+ var init_role_profiles = __esm(() => {
46673
+ init_schema();
46674
+ });
46675
+
46676
+ // src/memory/recall-planner.ts
46677
+ var init_recall_planner = __esm(() => {
46678
+ init_role_profiles();
46679
+ });
46680
+
46681
+ // src/memory/run-log.ts
46682
+ var init_run_log = __esm(() => {
46683
+ init_utils2();
46684
+ });
46685
+
46686
+ // src/memory/injector.ts
46687
+ var init_injector = __esm(() => {
46688
+ init_agent_output_schema();
46689
+ init_schema();
46690
+ init_normalize_tool_name();
46691
+ init_config3();
46692
+ init_gateway();
46693
+ init_recall_planner();
46694
+ init_run_log();
46695
+ });
46696
+
46697
+ // src/memory/index.ts
46698
+ var init_memory = __esm(() => {
46699
+ init_config3();
46700
+ init_errors6();
46701
+ init_gateway();
46702
+ init_injector();
46703
+ init_jsonl_migration();
46704
+ init_local_jsonl_provider();
46705
+ init_prompt_block();
46706
+ init_recall_planner();
46707
+ init_redaction();
46708
+ init_role_profiles();
46709
+ init_run_log();
46710
+ init_schema2();
46711
+ init_sqlite_provider();
46712
+ });
46713
+
46714
+ // src/commands/memory.ts
46715
+ import { existsSync as existsSync20 } from "fs";
46716
+ async function handleMemoryCommand(_directory, _args) {
46717
+ return [
46718
+ "## Swarm Memory",
46719
+ "",
46720
+ "- `/swarm memory status` - show provider, SQLite path, JSONL files, and last migration report",
46721
+ "- `/swarm memory export` - export current memory and proposals to `.swarm/memory/export/*.jsonl`",
46722
+ "- `/swarm memory import` - import `.swarm/memory/{memories,proposals}.jsonl` into SQLite",
46723
+ "- `/swarm memory migrate` - run the one-time legacy JSONL to SQLite migration"
46724
+ ].join(`
46725
+ `);
46726
+ }
46727
+ async function handleMemoryStatusCommand(directory, _args) {
46728
+ const config3 = resolveCommandMemoryConfig(directory);
46729
+ const storageDir = resolveMemoryStorageDir(directory, config3);
46730
+ const sqlitePath = resolveSqliteDatabasePath(directory, config3);
46731
+ const jsonlFiles = await getLegacyJsonlFileStatus(directory, config3);
46732
+ const report = await readMigrationReport(directory, config3);
46733
+ const lines = [
46734
+ "## Swarm Memory Status",
46735
+ "",
46736
+ `- Enabled: \`${config3.enabled}\``,
46737
+ `- Provider: \`${config3.provider}\``,
46738
+ `- Storage: \`${storageDir}\``,
46739
+ `- SQLite path: \`${sqlitePath}\``,
46740
+ `- SQLite database exists: \`${existsSync20(sqlitePath)}\``,
46741
+ "",
46742
+ "### Legacy JSONL"
46743
+ ];
46744
+ for (const file3 of jsonlFiles) {
46745
+ lines.push(`- ${file3.file}: \`${file3.exists ? "present" : "missing"}\` (${file3.sizeBytes} bytes)`);
46746
+ }
46747
+ lines.push("", "### Migration");
46748
+ if (!report) {
46749
+ lines.push("- Last report: `none`");
46750
+ } else {
46751
+ lines.push(`- Completed at: \`${report.completedAt}\``, `- Imported memories: \`${report.importedMemories}\``, `- Imported proposals: \`${report.importedProposals}\``, `- Invalid rows: \`${report.invalidRows.length}\``, `- Backups: \`${report.backups.length}\``);
46752
+ if (report.invalidRows.length > 0) {
46753
+ lines.push("", "Invalid rows:");
46754
+ for (const row of report.invalidRows.slice(0, 20)) {
46755
+ lines.push(`- ${row.file}:${row.line} - ${row.error}`);
46756
+ }
46757
+ if (report.invalidRows.length > 20) {
46758
+ lines.push(`- ... ${report.invalidRows.length - 20} more`);
46759
+ }
46760
+ }
46761
+ }
46762
+ return lines.join(`
46763
+ `);
46764
+ }
46765
+ async function handleMemoryMigrateCommand(directory, _args) {
46766
+ const config3 = {
46767
+ ...resolveCommandMemoryConfig(directory),
46768
+ provider: "sqlite"
46769
+ };
46770
+ const provider = new SQLiteMemoryProvider(directory, config3);
46771
+ try {
46772
+ await provider.initialize();
46773
+ const report = await readMigrationReport(directory, config3);
46774
+ return formatMigrationResult("migration", report);
46775
+ } finally {
46776
+ provider.close();
46777
+ }
46778
+ }
46779
+ async function handleMemoryImportCommand(directory, _args) {
46780
+ const config3 = {
46781
+ ...resolveCommandMemoryConfig(directory),
46782
+ provider: "sqlite"
46783
+ };
46784
+ const provider = new SQLiteMemoryProvider(directory, config3);
46785
+ try {
46786
+ const result = await provider.importJsonl();
46787
+ const lines = [
46788
+ "## Swarm Memory Import",
46789
+ "",
46790
+ `- Imported memories: \`${result.importedMemories}\``,
46791
+ `- Imported proposals: \`${result.importedProposals}\``,
46792
+ `- Total JSONL rows scanned: \`${result.totalRows}\``,
46793
+ `- Invalid rows: \`${result.invalidRows.length}\``
46794
+ ];
46795
+ appendInvalidRows(lines, result.invalidRows);
46796
+ return lines.join(`
46797
+ `);
46798
+ } finally {
46799
+ provider.close();
46800
+ }
46801
+ }
46802
+ async function handleMemoryExportCommand(directory, _args) {
46803
+ const config3 = resolveCommandMemoryConfig(directory);
46804
+ const provider = createConfiguredMemoryProvider(directory, config3);
46805
+ try {
46806
+ await provider.initialize?.();
46807
+ const memories = await provider.list({ includeExpired: true });
46808
+ const proposals = provider.listProposals ? await provider.listProposals() : [];
46809
+ const output = await writeJsonlExport(directory, config3, memories, proposals);
46810
+ return [
46811
+ "## Swarm Memory Export",
46812
+ "",
46813
+ `- Memories: \`${memories.length}\` -> \`${output.memoriesPath}\``,
46814
+ `- Proposals: \`${proposals.length}\` -> \`${output.proposalsPath}\``
46815
+ ].join(`
46816
+ `);
46817
+ } finally {
46818
+ await provider.close?.();
46819
+ }
46820
+ }
46821
+ function resolveCommandMemoryConfig(directory) {
46822
+ const loaded = loadPluginConfig(directory).memory;
46823
+ return resolveMemoryConfig(loaded ?? DEFAULT_MEMORY_CONFIG);
46824
+ }
46825
+ function formatMigrationResult(label, report) {
46826
+ if (!report) {
46827
+ return [
46828
+ `## Swarm Memory ${label}`,
46829
+ "",
46830
+ "No migration report was written."
46831
+ ].join(`
46832
+ `);
46833
+ }
46834
+ const lines = [
46835
+ `## Swarm Memory ${label}`,
46836
+ "",
46837
+ `- Completed at: \`${report.completedAt}\``,
46838
+ `- Imported memories: \`${report.importedMemories}\``,
46839
+ `- Imported proposals: \`${report.importedProposals}\``,
46840
+ `- Invalid rows: \`${report.invalidRows.length}\``,
46841
+ `- Backups: \`${report.backups.length}\``
46842
+ ];
46843
+ if (report.backups.length > 0) {
46844
+ lines.push("", "Backups:");
46845
+ for (const backup of report.backups) {
46846
+ lines.push(`- \`${backup.backup}\` (${backup.created ? "created" : "already existed"})`);
46847
+ }
46848
+ }
46849
+ appendInvalidRows(lines, report.invalidRows);
46850
+ return lines.join(`
46851
+ `);
46852
+ }
46853
+ function appendInvalidRows(lines, invalidRows) {
46854
+ if (invalidRows.length === 0)
46855
+ return;
46856
+ lines.push("", "Invalid rows:");
46857
+ for (const row of invalidRows.slice(0, 20)) {
46858
+ lines.push(`- ${row.file}:${row.line} - ${row.error}`);
46859
+ }
46860
+ if (invalidRows.length > 20) {
46861
+ lines.push(`- ... ${invalidRows.length - 20} more`);
46862
+ }
46863
+ }
46864
+ var init_memory2 = __esm(() => {
46865
+ init_loader();
46866
+ init_memory();
46867
+ });
46868
+
45271
46869
  // src/services/plan-service.ts
45272
46870
  async function getPlanData(directory, phaseArg) {
45273
46871
  const plan = await _internals18.loadPlanJsonOnly(directory);
@@ -45653,7 +47251,7 @@ var init_path_security = () => {};
45653
47251
 
45654
47252
  // src/tools/lint.ts
45655
47253
  import * as fs12 from "fs";
45656
- import * as path29 from "path";
47254
+ import * as path32 from "path";
45657
47255
  function validateArgs(args) {
45658
47256
  if (typeof args !== "object" || args === null)
45659
47257
  return false;
@@ -45664,9 +47262,9 @@ function validateArgs(args) {
45664
47262
  }
45665
47263
  function getLinterCommand(linter, mode, projectDir) {
45666
47264
  const isWindows = process.platform === "win32";
45667
- const binDir = path29.join(projectDir, "node_modules", ".bin");
45668
- const biomeBin = isWindows ? path29.join(binDir, "biome.EXE") : path29.join(binDir, "biome");
45669
- const eslintBin = isWindows ? path29.join(binDir, "eslint.cmd") : path29.join(binDir, "eslint");
47265
+ const binDir = path32.join(projectDir, "node_modules", ".bin");
47266
+ const biomeBin = isWindows ? path32.join(binDir, "biome.EXE") : path32.join(binDir, "biome");
47267
+ const eslintBin = isWindows ? path32.join(binDir, "eslint.cmd") : path32.join(binDir, "eslint");
45670
47268
  switch (linter) {
45671
47269
  case "biome":
45672
47270
  if (mode === "fix") {
@@ -45682,7 +47280,7 @@ function getLinterCommand(linter, mode, projectDir) {
45682
47280
  }
45683
47281
  function getAdditionalLinterCommand(linter, mode, cwd) {
45684
47282
  const gradlewName = process.platform === "win32" ? "gradlew.bat" : "gradlew";
45685
- const gradlew = fs12.existsSync(path29.join(cwd, gradlewName)) ? path29.join(cwd, gradlewName) : null;
47283
+ const gradlew = fs12.existsSync(path32.join(cwd, gradlewName)) ? path32.join(cwd, gradlewName) : null;
45686
47284
  switch (linter) {
45687
47285
  case "ruff":
45688
47286
  return mode === "fix" ? ["ruff", "check", "--fix", "."] : ["ruff", "check", "."];
@@ -45716,10 +47314,10 @@ function getAdditionalLinterCommand(linter, mode, cwd) {
45716
47314
  }
45717
47315
  }
45718
47316
  function detectRuff(cwd) {
45719
- if (fs12.existsSync(path29.join(cwd, "ruff.toml")))
47317
+ if (fs12.existsSync(path32.join(cwd, "ruff.toml")))
45720
47318
  return isCommandAvailable("ruff");
45721
47319
  try {
45722
- const pyproject = path29.join(cwd, "pyproject.toml");
47320
+ const pyproject = path32.join(cwd, "pyproject.toml");
45723
47321
  if (fs12.existsSync(pyproject)) {
45724
47322
  const content = fs12.readFileSync(pyproject, "utf-8");
45725
47323
  if (content.includes("[tool.ruff]"))
@@ -45729,19 +47327,19 @@ function detectRuff(cwd) {
45729
47327
  return false;
45730
47328
  }
45731
47329
  function detectClippy(cwd) {
45732
- return fs12.existsSync(path29.join(cwd, "Cargo.toml")) && isCommandAvailable("cargo");
47330
+ return fs12.existsSync(path32.join(cwd, "Cargo.toml")) && isCommandAvailable("cargo");
45733
47331
  }
45734
47332
  function detectGolangciLint(cwd) {
45735
- return fs12.existsSync(path29.join(cwd, "go.mod")) && isCommandAvailable("golangci-lint");
47333
+ return fs12.existsSync(path32.join(cwd, "go.mod")) && isCommandAvailable("golangci-lint");
45736
47334
  }
45737
47335
  function detectCheckstyle(cwd) {
45738
- const hasMaven = fs12.existsSync(path29.join(cwd, "pom.xml"));
45739
- const hasGradle = fs12.existsSync(path29.join(cwd, "build.gradle")) || fs12.existsSync(path29.join(cwd, "build.gradle.kts"));
45740
- const hasBinary = hasMaven && isCommandAvailable("mvn") || hasGradle && (fs12.existsSync(path29.join(cwd, "gradlew")) || isCommandAvailable("gradle"));
47336
+ const hasMaven = fs12.existsSync(path32.join(cwd, "pom.xml"));
47337
+ const hasGradle = fs12.existsSync(path32.join(cwd, "build.gradle")) || fs12.existsSync(path32.join(cwd, "build.gradle.kts"));
47338
+ const hasBinary = hasMaven && isCommandAvailable("mvn") || hasGradle && (fs12.existsSync(path32.join(cwd, "gradlew")) || isCommandAvailable("gradle"));
45741
47339
  return (hasMaven || hasGradle) && hasBinary;
45742
47340
  }
45743
47341
  function detectKtlint(cwd) {
45744
- const hasKotlin = fs12.existsSync(path29.join(cwd, "build.gradle.kts")) || fs12.existsSync(path29.join(cwd, "build.gradle")) || (() => {
47342
+ const hasKotlin = fs12.existsSync(path32.join(cwd, "build.gradle.kts")) || fs12.existsSync(path32.join(cwd, "build.gradle")) || (() => {
45745
47343
  try {
45746
47344
  return fs12.readdirSync(cwd).some((f) => f.endsWith(".kt") || f.endsWith(".kts"));
45747
47345
  } catch {
@@ -45760,11 +47358,11 @@ function detectDotnetFormat(cwd) {
45760
47358
  }
45761
47359
  }
45762
47360
  function detectCppcheck(cwd) {
45763
- if (fs12.existsSync(path29.join(cwd, "CMakeLists.txt"))) {
47361
+ if (fs12.existsSync(path32.join(cwd, "CMakeLists.txt"))) {
45764
47362
  return isCommandAvailable("cppcheck");
45765
47363
  }
45766
47364
  try {
45767
- const dirsToCheck = [cwd, path29.join(cwd, "src")];
47365
+ const dirsToCheck = [cwd, path32.join(cwd, "src")];
45768
47366
  const hasCpp = dirsToCheck.some((dir) => {
45769
47367
  try {
45770
47368
  return fs12.readdirSync(dir).some((f) => /\.(c|cpp|cc|cxx|h|hpp)$/.test(f));
@@ -45778,13 +47376,13 @@ function detectCppcheck(cwd) {
45778
47376
  }
45779
47377
  }
45780
47378
  function detectSwiftlint(cwd) {
45781
- return fs12.existsSync(path29.join(cwd, "Package.swift")) && isCommandAvailable("swiftlint");
47379
+ return fs12.existsSync(path32.join(cwd, "Package.swift")) && isCommandAvailable("swiftlint");
45782
47380
  }
45783
47381
  function detectDartAnalyze(cwd) {
45784
- return fs12.existsSync(path29.join(cwd, "pubspec.yaml")) && (isCommandAvailable("dart") || isCommandAvailable("flutter"));
47382
+ return fs12.existsSync(path32.join(cwd, "pubspec.yaml")) && (isCommandAvailable("dart") || isCommandAvailable("flutter"));
45785
47383
  }
45786
47384
  function detectRubocop(cwd) {
45787
- return (fs12.existsSync(path29.join(cwd, "Gemfile")) || fs12.existsSync(path29.join(cwd, "gems.rb")) || fs12.existsSync(path29.join(cwd, ".rubocop.yml"))) && (isCommandAvailable("rubocop") || isCommandAvailable("bundle"));
47385
+ return (fs12.existsSync(path32.join(cwd, "Gemfile")) || fs12.existsSync(path32.join(cwd, "gems.rb")) || fs12.existsSync(path32.join(cwd, ".rubocop.yml"))) && (isCommandAvailable("rubocop") || isCommandAvailable("bundle"));
45788
47386
  }
45789
47387
  function detectAdditionalLinter(cwd) {
45790
47388
  if (detectRuff(cwd))
@@ -45812,10 +47410,10 @@ function detectAdditionalLinter(cwd) {
45812
47410
  function findBinInAncestors(startDir, binName) {
45813
47411
  let dir = startDir;
45814
47412
  while (true) {
45815
- const candidate = path29.join(dir, "node_modules", ".bin", binName);
47413
+ const candidate = path32.join(dir, "node_modules", ".bin", binName);
45816
47414
  if (fs12.existsSync(candidate))
45817
47415
  return candidate;
45818
- const parent = path29.dirname(dir);
47416
+ const parent = path32.dirname(dir);
45819
47417
  if (parent === dir)
45820
47418
  break;
45821
47419
  dir = parent;
@@ -45824,10 +47422,10 @@ function findBinInAncestors(startDir, binName) {
45824
47422
  }
45825
47423
  function findBinInEnvPath(binName) {
45826
47424
  const searchPath = process.env.PATH ?? "";
45827
- for (const dir of searchPath.split(path29.delimiter)) {
47425
+ for (const dir of searchPath.split(path32.delimiter)) {
45828
47426
  if (!dir)
45829
47427
  continue;
45830
- const candidate = path29.join(dir, binName);
47428
+ const candidate = path32.join(dir, binName);
45831
47429
  if (fs12.existsSync(candidate))
45832
47430
  return candidate;
45833
47431
  }
@@ -45840,13 +47438,13 @@ async function detectAvailableLinter(directory) {
45840
47438
  return null;
45841
47439
  const projectDir = directory;
45842
47440
  const isWindows = process.platform === "win32";
45843
- const biomeBin = isWindows ? path29.join(projectDir, "node_modules", ".bin", "biome.EXE") : path29.join(projectDir, "node_modules", ".bin", "biome");
45844
- const eslintBin = isWindows ? path29.join(projectDir, "node_modules", ".bin", "eslint.cmd") : path29.join(projectDir, "node_modules", ".bin", "eslint");
47441
+ const biomeBin = isWindows ? path32.join(projectDir, "node_modules", ".bin", "biome.EXE") : path32.join(projectDir, "node_modules", ".bin", "biome");
47442
+ const eslintBin = isWindows ? path32.join(projectDir, "node_modules", ".bin", "eslint.cmd") : path32.join(projectDir, "node_modules", ".bin", "eslint");
45845
47443
  const localResult = await _detectAvailableLinter(projectDir, biomeBin, eslintBin);
45846
47444
  if (localResult)
45847
47445
  return localResult;
45848
- const biomeAncestor = findBinInAncestors(path29.dirname(projectDir), isWindows ? "biome.EXE" : "biome");
45849
- const eslintAncestor = findBinInAncestors(path29.dirname(projectDir), isWindows ? "eslint.cmd" : "eslint");
47446
+ const biomeAncestor = findBinInAncestors(path32.dirname(projectDir), isWindows ? "biome.EXE" : "biome");
47447
+ const eslintAncestor = findBinInAncestors(path32.dirname(projectDir), isWindows ? "eslint.cmd" : "eslint");
45850
47448
  if (biomeAncestor || eslintAncestor) {
45851
47449
  return _detectAvailableLinter(projectDir, biomeAncestor ?? biomeBin, eslintAncestor ?? eslintBin);
45852
47450
  }
@@ -46069,7 +47667,7 @@ For Rust: rustup component add clippy`
46069
47667
 
46070
47668
  // src/tools/secretscan.ts
46071
47669
  import * as fs13 from "fs";
46072
- import * as path30 from "path";
47670
+ import * as path33 from "path";
46073
47671
  function calculateShannonEntropy(str) {
46074
47672
  if (str.length === 0)
46075
47673
  return 0;
@@ -46117,7 +47715,7 @@ function isGlobOrPathPattern(pattern) {
46117
47715
  return pattern.includes("/") || pattern.includes("\\") || /[*?[\]{}]/.test(pattern);
46118
47716
  }
46119
47717
  function loadSecretScanIgnore(scanDir) {
46120
- const ignorePath = path30.join(scanDir, ".secretscanignore");
47718
+ const ignorePath = path33.join(scanDir, ".secretscanignore");
46121
47719
  try {
46122
47720
  if (!fs13.existsSync(ignorePath))
46123
47721
  return [];
@@ -46140,7 +47738,7 @@ function isExcluded(entry, relPath, exactNames, globPatterns) {
46140
47738
  if (exactNames.has(entry))
46141
47739
  return true;
46142
47740
  for (const pattern of globPatterns) {
46143
- if (path30.matchesGlob(relPath, pattern))
47741
+ if (path33.matchesGlob(relPath, pattern))
46144
47742
  return true;
46145
47743
  }
46146
47744
  return false;
@@ -46161,7 +47759,7 @@ function validateDirectoryInput(dir) {
46161
47759
  return null;
46162
47760
  }
46163
47761
  function isBinaryFile(filePath, buffer) {
46164
- const ext = path30.extname(filePath).toLowerCase();
47762
+ const ext = path33.extname(filePath).toLowerCase();
46165
47763
  if (DEFAULT_EXCLUDE_EXTENSIONS.has(ext)) {
46166
47764
  return true;
46167
47765
  }
@@ -46186,7 +47784,7 @@ function scanLineForSecrets(line, _lineNum) {
46186
47784
  if (line.length > MAX_LINE_LENGTH) {
46187
47785
  return results;
46188
47786
  }
46189
- for (const pattern of SECRET_PATTERNS) {
47787
+ for (const pattern of SECRET_PATTERNS2) {
46190
47788
  pattern.regex.lastIndex = 0;
46191
47789
  for (let match = pattern.regex.exec(line);match !== null; match = pattern.regex.exec(line)) {
46192
47790
  const fullMatch = match[0];
@@ -46297,9 +47895,9 @@ function isSymlinkLoop(realPath, visited) {
46297
47895
  return false;
46298
47896
  }
46299
47897
  function isPathWithinScope(realPath, scanDir) {
46300
- const resolvedScanDir = path30.resolve(scanDir);
46301
- const resolvedRealPath = path30.resolve(realPath);
46302
- return resolvedRealPath === resolvedScanDir || resolvedRealPath.startsWith(resolvedScanDir + path30.sep) || resolvedRealPath.startsWith(`${resolvedScanDir}/`) || resolvedRealPath.startsWith(`${resolvedScanDir}\\`);
47898
+ const resolvedScanDir = path33.resolve(scanDir);
47899
+ const resolvedRealPath = path33.resolve(realPath);
47900
+ return resolvedRealPath === resolvedScanDir || resolvedRealPath.startsWith(resolvedScanDir + path33.sep) || resolvedRealPath.startsWith(`${resolvedScanDir}/`) || resolvedRealPath.startsWith(`${resolvedScanDir}\\`);
46303
47901
  }
46304
47902
  function findScannableFiles(dir, excludeExact, excludeGlobs, scanDir, visited, stats = {
46305
47903
  skippedDirs: 0,
@@ -46325,8 +47923,8 @@ function findScannableFiles(dir, excludeExact, excludeGlobs, scanDir, visited, s
46325
47923
  return a.localeCompare(b);
46326
47924
  });
46327
47925
  for (const entry of entries) {
46328
- const fullPath = path30.join(dir, entry);
46329
- const relPath = path30.relative(scanDir, fullPath).replace(/\\/g, "/");
47926
+ const fullPath = path33.join(dir, entry);
47927
+ const relPath = path33.relative(scanDir, fullPath).replace(/\\/g, "/");
46330
47928
  if (isExcluded(entry, relPath, excludeExact, excludeGlobs)) {
46331
47929
  stats.skippedDirs++;
46332
47930
  continue;
@@ -46361,7 +47959,7 @@ function findScannableFiles(dir, excludeExact, excludeGlobs, scanDir, visited, s
46361
47959
  const subFiles = findScannableFiles(fullPath, excludeExact, excludeGlobs, scanDir, visited, stats);
46362
47960
  files.push(...subFiles);
46363
47961
  } else if (lstat.isFile()) {
46364
- const ext = path30.extname(fullPath).toLowerCase();
47962
+ const ext = path33.extname(fullPath).toLowerCase();
46365
47963
  if (!DEFAULT_EXCLUDE_EXTENSIONS.has(ext)) {
46366
47964
  files.push(fullPath);
46367
47965
  } else {
@@ -46388,7 +47986,7 @@ async function runSecretscan(directory) {
46388
47986
  return errorResult;
46389
47987
  }
46390
47988
  }
46391
- var MAX_FILE_PATH_LENGTH = 500, MAX_FILE_SIZE_BYTES, MAX_FILES_SCANNED = 1000, MAX_FINDINGS = 100, MAX_OUTPUT_BYTES2 = 512000, MAX_LINE_LENGTH = 1e4, MAX_CONTENT_BYTES, BINARY_SIGNATURES, BINARY_PREFIX_BYTES = 4, BINARY_NULL_CHECK_BYTES = 8192, BINARY_NULL_THRESHOLD = 0.1, DEFAULT_EXCLUDE_DIRS, DEFAULT_EXCLUDE_EXTENSIONS, SECRET_PATTERNS, O_NOFOLLOW, secretscan, _internals20;
47989
+ var MAX_FILE_PATH_LENGTH = 500, MAX_FILE_SIZE_BYTES, MAX_FILES_SCANNED = 1000, MAX_FINDINGS = 100, MAX_OUTPUT_BYTES2 = 512000, MAX_LINE_LENGTH = 1e4, MAX_CONTENT_BYTES, BINARY_SIGNATURES, BINARY_PREFIX_BYTES = 4, BINARY_NULL_CHECK_BYTES = 8192, BINARY_NULL_THRESHOLD = 0.1, DEFAULT_EXCLUDE_DIRS, DEFAULT_EXCLUDE_EXTENSIONS, SECRET_PATTERNS2, O_NOFOLLOW, secretscan, _internals20;
46392
47990
  var init_secretscan = __esm(() => {
46393
47991
  init_zod();
46394
47992
  init_path_security();
@@ -46451,7 +48049,7 @@ var init_secretscan = __esm(() => {
46451
48049
  ".log",
46452
48050
  ".md"
46453
48051
  ]);
46454
- SECRET_PATTERNS = [
48052
+ SECRET_PATTERNS2 = [
46455
48053
  {
46456
48054
  type: "aws_access_key",
46457
48055
  regex: /(?:AWS_ACCESS_KEY_ID|AWS_SECRET_ACCESS_KEY|aws_access_key_id|aws_secret_access_key)\s*[=:]\s*['"]?([A-Z0-9]{20})['"]?/gi,
@@ -46621,7 +48219,7 @@ var init_secretscan = __esm(() => {
46621
48219
  }
46622
48220
  }
46623
48221
  try {
46624
- const _scanDirRaw = path30.resolve(directory);
48222
+ const _scanDirRaw = path33.resolve(directory);
46625
48223
  const scanDir = (() => {
46626
48224
  try {
46627
48225
  return fs13.realpathSync(_scanDirRaw);
@@ -46691,8 +48289,8 @@ var init_secretscan = __esm(() => {
46691
48289
  break;
46692
48290
  const fileFindings = scanFileForSecrets(filePath);
46693
48291
  try {
46694
- const stat3 = fs13.statSync(filePath);
46695
- if (stat3.size > MAX_FILE_SIZE_BYTES) {
48292
+ const stat4 = fs13.statSync(filePath);
48293
+ if (stat4.size > MAX_FILE_SIZE_BYTES) {
46696
48294
  skippedFiles++;
46697
48295
  continue;
46698
48296
  }
@@ -46768,7 +48366,7 @@ var init_secretscan = __esm(() => {
46768
48366
 
46769
48367
  // src/lang/default-backend.ts
46770
48368
  import * as fs14 from "fs";
46771
- import * as path31 from "path";
48369
+ import * as path34 from "path";
46772
48370
  function detectFileExists(dir, pattern) {
46773
48371
  if (pattern.includes("*") || pattern.includes("?")) {
46774
48372
  try {
@@ -46780,7 +48378,7 @@ function detectFileExists(dir, pattern) {
46780
48378
  }
46781
48379
  }
46782
48380
  try {
46783
- fs14.accessSync(path31.join(dir, pattern));
48381
+ fs14.accessSync(path34.join(dir, pattern));
46784
48382
  return true;
46785
48383
  } catch {
46786
48384
  return false;
@@ -46908,8 +48506,8 @@ function defaultBuildTestCommand(profile, framework, files, dir = ".", opts = {}
46908
48506
  return ["mvn", "test"];
46909
48507
  case "gradle": {
46910
48508
  const isWindows = process.platform === "win32";
46911
- const hasGradlewBat = fs14.existsSync(path31.join(dir, "gradlew.bat"));
46912
- const hasGradlew = fs14.existsSync(path31.join(dir, "gradlew"));
48509
+ const hasGradlewBat = fs14.existsSync(path34.join(dir, "gradlew.bat"));
48510
+ const hasGradlew = fs14.existsSync(path34.join(dir, "gradlew"));
46913
48511
  if (hasGradlewBat && isWindows)
46914
48512
  return ["gradlew.bat", "test"];
46915
48513
  if (hasGradlew)
@@ -46926,7 +48524,7 @@ function defaultBuildTestCommand(profile, framework, files, dir = ".", opts = {}
46926
48524
  "cmake-build-release",
46927
48525
  "out"
46928
48526
  ];
46929
- const actualBuildDir = buildDirCandidates.find((d) => fs14.existsSync(path31.join(dir, d, "CMakeCache.txt"))) ?? "build";
48527
+ const actualBuildDir = buildDirCandidates.find((d) => fs14.existsSync(path34.join(dir, d, "CMakeCache.txt"))) ?? "build";
46930
48528
  return ["ctest", "--test-dir", actualBuildDir];
46931
48529
  }
46932
48530
  case "swift-test":
@@ -47213,17 +48811,17 @@ async function defaultSelectBuildCommand(profile, dir) {
47213
48811
  return null;
47214
48812
  }
47215
48813
  async function defaultTestFilesFor(profile, sourceFile, dir) {
47216
- const ext = path31.extname(sourceFile);
48814
+ const ext = path34.extname(sourceFile);
47217
48815
  if (!profile.extensions.includes(ext))
47218
48816
  return [];
47219
- const base = path31.basename(sourceFile, ext);
47220
- const rel = path31.relative(dir, sourceFile);
47221
- const relDir = path31.dirname(rel);
48817
+ const base = path34.basename(sourceFile, ext);
48818
+ const rel = path34.relative(dir, sourceFile);
48819
+ const relDir = path34.dirname(rel);
47222
48820
  const stripSrc = relDir.replace(/^src(\/|\\)/, "");
47223
48821
  const candidates = new Set;
47224
48822
  for (const tDir of ["tests", "test", "__tests__", "spec"]) {
47225
48823
  for (const suffix of ["", "_test", ".test", "_spec", ".spec"]) {
47226
- candidates.add(path31.join(dir, tDir, stripSrc, `${base}${suffix}${ext}`));
48824
+ candidates.add(path34.join(dir, tDir, stripSrc, `${base}${suffix}${ext}`));
47227
48825
  }
47228
48826
  }
47229
48827
  const existing = [];
@@ -47264,7 +48862,7 @@ var init_default_backend = __esm(() => {
47264
48862
 
47265
48863
  // src/lang/backends/go.ts
47266
48864
  import * as fs15 from "fs";
47267
- import * as path32 from "path";
48865
+ import * as path35 from "path";
47268
48866
  function extractImports(_sourceFile, source) {
47269
48867
  const out = new Set;
47270
48868
  IMPORT_REGEX_SINGLE.lastIndex = 0;
@@ -47290,7 +48888,7 @@ function extractImports(_sourceFile, source) {
47290
48888
  async function selectFramework(dir) {
47291
48889
  let content;
47292
48890
  try {
47293
- content = fs15.readFileSync(path32.join(dir, "go.mod"), "utf-8");
48891
+ content = fs15.readFileSync(path35.join(dir, "go.mod"), "utf-8");
47294
48892
  } catch {
47295
48893
  return null;
47296
48894
  }
@@ -47311,16 +48909,16 @@ async function selectFramework(dir) {
47311
48909
  async function selectEntryPoints(dir) {
47312
48910
  const points = [];
47313
48911
  try {
47314
- fs15.accessSync(path32.join(dir, "main.go"));
48912
+ fs15.accessSync(path35.join(dir, "main.go"));
47315
48913
  points.push("main.go");
47316
48914
  } catch {}
47317
48915
  try {
47318
- const cmdDir = path32.join(dir, "cmd");
48916
+ const cmdDir = path35.join(dir, "cmd");
47319
48917
  const subdirs = fs15.readdirSync(cmdDir, { withFileTypes: true }).filter((d) => d.isDirectory());
47320
48918
  for (const sub of subdirs) {
47321
- const main = path32.join("cmd", sub.name, "main.go");
48919
+ const main = path35.join("cmd", sub.name, "main.go");
47322
48920
  try {
47323
- fs15.accessSync(path32.join(dir, main));
48921
+ fs15.accessSync(path35.join(dir, main));
47324
48922
  points.push(main);
47325
48923
  } catch {}
47326
48924
  }
@@ -47351,7 +48949,7 @@ var init_go = __esm(() => {
47351
48949
 
47352
48950
  // src/lang/backends/python.ts
47353
48951
  import * as fs16 from "fs";
47354
- import * as path33 from "path";
48952
+ import * as path36 from "path";
47355
48953
  function parseImportTargets(rawTargets) {
47356
48954
  const cleaned = rawTargets.replace(/[()]/g, "").split(`
47357
48955
  `).map((line) => line.replace(/#.*$/, "").replace(/\\\s*$/, "")).join(" ");
@@ -47411,7 +49009,7 @@ async function selectFramework2(dir) {
47411
49009
  ];
47412
49010
  for (const candidate of ["pyproject.toml", "requirements.txt", "setup.py"]) {
47413
49011
  try {
47414
- const content = fs16.readFileSync(path33.join(dir, candidate), "utf-8");
49012
+ const content = fs16.readFileSync(path36.join(dir, candidate), "utf-8");
47415
49013
  const lower = content.toLowerCase();
47416
49014
  for (const [pkg, name] of candidates) {
47417
49015
  if (lower.includes(pkg)) {
@@ -47425,7 +49023,7 @@ async function selectFramework2(dir) {
47425
49023
  async function selectEntryPoints2(dir) {
47426
49024
  const points = new Set;
47427
49025
  try {
47428
- const content = fs16.readFileSync(path33.join(dir, "pyproject.toml"), "utf-8");
49026
+ const content = fs16.readFileSync(path36.join(dir, "pyproject.toml"), "utf-8");
47429
49027
  const scriptsBlock = content.match(/\[project\.scripts\][\s\S]*?(?=\n\[|$)/);
47430
49028
  if (scriptsBlock) {
47431
49029
  for (const line of scriptsBlock[0].split(`
@@ -47440,7 +49038,7 @@ async function selectEntryPoints2(dir) {
47440
49038
  } catch {}
47441
49039
  for (const name of ["manage.py", "main.py", "app.py", "__main__.py"]) {
47442
49040
  try {
47443
- fs16.accessSync(path33.join(dir, name));
49041
+ fs16.accessSync(path36.join(dir, name));
47444
49042
  points.add(name);
47445
49043
  } catch {}
47446
49044
  }
@@ -47469,15 +49067,15 @@ var init_python = __esm(() => {
47469
49067
 
47470
49068
  // src/test-impact/analyzer.ts
47471
49069
  import fs17 from "fs";
47472
- import path34 from "path";
49070
+ import path37 from "path";
47473
49071
  function normalizePath(p) {
47474
49072
  return p.replace(/\\/g, "/");
47475
49073
  }
47476
49074
  function isCacheStale(impactMap, generatedAtMs) {
47477
49075
  for (const sourcePath of Object.keys(impactMap)) {
47478
49076
  try {
47479
- const stat3 = fs17.statSync(sourcePath);
47480
- if (stat3.mtimeMs > generatedAtMs) {
49077
+ const stat4 = fs17.statSync(sourcePath);
49078
+ if (stat4.mtimeMs > generatedAtMs) {
47481
49079
  return true;
47482
49080
  }
47483
49081
  } catch {
@@ -47490,8 +49088,8 @@ function resolveRelativeImport(fromDir, importPath) {
47490
49088
  if (!importPath.startsWith(".")) {
47491
49089
  return null;
47492
49090
  }
47493
- const resolved = path34.resolve(fromDir, importPath);
47494
- if (path34.extname(resolved)) {
49091
+ const resolved = path37.resolve(fromDir, importPath);
49092
+ if (path37.extname(resolved)) {
47495
49093
  if (fs17.existsSync(resolved) && fs17.statSync(resolved).isFile()) {
47496
49094
  return normalizePath(resolved);
47497
49095
  }
@@ -47511,20 +49109,20 @@ function resolvePythonImport(fromDir, module) {
47511
49109
  const leadingDots = module.match(/^\.+/)?.[0].length ?? 0;
47512
49110
  let baseDir = fromDir;
47513
49111
  for (let i = 1;i < leadingDots; i++) {
47514
- baseDir = path34.dirname(baseDir);
49112
+ baseDir = path37.dirname(baseDir);
47515
49113
  }
47516
49114
  const rest = module.slice(leadingDots);
47517
49115
  if (rest.length === 0) {
47518
- const initPath = path34.join(baseDir, "__init__.py");
49116
+ const initPath = path37.join(baseDir, "__init__.py");
47519
49117
  if (fs17.existsSync(initPath) && fs17.statSync(initPath).isFile()) {
47520
49118
  return normalizePath(initPath);
47521
49119
  }
47522
49120
  return null;
47523
49121
  }
47524
- const subpath = rest.replace(/\./g, path34.sep);
49122
+ const subpath = rest.replace(/\./g, path37.sep);
47525
49123
  const candidates = [
47526
- `${path34.join(baseDir, subpath)}.py`,
47527
- path34.join(baseDir, subpath, "__init__.py")
49124
+ `${path37.join(baseDir, subpath)}.py`,
49125
+ path37.join(baseDir, subpath, "__init__.py")
47528
49126
  ];
47529
49127
  for (const c of candidates) {
47530
49128
  if (fs17.existsSync(c) && fs17.statSync(c).isFile())
@@ -47533,7 +49131,7 @@ function resolvePythonImport(fromDir, module) {
47533
49131
  return null;
47534
49132
  }
47535
49133
  function findGoModule(fromDir) {
47536
- const resolved = path34.resolve(fromDir);
49134
+ const resolved = path37.resolve(fromDir);
47537
49135
  let cur = resolved;
47538
49136
  const walked = [];
47539
49137
  for (let i = 0;i < 16; i++) {
@@ -47545,7 +49143,7 @@ function findGoModule(fromDir) {
47545
49143
  }
47546
49144
  walked.push(cur);
47547
49145
  try {
47548
- const goMod = path34.join(cur, "go.mod");
49146
+ const goMod = path37.join(cur, "go.mod");
47549
49147
  const content = fs17.readFileSync(goMod, "utf-8");
47550
49148
  const moduleMatch = content.match(/^\s*module\s+"?([^"\s/]+(?:\/[^"\s]+)*)"?/m);
47551
49149
  if (moduleMatch) {
@@ -47556,10 +49154,10 @@ function findGoModule(fromDir) {
47556
49154
  }
47557
49155
  } catch {}
47558
49156
  try {
47559
- fs17.accessSync(path34.join(cur, ".git"));
49157
+ fs17.accessSync(path37.join(cur, ".git"));
47560
49158
  break;
47561
49159
  } catch {}
47562
- const parent = path34.dirname(cur);
49160
+ const parent = path37.dirname(cur);
47563
49161
  if (parent === cur)
47564
49162
  break;
47565
49163
  cur = parent;
@@ -47571,12 +49169,12 @@ function findGoModule(fromDir) {
47571
49169
  function resolveGoImport(fromDir, importPath) {
47572
49170
  let dir = null;
47573
49171
  if (importPath.startsWith(".")) {
47574
- dir = path34.resolve(fromDir, importPath);
49172
+ dir = path37.resolve(fromDir, importPath);
47575
49173
  } else {
47576
49174
  const mod = findGoModule(fromDir);
47577
49175
  if (mod && (importPath === mod.modulePath || importPath.startsWith(`${mod.modulePath}/`))) {
47578
49176
  const subpath = importPath.slice(mod.modulePath.length);
47579
- dir = path34.join(mod.moduleRoot, subpath);
49177
+ dir = path37.join(mod.moduleRoot, subpath);
47580
49178
  }
47581
49179
  }
47582
49180
  if (dir === null)
@@ -47584,7 +49182,7 @@ function resolveGoImport(fromDir, importPath) {
47584
49182
  if (!fs17.existsSync(dir) || !fs17.statSync(dir).isDirectory())
47585
49183
  return [];
47586
49184
  try {
47587
- return fs17.readdirSync(dir).filter((f) => f.endsWith(".go") && !f.endsWith("_test.go")).map((f) => normalizePath(path34.join(dir, f)));
49185
+ return fs17.readdirSync(dir).filter((f) => f.endsWith(".go") && !f.endsWith("_test.go")).map((f) => normalizePath(path37.join(dir, f)));
47588
49186
  } catch {
47589
49187
  return [];
47590
49188
  }
@@ -47623,15 +49221,15 @@ function findTestFilesSync(cwd) {
47623
49221
  for (const entry of entries) {
47624
49222
  if (entry.isDirectory()) {
47625
49223
  if (!skipDirs.has(entry.name)) {
47626
- walk(path34.join(dir, entry.name), visitedInodes);
49224
+ walk(path37.join(dir, entry.name), visitedInodes);
47627
49225
  }
47628
49226
  } else if (entry.isFile()) {
47629
49227
  const name = entry.name;
47630
49228
  const isTsTest = /\.(test|spec)\.(ts|tsx|js|jsx)$/.test(name) || dir.includes("__tests__") && /\.(ts|tsx|js|jsx)$/.test(name);
47631
- const isPyTest = /^test_.+\.py$/.test(name) || /.+_test\.py$/.test(name) || dir.includes(`${path34.sep}tests${path34.sep}`) && name.endsWith(".py");
49229
+ const isPyTest = /^test_.+\.py$/.test(name) || /.+_test\.py$/.test(name) || dir.includes(`${path37.sep}tests${path37.sep}`) && name.endsWith(".py");
47632
49230
  const isGoTest = /.+_test\.go$/.test(name);
47633
49231
  if (isTsTest || isPyTest || isGoTest) {
47634
- testFiles.push(normalizePath(path34.join(dir, entry.name)));
49232
+ testFiles.push(normalizePath(path37.join(dir, entry.name)));
47635
49233
  }
47636
49234
  }
47637
49235
  }
@@ -47656,8 +49254,8 @@ function extractImports3(content) {
47656
49254
  ];
47657
49255
  }
47658
49256
  function addImpactEdgesForTestFile(testFile, content, impactMap) {
47659
- const ext = path34.extname(testFile).toLowerCase();
47660
- const testDir = path34.dirname(testFile);
49257
+ const ext = path37.extname(testFile).toLowerCase();
49258
+ const testDir = path37.dirname(testFile);
47661
49259
  function addEdge(source) {
47662
49260
  if (!impactMap[source])
47663
49261
  impactMap[source] = [];
@@ -47716,7 +49314,7 @@ async function buildImpactMap(cwd) {
47716
49314
  return impactMap;
47717
49315
  }
47718
49316
  async function loadImpactMap(cwd, options) {
47719
- const cachePath = path34.join(cwd, ".swarm", "cache", "impact-map.json");
49317
+ const cachePath = path37.join(cwd, ".swarm", "cache", "impact-map.json");
47720
49318
  if (fs17.existsSync(cachePath)) {
47721
49319
  try {
47722
49320
  const content = fs17.readFileSync(cachePath, "utf-8");
@@ -47749,12 +49347,12 @@ async function loadImpactMap(cwd, options) {
47749
49347
  return _internals23.buildImpactMap(cwd);
47750
49348
  }
47751
49349
  async function saveImpactMap(cwd, impactMap) {
47752
- if (!path34.isAbsolute(cwd)) {
49350
+ if (!path37.isAbsolute(cwd)) {
47753
49351
  throw new Error(`saveImpactMap requires an absolute project root path, got: "${cwd}"`);
47754
49352
  }
47755
49353
  _internals23.validateProjectRoot(cwd);
47756
- const cacheDir2 = path34.join(cwd, ".swarm", "cache");
47757
- const cachePath = path34.join(cacheDir2, "impact-map.json");
49354
+ const cacheDir2 = path37.join(cwd, ".swarm", "cache");
49355
+ const cachePath = path37.join(cacheDir2, "impact-map.json");
47758
49356
  if (!fs17.existsSync(cacheDir2)) {
47759
49357
  fs17.mkdirSync(cacheDir2, { recursive: true });
47760
49358
  }
@@ -47786,7 +49384,7 @@ async function analyzeImpact(changedFiles, cwd, budget) {
47786
49384
  budgetExceeded = true;
47787
49385
  break;
47788
49386
  }
47789
- const normalizedChanged = normalizePath(path34.resolve(changedFile));
49387
+ const normalizedChanged = normalizePath(path37.resolve(changedFile));
47790
49388
  const tests = impactMap[normalizedChanged];
47791
49389
  if (tests && tests.length > 0) {
47792
49390
  for (const test of tests) {
@@ -48079,15 +49677,15 @@ var FLAKY_THRESHOLD = 0.3, MIN_RUNS_FOR_QUARANTINE = 5, MAX_HISTORY_RUNS = 20;
48079
49677
 
48080
49678
  // src/test-impact/history-store.ts
48081
49679
  import fs18 from "fs";
48082
- import path35 from "path";
49680
+ import path38 from "path";
48083
49681
  function getHistoryPath(workingDir) {
48084
49682
  if (!workingDir) {
48085
49683
  throw new Error("getHistoryPath requires a working directory \u2014 project root must be provided by the caller");
48086
49684
  }
48087
- if (!path35.isAbsolute(workingDir)) {
49685
+ if (!path38.isAbsolute(workingDir)) {
48088
49686
  throw new Error(`getHistoryPath requires an absolute project root path, got: "${workingDir}"`);
48089
49687
  }
48090
- return path35.join(workingDir, ".swarm", "cache", "test-history.jsonl");
49688
+ return path38.join(workingDir, ".swarm", "cache", "test-history.jsonl");
48091
49689
  }
48092
49690
  function sanitizeErrorMessage(errorMessage) {
48093
49691
  if (errorMessage === undefined) {
@@ -48174,7 +49772,7 @@ function batchAppendTestRuns(records, workingDir) {
48174
49772
  }
48175
49773
  }
48176
49774
  const historyPath = getHistoryPath(workingDir);
48177
- const historyDir = path35.dirname(historyPath);
49775
+ const historyDir = path38.dirname(historyPath);
48178
49776
  _internals24.validateProjectRoot(workingDir);
48179
49777
  if (!fs18.existsSync(historyDir)) {
48180
49778
  fs18.mkdirSync(historyDir, { recursive: true });
@@ -48270,7 +49868,7 @@ var init_history_store = __esm(() => {
48270
49868
 
48271
49869
  // src/tools/resolve-working-directory.ts
48272
49870
  import * as fs19 from "fs";
48273
- import * as path36 from "path";
49871
+ import * as path39 from "path";
48274
49872
  function resolveWorkingDirectory(workingDirectory, fallbackDirectory) {
48275
49873
  if (workingDirectory == null || workingDirectory === "") {
48276
49874
  return { success: true, directory: fallbackDirectory };
@@ -48290,15 +49888,15 @@ function resolveWorkingDirectory(workingDirectory, fallbackDirectory) {
48290
49888
  };
48291
49889
  }
48292
49890
  }
48293
- const normalizedDir = path36.normalize(workingDirectory);
48294
- const pathParts = normalizedDir.split(path36.sep);
49891
+ const normalizedDir = path39.normalize(workingDirectory);
49892
+ const pathParts = normalizedDir.split(path39.sep);
48295
49893
  if (pathParts.includes("..")) {
48296
49894
  return {
48297
49895
  success: false,
48298
49896
  message: "Invalid working_directory: path traversal sequences (..) are not allowed"
48299
49897
  };
48300
49898
  }
48301
- const resolvedDir = path36.resolve(normalizedDir);
49899
+ const resolvedDir = path39.resolve(normalizedDir);
48302
49900
  let statResult;
48303
49901
  try {
48304
49902
  statResult = fs19.statSync(resolvedDir);
@@ -48314,7 +49912,7 @@ function resolveWorkingDirectory(workingDirectory, fallbackDirectory) {
48314
49912
  message: `Invalid working_directory: path "${resolvedDir}" is not a directory`
48315
49913
  };
48316
49914
  }
48317
- const resolvedFallback = path36.resolve(fallbackDirectory);
49915
+ const resolvedFallback = path39.resolve(fallbackDirectory);
48318
49916
  let fallbackExists = false;
48319
49917
  try {
48320
49918
  fs19.statSync(resolvedFallback);
@@ -48324,7 +49922,7 @@ function resolveWorkingDirectory(workingDirectory, fallbackDirectory) {
48324
49922
  }
48325
49923
  if (workingDirectory != null && workingDirectory !== "") {
48326
49924
  if (fallbackExists) {
48327
- const isSubdirectory = resolvedDir.startsWith(resolvedFallback + path36.sep);
49925
+ const isSubdirectory = resolvedDir.startsWith(resolvedFallback + path39.sep);
48328
49926
  if (isSubdirectory) {
48329
49927
  return {
48330
49928
  success: false,
@@ -48379,10 +49977,10 @@ var init_registry_backend = __esm(() => {
48379
49977
 
48380
49978
  // src/lang/backends/typescript.ts
48381
49979
  import * as fs20 from "fs";
48382
- import * as path37 from "path";
49980
+ import * as path40 from "path";
48383
49981
  function readPackageJsonRaw(dir) {
48384
49982
  try {
48385
- const content = fs20.readFileSync(path37.join(dir, "package.json"), "utf-8");
49983
+ const content = fs20.readFileSync(path40.join(dir, "package.json"), "utf-8");
48386
49984
  return JSON.parse(content);
48387
49985
  } catch {
48388
49986
  return null;
@@ -48602,7 +50200,7 @@ __export(exports_dispatch, {
48602
50200
  _internals: () => _internals26
48603
50201
  });
48604
50202
  import * as fs21 from "fs";
48605
- import * as path38 from "path";
50203
+ import * as path41 from "path";
48606
50204
  function safeReaddirSet(dir) {
48607
50205
  try {
48608
50206
  return new Set(fs21.readdirSync(dir));
@@ -48619,14 +50217,14 @@ function manifestHash(dir) {
48619
50217
  if (!entries.has(name))
48620
50218
  continue;
48621
50219
  try {
48622
- const stat3 = fs21.statSync(path38.join(dir, name));
48623
- parts.push(`${name}:${stat3.size}:${stat3.mtimeMs}:${stat3.ino}`);
50220
+ const stat4 = fs21.statSync(path41.join(dir, name));
50221
+ parts.push(`${name}:${stat4.size}:${stat4.mtimeMs}:${stat4.ino}`);
48624
50222
  } catch {}
48625
50223
  }
48626
50224
  return parts.join("|");
48627
50225
  }
48628
50226
  function findManifestRoot(start) {
48629
- const resolved = path38.resolve(start);
50227
+ const resolved = path41.resolve(start);
48630
50228
  const cached3 = manifestRootCache.get(resolved);
48631
50229
  if (cached3 !== undefined)
48632
50230
  return cached3;
@@ -48645,7 +50243,7 @@ function findManifestRoot(start) {
48645
50243
  return cur;
48646
50244
  }
48647
50245
  }
48648
- const parent = path38.dirname(cur);
50246
+ const parent = path41.dirname(cur);
48649
50247
  if (parent === cur)
48650
50248
  break;
48651
50249
  cur = parent;
@@ -48755,13 +50353,13 @@ var init_dispatch = __esm(() => {
48755
50353
 
48756
50354
  // src/tools/test-runner.ts
48757
50355
  import * as fs22 from "fs";
48758
- import * as path39 from "path";
50356
+ import * as path42 from "path";
48759
50357
  async function estimateFanOut(sourceFiles, cwd) {
48760
50358
  try {
48761
50359
  const impactMap = await loadImpactMap(cwd, { skipRebuild: true });
48762
50360
  const uniqueTestFiles = new Set;
48763
50361
  for (const sourceFile of sourceFiles) {
48764
- const resolvedPath = path39.resolve(cwd, sourceFile);
50362
+ const resolvedPath = path42.resolve(cwd, sourceFile);
48765
50363
  const normalizedPath = resolvedPath.replace(/\\/g, "/");
48766
50364
  const testFiles = impactMap[normalizedPath];
48767
50365
  if (testFiles) {
@@ -48839,14 +50437,14 @@ function hasDevDependency(devDeps, ...patterns) {
48839
50437
  return hasPackageJsonDependency(devDeps, ...patterns);
48840
50438
  }
48841
50439
  function detectGoTest(cwd) {
48842
- return fs22.existsSync(path39.join(cwd, "go.mod")) && isCommandAvailable("go");
50440
+ return fs22.existsSync(path42.join(cwd, "go.mod")) && isCommandAvailable("go");
48843
50441
  }
48844
50442
  function detectJavaMaven(cwd) {
48845
- return fs22.existsSync(path39.join(cwd, "pom.xml")) && isCommandAvailable("mvn");
50443
+ return fs22.existsSync(path42.join(cwd, "pom.xml")) && isCommandAvailable("mvn");
48846
50444
  }
48847
50445
  function detectGradle(cwd) {
48848
- const hasBuildFile = fs22.existsSync(path39.join(cwd, "build.gradle")) || fs22.existsSync(path39.join(cwd, "build.gradle.kts"));
48849
- const hasGradlew = fs22.existsSync(path39.join(cwd, "gradlew")) || fs22.existsSync(path39.join(cwd, "gradlew.bat"));
50446
+ const hasBuildFile = fs22.existsSync(path42.join(cwd, "build.gradle")) || fs22.existsSync(path42.join(cwd, "build.gradle.kts"));
50447
+ const hasGradlew = fs22.existsSync(path42.join(cwd, "gradlew")) || fs22.existsSync(path42.join(cwd, "gradlew.bat"));
48850
50448
  return hasBuildFile && (hasGradlew || isCommandAvailable("gradle"));
48851
50449
  }
48852
50450
  function detectDotnetTest(cwd) {
@@ -48859,25 +50457,25 @@ function detectDotnetTest(cwd) {
48859
50457
  }
48860
50458
  }
48861
50459
  function detectCTest(cwd) {
48862
- const hasSource = fs22.existsSync(path39.join(cwd, "CMakeLists.txt"));
48863
- const hasBuildCache = fs22.existsSync(path39.join(cwd, "CMakeCache.txt")) || fs22.existsSync(path39.join(cwd, "build", "CMakeCache.txt"));
50460
+ const hasSource = fs22.existsSync(path42.join(cwd, "CMakeLists.txt"));
50461
+ const hasBuildCache = fs22.existsSync(path42.join(cwd, "CMakeCache.txt")) || fs22.existsSync(path42.join(cwd, "build", "CMakeCache.txt"));
48864
50462
  return (hasSource || hasBuildCache) && isCommandAvailable("ctest");
48865
50463
  }
48866
50464
  function detectSwiftTest(cwd) {
48867
- return fs22.existsSync(path39.join(cwd, "Package.swift")) && isCommandAvailable("swift");
50465
+ return fs22.existsSync(path42.join(cwd, "Package.swift")) && isCommandAvailable("swift");
48868
50466
  }
48869
50467
  function detectDartTest(cwd) {
48870
- return fs22.existsSync(path39.join(cwd, "pubspec.yaml")) && (isCommandAvailable("dart") || isCommandAvailable("flutter"));
50468
+ return fs22.existsSync(path42.join(cwd, "pubspec.yaml")) && (isCommandAvailable("dart") || isCommandAvailable("flutter"));
48871
50469
  }
48872
50470
  function detectRSpec(cwd) {
48873
- const hasRSpecFile = fs22.existsSync(path39.join(cwd, ".rspec"));
48874
- const hasGemfile = fs22.existsSync(path39.join(cwd, "Gemfile"));
48875
- const hasSpecDir = fs22.existsSync(path39.join(cwd, "spec"));
50471
+ const hasRSpecFile = fs22.existsSync(path42.join(cwd, ".rspec"));
50472
+ const hasGemfile = fs22.existsSync(path42.join(cwd, "Gemfile"));
50473
+ const hasSpecDir = fs22.existsSync(path42.join(cwd, "spec"));
48876
50474
  const hasRSpec = hasRSpecFile || hasGemfile && hasSpecDir;
48877
50475
  return hasRSpec && (isCommandAvailable("bundle") || isCommandAvailable("rspec"));
48878
50476
  }
48879
50477
  function detectMinitest(cwd) {
48880
- return fs22.existsSync(path39.join(cwd, "test")) && (fs22.existsSync(path39.join(cwd, "Gemfile")) || fs22.existsSync(path39.join(cwd, "Rakefile"))) && isCommandAvailable("ruby");
50478
+ return fs22.existsSync(path42.join(cwd, "test")) && (fs22.existsSync(path42.join(cwd, "Gemfile")) || fs22.existsSync(path42.join(cwd, "Rakefile"))) && isCommandAvailable("ruby");
48881
50479
  }
48882
50480
  async function detectTestFrameworkViaDispatch(cwd) {
48883
50481
  try {
@@ -48939,7 +50537,7 @@ async function parseTestOutputViaDispatch(framework, output, baseDir) {
48939
50537
  async function detectTestFramework(cwd) {
48940
50538
  const baseDir = cwd;
48941
50539
  try {
48942
- const packageJsonPath = path39.join(baseDir, "package.json");
50540
+ const packageJsonPath = path42.join(baseDir, "package.json");
48943
50541
  if (fs22.existsSync(packageJsonPath)) {
48944
50542
  const content = fs22.readFileSync(packageJsonPath, "utf-8");
48945
50543
  const pkg = JSON.parse(content);
@@ -48960,16 +50558,16 @@ async function detectTestFramework(cwd) {
48960
50558
  return "jest";
48961
50559
  if (hasDevDependency(devDeps, "mocha", "@types/mocha"))
48962
50560
  return "mocha";
48963
- if (fs22.existsSync(path39.join(baseDir, "bun.lockb")) || fs22.existsSync(path39.join(baseDir, "bun.lock"))) {
50561
+ if (fs22.existsSync(path42.join(baseDir, "bun.lockb")) || fs22.existsSync(path42.join(baseDir, "bun.lock"))) {
48964
50562
  if (scripts.test?.includes("bun"))
48965
50563
  return "bun";
48966
50564
  }
48967
50565
  }
48968
50566
  } catch {}
48969
50567
  try {
48970
- const pyprojectTomlPath = path39.join(baseDir, "pyproject.toml");
48971
- const setupCfgPath = path39.join(baseDir, "setup.cfg");
48972
- const requirementsTxtPath = path39.join(baseDir, "requirements.txt");
50568
+ const pyprojectTomlPath = path42.join(baseDir, "pyproject.toml");
50569
+ const setupCfgPath = path42.join(baseDir, "setup.cfg");
50570
+ const requirementsTxtPath = path42.join(baseDir, "requirements.txt");
48973
50571
  if (fs22.existsSync(pyprojectTomlPath)) {
48974
50572
  const content = fs22.readFileSync(pyprojectTomlPath, "utf-8");
48975
50573
  if (content.includes("[tool.pytest"))
@@ -48989,7 +50587,7 @@ async function detectTestFramework(cwd) {
48989
50587
  }
48990
50588
  } catch {}
48991
50589
  try {
48992
- const cargoTomlPath = path39.join(baseDir, "Cargo.toml");
50590
+ const cargoTomlPath = path42.join(baseDir, "Cargo.toml");
48993
50591
  if (fs22.existsSync(cargoTomlPath)) {
48994
50592
  const content = fs22.readFileSync(cargoTomlPath, "utf-8");
48995
50593
  if (content.includes("[dev-dependencies]")) {
@@ -49000,9 +50598,9 @@ async function detectTestFramework(cwd) {
49000
50598
  }
49001
50599
  } catch {}
49002
50600
  try {
49003
- const pesterConfigPath = path39.join(baseDir, "pester.config.ps1");
49004
- const pesterConfigJsonPath = path39.join(baseDir, "pester.config.ps1.json");
49005
- const pesterPs1Path = path39.join(baseDir, "tests.ps1");
50601
+ const pesterConfigPath = path42.join(baseDir, "pester.config.ps1");
50602
+ const pesterConfigJsonPath = path42.join(baseDir, "pester.config.ps1.json");
50603
+ const pesterPs1Path = path42.join(baseDir, "tests.ps1");
49006
50604
  if (fs22.existsSync(pesterConfigPath) || fs22.existsSync(pesterConfigJsonPath) || fs22.existsSync(pesterPs1Path)) {
49007
50605
  return "pester";
49008
50606
  }
@@ -49031,12 +50629,12 @@ function isTestDirectoryPath(normalizedPath) {
49031
50629
  return normalizedPath.split("/").some((segment) => TEST_DIRECTORY_NAMES.includes(segment));
49032
50630
  }
49033
50631
  function resolveWorkspacePath(file3, workingDir) {
49034
- return path39.isAbsolute(file3) ? path39.resolve(file3) : path39.resolve(workingDir, file3);
50632
+ return path42.isAbsolute(file3) ? path42.resolve(file3) : path42.resolve(workingDir, file3);
49035
50633
  }
49036
50634
  function toWorkspaceOutputPath(absolutePath, workingDir, preferRelative) {
49037
50635
  if (!preferRelative)
49038
50636
  return absolutePath;
49039
- return path39.relative(workingDir, absolutePath);
50637
+ return path42.relative(workingDir, absolutePath);
49040
50638
  }
49041
50639
  function dedupePush(target, value) {
49042
50640
  if (!target.includes(value)) {
@@ -49073,18 +50671,18 @@ function buildLanguageSpecificTestNames(nameWithoutExt, ext) {
49073
50671
  }
49074
50672
  }
49075
50673
  function getRepoLevelCandidateDirectories(workingDir, relativePath, ext) {
49076
- const relativeDir = path39.dirname(relativePath);
50674
+ const relativeDir = path42.dirname(relativePath);
49077
50675
  const nestedRelativeDir = relativeDir === "." ? "" : relativeDir;
49078
50676
  const directories = TEST_DIRECTORY_NAMES.flatMap((dirName) => {
49079
- const rootDir = path39.join(workingDir, dirName);
49080
- return nestedRelativeDir ? [rootDir, path39.join(rootDir, nestedRelativeDir)] : [rootDir];
50677
+ const rootDir = path42.join(workingDir, dirName);
50678
+ return nestedRelativeDir ? [rootDir, path42.join(rootDir, nestedRelativeDir)] : [rootDir];
49081
50679
  });
49082
50680
  const normalizedRelativePath = relativePath.replace(/\\/g, "/");
49083
50681
  if (ext === ".java" && normalizedRelativePath.startsWith("src/main/java/")) {
49084
- directories.push(path39.join(workingDir, "src/test/java", path39.dirname(normalizedRelativePath.slice("src/main/java/".length))));
50682
+ directories.push(path42.join(workingDir, "src/test/java", path42.dirname(normalizedRelativePath.slice("src/main/java/".length))));
49085
50683
  }
49086
50684
  if ((ext === ".kt" || ext === ".java") && normalizedRelativePath.startsWith("src/main/kotlin/")) {
49087
- directories.push(path39.join(workingDir, "src/test/kotlin", path39.dirname(normalizedRelativePath.slice("src/main/kotlin/".length))));
50685
+ directories.push(path42.join(workingDir, "src/test/kotlin", path42.dirname(normalizedRelativePath.slice("src/main/kotlin/".length))));
49088
50686
  }
49089
50687
  return [...new Set(directories)];
49090
50688
  }
@@ -49112,23 +50710,23 @@ function isLanguageSpecificTestFile(basename6) {
49112
50710
  }
49113
50711
  function isConventionTestFilePath(filePath) {
49114
50712
  const normalizedPath = filePath.replace(/\\/g, "/");
49115
- const basename6 = path39.basename(filePath);
50713
+ const basename6 = path42.basename(filePath);
49116
50714
  return hasCompoundTestExtension(basename6) || basename6.includes(".spec.") || basename6.includes(".test.") || isLanguageSpecificTestFile(basename6) || isTestDirectoryPath(normalizedPath);
49117
50715
  }
49118
50716
  function getTestFilesFromConvention(sourceFiles, workingDir = process.cwd()) {
49119
50717
  const testFiles = [];
49120
50718
  for (const file3 of sourceFiles) {
49121
50719
  const absoluteFile = resolveWorkspacePath(file3, workingDir);
49122
- const relativeFile = path39.relative(workingDir, absoluteFile);
49123
- const basename6 = path39.basename(absoluteFile);
49124
- const dirname17 = path39.dirname(absoluteFile);
49125
- const preferRelativeOutput = !path39.isAbsolute(file3);
50720
+ const relativeFile = path42.relative(workingDir, absoluteFile);
50721
+ const basename6 = path42.basename(absoluteFile);
50722
+ const dirname20 = path42.dirname(absoluteFile);
50723
+ const preferRelativeOutput = !path42.isAbsolute(file3);
49126
50724
  if (isConventionTestFilePath(relativeFile) || isConventionTestFilePath(file3)) {
49127
50725
  dedupePush(testFiles, toWorkspaceOutputPath(absoluteFile, workingDir, preferRelativeOutput));
49128
50726
  continue;
49129
50727
  }
49130
50728
  const nameWithoutExt = basename6.replace(/\.[^.]+$/, "");
49131
- const ext = path39.extname(basename6);
50729
+ const ext = path42.extname(basename6);
49132
50730
  const genericTestNames = [
49133
50731
  `${nameWithoutExt}.spec${ext}`,
49134
50732
  `${nameWithoutExt}.test${ext}`
@@ -49137,7 +50735,7 @@ function getTestFilesFromConvention(sourceFiles, workingDir = process.cwd()) {
49137
50735
  const colocatedCandidates = [
49138
50736
  ...genericTestNames,
49139
50737
  ...languageSpecificTestNames
49140
- ].map((candidateName) => path39.join(dirname17, candidateName));
50738
+ ].map((candidateName) => path42.join(dirname20, candidateName));
49141
50739
  const testDirectoryNames = [
49142
50740
  basename6,
49143
50741
  ...genericTestNames,
@@ -49146,8 +50744,8 @@ function getTestFilesFromConvention(sourceFiles, workingDir = process.cwd()) {
49146
50744
  const repoLevelDirectories = getRepoLevelCandidateDirectories(workingDir, relativeFile, ext);
49147
50745
  const possibleTestFiles = [
49148
50746
  ...colocatedCandidates,
49149
- ...TEST_DIRECTORY_NAMES.flatMap((dirName) => testDirectoryNames.map((candidateName) => path39.join(dirname17, dirName, candidateName))),
49150
- ...repoLevelDirectories.flatMap((candidateDir) => testDirectoryNames.map((candidateName) => path39.join(candidateDir, candidateName)))
50747
+ ...TEST_DIRECTORY_NAMES.flatMap((dirName) => testDirectoryNames.map((candidateName) => path42.join(dirname20, dirName, candidateName))),
50748
+ ...repoLevelDirectories.flatMap((candidateDir) => testDirectoryNames.map((candidateName) => path42.join(candidateDir, candidateName)))
49151
50749
  ];
49152
50750
  for (const testFile of possibleTestFiles) {
49153
50751
  if (fs22.existsSync(testFile)) {
@@ -49168,7 +50766,7 @@ async function getTestFilesFromGraph(sourceFiles, workingDir) {
49168
50766
  try {
49169
50767
  const absoluteTestFile = resolveWorkspacePath(testFile, workingDir);
49170
50768
  const content = fs22.readFileSync(absoluteTestFile, "utf-8");
49171
- const testDir = path39.dirname(absoluteTestFile);
50769
+ const testDir = path42.dirname(absoluteTestFile);
49172
50770
  const importRegex = /import\s+.*?\s+from\s+['"]([^'"]+)['"]/g;
49173
50771
  let match;
49174
50772
  match = importRegex.exec(content);
@@ -49176,8 +50774,8 @@ async function getTestFilesFromGraph(sourceFiles, workingDir) {
49176
50774
  const importPath = match[1];
49177
50775
  let resolvedImport;
49178
50776
  if (importPath.startsWith(".")) {
49179
- resolvedImport = path39.resolve(testDir, importPath);
49180
- const existingExt = path39.extname(resolvedImport);
50777
+ resolvedImport = path42.resolve(testDir, importPath);
50778
+ const existingExt = path42.extname(resolvedImport);
49181
50779
  if (!existingExt) {
49182
50780
  for (const extToTry of [
49183
50781
  ".ts",
@@ -49197,12 +50795,12 @@ async function getTestFilesFromGraph(sourceFiles, workingDir) {
49197
50795
  } else {
49198
50796
  continue;
49199
50797
  }
49200
- const importBasename = path39.basename(resolvedImport, path39.extname(resolvedImport));
49201
- const importDir = path39.dirname(resolvedImport);
50798
+ const importBasename = path42.basename(resolvedImport, path42.extname(resolvedImport));
50799
+ const importDir = path42.dirname(resolvedImport);
49202
50800
  for (const sourceFile of absoluteSourceFiles) {
49203
- const sourceDir = path39.dirname(sourceFile);
49204
- const sourceBasename = path39.basename(sourceFile, path39.extname(sourceFile));
49205
- const isRelatedDir = importDir === sourceDir || importDir === path39.join(sourceDir, "__tests__") || importDir === path39.join(sourceDir, "tests") || importDir === path39.join(sourceDir, "test") || importDir === path39.join(sourceDir, "spec");
50801
+ const sourceDir = path42.dirname(sourceFile);
50802
+ const sourceBasename = path42.basename(sourceFile, path42.extname(sourceFile));
50803
+ const isRelatedDir = importDir === sourceDir || importDir === path42.join(sourceDir, "__tests__") || importDir === path42.join(sourceDir, "tests") || importDir === path42.join(sourceDir, "test") || importDir === path42.join(sourceDir, "spec");
49206
50804
  if (resolvedImport === sourceFile || importBasename === sourceBasename && isRelatedDir) {
49207
50805
  dedupePush(testFiles, testFile);
49208
50806
  break;
@@ -49215,8 +50813,8 @@ async function getTestFilesFromGraph(sourceFiles, workingDir) {
49215
50813
  while (match !== null) {
49216
50814
  const importPath = match[1];
49217
50815
  if (importPath.startsWith(".")) {
49218
- let resolvedImport = path39.resolve(testDir, importPath);
49219
- const existingExt = path39.extname(resolvedImport);
50816
+ let resolvedImport = path42.resolve(testDir, importPath);
50817
+ const existingExt = path42.extname(resolvedImport);
49220
50818
  if (!existingExt) {
49221
50819
  for (const extToTry of [
49222
50820
  ".ts",
@@ -49233,12 +50831,12 @@ async function getTestFilesFromGraph(sourceFiles, workingDir) {
49233
50831
  }
49234
50832
  }
49235
50833
  }
49236
- const importDir = path39.dirname(resolvedImport);
49237
- const importBasename = path39.basename(resolvedImport, path39.extname(resolvedImport));
50834
+ const importDir = path42.dirname(resolvedImport);
50835
+ const importBasename = path42.basename(resolvedImport, path42.extname(resolvedImport));
49238
50836
  for (const sourceFile of absoluteSourceFiles) {
49239
- const sourceDir = path39.dirname(sourceFile);
49240
- const sourceBasename = path39.basename(sourceFile, path39.extname(sourceFile));
49241
- const isRelatedDir = importDir === sourceDir || importDir === path39.join(sourceDir, "__tests__") || importDir === path39.join(sourceDir, "tests") || importDir === path39.join(sourceDir, "test") || importDir === path39.join(sourceDir, "spec");
50837
+ const sourceDir = path42.dirname(sourceFile);
50838
+ const sourceBasename = path42.basename(sourceFile, path42.extname(sourceFile));
50839
+ const isRelatedDir = importDir === sourceDir || importDir === path42.join(sourceDir, "__tests__") || importDir === path42.join(sourceDir, "tests") || importDir === path42.join(sourceDir, "test") || importDir === path42.join(sourceDir, "spec");
49242
50840
  if (resolvedImport === sourceFile || importBasename === sourceBasename && isRelatedDir) {
49243
50841
  dedupePush(testFiles, testFile);
49244
50842
  break;
@@ -49348,8 +50946,8 @@ function buildTestCommand2(framework, scope, files, coverage, baseDir) {
49348
50946
  return ["mvn", "test"];
49349
50947
  case "gradle": {
49350
50948
  const isWindows = process.platform === "win32";
49351
- const hasGradlewBat = fs22.existsSync(path39.join(baseDir, "gradlew.bat"));
49352
- const hasGradlew = fs22.existsSync(path39.join(baseDir, "gradlew"));
50949
+ const hasGradlewBat = fs22.existsSync(path42.join(baseDir, "gradlew.bat"));
50950
+ const hasGradlew = fs22.existsSync(path42.join(baseDir, "gradlew"));
49353
50951
  if (hasGradlewBat && isWindows)
49354
50952
  return ["gradlew.bat", "test"];
49355
50953
  if (hasGradlew)
@@ -49366,7 +50964,7 @@ function buildTestCommand2(framework, scope, files, coverage, baseDir) {
49366
50964
  "cmake-build-release",
49367
50965
  "out"
49368
50966
  ];
49369
- const actualBuildDir = buildDirCandidates.find((d) => fs22.existsSync(path39.join(baseDir, d, "CMakeCache.txt"))) ?? "build";
50967
+ const actualBuildDir = buildDirCandidates.find((d) => fs22.existsSync(path42.join(baseDir, d, "CMakeCache.txt"))) ?? "build";
49370
50968
  return ["ctest", "--test-dir", actualBuildDir];
49371
50969
  }
49372
50970
  case "swift-test":
@@ -49798,11 +51396,11 @@ async function runTests(framework, scope, files, coverage, timeout_ms, cwd) {
49798
51396
  };
49799
51397
  }
49800
51398
  const startTime = Date.now();
49801
- const vitestJsonOutputPath = framework === "vitest" ? path39.join(cwd, ".swarm", "cache", "test-runner-vitest.json") : undefined;
51399
+ const vitestJsonOutputPath = framework === "vitest" ? path42.join(cwd, ".swarm", "cache", "test-runner-vitest.json") : undefined;
49802
51400
  try {
49803
51401
  if (vitestJsonOutputPath) {
49804
51402
  try {
49805
- fs22.mkdirSync(path39.dirname(vitestJsonOutputPath), { recursive: true });
51403
+ fs22.mkdirSync(path42.dirname(vitestJsonOutputPath), { recursive: true });
49806
51404
  if (fs22.existsSync(vitestJsonOutputPath)) {
49807
51405
  fs22.unlinkSync(vitestJsonOutputPath);
49808
51406
  }
@@ -49918,10 +51516,10 @@ async function runTests(framework, scope, files, coverage, timeout_ms, cwd) {
49918
51516
  }
49919
51517
  function normalizeHistoryTestFile(testFile, workingDir) {
49920
51518
  const normalized = testFile.replace(/\\/g, "/");
49921
- if (!path39.isAbsolute(testFile))
51519
+ if (!path42.isAbsolute(testFile))
49922
51520
  return normalized;
49923
- const relative9 = path39.relative(workingDir, testFile);
49924
- if (relative9.startsWith("..") || path39.isAbsolute(relative9)) {
51521
+ const relative9 = path42.relative(workingDir, testFile);
51522
+ if (relative9.startsWith("..") || path42.isAbsolute(relative9)) {
49925
51523
  return normalized;
49926
51524
  }
49927
51525
  return relative9.replace(/\\/g, "/");
@@ -50259,7 +51857,7 @@ var init_test_runner = __esm(() => {
50259
51857
  const sourceFiles = args.files.filter((file3) => {
50260
51858
  if (directTestFiles.includes(file3))
50261
51859
  return false;
50262
- const ext = path39.extname(file3).toLowerCase();
51860
+ const ext = path42.extname(file3).toLowerCase();
50263
51861
  return SOURCE_EXTENSIONS.has(ext);
50264
51862
  });
50265
51863
  const invalidFiles = args.files.filter((file3) => !directTestFiles.includes(file3) && !sourceFiles.includes(file3));
@@ -50305,7 +51903,7 @@ var init_test_runner = __esm(() => {
50305
51903
  if (isConventionTestFilePath(f)) {
50306
51904
  return false;
50307
51905
  }
50308
- const ext = path39.extname(f).toLowerCase();
51906
+ const ext = path42.extname(f).toLowerCase();
50309
51907
  return SOURCE_EXTENSIONS.has(ext);
50310
51908
  });
50311
51909
  if (sourceFiles.length === 0) {
@@ -50355,7 +51953,7 @@ var init_test_runner = __esm(() => {
50355
51953
  if (isConventionTestFilePath(f)) {
50356
51954
  return false;
50357
51955
  }
50358
- const ext = path39.extname(f).toLowerCase();
51956
+ const ext = path42.extname(f).toLowerCase();
50359
51957
  return SOURCE_EXTENSIONS.has(ext);
50360
51958
  });
50361
51959
  if (sourceFiles.length === 0) {
@@ -50407,8 +52005,8 @@ var init_test_runner = __esm(() => {
50407
52005
  }
50408
52006
  if (impactResult.impactedTests.length > 0) {
50409
52007
  testFiles = impactResult.impactedTests.map((absPath) => {
50410
- const relativePath = path39.relative(workingDir, absPath);
50411
- return path39.isAbsolute(relativePath) ? absPath : relativePath;
52008
+ const relativePath = path42.relative(workingDir, absPath);
52009
+ return path42.isAbsolute(relativePath) ? absPath : relativePath;
50412
52010
  });
50413
52011
  } else {
50414
52012
  graphFallbackReason = "no impacted tests found via impact analysis, falling back to graph";
@@ -50484,7 +52082,7 @@ var init_test_runner = __esm(() => {
50484
52082
 
50485
52083
  // src/services/preflight-service.ts
50486
52084
  import * as fs23 from "fs";
50487
- import * as path40 from "path";
52085
+ import * as path43 from "path";
50488
52086
  function validateDirectoryPath(dir) {
50489
52087
  if (!dir || typeof dir !== "string") {
50490
52088
  throw new Error("Directory path is required");
@@ -50492,8 +52090,8 @@ function validateDirectoryPath(dir) {
50492
52090
  if (dir.includes("..")) {
50493
52091
  throw new Error("Directory path must not contain path traversal sequences");
50494
52092
  }
50495
- const normalized = path40.normalize(dir);
50496
- const absolutePath = path40.isAbsolute(normalized) ? normalized : path40.resolve(normalized);
52093
+ const normalized = path43.normalize(dir);
52094
+ const absolutePath = path43.isAbsolute(normalized) ? normalized : path43.resolve(normalized);
50497
52095
  return absolutePath;
50498
52096
  }
50499
52097
  function validateTimeout(timeoutMs, defaultValue) {
@@ -50516,7 +52114,7 @@ function validateTimeout(timeoutMs, defaultValue) {
50516
52114
  }
50517
52115
  function getPackageVersion(dir) {
50518
52116
  try {
50519
- const packagePath = path40.join(dir, "package.json");
52117
+ const packagePath = path43.join(dir, "package.json");
50520
52118
  if (fs23.existsSync(packagePath)) {
50521
52119
  const content = fs23.readFileSync(packagePath, "utf-8");
50522
52120
  const pkg = JSON.parse(content);
@@ -50527,7 +52125,7 @@ function getPackageVersion(dir) {
50527
52125
  }
50528
52126
  function getChangelogVersion(dir) {
50529
52127
  try {
50530
- const changelogPath = path40.join(dir, "CHANGELOG.md");
52128
+ const changelogPath = path43.join(dir, "CHANGELOG.md");
50531
52129
  if (fs23.existsSync(changelogPath)) {
50532
52130
  const content = fs23.readFileSync(changelogPath, "utf-8");
50533
52131
  const match = content.match(/^##\s*\[?(\d+\.\d+\.\d+)\]?/m);
@@ -50541,7 +52139,7 @@ function getChangelogVersion(dir) {
50541
52139
  function getVersionFileVersion(dir) {
50542
52140
  const possibleFiles = ["VERSION.txt", "version.txt", "VERSION", "version"];
50543
52141
  for (const file3 of possibleFiles) {
50544
- const filePath = path40.join(dir, file3);
52142
+ const filePath = path43.join(dir, file3);
50545
52143
  if (fs23.existsSync(filePath)) {
50546
52144
  try {
50547
52145
  const content = fs23.readFileSync(filePath, "utf-8").trim();
@@ -50883,7 +52481,7 @@ async function runEvidenceCheck(dir) {
50883
52481
  async function runRequirementCoverageCheck(dir, currentPhase) {
50884
52482
  const startTime = Date.now();
50885
52483
  try {
50886
- const specPath = path40.join(dir, ".swarm", "spec.md");
52484
+ const specPath = path43.join(dir, ".swarm", "spec.md");
50887
52485
  if (!fs23.existsSync(specPath)) {
50888
52486
  return {
50889
52487
  type: "req_coverage",
@@ -52001,7 +53599,7 @@ var init_manager3 = __esm(() => {
52001
53599
 
52002
53600
  // src/commands/reset.ts
52003
53601
  import * as fs24 from "fs";
52004
- import * as path41 from "path";
53602
+ import * as path44 from "path";
52005
53603
  async function handleResetCommand(directory, args) {
52006
53604
  const hasConfirm = args.includes("--confirm");
52007
53605
  if (!hasConfirm) {
@@ -52041,7 +53639,7 @@ async function handleResetCommand(directory, args) {
52041
53639
  }
52042
53640
  for (const filename of ["SWARM_PLAN.md", "SWARM_PLAN.json"]) {
52043
53641
  try {
52044
- const rootPath = path41.join(directory, filename);
53642
+ const rootPath = path44.join(directory, filename);
52045
53643
  if (fs24.existsSync(rootPath)) {
52046
53644
  fs24.unlinkSync(rootPath);
52047
53645
  results.push(`- \u2705 Deleted ${filename} (root)`);
@@ -52081,7 +53679,7 @@ var init_reset = __esm(() => {
52081
53679
 
52082
53680
  // src/commands/reset-session.ts
52083
53681
  import * as fs25 from "fs";
52084
- import * as path42 from "path";
53682
+ import * as path45 from "path";
52085
53683
  async function handleResetSessionCommand(directory, _args) {
52086
53684
  const results = [];
52087
53685
  try {
@@ -52096,13 +53694,13 @@ async function handleResetSessionCommand(directory, _args) {
52096
53694
  results.push("\u274C Failed to delete state.json");
52097
53695
  }
52098
53696
  try {
52099
- const sessionDir = path42.dirname(validateSwarmPath(directory, "session/state.json"));
53697
+ const sessionDir = path45.dirname(validateSwarmPath(directory, "session/state.json"));
52100
53698
  if (fs25.existsSync(sessionDir)) {
52101
53699
  const files = fs25.readdirSync(sessionDir);
52102
53700
  const otherFiles = files.filter((f) => f !== "state.json");
52103
53701
  let deletedCount = 0;
52104
53702
  for (const file3 of otherFiles) {
52105
- const filePath = path42.join(sessionDir, file3);
53703
+ const filePath = path45.join(sessionDir, file3);
52106
53704
  if (fs25.lstatSync(filePath).isFile()) {
52107
53705
  fs25.unlinkSync(filePath);
52108
53706
  deletedCount++;
@@ -52134,7 +53732,7 @@ var init_reset_session = __esm(() => {
52134
53732
  });
52135
53733
 
52136
53734
  // src/summaries/manager.ts
52137
- import * as path43 from "path";
53735
+ import * as path46 from "path";
52138
53736
  function sanitizeSummaryId(id) {
52139
53737
  if (!id || id.length === 0) {
52140
53738
  throw new Error("Invalid summary ID: empty string");
@@ -52157,7 +53755,7 @@ function sanitizeSummaryId(id) {
52157
53755
  }
52158
53756
  async function loadFullOutput(directory, id) {
52159
53757
  const sanitizedId = sanitizeSummaryId(id);
52160
- const relativePath = path43.join("summaries", `${sanitizedId}.json`);
53758
+ const relativePath = path46.join("summaries", `${sanitizedId}.json`);
52161
53759
  validateSwarmPath(directory, relativePath);
52162
53760
  const content = await readSwarmFileAsync(directory, relativePath);
52163
53761
  if (content === null) {
@@ -52220,7 +53818,7 @@ var init_retrieve = __esm(() => {
52220
53818
 
52221
53819
  // src/commands/rollback.ts
52222
53820
  import * as fs26 from "fs";
52223
- import * as path44 from "path";
53821
+ import * as path47 from "path";
52224
53822
  async function handleRollbackCommand(directory, args) {
52225
53823
  const phaseArg = args[0];
52226
53824
  if (!phaseArg) {
@@ -52285,8 +53883,8 @@ async function handleRollbackCommand(directory, args) {
52285
53883
  if (EXCLUDE_FILES.has(file3) || file3.startsWith("plan-ledger.archived-")) {
52286
53884
  continue;
52287
53885
  }
52288
- const src = path44.join(checkpointDir, file3);
52289
- const dest = path44.join(swarmDir, file3);
53886
+ const src = path47.join(checkpointDir, file3);
53887
+ const dest = path47.join(swarmDir, file3);
52290
53888
  try {
52291
53889
  fs26.cpSync(src, dest, { recursive: true, force: true });
52292
53890
  successes.push(file3);
@@ -52305,12 +53903,12 @@ async function handleRollbackCommand(directory, args) {
52305
53903
  ].join(`
52306
53904
  `);
52307
53905
  }
52308
- const existingLedgerPath = path44.join(swarmDir, "plan-ledger.jsonl");
53906
+ const existingLedgerPath = path47.join(swarmDir, "plan-ledger.jsonl");
52309
53907
  if (fs26.existsSync(existingLedgerPath)) {
52310
53908
  fs26.unlinkSync(existingLedgerPath);
52311
53909
  }
52312
53910
  try {
52313
- const planJsonPath = path44.join(swarmDir, "plan.json");
53911
+ const planJsonPath = path47.join(swarmDir, "plan.json");
52314
53912
  if (fs26.existsSync(planJsonPath)) {
52315
53913
  const planRaw = fs26.readFileSync(planJsonPath, "utf-8");
52316
53914
  const plan = PlanSchema.parse(JSON.parse(planRaw));
@@ -52401,9 +53999,9 @@ Ensure this is a git repository with commit history.`;
52401
53999
  `);
52402
54000
  try {
52403
54001
  const fs27 = await import("fs/promises");
52404
- const path45 = await import("path");
52405
- const reportPath = path45.join(directory, ".swarm", "simulate-report.md");
52406
- await fs27.mkdir(path45.dirname(reportPath), { recursive: true });
54002
+ const path48 = await import("path");
54003
+ const reportPath = path48.join(directory, ".swarm", "simulate-report.md");
54004
+ await fs27.mkdir(path48.dirname(reportPath), { recursive: true });
52407
54005
  await fs27.writeFile(reportPath, report, "utf-8");
52408
54006
  } catch (err) {
52409
54007
  const writeErr = err instanceof Error ? err.message : String(err);
@@ -52427,12 +54025,12 @@ async function handleSpecifyCommand(_directory, args) {
52427
54025
 
52428
54026
  // src/turbo/lean/state.ts
52429
54027
  import * as fs27 from "fs";
52430
- import * as path45 from "path";
54028
+ import * as path48 from "path";
52431
54029
  function nowISO2() {
52432
54030
  return new Date().toISOString();
52433
54031
  }
52434
54032
  function ensureSwarmDir2(directory) {
52435
- const swarmDir = path45.resolve(directory, ".swarm");
54033
+ const swarmDir = path48.resolve(directory, ".swarm");
52436
54034
  if (!fs27.existsSync(swarmDir)) {
52437
54035
  fs27.mkdirSync(swarmDir, { recursive: true });
52438
54036
  }
@@ -52476,7 +54074,7 @@ function markStateUnreadable2(directory, reason) {
52476
54074
  }
52477
54075
  function readPersisted2(directory) {
52478
54076
  try {
52479
- const filePath = path45.join(directory, ".swarm", STATE_FILE2);
54077
+ const filePath = path48.join(directory, ".swarm", STATE_FILE2);
52480
54078
  if (!fs27.existsSync(filePath)) {
52481
54079
  const seed = emptyPersisted2();
52482
54080
  try {
@@ -52512,7 +54110,7 @@ function writePersisted2(directory, persisted) {
52512
54110
  let payload;
52513
54111
  try {
52514
54112
  ensureSwarmDir2(directory);
52515
- filePath = path45.join(directory, ".swarm", STATE_FILE2);
54113
+ filePath = path48.join(directory, ".swarm", STATE_FILE2);
52516
54114
  tmpPath = `${filePath}.tmp.${Date.now()}`;
52517
54115
  persisted.updatedAt = nowISO2();
52518
54116
  payload = `${JSON.stringify(persisted, null, 2)}
@@ -52639,10 +54237,10 @@ var init_context_budget_service = __esm(() => {
52639
54237
 
52640
54238
  // src/services/status-service.ts
52641
54239
  import * as fsSync2 from "fs";
52642
- import * as path46 from "path";
54240
+ import * as path49 from "path";
52643
54241
  function readSpecStalenessSnapshot(directory) {
52644
54242
  try {
52645
- const p = path46.join(directory, ".swarm", "spec-staleness.json");
54243
+ const p = path49.join(directory, ".swarm", "spec-staleness.json");
52646
54244
  if (!fsSync2.existsSync(p))
52647
54245
  return { stale: false };
52648
54246
  const raw = fsSync2.readFileSync(p, "utf-8");
@@ -53168,7 +54766,7 @@ var init_write_retro2 = __esm(() => {
53168
54766
 
53169
54767
  // src/commands/command-dispatch.ts
53170
54768
  import fs28 from "fs";
53171
- import path47 from "path";
54769
+ import path50 from "path";
53172
54770
  function normalizeSwarmCommandInput(command, argumentText) {
53173
54771
  if (command !== "swarm" && !command.startsWith("swarm-")) {
53174
54772
  return { isSwarmCommand: false, tokens: [] };
@@ -53204,9 +54802,9 @@ ${similar.map((cmd) => ` - /swarm ${cmd}`).join(`
53204
54802
  `);
53205
54803
  }
53206
54804
  function maybeMarkFirstRun(directory) {
53207
- const sentinelPath = path47.join(directory, ".swarm", ".first-run-complete");
54805
+ const sentinelPath = path50.join(directory, ".swarm", ".first-run-complete");
53208
54806
  try {
53209
- const swarmDir = path47.join(directory, ".swarm");
54807
+ const swarmDir = path50.join(directory, ".swarm");
53210
54808
  fs28.mkdirSync(swarmDir, { recursive: true });
53211
54809
  fs28.writeFileSync(sentinelPath, `first-run-complete: ${new Date().toISOString()}
53212
54810
  `, { flag: "wx" });
@@ -53315,6 +54913,14 @@ function classifySwarmCommandToolUse(resolved) {
53315
54913
  message: "Only `/swarm knowledge` and `/swarm knowledge list` are available through swarm_command. Knowledge migrate/quarantine/restore are intentionally excluded."
53316
54914
  };
53317
54915
  }
54916
+ if (canonicalKey === "memory") {
54917
+ if (args.length === 0)
54918
+ return { allowed: true };
54919
+ return {
54920
+ allowed: false,
54921
+ message: "Use `/swarm memory status` or `/swarm memory export` through swarm_command. Memory import and migrate are intentionally excluded from chat-tool execution."
54922
+ };
54923
+ }
53318
54924
  if (canonicalKey === "retrieve") {
53319
54925
  if (args.length !== 1 || !SUMMARY_ID_PATTERN.test(args[0])) {
53320
54926
  return {
@@ -53366,10 +54972,10 @@ function classifySwarmCommandChatFallbackUse(resolved) {
53366
54972
  message: "/swarm config doctor --fix is not available through chat fallback because it can modify configuration files. Run the CLI command directly when you intend to apply fixes."
53367
54973
  };
53368
54974
  }
53369
- if (canonicalKey === "knowledge migrate" || canonicalKey === "knowledge quarantine" || canonicalKey === "knowledge restore") {
54975
+ if (canonicalKey === "knowledge migrate" || canonicalKey === "knowledge quarantine" || canonicalKey === "knowledge restore" || canonicalKey === "memory import" || canonicalKey === "memory migrate") {
53370
54976
  return {
53371
54977
  allowed: false,
53372
- message: `/swarm ${canonicalKey} is not available through chat fallback because it mutates .swarm knowledge state. ` + "Run the CLI command directly after confirming the intended state change."
54978
+ message: `/swarm ${canonicalKey} is not available through chat fallback because it mutates .swarm state. ` + "Run the CLI command directly after confirming the intended state change."
53373
54979
  };
53374
54980
  }
53375
54981
  return { allowed: true };
@@ -53397,6 +55003,11 @@ var init_tool_policy = __esm(() => {
53397
55003
  "preflight",
53398
55004
  "benchmark",
53399
55005
  "knowledge",
55006
+ "memory",
55007
+ "memory status",
55008
+ "memory export",
55009
+ "memory import",
55010
+ "memory migrate",
53400
55011
  "sync-plan",
53401
55012
  "export",
53402
55013
  "list-agents"
@@ -53417,6 +55028,9 @@ var init_tool_policy = __esm(() => {
53417
55028
  "preflight",
53418
55029
  "benchmark",
53419
55030
  "knowledge",
55031
+ "memory",
55032
+ "memory status",
55033
+ "memory export",
53420
55034
  "sync-plan",
53421
55035
  "export"
53422
55036
  ]);
@@ -53425,7 +55039,9 @@ var init_tool_policy = __esm(() => {
53425
55039
  "reset",
53426
55040
  "reset-session",
53427
55041
  "rollback",
53428
- "checkpoint"
55042
+ "checkpoint",
55043
+ "memory import",
55044
+ "memory migrate"
53429
55045
  ]);
53430
55046
  NO_ARGS = new Set([
53431
55047
  "agents",
@@ -53438,7 +55054,10 @@ var init_tool_policy = __esm(() => {
53438
55054
  "diagnose",
53439
55055
  "preflight",
53440
55056
  "sync-plan",
53441
- "export"
55057
+ "export",
55058
+ "memory",
55059
+ "memory status",
55060
+ "memory export"
53442
55061
  ]);
53443
55062
  SUMMARY_ID_PATTERN = /^[A-Za-z][A-Za-z0-9_-]{0,63}$/;
53444
55063
  TASK_ID_PATTERN = /^[A-Za-z0-9_.:-]{1,64}$/;
@@ -53471,6 +55090,11 @@ __export(exports_commands, {
53471
55090
  handlePromoteCommand: () => handlePromoteCommand,
53472
55091
  handlePreflightCommand: () => handlePreflightCommand,
53473
55092
  handlePlanCommand: () => handlePlanCommand,
55093
+ handleMemoryStatusCommand: () => handleMemoryStatusCommand,
55094
+ handleMemoryMigrateCommand: () => handleMemoryMigrateCommand,
55095
+ handleMemoryImportCommand: () => handleMemoryImportCommand,
55096
+ handleMemoryExportCommand: () => handleMemoryExportCommand,
55097
+ handleMemoryCommand: () => handleMemoryCommand,
53474
55098
  handleKnowledgeRestoreCommand: () => handleKnowledgeRestoreCommand,
53475
55099
  handleKnowledgeQuarantineCommand: () => handleKnowledgeQuarantineCommand,
53476
55100
  handleKnowledgeMigrateCommand: () => handleKnowledgeMigrateCommand,
@@ -53748,6 +55372,7 @@ var init_commands = __esm(() => {
53748
55372
  init_handoff();
53749
55373
  init_history();
53750
55374
  init_knowledge();
55375
+ init_memory2();
53751
55376
  init_plan();
53752
55377
  init_preflight();
53753
55378
  init_promote();
@@ -53888,24 +55513,24 @@ function validateAliases() {
53888
55513
  }
53889
55514
  aliasTargets.get(target).push(name);
53890
55515
  const visited = new Set;
53891
- const path48 = [];
55516
+ const path51 = [];
53892
55517
  let current = target;
53893
55518
  while (current) {
53894
55519
  const currentEntry = COMMAND_REGISTRY[current];
53895
55520
  if (!currentEntry)
53896
55521
  break;
53897
55522
  if (visited.has(current)) {
53898
- const cycleStart = path48.indexOf(current);
55523
+ const cycleStart = path51.indexOf(current);
53899
55524
  const fullChain = [
53900
55525
  name,
53901
- ...path48.slice(0, cycleStart > 0 ? cycleStart : path48.length),
55526
+ ...path51.slice(0, cycleStart > 0 ? cycleStart : path51.length),
53902
55527
  current
53903
55528
  ].join(" \u2192 ");
53904
55529
  errors5.push(`Circular alias detected: ${fullChain}`);
53905
55530
  break;
53906
55531
  }
53907
55532
  visited.add(current);
53908
- path48.push(current);
55533
+ path51.push(current);
53909
55534
  current = currentEntry.aliasOf || "";
53910
55535
  }
53911
55536
  }
@@ -53968,6 +55593,7 @@ var init_registry = __esm(() => {
53968
55593
  init_history();
53969
55594
  init_issue();
53970
55595
  init_knowledge();
55596
+ init_memory2();
53971
55597
  init_plan();
53972
55598
  init_pr_review();
53973
55599
  init_preflight();
@@ -54378,6 +56004,39 @@ Subcommands:
54378
56004
  description: "List knowledge entries",
54379
56005
  category: "utility"
54380
56006
  },
56007
+ memory: {
56008
+ handler: (ctx) => handleMemoryCommand(ctx.directory, ctx.args),
56009
+ description: "Show Swarm memory commands",
56010
+ category: "utility"
56011
+ },
56012
+ "memory status": {
56013
+ handler: (ctx) => handleMemoryStatusCommand(ctx.directory, ctx.args),
56014
+ description: "Show Swarm memory provider, JSONL, and migration status",
56015
+ subcommandOf: "memory",
56016
+ args: "",
56017
+ category: "diagnostics"
56018
+ },
56019
+ "memory export": {
56020
+ handler: (ctx) => handleMemoryExportCommand(ctx.directory, ctx.args),
56021
+ description: "Export current Swarm memory to JSONL files",
56022
+ subcommandOf: "memory",
56023
+ args: "",
56024
+ category: "utility"
56025
+ },
56026
+ "memory import": {
56027
+ handler: (ctx) => handleMemoryImportCommand(ctx.directory, ctx.args),
56028
+ description: "Import legacy JSONL memory into SQLite",
56029
+ subcommandOf: "memory",
56030
+ args: "",
56031
+ category: "utility"
56032
+ },
56033
+ "memory migrate": {
56034
+ handler: (ctx) => handleMemoryMigrateCommand(ctx.directory, ctx.args),
56035
+ description: "Run the one-time legacy JSONL to SQLite migration",
56036
+ subcommandOf: "memory",
56037
+ args: "",
56038
+ category: "utility"
56039
+ },
54381
56040
  checkpoint: {
54382
56041
  handler: (ctx) => handleCheckpointCommand(ctx.directory, ctx.args),
54383
56042
  description: "Manage project checkpoints [save|restore|delete|list] <label>",
@@ -54416,53 +56075,53 @@ init_cache_paths();
54416
56075
  init_constants();
54417
56076
  import * as fs29 from "fs";
54418
56077
  import * as os7 from "os";
54419
- import * as path48 from "path";
56078
+ import * as path51 from "path";
54420
56079
  var { version: version4 } = package_default;
54421
56080
  var CONFIG_DIR = getPluginConfigDir();
54422
- var OPENCODE_CONFIG_PATH = path48.join(CONFIG_DIR, "opencode.json");
54423
- var PLUGIN_CONFIG_PATH = path48.join(CONFIG_DIR, "opencode-swarm.json");
54424
- var PROMPTS_DIR = path48.join(CONFIG_DIR, "opencode-swarm");
56081
+ var OPENCODE_CONFIG_PATH = path51.join(CONFIG_DIR, "opencode.json");
56082
+ var PLUGIN_CONFIG_PATH = path51.join(CONFIG_DIR, "opencode-swarm.json");
56083
+ var PROMPTS_DIR = path51.join(CONFIG_DIR, "opencode-swarm");
54425
56084
  var OPENCODE_PLUGIN_CACHE_PATHS = getPluginCachePaths();
54426
56085
  var OPENCODE_PLUGIN_LOCK_FILE_PATHS = getPluginLockFilePaths();
54427
56086
  function isSafeCachePath(p) {
54428
- const resolved = path48.resolve(p);
54429
- const home = path48.resolve(os7.homedir());
56087
+ const resolved = path51.resolve(p);
56088
+ const home = path51.resolve(os7.homedir());
54430
56089
  if (resolved === "/" || resolved === home || resolved.length <= home.length) {
54431
56090
  return false;
54432
56091
  }
54433
- const segments = resolved.split(path48.sep).filter((s) => s.length > 0);
56092
+ const segments = resolved.split(path51.sep).filter((s) => s.length > 0);
54434
56093
  if (segments.length < 4) {
54435
56094
  return false;
54436
56095
  }
54437
- const leaf = path48.basename(resolved);
56096
+ const leaf = path51.basename(resolved);
54438
56097
  if (leaf !== "opencode-swarm@latest" && leaf !== "opencode-swarm") {
54439
56098
  return false;
54440
56099
  }
54441
- const parent = path48.basename(path48.dirname(resolved));
56100
+ const parent = path51.basename(path51.dirname(resolved));
54442
56101
  if (parent !== "packages" && parent !== "node_modules") {
54443
56102
  return false;
54444
56103
  }
54445
- const grandparent = path48.basename(path48.dirname(path48.dirname(resolved)));
56104
+ const grandparent = path51.basename(path51.dirname(path51.dirname(resolved)));
54446
56105
  if (grandparent !== "opencode") {
54447
56106
  return false;
54448
56107
  }
54449
56108
  return true;
54450
56109
  }
54451
56110
  function isSafeLockFilePath(p) {
54452
- const resolved = path48.resolve(p);
54453
- const home = path48.resolve(os7.homedir());
56111
+ const resolved = path51.resolve(p);
56112
+ const home = path51.resolve(os7.homedir());
54454
56113
  if (resolved === "/" || resolved === home || resolved.length <= home.length) {
54455
56114
  return false;
54456
56115
  }
54457
- const segments = resolved.split(path48.sep).filter((s) => s.length > 0);
56116
+ const segments = resolved.split(path51.sep).filter((s) => s.length > 0);
54458
56117
  if (segments.length < 4) {
54459
56118
  return false;
54460
56119
  }
54461
- const leaf = path48.basename(resolved);
56120
+ const leaf = path51.basename(resolved);
54462
56121
  if (leaf !== "bun.lock" && leaf !== "bun.lockb" && leaf !== "package-lock.json") {
54463
56122
  return false;
54464
56123
  }
54465
- const parent = path48.basename(path48.dirname(resolved));
56124
+ const parent = path51.basename(path51.dirname(resolved));
54466
56125
  if (parent !== "opencode") {
54467
56126
  return false;
54468
56127
  }
@@ -54488,8 +56147,8 @@ function saveJson(filepath, data) {
54488
56147
  }
54489
56148
  function writeProjectConfigIfMissing(cwd) {
54490
56149
  try {
54491
- const opencodeDir = path48.join(cwd, ".opencode");
54492
- const projectConfigPath = path48.join(opencodeDir, "opencode-swarm.json");
56150
+ const opencodeDir = path51.join(cwd, ".opencode");
56151
+ const projectConfigPath = path51.join(opencodeDir, "opencode-swarm.json");
54493
56152
  if (fs29.existsSync(projectConfigPath)) {
54494
56153
  return;
54495
56154
  }
@@ -54506,7 +56165,7 @@ async function install() {
54506
56165
  `);
54507
56166
  ensureDir(CONFIG_DIR);
54508
56167
  ensureDir(PROMPTS_DIR);
54509
- const LEGACY_CONFIG_PATH = path48.join(CONFIG_DIR, "config.json");
56168
+ const LEGACY_CONFIG_PATH = path51.join(CONFIG_DIR, "config.json");
54510
56169
  let opencodeConfig = loadJson(OPENCODE_CONFIG_PATH);
54511
56170
  if (!opencodeConfig) {
54512
56171
  const legacyConfig = loadJson(LEGACY_CONFIG_PATH);