opencode-swarm 7.32.2 → 7.33.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/index.js CHANGED
@@ -48,7 +48,7 @@ var package_default;
48
48
  var init_package = __esm(() => {
49
49
  package_default = {
50
50
  name: "opencode-swarm",
51
- version: "7.32.2",
51
+ version: "7.33.0",
52
52
  description: "Architect-centric agentic swarm plugin for OpenCode - hub-and-spoke orchestration with SME consultation, code generation, and QA review",
53
53
  main: "dist/index.js",
54
54
  types: "dist/index.d.ts",
@@ -15539,13 +15539,41 @@ var init_schema = __esm(() => {
15539
15539
  });
15540
15540
  MemoryConfigSchema = exports_external.object({
15541
15541
  enabled: exports_external.boolean().default(false),
15542
- provider: exports_external.literal("local-jsonl").default("local-jsonl"),
15542
+ provider: exports_external.enum(["local-jsonl", "sqlite"]).default("local-jsonl"),
15543
15543
  storageDir: exports_external.string().default(".swarm/memory"),
15544
+ sqlite: exports_external.object({
15545
+ path: exports_external.string().default(".swarm/memory/memory.db"),
15546
+ busyTimeoutMs: exports_external.number().int().min(0).max(60000).default(5000)
15547
+ }).default({ path: ".swarm/memory/memory.db", busyTimeoutMs: 5000 }),
15544
15548
  recall: exports_external.object({
15545
15549
  defaultMaxItems: exports_external.number().int().min(1).max(20).default(8),
15546
15550
  defaultTokenBudget: exports_external.number().int().min(100).max(5000).default(1200),
15547
- minScore: exports_external.number().min(0).max(1).default(0.05)
15548
- }).default({ defaultMaxItems: 8, defaultTokenBudget: 1200, minScore: 0.05 }),
15551
+ minScore: exports_external.number().min(0).max(1).default(0.05),
15552
+ injection: exports_external.object({
15553
+ enabled: exports_external.boolean().default(true),
15554
+ minScore: exports_external.number().min(0).max(1).default(0.25),
15555
+ requireQuerySignal: exports_external.boolean().default(true),
15556
+ maxItems: exports_external.number().int().min(1).max(20).default(6),
15557
+ tokenBudget: exports_external.number().int().min(100).max(5000).default(1000)
15558
+ }).default({
15559
+ enabled: true,
15560
+ minScore: 0.25,
15561
+ requireQuerySignal: true,
15562
+ maxItems: 6,
15563
+ tokenBudget: 1000
15564
+ })
15565
+ }).default({
15566
+ defaultMaxItems: 8,
15567
+ defaultTokenBudget: 1200,
15568
+ minScore: 0.05,
15569
+ injection: {
15570
+ enabled: true,
15571
+ minScore: 0.25,
15572
+ requireQuerySignal: true,
15573
+ maxItems: 6,
15574
+ tokenBudget: 1000
15575
+ }
15576
+ }),
15549
15577
  writes: exports_external.object({
15550
15578
  mode: exports_external.literal("propose").default("propose")
15551
15579
  }).default({ mode: "propose" }),
@@ -84575,7 +84603,7 @@ __export(exports_project_context, {
84575
84603
  LANG_BACKEND_DETECTION_TIMEOUT_MS: () => LANG_BACKEND_DETECTION_TIMEOUT_MS
84576
84604
  });
84577
84605
  import * as fs113 from "node:fs";
84578
- import * as path147 from "node:path";
84606
+ import * as path148 from "node:path";
84579
84607
  function detectFileExists2(directory, pattern) {
84580
84608
  if (pattern.includes("*") || pattern.includes("?")) {
84581
84609
  try {
@@ -84587,7 +84615,7 @@ function detectFileExists2(directory, pattern) {
84587
84615
  }
84588
84616
  }
84589
84617
  try {
84590
- fs113.accessSync(path147.join(directory, pattern));
84618
+ fs113.accessSync(path148.join(directory, pattern));
84591
84619
  return true;
84592
84620
  } catch {
84593
84621
  return false;
@@ -84596,7 +84624,7 @@ function detectFileExists2(directory, pattern) {
84596
84624
  function selectTestCommandFromScriptsTest(backend, directory) {
84597
84625
  let pkgRaw;
84598
84626
  try {
84599
- pkgRaw = fs113.readFileSync(path147.join(directory, "package.json"), "utf-8");
84627
+ pkgRaw = fs113.readFileSync(path148.join(directory, "package.json"), "utf-8");
84600
84628
  } catch {
84601
84629
  return null;
84602
84630
  }
@@ -84705,7 +84733,7 @@ var init_project_context = __esm(() => {
84705
84733
  init_package();
84706
84734
  init_agents2();
84707
84735
  init_critic();
84708
- import * as path148 from "node:path";
84736
+ import * as path149 from "node:path";
84709
84737
 
84710
84738
  // src/background/index.ts
84711
84739
  init_event_bus();
@@ -97571,10 +97599,21 @@ var DEFAULT_MEMORY_CONFIG = {
97571
97599
  enabled: false,
97572
97600
  provider: "local-jsonl",
97573
97601
  storageDir: ".swarm/memory",
97602
+ sqlite: {
97603
+ path: ".swarm/memory/memory.db",
97604
+ busyTimeoutMs: 5000
97605
+ },
97574
97606
  recall: {
97575
97607
  defaultMaxItems: 8,
97576
97608
  defaultTokenBudget: 1200,
97577
- minScore: 0.05
97609
+ minScore: 0.05,
97610
+ injection: {
97611
+ enabled: true,
97612
+ minScore: 0.25,
97613
+ requireQuerySignal: true,
97614
+ maxItems: 6,
97615
+ tokenBudget: 1000
97616
+ }
97578
97617
  },
97579
97618
  writes: {
97580
97619
  mode: "propose"
@@ -97603,9 +97642,17 @@ function resolveMemoryConfig(input) {
97603
97642
  return {
97604
97643
  ...DEFAULT_MEMORY_CONFIG,
97605
97644
  ...input ?? {},
97645
+ sqlite: {
97646
+ ...DEFAULT_MEMORY_CONFIG.sqlite,
97647
+ ...input?.sqlite ?? {}
97648
+ },
97606
97649
  recall: {
97607
97650
  ...DEFAULT_MEMORY_CONFIG.recall,
97608
- ...input?.recall ?? {}
97651
+ ...input?.recall ?? {},
97652
+ injection: {
97653
+ ...DEFAULT_MEMORY_CONFIG.recall.injection,
97654
+ ...input?.recall?.injection ?? {}
97655
+ }
97609
97656
  },
97610
97657
  writes: {
97611
97658
  ...DEFAULT_MEMORY_CONFIG.writes,
@@ -97636,7 +97683,7 @@ class MemoryDisabledError extends Error {
97636
97683
  // src/memory/gateway.ts
97637
97684
  import { createHash as createHash9 } from "node:crypto";
97638
97685
  import { existsSync as existsSync50, readFileSync as readFileSync39 } from "node:fs";
97639
- import * as path96 from "node:path";
97686
+ import * as path97 from "node:path";
97640
97687
 
97641
97688
  // src/memory/local-jsonl-provider.ts
97642
97689
  init_utils2();
@@ -97887,6 +97934,24 @@ function validateMemoryProposal(proposal) {
97887
97934
  function tokenize(text) {
97888
97935
  return new Set(text.toLowerCase().replace(/[^\w\s-]/g, " ").split(/\s+/).map((token) => token.trim()).filter(Boolean));
97889
97936
  }
97937
+ function normalizeKindText(kind) {
97938
+ return kind.replace(/_/g, " ");
97939
+ }
97940
+ function collectMetadataStrings(metadata2, keys) {
97941
+ const values = [];
97942
+ for (const key of keys) {
97943
+ const value = metadata2[key];
97944
+ if (typeof value === "string")
97945
+ values.push(value);
97946
+ if (Array.isArray(value)) {
97947
+ for (const item of value) {
97948
+ if (typeof item === "string")
97949
+ values.push(item);
97950
+ }
97951
+ }
97952
+ }
97953
+ return values;
97954
+ }
97890
97955
  function overlap(a, b) {
97891
97956
  if (a.size === 0 || b.size === 0)
97892
97957
  return 0;
@@ -97924,37 +97989,101 @@ function sameScope(a, b) {
97924
97989
  function scopeAllowed(recordScope, allowedScopes) {
97925
97990
  return allowedScopes.some((scope) => sameScope(recordScope, scope));
97926
97991
  }
97927
- function scoreMemoryRecord(record3, request) {
97928
- if (!request.includeExpired && isExpired2(record3))
97929
- return null;
97992
+ function scoreMemoryRecordDetailed(record3, request) {
97993
+ if (!request.includeExpired && isExpired2(record3)) {
97994
+ return { item: null, skipReason: "filtered" };
97995
+ }
97930
97996
  if (record3.supersededBy)
97931
- return null;
97932
- if (record3.metadata.deleted === true)
97933
- return null;
97934
- if (!scopeAllowed(record3.scope, request.scopes))
97935
- return null;
97936
- if (request.kinds && !request.kinds.includes(record3.kind))
97937
- return null;
97938
- const queryTokens = tokenize(request.query);
97997
+ return { item: null, skipReason: "filtered" };
97998
+ if (record3.metadata.deleted === true) {
97999
+ return { item: null, skipReason: "filtered" };
98000
+ }
98001
+ if (!scopeAllowed(record3.scope, request.scopes)) {
98002
+ return { item: null, skipReason: "filtered" };
98003
+ }
98004
+ if (request.kinds && !request.kinds.includes(record3.kind)) {
98005
+ return { item: null, skipReason: "filtered" };
98006
+ }
98007
+ const queryTokens = request.mode === "injection" && request.task ? tokenize(request.task) : tokenize(request.query);
97939
98008
  const textTokens = tokenize(record3.text);
97940
98009
  const tagTokens = tokenize(record3.tags.join(" "));
98010
+ const fileTokens = tokenize([
98011
+ record3.source.filePath,
98012
+ ...collectMetadataStrings(record3.metadata, [
98013
+ "file",
98014
+ "filePath",
98015
+ "files",
98016
+ "touchedFiles"
98017
+ ])
98018
+ ].filter((value) => typeof value === "string").join(" "));
98019
+ const symbolTokens = tokenize(collectMetadataStrings(record3.metadata, ["symbol", "symbols"]).join(" "));
98020
+ const kindQueryOverlap = overlap(queryTokens, tokenize(normalizeKindText(record3.kind)));
97941
98021
  const textOverlap = overlap(queryTokens, textTokens);
97942
98022
  const tagOverlap = overlap(queryTokens, tagTokens);
97943
- const score = textOverlap * 0.45 + tagOverlap * 0.2 + scopeSpecificityBoost(record3.scope) * 0.15 + kindProfileBoost(record3.kind, request) * 0.1 + record3.confidence * 0.1;
98023
+ const fileOverlap = overlap(queryTokens, fileTokens);
98024
+ const symbolOverlap = overlap(queryTokens, symbolTokens);
98025
+ const kindMatch = request.kinds?.includes(record3.kind) ?? false;
98026
+ const scopeMatch = scopeAllowed(record3.scope, request.scopes);
98027
+ const hasQuerySignal = textOverlap > 0 || tagOverlap > 0 || fileOverlap > 0 || symbolOverlap > 0 || kindQueryOverlap > 0;
98028
+ if (request.mode === "injection" && request.requireQuerySignal !== false && !hasQuerySignal) {
98029
+ return { item: null, skipReason: "no_signal" };
98030
+ }
98031
+ 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;
97944
98032
  const reasonParts = [
97945
98033
  textOverlap > 0 ? `text_overlap=${textOverlap.toFixed(2)}` : null,
97946
98034
  tagOverlap > 0 ? `tag_overlap=${tagOverlap.toFixed(2)}` : null,
98035
+ fileOverlap > 0 ? `file_overlap=${fileOverlap.toFixed(2)}` : null,
98036
+ symbolOverlap > 0 ? `symbol_overlap=${symbolOverlap.toFixed(2)}` : null,
98037
+ kindQueryOverlap > 0 ? `kind_query=${kindQueryOverlap.toFixed(2)}` : null,
97947
98038
  `scope=${record3.scope.type}`,
97948
98039
  `confidence=${record3.confidence.toFixed(2)}`
97949
98040
  ].filter(Boolean);
97950
98041
  return {
97951
- record: record3,
97952
- score,
97953
- reason: reasonParts.join(", ")
98042
+ item: {
98043
+ record: record3,
98044
+ score,
98045
+ reason: reasonParts.join(", "),
98046
+ signals: {
98047
+ textOverlap,
98048
+ tagOverlap,
98049
+ fileOverlap,
98050
+ symbolOverlap,
98051
+ kindMatch,
98052
+ scopeMatch
98053
+ }
98054
+ }
97954
98055
  };
97955
98056
  }
97956
- function scoreMemoryRecords(records, request) {
97957
- return records.map((record3) => scoreMemoryRecord(record3, request)).filter((item) => item !== null).filter((item) => item.score >= (request.minScore ?? 0)).sort((a, b) => b.score - a.score || a.record.id.localeCompare(b.record.id));
98057
+ function scoreMemoryRecordsWithDiagnostics(records, request) {
98058
+ const minScore = request.minScore ?? 0;
98059
+ const diagnostics = {
98060
+ candidateCount: records.length,
98061
+ preScoredFilteredCount: 0,
98062
+ scoredCount: 0,
98063
+ returnedCount: 0,
98064
+ noSignalCount: 0,
98065
+ belowThresholdCount: 0
98066
+ };
98067
+ const items = [];
98068
+ for (const record3 of records) {
98069
+ const result = scoreMemoryRecordDetailed(record3, request);
98070
+ if (!result.item) {
98071
+ if (result.skipReason === "filtered")
98072
+ diagnostics.preScoredFilteredCount++;
98073
+ if (result.skipReason === "no_signal")
98074
+ diagnostics.noSignalCount++;
98075
+ continue;
98076
+ }
98077
+ diagnostics.scoredCount++;
98078
+ if (result.item.score < minScore) {
98079
+ diagnostics.belowThresholdCount++;
98080
+ continue;
98081
+ }
98082
+ items.push(result.item);
98083
+ }
98084
+ items.sort((a, b) => b.score - a.score || a.record.id.localeCompare(b.record.id));
98085
+ diagnostics.returnedCount = items.length;
98086
+ return { items, diagnostics };
97958
98087
  }
97959
98088
 
97960
98089
  // src/memory/local-jsonl-provider.ts
@@ -98030,13 +98159,23 @@ class LocalJsonlMemoryProvider {
98030
98159
  await this.audit("delete", id, reason);
98031
98160
  }
98032
98161
  async recall(request) {
98162
+ return (await this.recallWithDiagnostics(request)).items;
98163
+ }
98164
+ async recallWithDiagnostics(request) {
98033
98165
  await this.initialize();
98034
98166
  const records = await this.list({
98035
98167
  scopes: request.scopes,
98036
98168
  kinds: request.kinds,
98037
98169
  includeExpired: request.includeExpired
98038
98170
  });
98039
- return scoreMemoryRecords(records, request).slice(0, request.maxItems);
98171
+ const result = scoreMemoryRecordsWithDiagnostics(records, request);
98172
+ return {
98173
+ items: result.items.slice(0, request.maxItems),
98174
+ diagnostics: {
98175
+ ...result.diagnostics,
98176
+ returnedCount: Math.min(result.diagnostics.returnedCount, request.maxItems)
98177
+ }
98178
+ };
98040
98179
  }
98041
98180
  async recordRecallUsage(event) {
98042
98181
  await this.initialize();
@@ -98241,10 +98380,372 @@ function toRecallBundle(input) {
98241
98380
  generatedAt: input.generatedAt,
98242
98381
  items: block.items,
98243
98382
  tokenEstimate: block.tokenEstimate,
98244
- promptBlock: block.promptBlock
98383
+ promptBlock: block.promptBlock,
98384
+ diagnostics: input.diagnostics
98245
98385
  };
98246
98386
  }
98247
98387
 
98388
+ // src/memory/sqlite-provider.ts
98389
+ init_utils2();
98390
+ import { randomUUID as randomUUID9 } from "node:crypto";
98391
+ import { mkdirSync as mkdirSync24 } from "node:fs";
98392
+ import { createRequire as createRequire3 } from "node:module";
98393
+ import * as path96 from "node:path";
98394
+ var _DatabaseCtor2 = null;
98395
+ function loadDatabaseCtor2() {
98396
+ if (_DatabaseCtor2)
98397
+ return _DatabaseCtor2;
98398
+ const req = createRequire3(import.meta.url);
98399
+ _DatabaseCtor2 = req("bun:sqlite").Database;
98400
+ return _DatabaseCtor2;
98401
+ }
98402
+ var MIGRATIONS2 = [
98403
+ {
98404
+ version: 1,
98405
+ name: "create_memory_provider_tables",
98406
+ sql: `
98407
+ CREATE TABLE IF NOT EXISTS memory_items (
98408
+ id TEXT PRIMARY KEY,
98409
+ scope_key TEXT NOT NULL,
98410
+ kind TEXT NOT NULL,
98411
+ updated_at TEXT NOT NULL,
98412
+ expires_at TEXT,
98413
+ superseded_by TEXT,
98414
+ deleted INTEGER NOT NULL DEFAULT 0,
98415
+ record_json TEXT NOT NULL
98416
+ );
98417
+ CREATE INDEX IF NOT EXISTS idx_memory_items_scope_kind
98418
+ ON memory_items(scope_key, kind);
98419
+ CREATE INDEX IF NOT EXISTS idx_memory_items_updated_at
98420
+ ON memory_items(updated_at);
98421
+
98422
+ CREATE TABLE IF NOT EXISTS memory_proposals (
98423
+ id TEXT PRIMARY KEY,
98424
+ status TEXT NOT NULL,
98425
+ created_at TEXT NOT NULL,
98426
+ proposal_json TEXT NOT NULL
98427
+ );
98428
+ CREATE INDEX IF NOT EXISTS idx_memory_proposals_status_created
98429
+ ON memory_proposals(status, created_at);
98430
+
98431
+ CREATE TABLE IF NOT EXISTS memory_events (
98432
+ id TEXT PRIMARY KEY,
98433
+ operation TEXT NOT NULL,
98434
+ target_id TEXT NOT NULL,
98435
+ reason TEXT,
98436
+ timestamp TEXT NOT NULL,
98437
+ event_json TEXT
98438
+ );
98439
+
98440
+ CREATE TABLE IF NOT EXISTS memory_recall_usage (
98441
+ id TEXT PRIMARY KEY,
98442
+ bundle_id TEXT NOT NULL,
98443
+ timestamp TEXT NOT NULL,
98444
+ usage_json TEXT NOT NULL
98445
+ );
98446
+ CREATE INDEX IF NOT EXISTS idx_memory_recall_usage_bundle
98447
+ ON memory_recall_usage(bundle_id);
98448
+ `
98449
+ }
98450
+ ];
98451
+
98452
+ class SQLiteMemoryProvider {
98453
+ name = "sqlite";
98454
+ rootDirectory;
98455
+ config;
98456
+ initialized = false;
98457
+ db = null;
98458
+ memories = new Map;
98459
+ proposals = new Map;
98460
+ constructor(rootDirectory, config3 = {}) {
98461
+ this.rootDirectory = rootDirectory;
98462
+ this.config = {
98463
+ ...DEFAULT_MEMORY_CONFIG,
98464
+ ...config3,
98465
+ sqlite: {
98466
+ ...DEFAULT_MEMORY_CONFIG.sqlite,
98467
+ ...config3.sqlite ?? {}
98468
+ },
98469
+ recall: {
98470
+ ...DEFAULT_MEMORY_CONFIG.recall,
98471
+ ...config3.recall ?? {},
98472
+ injection: {
98473
+ ...DEFAULT_MEMORY_CONFIG.recall.injection,
98474
+ ...config3.recall?.injection ?? {}
98475
+ }
98476
+ },
98477
+ writes: {
98478
+ ...DEFAULT_MEMORY_CONFIG.writes,
98479
+ ...config3.writes ?? {}
98480
+ },
98481
+ redaction: {
98482
+ ...DEFAULT_MEMORY_CONFIG.redaction,
98483
+ ...config3.redaction ?? {}
98484
+ }
98485
+ };
98486
+ }
98487
+ databasePath() {
98488
+ const relativePath = this.config.sqlite.path.replace(/^\.swarm[/\\]?/, "");
98489
+ return validateSwarmPath(this.rootDirectory, relativePath);
98490
+ }
98491
+ async initialize() {
98492
+ if (this.initialized)
98493
+ return;
98494
+ const dbPath = this.databasePath();
98495
+ mkdirSync24(path96.dirname(dbPath), { recursive: true });
98496
+ const Db = loadDatabaseCtor2();
98497
+ this.db = new Db(dbPath);
98498
+ this.db.run("PRAGMA journal_mode = WAL;");
98499
+ this.db.run("PRAGMA synchronous = NORMAL;");
98500
+ const busyTimeoutMs = Math.min(60000, Math.max(0, Math.trunc(this.config.sqlite.busyTimeoutMs)));
98501
+ this.db.run(`PRAGMA busy_timeout = ${busyTimeoutMs};`);
98502
+ this.db.run("PRAGMA foreign_keys = ON;");
98503
+ this.runMigrations();
98504
+ const memoryLoad = this.loadMemories();
98505
+ const proposalLoad = this.loadProposals();
98506
+ this.memories = new Map(memoryLoad.records.map((record3) => [record3.id, record3]));
98507
+ this.proposals = new Map(proposalLoad.records.map((proposal) => [proposal.id, proposal]));
98508
+ this.initialized = true;
98509
+ if (memoryLoad.invalidCount > 0) {
98510
+ await this.event("invalid_load", "memory_items", `${memoryLoad.invalidCount} invalid SQLite memory row(s) skipped`);
98511
+ }
98512
+ if (proposalLoad.invalidCount > 0) {
98513
+ await this.event("invalid_load", "memory_proposals", `${proposalLoad.invalidCount} invalid SQLite proposal row(s) skipped`);
98514
+ }
98515
+ }
98516
+ async upsert(record3) {
98517
+ await this.initialize();
98518
+ const existing = this.memories.get(record3.id);
98519
+ if (existing?.metadata.deleted === true) {
98520
+ throw new MemoryValidationError("memory is tombstoned and cannot be upserted");
98521
+ }
98522
+ const next = validateMemoryRecordRules({
98523
+ ...record3,
98524
+ createdAt: existing?.createdAt ?? record3.createdAt
98525
+ }, { rejectDurableSecrets: this.config.redaction.rejectDurableSecrets });
98526
+ this.memories.set(next.id, next);
98527
+ this.writeMemory(next);
98528
+ await this.event("upsert", next.id);
98529
+ return next;
98530
+ }
98531
+ async get(id) {
98532
+ await this.initialize();
98533
+ return this.memories.get(id) ?? null;
98534
+ }
98535
+ async delete(id, reason) {
98536
+ await this.initialize();
98537
+ const existing = this.memories.get(id);
98538
+ if (!existing)
98539
+ return;
98540
+ if (this.config.hardDelete) {
98541
+ this.memories.delete(id);
98542
+ this.requireDb().run("DELETE FROM memory_items WHERE id = ?", [id]);
98543
+ } else {
98544
+ const tombstone = {
98545
+ ...existing,
98546
+ updatedAt: new Date().toISOString(),
98547
+ metadata: { ...existing.metadata, deleted: true, deleteReason: reason }
98548
+ };
98549
+ this.memories.set(id, tombstone);
98550
+ this.writeMemory(tombstone);
98551
+ }
98552
+ await this.event("delete", id, reason);
98553
+ }
98554
+ async recall(request) {
98555
+ return (await this.recallWithDiagnostics(request)).items;
98556
+ }
98557
+ async recallWithDiagnostics(request) {
98558
+ await this.initialize();
98559
+ const records = await this.list({
98560
+ scopes: request.scopes,
98561
+ kinds: request.kinds,
98562
+ includeExpired: request.includeExpired
98563
+ });
98564
+ const result = scoreMemoryRecordsWithDiagnostics(records, request);
98565
+ return {
98566
+ items: result.items.slice(0, request.maxItems),
98567
+ diagnostics: {
98568
+ ...result.diagnostics,
98569
+ returnedCount: Math.min(result.diagnostics.returnedCount, request.maxItems)
98570
+ }
98571
+ };
98572
+ }
98573
+ async recordRecallUsage(event) {
98574
+ await this.initialize();
98575
+ this.requireDb().run(`INSERT INTO memory_recall_usage (
98576
+ id,
98577
+ bundle_id,
98578
+ timestamp,
98579
+ usage_json
98580
+ ) VALUES (?, ?, ?, ?)`, [randomUUID9(), event.bundleId, event.timestamp, JSON.stringify(event)]);
98581
+ await this.event("recall", event.bundleId, JSON.stringify(event));
98582
+ }
98583
+ async list(filter = {}) {
98584
+ await this.initialize();
98585
+ let records = Array.from(this.memories.values());
98586
+ if (filter.scopes && filter.scopes.length > 0) {
98587
+ records = records.filter((record3) => scopeAllowed(record3.scope, filter.scopes ?? []));
98588
+ }
98589
+ if (filter.kinds && filter.kinds.length > 0) {
98590
+ records = records.filter((record3) => filter.kinds?.includes(record3.kind));
98591
+ }
98592
+ if (!filter.includeExpired) {
98593
+ const now = Date.now();
98594
+ records = records.filter((record3) => {
98595
+ if (!record3.expiresAt)
98596
+ return true;
98597
+ const expires = Date.parse(record3.expiresAt);
98598
+ return !Number.isFinite(expires) || expires > now;
98599
+ });
98600
+ }
98601
+ records = records.filter((record3) => !record3.supersededBy && record3.metadata.deleted !== true);
98602
+ records.sort((a, b) => b.updatedAt.localeCompare(a.updatedAt));
98603
+ return records.slice(0, filter.limit ?? records.length);
98604
+ }
98605
+ async createProposal(proposal) {
98606
+ await this.initialize();
98607
+ const next = validateMemoryProposal(proposal);
98608
+ if (next.proposedRecord) {
98609
+ validateMemoryRecordRules(next.proposedRecord, {
98610
+ rejectDurableSecrets: this.config.redaction.rejectDurableSecrets
98611
+ });
98612
+ }
98613
+ this.proposals.set(next.id, next);
98614
+ this.requireDb().run(`INSERT OR REPLACE INTO memory_proposals (
98615
+ id,
98616
+ status,
98617
+ created_at,
98618
+ proposal_json
98619
+ ) VALUES (?, ?, ?, ?)`, [next.id, next.status, next.createdAt, JSON.stringify(next)]);
98620
+ await this.event("proposal", next.id);
98621
+ return next;
98622
+ }
98623
+ async listProposals(filter = {}) {
98624
+ await this.initialize();
98625
+ let proposals = Array.from(this.proposals.values());
98626
+ if (filter.status) {
98627
+ proposals = proposals.filter((proposal) => proposal.status === filter.status);
98628
+ }
98629
+ proposals.sort((a, b) => b.createdAt.localeCompare(a.createdAt));
98630
+ return proposals.slice(0, filter.limit ?? proposals.length);
98631
+ }
98632
+ close() {
98633
+ if (!this.db)
98634
+ return;
98635
+ this.db.close();
98636
+ this.db = null;
98637
+ this.initialized = false;
98638
+ }
98639
+ runMigrations() {
98640
+ const db = this.requireDb();
98641
+ db.run(`CREATE TABLE IF NOT EXISTS schema_migrations (
98642
+ version INTEGER PRIMARY KEY,
98643
+ name TEXT NOT NULL,
98644
+ applied_at TEXT NOT NULL DEFAULT (datetime('now'))
98645
+ )`);
98646
+ const row = db.query("SELECT MAX(version) as version FROM schema_migrations").get();
98647
+ const currentVersion = row?.version ?? 0;
98648
+ for (const migration of MIGRATIONS2) {
98649
+ if (migration.version <= currentVersion)
98650
+ continue;
98651
+ const apply = db.transaction(() => {
98652
+ for (const statement of splitSql(migration.sql)) {
98653
+ db.run(statement);
98654
+ }
98655
+ db.run("INSERT INTO schema_migrations (version, name) VALUES (?, ?)", [
98656
+ migration.version,
98657
+ migration.name
98658
+ ]);
98659
+ this.insertEvent("migration", String(migration.version), migration.name);
98660
+ });
98661
+ apply();
98662
+ }
98663
+ }
98664
+ loadMemories() {
98665
+ const rows = this.requireDb().query("SELECT id, record_json FROM memory_items ORDER BY updated_at ASC").all();
98666
+ const records = [];
98667
+ let invalidCount = 0;
98668
+ for (const row of rows) {
98669
+ try {
98670
+ records.push(validateMemoryRecordRules(JSON.parse(row.record_json), {
98671
+ rejectDurableSecrets: this.config.redaction.rejectDurableSecrets
98672
+ }));
98673
+ } catch {
98674
+ invalidCount++;
98675
+ }
98676
+ }
98677
+ return { records, invalidCount };
98678
+ }
98679
+ loadProposals() {
98680
+ const rows = this.requireDb().query("SELECT id, proposal_json FROM memory_proposals ORDER BY created_at ASC").all();
98681
+ const records = [];
98682
+ let invalidCount = 0;
98683
+ for (const row of rows) {
98684
+ try {
98685
+ const proposal = validateMemoryProposal(JSON.parse(row.proposal_json));
98686
+ if (proposal.proposedRecord) {
98687
+ validateMemoryRecordRules(proposal.proposedRecord, {
98688
+ rejectDurableSecrets: this.config.redaction.rejectDurableSecrets
98689
+ });
98690
+ }
98691
+ records.push(proposal);
98692
+ } catch {
98693
+ invalidCount++;
98694
+ }
98695
+ }
98696
+ return { records, invalidCount };
98697
+ }
98698
+ writeMemory(record3) {
98699
+ this.requireDb().run(`INSERT OR REPLACE INTO memory_items (
98700
+ id,
98701
+ scope_key,
98702
+ kind,
98703
+ updated_at,
98704
+ expires_at,
98705
+ superseded_by,
98706
+ deleted,
98707
+ record_json
98708
+ ) VALUES (?, ?, ?, ?, ?, ?, ?, ?)`, [
98709
+ record3.id,
98710
+ JSON.stringify(record3.scope),
98711
+ record3.kind,
98712
+ record3.updatedAt,
98713
+ record3.expiresAt ?? null,
98714
+ record3.supersededBy ?? null,
98715
+ record3.metadata.deleted === true ? 1 : 0,
98716
+ JSON.stringify(record3)
98717
+ ]);
98718
+ }
98719
+ async event(operation, targetId, reason) {
98720
+ this.insertEvent(operation, targetId, reason);
98721
+ }
98722
+ insertEvent(operation, targetId, reason) {
98723
+ this.requireDb().run(`INSERT INTO memory_events (
98724
+ id,
98725
+ operation,
98726
+ target_id,
98727
+ reason,
98728
+ timestamp,
98729
+ event_json
98730
+ ) VALUES (?, ?, ?, ?, ?, ?)`, [
98731
+ randomUUID9(),
98732
+ operation,
98733
+ targetId,
98734
+ reason ?? null,
98735
+ new Date().toISOString(),
98736
+ reason ? JSON.stringify({ reason }) : null
98737
+ ]);
98738
+ }
98739
+ requireDb() {
98740
+ if (!this.db)
98741
+ throw new Error("SQLite memory provider is not initialized");
98742
+ return this.db;
98743
+ }
98744
+ }
98745
+ function splitSql(sql) {
98746
+ return sql.split(";").map((statement) => statement.trim()).filter(Boolean);
98747
+ }
98748
+
98248
98749
  // src/memory/gateway.ts
98249
98750
  class MemoryGateway {
98250
98751
  context;
@@ -98254,16 +98755,19 @@ class MemoryGateway {
98254
98755
  constructor(context, options = {}) {
98255
98756
  this.context = context;
98256
98757
  this.config = resolveMemoryConfig(options.config ?? DEFAULT_MEMORY_CONFIG);
98257
- this.provider = options.provider ?? new LocalJsonlMemoryProvider(context.directory, this.config);
98758
+ this.provider = options.provider ?? createConfiguredMemoryProvider(context.directory, this.config);
98258
98759
  this.now = options.now ?? (() => new Date);
98259
98760
  }
98260
98761
  isEnabled() {
98261
98762
  return this.config.enabled;
98262
98763
  }
98764
+ async dispose() {
98765
+ await this.provider.close?.();
98766
+ }
98263
98767
  deriveAllowedScopes() {
98264
- const resolvedRoot = path96.resolve(this.context.directory);
98265
- const repoId = createStableId(readGitRemoteUrl(resolvedRoot) ?? path96.basename(resolvedRoot));
98266
- const workspaceId = createStableId(path96.dirname(resolvedRoot));
98768
+ const resolvedRoot = path97.resolve(this.context.directory);
98769
+ const repoId = createStableId(readGitRemoteUrl(resolvedRoot) ?? path97.basename(resolvedRoot));
98770
+ const workspaceId = createStableId(path97.dirname(resolvedRoot));
98267
98771
  const scopes = [
98268
98772
  { type: "workspace", workspaceId },
98269
98773
  {
@@ -98302,20 +98806,29 @@ class MemoryGateway {
98302
98806
  query,
98303
98807
  task: input.task,
98304
98808
  agentRole: this.context.agentRole,
98809
+ mode: input.mode ?? "manual",
98305
98810
  scopes,
98306
98811
  kinds: input.kinds,
98307
98812
  maxItems,
98308
98813
  tokenBudget,
98309
98814
  minScore: input.minScore ?? this.config.recall.minScore,
98815
+ requireQuerySignal: input.requireQuerySignal,
98310
98816
  includeExpired: input.includeExpired
98311
98817
  };
98312
- const results = await this.provider.recall(request);
98818
+ const recallResult = this.provider.recallWithDiagnostics ? await this.provider.recallWithDiagnostics(request) : { items: await this.provider.recall(request) };
98313
98819
  const bundle = toRecallBundle({
98314
98820
  id: createBundleId(query, generatedAt),
98315
98821
  query,
98316
98822
  generatedAt,
98317
- items: results,
98318
- tokenBudget
98823
+ items: recallResult.items,
98824
+ tokenBudget,
98825
+ diagnostics: recallResult.diagnostics ? {
98826
+ injectionSkipReason: input.mode === "injection" ? resolveInjectionSkipReason(recallResult.diagnostics) : undefined,
98827
+ candidateCount: recallResult.diagnostics.candidateCount,
98828
+ preScoredFilteredCount: recallResult.diagnostics.preScoredFilteredCount,
98829
+ noSignalCount: recallResult.diagnostics.noSignalCount,
98830
+ belowThresholdCount: recallResult.diagnostics.belowThresholdCount
98831
+ } : undefined
98319
98832
  });
98320
98833
  await this.provider.recordRecallUsage?.({
98321
98834
  bundleId: bundle.id,
@@ -98454,6 +98967,12 @@ class MemoryGateway {
98454
98967
  function createMemoryGateway(context, options = {}) {
98455
98968
  return new MemoryGateway(context, options);
98456
98969
  }
98970
+ function createConfiguredMemoryProvider(directory, config3) {
98971
+ if (config3.provider === "sqlite") {
98972
+ return new SQLiteMemoryProvider(directory, config3);
98973
+ }
98974
+ return new LocalJsonlMemoryProvider(directory, config3);
98975
+ }
98457
98976
  function sourceFromEvidence(evidenceRefs, context) {
98458
98977
  const first = evidenceRefs[0];
98459
98978
  if (!first) {
@@ -98475,7 +98994,7 @@ var gitRemoteUrlCache = new Map;
98475
98994
  function readGitRemoteUrl(directory) {
98476
98995
  if (gitRemoteUrlCache.has(directory))
98477
98996
  return gitRemoteUrlCache.get(directory);
98478
- const gitConfigPath = path96.join(directory, ".git", "config");
98997
+ const gitConfigPath = path97.join(directory, ".git", "config");
98479
98998
  if (!existsSync50(gitConfigPath)) {
98480
98999
  gitRemoteUrlCache.set(directory, undefined);
98481
99000
  return;
@@ -98503,6 +99022,19 @@ function validateRequestedScopes(requested, allowed) {
98503
99022
  }
98504
99023
  return requested;
98505
99024
  }
99025
+ function resolveInjectionSkipReason(diagnostics) {
99026
+ if (diagnostics.returnedCount > 0)
99027
+ return;
99028
+ if (diagnostics.candidateCount === 0)
99029
+ return "no_results";
99030
+ const signalEligibleCount = diagnostics.candidateCount - diagnostics.preScoredFilteredCount;
99031
+ if (signalEligibleCount > 0 && diagnostics.noSignalCount > 0 && diagnostics.noSignalCount >= signalEligibleCount) {
99032
+ return "no_signal";
99033
+ }
99034
+ if (diagnostics.belowThresholdCount > 0)
99035
+ return "below_threshold";
99036
+ return "no_results";
99037
+ }
98506
99038
  function scopeKey(scope) {
98507
99039
  return JSON.stringify({
98508
99040
  type: scope.type,
@@ -98510,7 +99042,7 @@ function scopeKey(scope) {
98510
99042
  workspaceId: scope.workspaceId,
98511
99043
  projectId: scope.projectId,
98512
99044
  repoId: scope.repoId,
98513
- repoRoot: scope.repoRoot ? path96.resolve(scope.repoRoot) : undefined,
99045
+ repoRoot: scope.repoRoot ? path97.resolve(scope.repoRoot) : undefined,
98514
99046
  runId: scope.runId,
98515
99047
  agentId: scope.agentId
98516
99048
  });
@@ -98757,12 +99289,12 @@ function buildScopesFromInput(input) {
98757
99289
  // src/memory/run-log.ts
98758
99290
  init_utils2();
98759
99291
  import { appendFile as appendFile12, mkdir as mkdir19 } from "node:fs/promises";
98760
- import * as path97 from "node:path";
99292
+ import * as path98 from "node:path";
98761
99293
  async function appendMemoryRunLog(directory, runId, event) {
98762
99294
  const safeRunId = sanitizeRunId(runId);
98763
- const relativePath = path97.join("runs", safeRunId, "memory.jsonl");
99295
+ const relativePath = path98.join("runs", safeRunId, "memory.jsonl");
98764
99296
  const filePath = validateSwarmPath(directory, relativePath);
98765
- await mkdir19(path97.dirname(filePath), { recursive: true });
99297
+ await mkdir19(path98.dirname(filePath), { recursive: true });
98766
99298
  await appendFile12(filePath, `${JSON.stringify({
98767
99299
  ...event,
98768
99300
  runId: safeRunId,
@@ -98897,8 +99429,15 @@ async function recallForAgent(input) {
98897
99429
  agentId: input.agentId,
98898
99430
  runId: input.sessionID
98899
99431
  }, { config: input.config });
98900
- if (!gateway.isEnabled())
99432
+ const resolvedConfig = resolveMemoryConfig(input.config);
99433
+ if (!gateway.isEnabled()) {
99434
+ await logInjectionSkipped(input, "disabled");
99435
+ return null;
99436
+ }
99437
+ if (!resolvedConfig.recall.injection.enabled) {
99438
+ await logInjectionSkipped(input, "disabled");
98901
99439
  return null;
99440
+ }
98902
99441
  const scopes = gateway.deriveAllowedScopes();
98903
99442
  const planInput = {
98904
99443
  userGoal: compactText(input.userGoal),
@@ -98909,6 +99448,8 @@ async function recallForAgent(input) {
98909
99448
  touchedFiles: extractTouchedFiles(input.agentTask)
98910
99449
  };
98911
99450
  const plan = buildMemoryRecallPlan(planInput, { scopes });
99451
+ plan.maxItems = resolvedConfig.recall.injection.maxItems;
99452
+ plan.tokenBudget = resolvedConfig.recall.injection.tokenBudget;
98912
99453
  await input.appendRunLog(input.directory, input.sessionID, {
98913
99454
  event: "recall_requested",
98914
99455
  runId: input.sessionID ?? "unknown",
@@ -98924,10 +99465,13 @@ async function recallForAgent(input) {
98924
99465
  const recallInput = {
98925
99466
  query: plan.query,
98926
99467
  task: planInput.agentTask,
99468
+ mode: "injection",
98927
99469
  scopes: plan.scopes,
98928
99470
  kinds: plan.kinds,
98929
99471
  maxItems: plan.maxItems,
98930
- tokenBudget: plan.tokenBudget
99472
+ tokenBudget: plan.tokenBudget,
99473
+ minScore: resolvedConfig.recall.injection.minScore,
99474
+ requireQuerySignal: resolvedConfig.recall.injection.requireQuerySignal
98931
99475
  };
98932
99476
  const bundle = await gateway.recall(recallInput);
98933
99477
  await input.appendRunLog(input.directory, input.sessionID, {
@@ -98940,8 +99484,31 @@ async function recallForAgent(input) {
98940
99484
  scores: bundle.items.map((item) => item.score),
98941
99485
  tokenEstimate: bundle.tokenEstimate
98942
99486
  });
99487
+ if (bundle.items.length === 0) {
99488
+ await logInjectionSkipped(input, bundle.diagnostics?.injectionSkipReason ?? "no_results", bundle);
99489
+ }
98943
99490
  return { bundle, scopes };
98944
99491
  }
99492
+ async function logInjectionSkipped(input, reason, bundle) {
99493
+ await input.appendRunLog(input.directory, input.sessionID, {
99494
+ event: "prompt_injection_skipped",
99495
+ runId: input.sessionID ?? "unknown",
99496
+ agentRole: input.agentRole,
99497
+ agentId: input.agentId,
99498
+ bundleId: bundle?.id,
99499
+ memoryIds: bundle?.items.map((item) => item.record.id),
99500
+ scores: bundle?.items.map((item) => item.score),
99501
+ tokenEstimate: bundle?.tokenEstimate,
99502
+ rejectionReason: reason,
99503
+ metadata: {
99504
+ reason,
99505
+ candidateCount: bundle?.diagnostics?.candidateCount,
99506
+ preScoredFilteredCount: bundle?.diagnostics?.preScoredFilteredCount,
99507
+ noSignalCount: bundle?.diagnostics?.noSignalCount,
99508
+ belowThresholdCount: bundle?.diagnostics?.belowThresholdCount
99509
+ }
99510
+ });
99511
+ }
98945
99512
  function parseTaskToolInput(input) {
98946
99513
  const record3 = input;
98947
99514
  const rawTool = typeof record3.tool === "string" ? record3.tool : undefined;
@@ -99505,16 +100072,16 @@ init_telemetry();
99505
100072
 
99506
100073
  // src/prm/replay.ts
99507
100074
  import { promises as fs68 } from "node:fs";
99508
- import path98 from "node:path";
100075
+ import path99 from "node:path";
99509
100076
  function isPathSafe2(targetPath, basePath) {
99510
- const resolvedTarget = path98.resolve(targetPath);
99511
- const resolvedBase = path98.resolve(basePath);
99512
- const rel = path98.relative(resolvedBase, resolvedTarget);
99513
- return !rel.startsWith("..") && !path98.isAbsolute(rel);
100077
+ const resolvedTarget = path99.resolve(targetPath);
100078
+ const resolvedBase = path99.resolve(basePath);
100079
+ const rel = path99.relative(resolvedBase, resolvedTarget);
100080
+ return !rel.startsWith("..") && !path99.isAbsolute(rel);
99514
100081
  }
99515
100082
  function isWithinReplaysDir(targetPath) {
99516
- const resolved = path98.resolve(targetPath);
99517
- const parts2 = resolved.split(path98.sep);
100083
+ const resolved = path99.resolve(targetPath);
100084
+ const parts2 = resolved.split(path99.sep);
99518
100085
  for (let i2 = 0;i2 < parts2.length - 1; i2++) {
99519
100086
  if (parts2[i2] === ".swarm" && parts2[i2 + 1] === "replays") {
99520
100087
  return true;
@@ -99527,10 +100094,10 @@ function sanitizeFilename(input) {
99527
100094
  }
99528
100095
  async function startReplayRecording(sessionID, directory) {
99529
100096
  try {
99530
- const replayDir = path98.join(directory, ".swarm", "replays");
100097
+ const replayDir = path99.join(directory, ".swarm", "replays");
99531
100098
  const safeSessionID = sanitizeFilename(sessionID);
99532
100099
  const filename = `${safeSessionID}-${Date.now()}.jsonl`;
99533
- const filepath = path98.join(replayDir, filename);
100100
+ const filepath = path99.join(replayDir, filename);
99534
100101
  if (!isPathSafe2(filepath, replayDir)) {
99535
100102
  console.warn(`[replay] Invalid path detected - path traversal attempt blocked for session ${sessionID}`);
99536
100103
  return null;
@@ -99911,7 +100478,7 @@ init_telemetry();
99911
100478
  init_dist();
99912
100479
  init_create_tool();
99913
100480
  import * as fs69 from "node:fs";
99914
- import * as path99 from "node:path";
100481
+ import * as path100 from "node:path";
99915
100482
  init_path_security();
99916
100483
  var WINDOWS_RESERVED_NAMES2 = /^(con|prn|aux|nul|com[1-9]|lpt[1-9])(\.|:|$)/i;
99917
100484
  function containsWindowsAttacks2(str) {
@@ -99928,14 +100495,14 @@ function containsWindowsAttacks2(str) {
99928
100495
  }
99929
100496
  function isPathInWorkspace2(filePath, workspace) {
99930
100497
  try {
99931
- const resolvedPath = path99.resolve(workspace, filePath);
100498
+ const resolvedPath = path100.resolve(workspace, filePath);
99932
100499
  if (!fs69.existsSync(resolvedPath)) {
99933
100500
  return true;
99934
100501
  }
99935
100502
  const realWorkspace = fs69.realpathSync(workspace);
99936
100503
  const realResolvedPath = fs69.realpathSync(resolvedPath);
99937
- const relativePath = path99.relative(realWorkspace, realResolvedPath);
99938
- if (relativePath.startsWith("..") || path99.isAbsolute(relativePath)) {
100504
+ const relativePath = path100.relative(realWorkspace, realResolvedPath);
100505
+ if (relativePath.startsWith("..") || path100.isAbsolute(relativePath)) {
99939
100506
  return false;
99940
100507
  }
99941
100508
  return true;
@@ -99944,7 +100511,7 @@ function isPathInWorkspace2(filePath, workspace) {
99944
100511
  }
99945
100512
  }
99946
100513
  function processFile2(file3, cwd, exportedOnly) {
99947
- const ext = path99.extname(file3);
100514
+ const ext = path100.extname(file3);
99948
100515
  if (containsControlChars(file3)) {
99949
100516
  return {
99950
100517
  file: file3,
@@ -99977,7 +100544,7 @@ function processFile2(file3, cwd, exportedOnly) {
99977
100544
  errorType: "path-outside-workspace"
99978
100545
  };
99979
100546
  }
99980
- const fullPath = path99.join(cwd, file3);
100547
+ const fullPath = path100.join(cwd, file3);
99981
100548
  if (!fs69.existsSync(fullPath)) {
99982
100549
  return {
99983
100550
  file: file3,
@@ -100269,15 +100836,15 @@ init_task_id();
100269
100836
  init_create_tool();
100270
100837
  init_resolve_working_directory();
100271
100838
  import * as fs70 from "node:fs";
100272
- import * as path100 from "node:path";
100839
+ import * as path101 from "node:path";
100273
100840
  var EVIDENCE_DIR = ".swarm/evidence";
100274
100841
  function isValidTaskId3(taskId) {
100275
100842
  return isStrictTaskId(taskId);
100276
100843
  }
100277
100844
  function isPathWithinSwarm(filePath, workspaceRoot) {
100278
- const normalizedWorkspace = path100.resolve(workspaceRoot);
100279
- const swarmPath = path100.join(normalizedWorkspace, ".swarm", "evidence");
100280
- const normalizedPath = path100.resolve(filePath);
100845
+ const normalizedWorkspace = path101.resolve(workspaceRoot);
100846
+ const swarmPath = path101.join(normalizedWorkspace, ".swarm", "evidence");
100847
+ const normalizedPath = path101.resolve(filePath);
100281
100848
  return normalizedPath.startsWith(swarmPath);
100282
100849
  }
100283
100850
  function readEvidenceFile(evidencePath) {
@@ -100358,7 +100925,7 @@ var check_gate_status = createSwarmTool({
100358
100925
  };
100359
100926
  return JSON.stringify(errorResult, null, 2);
100360
100927
  }
100361
- const evidencePath = path100.join(directory, EVIDENCE_DIR, `${taskIdInput}.json`);
100928
+ const evidencePath = path101.join(directory, EVIDENCE_DIR, `${taskIdInput}.json`);
100362
100929
  if (!isPathWithinSwarm(evidencePath, directory)) {
100363
100930
  const errorResult = {
100364
100931
  taskId: taskIdInput,
@@ -100455,7 +101022,7 @@ init_state();
100455
101022
  init_create_tool();
100456
101023
  init_resolve_working_directory();
100457
101024
  import * as fs71 from "node:fs";
100458
- import * as path101 from "node:path";
101025
+ import * as path102 from "node:path";
100459
101026
  function extractMatches(regex, text) {
100460
101027
  return Array.from(text.matchAll(regex));
100461
101028
  }
@@ -100607,10 +101174,10 @@ async function executeCompletionVerify(args2, directory) {
100607
101174
  let hasFileReadFailure = false;
100608
101175
  for (const filePath of fileTargets) {
100609
101176
  const normalizedPath = filePath.replace(/\\/g, "/");
100610
- const resolvedPath = path101.resolve(directory, normalizedPath);
100611
- const projectRoot = path101.resolve(directory);
100612
- const relative21 = path101.relative(projectRoot, resolvedPath);
100613
- const withinProject = relative21 === "" || !relative21.startsWith("..") && !path101.isAbsolute(relative21);
101177
+ const resolvedPath = path102.resolve(directory, normalizedPath);
101178
+ const projectRoot = path102.resolve(directory);
101179
+ const relative21 = path102.relative(projectRoot, resolvedPath);
101180
+ const withinProject = relative21 === "" || !relative21.startsWith("..") && !path102.isAbsolute(relative21);
100614
101181
  if (!withinProject) {
100615
101182
  blockedTasks.push({
100616
101183
  task_id: task.id,
@@ -100665,8 +101232,8 @@ async function executeCompletionVerify(args2, directory) {
100665
101232
  blockedTasks
100666
101233
  };
100667
101234
  try {
100668
- const evidenceDir = path101.join(directory, ".swarm", "evidence", `${phase}`);
100669
- const evidencePath = path101.join(evidenceDir, "completion-verify.json");
101235
+ const evidenceDir = path102.join(directory, ".swarm", "evidence", `${phase}`);
101236
+ const evidencePath = path102.join(evidenceDir, "completion-verify.json");
100670
101237
  fs71.mkdirSync(evidenceDir, { recursive: true });
100671
101238
  const evidenceBundle = {
100672
101239
  schema_version: "1.0.0",
@@ -100743,11 +101310,11 @@ var completion_verify = createSwarmTool({
100743
101310
  // src/tools/complexity-hotspots.ts
100744
101311
  init_zod();
100745
101312
  import * as fs73 from "node:fs";
100746
- import * as path103 from "node:path";
101313
+ import * as path104 from "node:path";
100747
101314
 
100748
101315
  // src/quality/metrics.ts
100749
101316
  import * as fs72 from "node:fs";
100750
- import * as path102 from "node:path";
101317
+ import * as path103 from "node:path";
100751
101318
  var MAX_FILE_SIZE_BYTES4 = 256 * 1024;
100752
101319
  var MIN_DUPLICATION_LINES = 10;
100753
101320
  function estimateCyclomaticComplexity(content) {
@@ -100799,7 +101366,7 @@ async function computeComplexityDelta(files, workingDir) {
100799
101366
  let totalComplexity = 0;
100800
101367
  const analyzedFiles = [];
100801
101368
  for (const file3 of files) {
100802
- const fullPath = path102.isAbsolute(file3) ? file3 : path102.join(workingDir, file3);
101369
+ const fullPath = path103.isAbsolute(file3) ? file3 : path103.join(workingDir, file3);
100803
101370
  if (!fs72.existsSync(fullPath)) {
100804
101371
  continue;
100805
101372
  }
@@ -100922,7 +101489,7 @@ function countGoExports(content) {
100922
101489
  function getExportCountForFile(filePath) {
100923
101490
  try {
100924
101491
  const content = fs72.readFileSync(filePath, "utf-8");
100925
- const ext = path102.extname(filePath).toLowerCase();
101492
+ const ext = path103.extname(filePath).toLowerCase();
100926
101493
  switch (ext) {
100927
101494
  case ".ts":
100928
101495
  case ".tsx":
@@ -100948,7 +101515,7 @@ async function computePublicApiDelta(files, workingDir) {
100948
101515
  let totalExports = 0;
100949
101516
  const analyzedFiles = [];
100950
101517
  for (const file3 of files) {
100951
- const fullPath = path102.isAbsolute(file3) ? file3 : path102.join(workingDir, file3);
101518
+ const fullPath = path103.isAbsolute(file3) ? file3 : path103.join(workingDir, file3);
100952
101519
  if (!fs72.existsSync(fullPath)) {
100953
101520
  continue;
100954
101521
  }
@@ -100982,7 +101549,7 @@ async function computeDuplicationRatio(files, workingDir) {
100982
101549
  let duplicateLines = 0;
100983
101550
  const analyzedFiles = [];
100984
101551
  for (const file3 of files) {
100985
- const fullPath = path102.isAbsolute(file3) ? file3 : path102.join(workingDir, file3);
101552
+ const fullPath = path103.isAbsolute(file3) ? file3 : path103.join(workingDir, file3);
100986
101553
  if (!fs72.existsSync(fullPath)) {
100987
101554
  continue;
100988
101555
  }
@@ -101015,8 +101582,8 @@ function countCodeLines(content) {
101015
101582
  return lines.length;
101016
101583
  }
101017
101584
  function isTestFile(filePath) {
101018
- const basename15 = path102.basename(filePath);
101019
- const _ext = path102.extname(filePath).toLowerCase();
101585
+ const basename15 = path103.basename(filePath);
101586
+ const _ext = path103.extname(filePath).toLowerCase();
101020
101587
  const testPatterns = [
101021
101588
  ".test.",
101022
101589
  ".spec.",
@@ -101097,8 +101664,8 @@ function matchGlobSegment(globSegments, pathSegments) {
101097
101664
  }
101098
101665
  return gIndex === globSegments.length && pIndex === pathSegments.length;
101099
101666
  }
101100
- function matchesGlobSegment(path103, glob) {
101101
- const normalizedPath = path103.replace(/\\/g, "/");
101667
+ function matchesGlobSegment(path104, glob) {
101668
+ const normalizedPath = path104.replace(/\\/g, "/");
101102
101669
  const normalizedGlob = glob.replace(/\\/g, "/");
101103
101670
  if (normalizedPath.includes("//")) {
101104
101671
  return false;
@@ -101129,8 +101696,8 @@ function simpleGlobToRegex2(glob) {
101129
101696
  function hasGlobstar(glob) {
101130
101697
  return glob.includes("**");
101131
101698
  }
101132
- function globMatches(path103, glob) {
101133
- const normalizedPath = path103.replace(/\\/g, "/");
101699
+ function globMatches(path104, glob) {
101700
+ const normalizedPath = path104.replace(/\\/g, "/");
101134
101701
  if (!glob || glob === "") {
101135
101702
  if (normalizedPath.includes("//")) {
101136
101703
  return false;
@@ -101166,7 +101733,7 @@ function shouldExcludeFile(filePath, excludeGlobs) {
101166
101733
  async function computeTestToCodeRatio(workingDir, enforceGlobs, excludeGlobs) {
101167
101734
  let testLines = 0;
101168
101735
  let codeLines = 0;
101169
- const srcDir = path102.join(workingDir, "src");
101736
+ const srcDir = path103.join(workingDir, "src");
101170
101737
  if (fs72.existsSync(srcDir)) {
101171
101738
  await scanDirectoryForLines(srcDir, enforceGlobs, excludeGlobs, false, (lines) => {
101172
101739
  codeLines += lines;
@@ -101174,14 +101741,14 @@ async function computeTestToCodeRatio(workingDir, enforceGlobs, excludeGlobs) {
101174
101741
  }
101175
101742
  const possibleSrcDirs = ["lib", "app", "source", "core"];
101176
101743
  for (const dir of possibleSrcDirs) {
101177
- const dirPath = path102.join(workingDir, dir);
101744
+ const dirPath = path103.join(workingDir, dir);
101178
101745
  if (fs72.existsSync(dirPath)) {
101179
101746
  await scanDirectoryForLines(dirPath, enforceGlobs, excludeGlobs, false, (lines) => {
101180
101747
  codeLines += lines;
101181
101748
  });
101182
101749
  }
101183
101750
  }
101184
- const testsDir = path102.join(workingDir, "tests");
101751
+ const testsDir = path103.join(workingDir, "tests");
101185
101752
  if (fs72.existsSync(testsDir)) {
101186
101753
  await scanDirectoryForLines(testsDir, ["**"], ["node_modules", "dist"], true, (lines) => {
101187
101754
  testLines += lines;
@@ -101189,7 +101756,7 @@ async function computeTestToCodeRatio(workingDir, enforceGlobs, excludeGlobs) {
101189
101756
  }
101190
101757
  const possibleTestDirs = ["test", "__tests__", "specs"];
101191
101758
  for (const dir of possibleTestDirs) {
101192
- const dirPath = path102.join(workingDir, dir);
101759
+ const dirPath = path103.join(workingDir, dir);
101193
101760
  if (fs72.existsSync(dirPath) && dirPath !== testsDir) {
101194
101761
  await scanDirectoryForLines(dirPath, ["**"], ["node_modules", "dist"], true, (lines) => {
101195
101762
  testLines += lines;
@@ -101204,7 +101771,7 @@ async function scanDirectoryForLines(dirPath, includeGlobs, excludeGlobs, isTest
101204
101771
  try {
101205
101772
  const entries = fs72.readdirSync(dirPath, { withFileTypes: true });
101206
101773
  for (const entry of entries) {
101207
- const fullPath = path102.join(dirPath, entry.name);
101774
+ const fullPath = path103.join(dirPath, entry.name);
101208
101775
  if (entry.isDirectory()) {
101209
101776
  if (entry.name === "node_modules" || entry.name === "dist" || entry.name === "build" || entry.name === ".git") {
101210
101777
  continue;
@@ -101212,7 +101779,7 @@ async function scanDirectoryForLines(dirPath, includeGlobs, excludeGlobs, isTest
101212
101779
  await scanDirectoryForLines(fullPath, includeGlobs, excludeGlobs, isTestScan, callback);
101213
101780
  } else if (entry.isFile()) {
101214
101781
  const relativePath = fullPath.replace(`${dirPath}/`, "");
101215
- const ext = path102.extname(entry.name).toLowerCase();
101782
+ const ext = path103.extname(entry.name).toLowerCase();
101216
101783
  const validExts = [
101217
101784
  ".ts",
101218
101785
  ".tsx",
@@ -101463,7 +102030,7 @@ async function analyzeHotspots(days, topN, extensions, directory) {
101463
102030
  const extSet = new Set(extensions.map((e) => e.startsWith(".") ? e : `.${e}`));
101464
102031
  const filteredChurn = new Map;
101465
102032
  for (const [file3, count] of churnMap) {
101466
- const ext = path103.extname(file3).toLowerCase();
102033
+ const ext = path104.extname(file3).toLowerCase();
101467
102034
  if (extSet.has(ext)) {
101468
102035
  filteredChurn.set(file3, count);
101469
102036
  }
@@ -101474,7 +102041,7 @@ async function analyzeHotspots(days, topN, extensions, directory) {
101474
102041
  for (const [file3, churnCount] of filteredChurn) {
101475
102042
  let fullPath = file3;
101476
102043
  if (!fs73.existsSync(fullPath)) {
101477
- fullPath = path103.join(cwd, file3);
102044
+ fullPath = path104.join(cwd, file3);
101478
102045
  }
101479
102046
  const complexity = getComplexityForFile2(fullPath);
101480
102047
  if (complexity !== null) {
@@ -101642,7 +102209,7 @@ ${body2}`);
101642
102209
 
101643
102210
  // src/council/council-evidence-writer.ts
101644
102211
  init_task_file();
101645
- import { appendFileSync as appendFileSync12, existsSync as existsSync55, mkdirSync as mkdirSync25, readFileSync as readFileSync45 } from "node:fs";
102212
+ import { appendFileSync as appendFileSync12, existsSync as existsSync55, mkdirSync as mkdirSync26, readFileSync as readFileSync45 } from "node:fs";
101646
102213
  import { join as join88 } from "node:path";
101647
102214
  var EVIDENCE_DIR2 = ".swarm/evidence";
101648
102215
  var VALID_TASK_ID = /^\d+\.\d+(\.\d+)*$/;
@@ -101681,7 +102248,7 @@ async function writeCouncilEvidence(workingDir, synthesis) {
101681
102248
  throw new Error(`writeCouncilEvidence: invalid taskId "${synthesis.taskId}" — must match N.M or N.M.P format`);
101682
102249
  }
101683
102250
  const dir = join88(workingDir, EVIDENCE_DIR2);
101684
- mkdirSync25(dir, { recursive: true });
102251
+ mkdirSync26(dir, { recursive: true });
101685
102252
  const filePath = taskEvidencePath(workingDir, synthesis.taskId);
101686
102253
  await _internals45.withTaskEvidenceLock(workingDir, synthesis.taskId, COUNCIL_AGENT_ID, async () => {
101687
102254
  const existingRoot = Object.create(null);
@@ -101719,7 +102286,7 @@ async function writeCouncilEvidence(workingDir, synthesis) {
101719
102286
  });
101720
102287
  try {
101721
102288
  const councilDir = join88(workingDir, ".swarm", "council");
101722
- mkdirSync25(councilDir, { recursive: true });
102289
+ mkdirSync26(councilDir, { recursive: true });
101723
102290
  const auditLine = JSON.stringify({
101724
102291
  round: synthesis.roundNumber,
101725
102292
  verdict: synthesis.overallVerdict,
@@ -102048,12 +102615,12 @@ function buildFinalCouncilFeedback(projectSummary, verdict, vetoedBy, requiredFi
102048
102615
  }
102049
102616
 
102050
102617
  // src/council/criteria-store.ts
102051
- import { existsSync as existsSync56, mkdirSync as mkdirSync26, readFileSync as readFileSync46, writeFileSync as writeFileSync17 } from "node:fs";
102618
+ import { existsSync as existsSync56, mkdirSync as mkdirSync27, readFileSync as readFileSync46, writeFileSync as writeFileSync17 } from "node:fs";
102052
102619
  import { join as join89 } from "node:path";
102053
102620
  var COUNCIL_DIR = ".swarm/council";
102054
102621
  function writeCriteria(workingDir, taskId, criteria) {
102055
102622
  const dir = join89(workingDir, COUNCIL_DIR);
102056
- mkdirSync26(dir, { recursive: true });
102623
+ mkdirSync27(dir, { recursive: true });
102057
102624
  const payload = {
102058
102625
  taskId,
102059
102626
  criteria,
@@ -102215,7 +102782,7 @@ var submit_council_verdicts = createSwarmTool({
102215
102782
  init_zod();
102216
102783
  init_loader();
102217
102784
  import * as fs74 from "node:fs";
102218
- import * as path104 from "node:path";
102785
+ import * as path105 from "node:path";
102219
102786
 
102220
102787
  // src/council/general-council-advisory.ts
102221
102788
  var ADVISORY_HEADER = "[general_council] (advisory; not blocking)";
@@ -102643,10 +103210,10 @@ var convene_general_council = createSwarmTool({
102643
103210
  const round1 = input.round1Responses;
102644
103211
  const round2 = input.round2Responses ?? [];
102645
103212
  const result = synthesizeGeneralCouncil(input.question, input.mode, round1, round2);
102646
- const evidenceDir = path104.join(workingDir, ".swarm", "council", "general");
103213
+ const evidenceDir = path105.join(workingDir, ".swarm", "council", "general");
102647
103214
  const safeTimestamp = result.timestamp.replace(/[:.]/g, "-");
102648
103215
  const evidenceFile = `${safeTimestamp}-${input.mode}.json`;
102649
- const evidencePath = path104.join(evidenceDir, evidenceFile);
103216
+ const evidencePath = path105.join(evidenceDir, evidenceFile);
102650
103217
  try {
102651
103218
  await fs74.promises.mkdir(evidenceDir, { recursive: true });
102652
103219
  await fs74.promises.writeFile(evidencePath, JSON.stringify(result, null, 2));
@@ -102891,7 +103458,7 @@ init_state();
102891
103458
  init_task_id();
102892
103459
  init_create_tool();
102893
103460
  import * as fs75 from "node:fs";
102894
- import * as path105 from "node:path";
103461
+ import * as path106 from "node:path";
102895
103462
  function validateTaskIdFormat2(taskId) {
102896
103463
  return validateTaskIdFormat(taskId);
102897
103464
  }
@@ -102965,8 +103532,8 @@ async function executeDeclareScope(args2, fallbackDir) {
102965
103532
  };
102966
103533
  }
102967
103534
  }
102968
- normalizedDir = path105.normalize(args2.working_directory);
102969
- const pathParts = normalizedDir.split(path105.sep);
103535
+ normalizedDir = path106.normalize(args2.working_directory);
103536
+ const pathParts = normalizedDir.split(path106.sep);
102970
103537
  if (pathParts.includes("..")) {
102971
103538
  return {
102972
103539
  success: false,
@@ -102976,10 +103543,10 @@ async function executeDeclareScope(args2, fallbackDir) {
102976
103543
  ]
102977
103544
  };
102978
103545
  }
102979
- const resolvedDir = path105.resolve(normalizedDir);
103546
+ const resolvedDir = path106.resolve(normalizedDir);
102980
103547
  try {
102981
103548
  const realPath = fs75.realpathSync(resolvedDir);
102982
- const planPath2 = path105.join(realPath, ".swarm", "plan.json");
103549
+ const planPath2 = path106.join(realPath, ".swarm", "plan.json");
102983
103550
  if (!fs75.existsSync(planPath2)) {
102984
103551
  return {
102985
103552
  success: false,
@@ -103000,9 +103567,9 @@ async function executeDeclareScope(args2, fallbackDir) {
103000
103567
  }
103001
103568
  if (normalizedDir && fallbackDir) {
103002
103569
  try {
103003
- const canonicalWorkingDir = fs75.realpathSync(path105.resolve(normalizedDir));
103004
- const canonicalProjectRoot = fs75.realpathSync(path105.resolve(fallbackDir));
103005
- if (canonicalWorkingDir.startsWith(canonicalProjectRoot + path105.sep)) {
103570
+ const canonicalWorkingDir = fs75.realpathSync(path106.resolve(normalizedDir));
103571
+ const canonicalProjectRoot = fs75.realpathSync(path106.resolve(fallbackDir));
103572
+ if (canonicalWorkingDir.startsWith(canonicalProjectRoot + path106.sep)) {
103006
103573
  return {
103007
103574
  success: false,
103008
103575
  message: `working_directory "${normalizedDir}" is a subdirectory of the project root. Use the project root "${fallbackDir}" instead.`,
@@ -103024,7 +103591,7 @@ async function executeDeclareScope(args2, fallbackDir) {
103024
103591
  };
103025
103592
  }
103026
103593
  const directory = normalizedDir || fallbackDir;
103027
- const planPath = path105.resolve(directory, ".swarm", "plan.json");
103594
+ const planPath = path106.resolve(directory, ".swarm", "plan.json");
103028
103595
  if (!fs75.existsSync(planPath)) {
103029
103596
  return {
103030
103597
  success: false,
@@ -103064,8 +103631,8 @@ async function executeDeclareScope(args2, fallbackDir) {
103064
103631
  const normalizeErrors = [];
103065
103632
  const dir = directory;
103066
103633
  const mergedFiles = rawMergedFiles.map((file3) => {
103067
- if (path105.isAbsolute(file3)) {
103068
- const relativePath = path105.relative(dir, file3).replace(/\\/g, "/");
103634
+ if (path106.isAbsolute(file3)) {
103635
+ const relativePath = path106.relative(dir, file3).replace(/\\/g, "/");
103069
103636
  if (relativePath.startsWith("..")) {
103070
103637
  normalizeErrors.push(`Path '${file3}' resolves outside the project directory`);
103071
103638
  return file3;
@@ -103126,7 +103693,7 @@ var declare_scope = createSwarmTool({
103126
103693
  init_zod();
103127
103694
  import * as child_process7 from "node:child_process";
103128
103695
  import * as fs76 from "node:fs";
103129
- import * as path106 from "node:path";
103696
+ import * as path107 from "node:path";
103130
103697
  init_create_tool();
103131
103698
  var MAX_DIFF_LINES = 500;
103132
103699
  var DIFF_TIMEOUT_MS = 30000;
@@ -103155,20 +103722,20 @@ function validateBase(base) {
103155
103722
  function validatePaths(paths) {
103156
103723
  if (!paths)
103157
103724
  return null;
103158
- for (const path107 of paths) {
103159
- if (!path107 || path107.length === 0) {
103725
+ for (const path108 of paths) {
103726
+ if (!path108 || path108.length === 0) {
103160
103727
  return "empty path not allowed";
103161
103728
  }
103162
- if (path107.length > MAX_PATH_LENGTH) {
103729
+ if (path108.length > MAX_PATH_LENGTH) {
103163
103730
  return `path exceeds maximum length of ${MAX_PATH_LENGTH}`;
103164
103731
  }
103165
- if (SHELL_METACHARACTERS2.test(path107)) {
103732
+ if (SHELL_METACHARACTERS2.test(path108)) {
103166
103733
  return "path contains shell metacharacters";
103167
103734
  }
103168
- if (path107.startsWith("-")) {
103735
+ if (path108.startsWith("-")) {
103169
103736
  return 'path cannot start with "-" (option-like arguments not allowed)';
103170
103737
  }
103171
- if (CONTROL_CHAR_PATTERN2.test(path107)) {
103738
+ if (CONTROL_CHAR_PATTERN2.test(path108)) {
103172
103739
  return "path contains control characters";
103173
103740
  }
103174
103741
  }
@@ -103276,8 +103843,8 @@ var diff = createSwarmTool({
103276
103843
  if (parts2.length >= 3) {
103277
103844
  const additions = parseInt(parts2[0], 10) || 0;
103278
103845
  const deletions = parseInt(parts2[1], 10) || 0;
103279
- const path107 = parts2[2];
103280
- files.push({ path: path107, additions, deletions });
103846
+ const path108 = parts2[2];
103847
+ files.push({ path: path108, additions, deletions });
103281
103848
  }
103282
103849
  }
103283
103850
  const contractChanges = [];
@@ -103317,7 +103884,7 @@ var diff = createSwarmTool({
103317
103884
  } else if (base === "unstaged") {
103318
103885
  const oldRef = `:${file3.path}`;
103319
103886
  oldContent = fileExistsInRef(oldRef) ? getContentFromRef(oldRef) : "";
103320
- newContent = fs76.readFileSync(path106.join(directory, file3.path), "utf-8");
103887
+ newContent = fs76.readFileSync(path107.join(directory, file3.path), "utf-8");
103321
103888
  } else {
103322
103889
  const oldRef = `${base}:${file3.path}`;
103323
103890
  oldContent = fileExistsInRef(oldRef) ? getContentFromRef(oldRef) : "";
@@ -103392,7 +103959,7 @@ var diff = createSwarmTool({
103392
103959
  init_zod();
103393
103960
  import * as child_process8 from "node:child_process";
103394
103961
  import * as fs77 from "node:fs";
103395
- import * as path107 from "node:path";
103962
+ import * as path108 from "node:path";
103396
103963
  init_create_tool();
103397
103964
  init_resolve_working_directory();
103398
103965
  var diff_summary = createSwarmTool({
@@ -103445,7 +104012,7 @@ var diff_summary = createSwarmTool({
103445
104012
  }
103446
104013
  try {
103447
104014
  let oldContent;
103448
- const newContent = fs77.readFileSync(path107.join(workingDir, filePath), "utf-8");
104015
+ const newContent = fs77.readFileSync(path108.join(workingDir, filePath), "utf-8");
103449
104016
  if (fileExistsInHead) {
103450
104017
  oldContent = child_process8.execFileSync("git", ["show", `HEAD:${filePath}`], {
103451
104018
  encoding: "utf-8",
@@ -103674,7 +104241,7 @@ init_zod();
103674
104241
  init_create_tool();
103675
104242
  init_path_security();
103676
104243
  import * as fs78 from "node:fs";
103677
- import * as path108 from "node:path";
104244
+ import * as path109 from "node:path";
103678
104245
  var MAX_FILE_SIZE_BYTES6 = 1024 * 1024;
103679
104246
  var MAX_EVIDENCE_FILES = 1000;
103680
104247
  var EVIDENCE_DIR3 = ".swarm/evidence";
@@ -103701,9 +104268,9 @@ function validateRequiredTypes(input) {
103701
104268
  return null;
103702
104269
  }
103703
104270
  function isPathWithinSwarm2(filePath, cwd) {
103704
- const normalizedCwd = path108.resolve(cwd);
103705
- const swarmPath = path108.join(normalizedCwd, ".swarm");
103706
- const normalizedPath = path108.resolve(filePath);
104271
+ const normalizedCwd = path109.resolve(cwd);
104272
+ const swarmPath = path109.join(normalizedCwd, ".swarm");
104273
+ const normalizedPath = path109.resolve(filePath);
103707
104274
  return normalizedPath.startsWith(swarmPath);
103708
104275
  }
103709
104276
  function parseCompletedTasks(planContent) {
@@ -103733,10 +104300,10 @@ function readEvidenceFiles(evidenceDir, _cwd) {
103733
104300
  if (!VALID_EVIDENCE_FILENAME_REGEX.test(filename)) {
103734
104301
  continue;
103735
104302
  }
103736
- const filePath = path108.join(evidenceDir, filename);
104303
+ const filePath = path109.join(evidenceDir, filename);
103737
104304
  try {
103738
- const resolvedPath = path108.resolve(filePath);
103739
- const evidenceDirResolved = path108.resolve(evidenceDir);
104305
+ const resolvedPath = path109.resolve(filePath);
104306
+ const evidenceDirResolved = path109.resolve(evidenceDir);
103740
104307
  if (!resolvedPath.startsWith(evidenceDirResolved)) {
103741
104308
  continue;
103742
104309
  }
@@ -103854,7 +104421,7 @@ var evidence_check = createSwarmTool({
103854
104421
  return JSON.stringify(errorResult, null, 2);
103855
104422
  }
103856
104423
  const requiredTypes = requiredTypesValue.split(",").map((t) => t.trim()).filter((t) => t.length > 0).map(normalizeEvidenceType);
103857
- const planPath = path108.join(cwd, PLAN_FILE);
104424
+ const planPath = path109.join(cwd, PLAN_FILE);
103858
104425
  if (!isPathWithinSwarm2(planPath, cwd)) {
103859
104426
  const errorResult = {
103860
104427
  error: "plan file path validation failed",
@@ -103886,7 +104453,7 @@ var evidence_check = createSwarmTool({
103886
104453
  };
103887
104454
  return JSON.stringify(result2, null, 2);
103888
104455
  }
103889
- const evidenceDir = path108.join(cwd, EVIDENCE_DIR3);
104456
+ const evidenceDir = path109.join(cwd, EVIDENCE_DIR3);
103890
104457
  const evidence = readEvidenceFiles(evidenceDir, cwd);
103891
104458
  const { tasksWithFullEvidence, gaps } = analyzeGaps(completedTasks, evidence, requiredTypes);
103892
104459
  const completeness = completedTasks.length > 0 ? Math.round(tasksWithFullEvidence.length / completedTasks.length * 100) / 100 : 1;
@@ -103904,7 +104471,7 @@ var evidence_check = createSwarmTool({
103904
104471
  init_zod();
103905
104472
  init_create_tool();
103906
104473
  import * as fs79 from "node:fs";
103907
- import * as path109 from "node:path";
104474
+ import * as path110 from "node:path";
103908
104475
  var EXT_MAP = {
103909
104476
  python: ".py",
103910
104477
  py: ".py",
@@ -103985,12 +104552,12 @@ var extract_code_blocks = createSwarmTool({
103985
104552
  if (prefix) {
103986
104553
  filename = `${prefix}_${filename}`;
103987
104554
  }
103988
- let filepath = path109.join(targetDir, filename);
103989
- const base = path109.basename(filepath, path109.extname(filepath));
103990
- const ext = path109.extname(filepath);
104555
+ let filepath = path110.join(targetDir, filename);
104556
+ const base = path110.basename(filepath, path110.extname(filepath));
104557
+ const ext = path110.extname(filepath);
103991
104558
  let counter = 1;
103992
104559
  while (fs79.existsSync(filepath)) {
103993
- filepath = path109.join(targetDir, `${base}_${counter}${ext}`);
104560
+ filepath = path110.join(targetDir, `${base}_${counter}${ext}`);
103994
104561
  counter++;
103995
104562
  }
103996
104563
  try {
@@ -104248,7 +104815,7 @@ init_zod();
104248
104815
  init_create_tool();
104249
104816
  init_path_security();
104250
104817
  import * as fs80 from "node:fs";
104251
- import * as path110 from "node:path";
104818
+ import * as path111 from "node:path";
104252
104819
  var MAX_FILE_PATH_LENGTH2 = 500;
104253
104820
  var MAX_SYMBOL_LENGTH = 256;
104254
104821
  var MAX_FILE_SIZE_BYTES7 = 1024 * 1024;
@@ -104296,7 +104863,7 @@ function validateSymbolInput(symbol3) {
104296
104863
  return null;
104297
104864
  }
104298
104865
  function isBinaryFile2(filePath, buffer) {
104299
- const ext = path110.extname(filePath).toLowerCase();
104866
+ const ext = path111.extname(filePath).toLowerCase();
104300
104867
  if (ext === ".json" || ext === ".md" || ext === ".txt") {
104301
104868
  return false;
104302
104869
  }
@@ -104320,15 +104887,15 @@ function parseImports(content, targetFile, targetSymbol) {
104320
104887
  const imports = [];
104321
104888
  let _resolvedTarget;
104322
104889
  try {
104323
- _resolvedTarget = path110.resolve(targetFile);
104890
+ _resolvedTarget = path111.resolve(targetFile);
104324
104891
  } catch {
104325
104892
  _resolvedTarget = targetFile;
104326
104893
  }
104327
- const targetBasename = path110.basename(targetFile, path110.extname(targetFile));
104894
+ const targetBasename = path111.basename(targetFile, path111.extname(targetFile));
104328
104895
  const targetWithExt = targetFile;
104329
104896
  const targetWithoutExt = targetFile.replace(/\.(ts|tsx|js|jsx|mjs|cjs)$/i, "");
104330
- const normalizedTargetWithExt = path110.normalize(targetWithExt).replace(/\\/g, "/");
104331
- const normalizedTargetWithoutExt = path110.normalize(targetWithoutExt).replace(/\\/g, "/");
104897
+ const normalizedTargetWithExt = path111.normalize(targetWithExt).replace(/\\/g, "/");
104898
+ const normalizedTargetWithoutExt = path111.normalize(targetWithoutExt).replace(/\\/g, "/");
104332
104899
  const importRegex = /import\s+(?:\{[\s\S]*?\}|(?:\*\s+as\s+\w+)|\w+)\s+from\s+['"`]([^'"`]+)['"`]|import\s+['"`]([^'"`]+)['"`]|require\s*\(\s*['"`]([^'"`]+)['"`]\s*\)/g;
104333
104900
  for (let match = importRegex.exec(content);match !== null; match = importRegex.exec(content)) {
104334
104901
  const modulePath = match[1] || match[2] || match[3];
@@ -104351,9 +104918,9 @@ function parseImports(content, targetFile, targetSymbol) {
104351
104918
  }
104352
104919
  const _normalizedModule = modulePath.replace(/^\.\//, "").replace(/^\.\.\\/, "../");
104353
104920
  let isMatch = false;
104354
- const _targetDir = path110.dirname(targetFile);
104355
- const targetExt = path110.extname(targetFile);
104356
- const targetBasenameNoExt = path110.basename(targetFile, targetExt);
104921
+ const _targetDir = path111.dirname(targetFile);
104922
+ const targetExt = path111.extname(targetFile);
104923
+ const targetBasenameNoExt = path111.basename(targetFile, targetExt);
104357
104924
  const moduleNormalized = modulePath.replace(/\\/g, "/").replace(/^\.\//, "");
104358
104925
  const moduleName = modulePath.split(/[/\\]/).pop() || "";
104359
104926
  const moduleNameNoExt = moduleName.replace(/\.(ts|tsx|js|jsx|mjs|cjs)$/i, "");
@@ -104421,10 +104988,10 @@ function findSourceFiles2(dir, files = [], stats = { skippedDirs: [], skippedFil
104421
104988
  entries.sort((a, b) => a.toLowerCase().localeCompare(b.toLowerCase()));
104422
104989
  for (const entry of entries) {
104423
104990
  if (SKIP_DIRECTORIES4.has(entry)) {
104424
- stats.skippedDirs.push(path110.join(dir, entry));
104991
+ stats.skippedDirs.push(path111.join(dir, entry));
104425
104992
  continue;
104426
104993
  }
104427
- const fullPath = path110.join(dir, entry);
104994
+ const fullPath = path111.join(dir, entry);
104428
104995
  let stat8;
104429
104996
  try {
104430
104997
  stat8 = fs80.statSync(fullPath);
@@ -104438,7 +105005,7 @@ function findSourceFiles2(dir, files = [], stats = { skippedDirs: [], skippedFil
104438
105005
  if (stat8.isDirectory()) {
104439
105006
  findSourceFiles2(fullPath, files, stats);
104440
105007
  } else if (stat8.isFile()) {
104441
- const ext = path110.extname(fullPath).toLowerCase();
105008
+ const ext = path111.extname(fullPath).toLowerCase();
104442
105009
  if (SUPPORTED_EXTENSIONS3.includes(ext)) {
104443
105010
  files.push(fullPath);
104444
105011
  }
@@ -104495,7 +105062,7 @@ var imports = createSwarmTool({
104495
105062
  return JSON.stringify(errorResult, null, 2);
104496
105063
  }
104497
105064
  try {
104498
- const targetFile = path110.resolve(file3);
105065
+ const targetFile = path111.resolve(file3);
104499
105066
  if (!fs80.existsSync(targetFile)) {
104500
105067
  const errorResult = {
104501
105068
  error: `target file not found: ${file3}`,
@@ -104517,7 +105084,7 @@ var imports = createSwarmTool({
104517
105084
  };
104518
105085
  return JSON.stringify(errorResult, null, 2);
104519
105086
  }
104520
- const baseDir = path110.dirname(targetFile);
105087
+ const baseDir = path111.dirname(targetFile);
104521
105088
  const scanStats = {
104522
105089
  skippedDirs: [],
104523
105090
  skippedFiles: 0,
@@ -104602,7 +105169,7 @@ var imports = createSwarmTool({
104602
105169
  });
104603
105170
  // src/tools/knowledge-ack.ts
104604
105171
  init_zod();
104605
- import { randomUUID as randomUUID9 } from "node:crypto";
105172
+ import { randomUUID as randomUUID10 } from "node:crypto";
104606
105173
  init_state();
104607
105174
  init_logger();
104608
105175
  init_create_tool();
@@ -104635,7 +105202,7 @@ var knowledge_ack = createSwarmTool({
104635
105202
  let sessionId = ctx?.sessionID;
104636
105203
  if (!sessionId) {
104637
105204
  warn("[knowledge-ack] No sessionID in tool context — dedup disabled for this acknowledgment");
104638
- sessionId = randomUUID9();
105205
+ sessionId = randomUUID10();
104639
105206
  }
104640
105207
  const dedupKey = buildAckDedupKey(sessionId, a.id, a.result);
104641
105208
  if (swarmState.knowledgeAckDedup.has(dedupKey)) {
@@ -104665,7 +105232,7 @@ init_knowledge_store();
104665
105232
  init_knowledge_validator();
104666
105233
  init_manager();
104667
105234
  init_create_tool();
104668
- import { randomUUID as randomUUID10 } from "node:crypto";
105235
+ import { randomUUID as randomUUID11 } from "node:crypto";
104669
105236
  var VALID_CATEGORIES2 = [
104670
105237
  "process",
104671
105238
  "architecture",
@@ -104739,7 +105306,7 @@ var knowledge_add = createSwarmTool({
104739
105306
  project_name = plan?.title ?? "";
104740
105307
  } catch {}
104741
105308
  const entry = {
104742
- id: randomUUID10(),
105309
+ id: randomUUID11(),
104743
105310
  tier: "swarm",
104744
105311
  lesson,
104745
105312
  category,
@@ -105142,22 +105709,22 @@ init_schema();
105142
105709
  init_qa_gate_profile();
105143
105710
  init_manager2();
105144
105711
  import * as fs85 from "node:fs";
105145
- import * as path115 from "node:path";
105712
+ import * as path116 from "node:path";
105146
105713
 
105147
105714
  // src/full-auto/phase-approval.ts
105148
105715
  init_utils2();
105149
105716
  init_logger();
105150
105717
  init_state2();
105151
105718
  import * as fs81 from "node:fs";
105152
- import * as path111 from "node:path";
105719
+ import * as path112 from "node:path";
105153
105720
  var APPROVAL_TTL_MS = 24 * 60 * 60 * 1000;
105154
105721
  function readEvidenceDir(directory, phase) {
105155
105722
  try {
105156
- const dirPath = validateSwarmPath(directory, path111.posix.join("evidence", String(phase)));
105723
+ const dirPath = validateSwarmPath(directory, path112.posix.join("evidence", String(phase)));
105157
105724
  if (!fs81.existsSync(dirPath))
105158
105725
  return [];
105159
105726
  const entries = fs81.readdirSync(dirPath);
105160
- return entries.filter((e) => e.startsWith("full-auto-") && e.endsWith(".json")).map((e) => path111.join(dirPath, e));
105727
+ return entries.filter((e) => e.startsWith("full-auto-") && e.endsWith(".json")).map((e) => path112.join(dirPath, e));
105161
105728
  } catch {
105162
105729
  return [];
105163
105730
  }
@@ -105296,16 +105863,16 @@ init_plan_schema();
105296
105863
  init_ledger();
105297
105864
  init_manager();
105298
105865
  import * as fs82 from "node:fs";
105299
- import * as path112 from "node:path";
105866
+ import * as path113 from "node:path";
105300
105867
  async function writeCheckpoint(directory) {
105301
105868
  try {
105302
105869
  const plan = await loadPlan(directory);
105303
105870
  if (!plan)
105304
105871
  return;
105305
- const swarmDir = path112.join(directory, ".swarm");
105872
+ const swarmDir = path113.join(directory, ".swarm");
105306
105873
  fs82.mkdirSync(swarmDir, { recursive: true });
105307
- const jsonPath = path112.join(swarmDir, "SWARM_PLAN.json");
105308
- const mdPath = path112.join(swarmDir, "SWARM_PLAN.md");
105874
+ const jsonPath = path113.join(swarmDir, "SWARM_PLAN.json");
105875
+ const mdPath = path113.join(swarmDir, "SWARM_PLAN.md");
105309
105876
  fs82.writeFileSync(jsonPath, JSON.stringify(plan, null, 2), "utf8");
105310
105877
  const md = derivePlanMarkdown(plan);
105311
105878
  fs82.writeFileSync(mdPath, md, "utf8");
@@ -105324,15 +105891,15 @@ init_telemetry();
105324
105891
  // src/turbo/lean/phase-ready.ts
105325
105892
  init_file_locks();
105326
105893
  import * as fs84 from "node:fs";
105327
- import * as path114 from "node:path";
105894
+ import * as path115 from "node:path";
105328
105895
 
105329
105896
  // src/turbo/lean/evidence.ts
105330
105897
  init_bun_compat();
105331
105898
  import { rmSync as rmSync6 } from "node:fs";
105332
105899
  import * as fs83 from "node:fs/promises";
105333
- import * as path113 from "node:path";
105900
+ import * as path114 from "node:path";
105334
105901
  function leanTurboEvidenceDir(directory, phase) {
105335
- return path113.join(directory, ".swarm", "evidence", String(phase), "lean-turbo");
105902
+ return path114.join(directory, ".swarm", "evidence", String(phase), "lean-turbo");
105336
105903
  }
105337
105904
  function validateLaneId(laneId) {
105338
105905
  if (laneId.length === 0) {
@@ -105354,16 +105921,16 @@ function validateLaneId(laneId) {
105354
105921
  function laneEvidencePath(directory, phase, laneId) {
105355
105922
  validateLaneId(laneId);
105356
105923
  const expectedDir = leanTurboEvidenceDir(directory, phase);
105357
- const resolvedPath = path113.resolve(path113.join(expectedDir, `${laneId}.json`));
105358
- const resolvedDir = path113.resolve(expectedDir);
105359
- if (!resolvedPath.startsWith(resolvedDir + path113.sep) && resolvedPath !== resolvedDir) {
105924
+ const resolvedPath = path114.resolve(path114.join(expectedDir, `${laneId}.json`));
105925
+ const resolvedDir = path114.resolve(expectedDir);
105926
+ if (!resolvedPath.startsWith(resolvedDir + path114.sep) && resolvedPath !== resolvedDir) {
105360
105927
  throw new Error(`Invalid laneId: path traversal detected (got "${laneId}")`);
105361
105928
  }
105362
105929
  return resolvedPath;
105363
105930
  }
105364
105931
  async function atomicWriteJson(filePath, data) {
105365
105932
  const content = JSON.stringify(data, null, 2);
105366
- const dir = path113.dirname(filePath);
105933
+ const dir = path114.dirname(filePath);
105367
105934
  await fs83.mkdir(dir, { recursive: true });
105368
105935
  const tempPath = `${filePath}.tmp.${process.pid}.${Date.now()}.${Math.random().toString(36).slice(2)}`;
105369
105936
  try {
@@ -105377,7 +105944,7 @@ async function atomicWriteJson(filePath, data) {
105377
105944
  }
105378
105945
  }
105379
105946
  function phaseEvidencePath(directory, phase) {
105380
- return path113.join(leanTurboEvidenceDir(directory, phase), "lean-turbo-phase.json");
105947
+ return path114.join(leanTurboEvidenceDir(directory, phase), "lean-turbo-phase.json");
105381
105948
  }
105382
105949
  async function writeLaneEvidence(directory, phase, evidence) {
105383
105950
  const targetPath = laneEvidencePath(directory, phase, evidence.laneId);
@@ -105421,7 +105988,7 @@ async function listLaneEvidence(directory, phase) {
105421
105988
  if (entry === "lean-turbo-phase.json") {
105422
105989
  continue;
105423
105990
  }
105424
- const filePath = path113.join(evidenceDir, entry);
105991
+ const filePath = path114.join(evidenceDir, entry);
105425
105992
  let content;
105426
105993
  try {
105427
105994
  content = await fs83.readFile(filePath, "utf-8");
@@ -105445,7 +106012,7 @@ var DEFAULT_CONFIG2 = {
105445
106012
  };
105446
106013
  function defaultReadPlanJson(dir) {
105447
106014
  try {
105448
- const planPath = path114.join(dir, ".swarm", "plan.json");
106015
+ const planPath = path115.join(dir, ".swarm", "plan.json");
105449
106016
  if (!fs84.existsSync(planPath))
105450
106017
  return null;
105451
106018
  const raw = fs84.readFileSync(planPath, "utf-8");
@@ -105460,7 +106027,7 @@ function defaultReadPlanJson(dir) {
105460
106027
  }
105461
106028
  function readReviewerEvidenceFromFile(directory, phase) {
105462
106029
  try {
105463
- const evidencePath = path114.join(directory, ".swarm", "evidence", String(phase), "lean-turbo-reviewer.json");
106030
+ const evidencePath = path115.join(directory, ".swarm", "evidence", String(phase), "lean-turbo-reviewer.json");
105464
106031
  if (!fs84.existsSync(evidencePath)) {
105465
106032
  return null;
105466
106033
  }
@@ -105480,7 +106047,7 @@ function readReviewerEvidenceFromFile(directory, phase) {
105480
106047
  }
105481
106048
  function readCriticEvidenceFromFile(directory, phase) {
105482
106049
  try {
105483
- const evidencePath = path114.join(directory, ".swarm", "evidence", String(phase), "lean-turbo-critic.json");
106050
+ const evidencePath = path115.join(directory, ".swarm", "evidence", String(phase), "lean-turbo-critic.json");
105484
106051
  if (!fs84.existsSync(evidencePath)) {
105485
106052
  return null;
105486
106053
  }
@@ -105499,7 +106066,7 @@ function readCriticEvidenceFromFile(directory, phase) {
105499
106066
  }
105500
106067
  }
105501
106068
  function listLaneEvidenceSync(directory, phase) {
105502
- const evidenceDir = path114.join(directory, ".swarm", "evidence", String(phase), "lean-turbo");
106069
+ const evidenceDir = path115.join(directory, ".swarm", "evidence", String(phase), "lean-turbo");
105503
106070
  let entries;
105504
106071
  try {
105505
106072
  entries = fs84.readdirSync(evidenceDir);
@@ -105569,7 +106136,7 @@ function verifyLeanTurboPhaseReady(directory, phase, sessionIDOrConfig, config3)
105569
106136
  ...DEFAULT_CONFIG2,
105570
106137
  ...actualConfig
105571
106138
  };
105572
- const statePath = path114.join(directory, ".swarm", "turbo-state.json");
106139
+ const statePath = path115.join(directory, ".swarm", "turbo-state.json");
105573
106140
  if (!fs84.existsSync(statePath)) {
105574
106141
  return {
105575
106142
  ok: false,
@@ -105757,7 +106324,7 @@ function verifyLeanTurboPhaseReady(directory, phase, sessionIDOrConfig, config3)
105757
106324
  }
105758
106325
  }
105759
106326
  if (mergedConfig.integrated_diff_required) {
105760
- const evidencePath = path114.join(directory, ".swarm", "evidence", String(phase), "lean-turbo-phase.json");
106327
+ const evidencePath = path115.join(directory, ".swarm", "evidence", String(phase), "lean-turbo-phase.json");
105761
106328
  let hasDiff = false;
105762
106329
  try {
105763
106330
  const content = fs84.readFileSync(evidencePath, "utf-8");
@@ -106052,7 +106619,7 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
106052
106619
  let driftCheckEnabled = true;
106053
106620
  let driftHasSpecMd = false;
106054
106621
  try {
106055
- const specMdPath = path115.join(dir, ".swarm", "spec.md");
106622
+ const specMdPath = path116.join(dir, ".swarm", "spec.md");
106056
106623
  driftHasSpecMd = fs85.existsSync(specMdPath);
106057
106624
  const gatePlan = await loadPlan(dir);
106058
106625
  if (gatePlan) {
@@ -106073,7 +106640,7 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
106073
106640
  } else {
106074
106641
  let phaseType;
106075
106642
  try {
106076
- const planPath = path115.join(dir, ".swarm", "plan.json");
106643
+ const planPath = path116.join(dir, ".swarm", "plan.json");
106077
106644
  if (fs85.existsSync(planPath)) {
106078
106645
  const planRaw = fs85.readFileSync(planPath, "utf-8");
106079
106646
  const plan = JSON.parse(planRaw);
@@ -106085,7 +106652,7 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
106085
106652
  warnings.push(`Phase ${phase} is annotated as 'non-code'. Drift verification was skipped per phase type annotation.`);
106086
106653
  } else {
106087
106654
  try {
106088
- const driftEvidencePath = path115.join(dir, ".swarm", "evidence", String(phase), "drift-verifier.json");
106655
+ const driftEvidencePath = path116.join(dir, ".swarm", "evidence", String(phase), "drift-verifier.json");
106089
106656
  let driftVerdictFound = false;
106090
106657
  let driftVerdictApproved = false;
106091
106658
  try {
@@ -106123,7 +106690,7 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
106123
106690
  let incompleteTaskCount = 0;
106124
106691
  let planParseable = false;
106125
106692
  try {
106126
- const planPath = path115.join(dir, ".swarm", "plan.json");
106693
+ const planPath = path116.join(dir, ".swarm", "plan.json");
106127
106694
  if (fs85.existsSync(planPath)) {
106128
106695
  const planRaw = fs85.readFileSync(planPath, "utf-8");
106129
106696
  const plan = JSON.parse(planRaw);
@@ -106190,7 +106757,7 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
106190
106757
  const overrides = session2?.qaGateSessionOverrides ?? {};
106191
106758
  const effective = getEffectiveGates(profile, overrides);
106192
106759
  if (effective.hallucination_guard === true) {
106193
- const hgPath = path115.join(dir, ".swarm", "evidence", String(phase), "hallucination-guard.json");
106760
+ const hgPath = path116.join(dir, ".swarm", "evidence", String(phase), "hallucination-guard.json");
106194
106761
  let hgVerdictFound = false;
106195
106762
  let hgVerdictApproved = false;
106196
106763
  try {
@@ -106262,7 +106829,7 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
106262
106829
  const overrides = session2?.qaGateSessionOverrides ?? {};
106263
106830
  const effective = getEffectiveGates(profile, overrides);
106264
106831
  if (effective.mutation_test === true) {
106265
- const mgPath = path115.join(dir, ".swarm", "evidence", String(phase), "mutation-gate.json");
106832
+ const mgPath = path116.join(dir, ".swarm", "evidence", String(phase), "mutation-gate.json");
106266
106833
  let mgVerdictFound = false;
106267
106834
  let mgVerdict;
106268
106835
  try {
@@ -106336,7 +106903,7 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
106336
106903
  const effective = getEffectiveGates(profile, overrides);
106337
106904
  if (effective.council_mode === true) {
106338
106905
  councilModeEnabled = true;
106339
- const pcPath = path115.join(dir, ".swarm", "evidence", String(phase), "phase-council.json");
106906
+ const pcPath = path116.join(dir, ".swarm", "evidence", String(phase), "phase-council.json");
106340
106907
  let pcVerdictFound = false;
106341
106908
  let _pcVerdict;
106342
106909
  let pcQuorumSize;
@@ -106544,7 +107111,7 @@ Advisory notes: ${advisoryNotes.join("; ")}` : "";
106544
107111
  const effective = getEffectiveGates(profile, overrides);
106545
107112
  if (effective.final_council === true) {
106546
107113
  finalCouncilEnabled = true;
106547
- const fcPath = path115.join(dir, ".swarm", "evidence", "final-council.json");
107114
+ const fcPath = path116.join(dir, ".swarm", "evidence", "final-council.json");
106548
107115
  let fcVerdictFound = false;
106549
107116
  let _fcVerdict;
106550
107117
  try {
@@ -106732,7 +107299,7 @@ Advisory notes: ${advisoryNotes.join("; ")}` : "";
106732
107299
  }
106733
107300
  if (retroFound && retroEntry?.lessons_learned && retroEntry.lessons_learned.length > 0) {
106734
107301
  try {
106735
- const projectName = path115.basename(dir);
107302
+ const projectName = path116.basename(dir);
106736
107303
  const curationResult = await curateAndStoreSwarm(retroEntry.lessons_learned, projectName, { phase_number: phase }, dir, knowledgeConfig);
106737
107304
  if (curationResult) {
106738
107305
  const sessionState = swarmState.agentSessions.get(sessionID);
@@ -107102,7 +107669,7 @@ init_utils();
107102
107669
  init_bun_compat();
107103
107670
  init_create_tool();
107104
107671
  import * as fs86 from "node:fs";
107105
- import * as path116 from "node:path";
107672
+ import * as path117 from "node:path";
107106
107673
  var MAX_OUTPUT_BYTES5 = 52428800;
107107
107674
  var AUDIT_TIMEOUT_MS = 120000;
107108
107675
  function isValidEcosystem(value) {
@@ -107130,16 +107697,16 @@ function validateArgs3(args2) {
107130
107697
  function detectEcosystems(directory) {
107131
107698
  const ecosystems = [];
107132
107699
  const cwd = directory;
107133
- if (fs86.existsSync(path116.join(cwd, "package.json"))) {
107700
+ if (fs86.existsSync(path117.join(cwd, "package.json"))) {
107134
107701
  ecosystems.push("npm");
107135
107702
  }
107136
- if (fs86.existsSync(path116.join(cwd, "pyproject.toml")) || fs86.existsSync(path116.join(cwd, "requirements.txt"))) {
107703
+ if (fs86.existsSync(path117.join(cwd, "pyproject.toml")) || fs86.existsSync(path117.join(cwd, "requirements.txt"))) {
107137
107704
  ecosystems.push("pip");
107138
107705
  }
107139
- if (fs86.existsSync(path116.join(cwd, "Cargo.toml"))) {
107706
+ if (fs86.existsSync(path117.join(cwd, "Cargo.toml"))) {
107140
107707
  ecosystems.push("cargo");
107141
107708
  }
107142
- if (fs86.existsSync(path116.join(cwd, "go.mod"))) {
107709
+ if (fs86.existsSync(path117.join(cwd, "go.mod"))) {
107143
107710
  ecosystems.push("go");
107144
107711
  }
107145
107712
  try {
@@ -107148,13 +107715,13 @@ function detectEcosystems(directory) {
107148
107715
  ecosystems.push("dotnet");
107149
107716
  }
107150
107717
  } catch {}
107151
- if (fs86.existsSync(path116.join(cwd, "Gemfile")) || fs86.existsSync(path116.join(cwd, "Gemfile.lock"))) {
107718
+ if (fs86.existsSync(path117.join(cwd, "Gemfile")) || fs86.existsSync(path117.join(cwd, "Gemfile.lock"))) {
107152
107719
  ecosystems.push("ruby");
107153
107720
  }
107154
- if (fs86.existsSync(path116.join(cwd, "pubspec.yaml"))) {
107721
+ if (fs86.existsSync(path117.join(cwd, "pubspec.yaml"))) {
107155
107722
  ecosystems.push("dart");
107156
107723
  }
107157
- if (fs86.existsSync(path116.join(cwd, "composer.lock"))) {
107724
+ if (fs86.existsSync(path117.join(cwd, "composer.lock"))) {
107158
107725
  ecosystems.push("composer");
107159
107726
  }
107160
107727
  return ecosystems;
@@ -108290,7 +108857,7 @@ var pkg_audit = createSwarmTool({
108290
108857
  init_zod();
108291
108858
  init_manager2();
108292
108859
  import * as fs87 from "node:fs";
108293
- import * as path117 from "node:path";
108860
+ import * as path118 from "node:path";
108294
108861
  init_utils();
108295
108862
  init_create_tool();
108296
108863
  var MAX_FILE_SIZE = 1024 * 1024;
@@ -108413,7 +108980,7 @@ function isScaffoldFile(filePath) {
108413
108980
  if (SCAFFOLD_PATH_PATTERNS.some((pattern) => pattern.test(normalizedPath))) {
108414
108981
  return true;
108415
108982
  }
108416
- const filename = path117.basename(filePath);
108983
+ const filename = path118.basename(filePath);
108417
108984
  if (SCAFFOLD_FILENAME_PATTERNS.some((pattern) => pattern.test(filename))) {
108418
108985
  return true;
108419
108986
  }
@@ -108430,7 +108997,7 @@ function isAllowedByGlobs(filePath, allowGlobs) {
108430
108997
  if (regex.test(normalizedPath)) {
108431
108998
  return true;
108432
108999
  }
108433
- const filename = path117.basename(filePath);
109000
+ const filename = path118.basename(filePath);
108434
109001
  const filenameRegex = new RegExp(`^${regexPattern}$`, "i");
108435
109002
  if (filenameRegex.test(filename)) {
108436
109003
  return true;
@@ -108439,7 +109006,7 @@ function isAllowedByGlobs(filePath, allowGlobs) {
108439
109006
  return false;
108440
109007
  }
108441
109008
  function isParserSupported(filePath) {
108442
- const ext = path117.extname(filePath).toLowerCase();
109009
+ const ext = path118.extname(filePath).toLowerCase();
108443
109010
  return SUPPORTED_PARSER_EXTENSIONS.has(ext);
108444
109011
  }
108445
109012
  function isPlanFile(filePath) {
@@ -108686,9 +109253,9 @@ async function placeholderScan(input, directory) {
108686
109253
  let filesScanned = 0;
108687
109254
  const filesWithFindings = new Set;
108688
109255
  for (const filePath of changed_files) {
108689
- const fullPath = path117.isAbsolute(filePath) ? filePath : path117.resolve(directory, filePath);
108690
- const resolvedDirectory = path117.resolve(directory);
108691
- if (!fullPath.startsWith(resolvedDirectory + path117.sep) && fullPath !== resolvedDirectory) {
109256
+ const fullPath = path118.isAbsolute(filePath) ? filePath : path118.resolve(directory, filePath);
109257
+ const resolvedDirectory = path118.resolve(directory);
109258
+ if (!fullPath.startsWith(resolvedDirectory + path118.sep) && fullPath !== resolvedDirectory) {
108692
109259
  continue;
108693
109260
  }
108694
109261
  if (!fs87.existsSync(fullPath)) {
@@ -108697,7 +109264,7 @@ async function placeholderScan(input, directory) {
108697
109264
  if (isAllowedByGlobs(filePath, allow_globs)) {
108698
109265
  continue;
108699
109266
  }
108700
- const relativeFilePath = path117.relative(directory, fullPath).replace(/\\/g, "/");
109267
+ const relativeFilePath = path118.relative(directory, fullPath).replace(/\\/g, "/");
108701
109268
  if (FILE_ALLOWLIST.some((allowed) => relativeFilePath.endsWith(allowed))) {
108702
109269
  continue;
108703
109270
  }
@@ -108769,7 +109336,7 @@ var placeholder_scan = createSwarmTool({
108769
109336
  });
108770
109337
  // src/tools/pre-check-batch.ts
108771
109338
  import * as fs91 from "node:fs";
108772
- import * as path121 from "node:path";
109339
+ import * as path122 from "node:path";
108773
109340
  init_zod();
108774
109341
  init_manager2();
108775
109342
  init_utils();
@@ -108910,7 +109477,7 @@ init_zod();
108910
109477
  init_manager2();
108911
109478
  init_detector();
108912
109479
  import * as fs90 from "node:fs";
108913
- import * as path120 from "node:path";
109480
+ import * as path121 from "node:path";
108914
109481
  import { extname as extname20 } from "node:path";
108915
109482
 
108916
109483
  // src/sast/rules/c.ts
@@ -109626,7 +110193,7 @@ function executeRulesSync(filePath, content, language) {
109626
110193
  // src/sast/semgrep.ts
109627
110194
  import * as child_process9 from "node:child_process";
109628
110195
  import * as fs88 from "node:fs";
109629
- import * as path118 from "node:path";
110196
+ import * as path119 from "node:path";
109630
110197
  var semgrepAvailableCache = null;
109631
110198
  var DEFAULT_RULES_DIR = ".swarm/semgrep-rules";
109632
110199
  var DEFAULT_TIMEOUT_MS3 = 30000;
@@ -109813,7 +110380,7 @@ async function runSemgrep(options) {
109813
110380
  }
109814
110381
  function getRulesDirectory(projectRoot) {
109815
110382
  if (projectRoot) {
109816
- return path118.resolve(projectRoot, DEFAULT_RULES_DIR);
110383
+ return path119.resolve(projectRoot, DEFAULT_RULES_DIR);
109817
110384
  }
109818
110385
  return DEFAULT_RULES_DIR;
109819
110386
  }
@@ -109834,24 +110401,24 @@ init_create_tool();
109834
110401
  init_utils2();
109835
110402
  import * as crypto10 from "node:crypto";
109836
110403
  import * as fs89 from "node:fs";
109837
- import * as path119 from "node:path";
110404
+ import * as path120 from "node:path";
109838
110405
  var BASELINE_SCHEMA_VERSION = "1.0.0";
109839
110406
  var MAX_BASELINE_FINDINGS = 2000;
109840
110407
  var MAX_BASELINE_BYTES = 2 * 1048576;
109841
110408
  var LOCK_RETRY_DELAYS_MS = [50, 100, 200, 400, 800];
109842
110409
  function normalizeFindingPath(directory, file3) {
109843
- const resolved = path119.isAbsolute(file3) ? file3 : path119.resolve(directory, file3);
109844
- const rel = path119.relative(path119.resolve(directory), resolved);
110410
+ const resolved = path120.isAbsolute(file3) ? file3 : path120.resolve(directory, file3);
110411
+ const rel = path120.relative(path120.resolve(directory), resolved);
109845
110412
  return rel.replace(/\\/g, "/");
109846
110413
  }
109847
110414
  function baselineRelPath(phase) {
109848
- return path119.join("evidence", String(phase), "sast-baseline.json");
110415
+ return path120.join("evidence", String(phase), "sast-baseline.json");
109849
110416
  }
109850
110417
  function tempRelPath(phase) {
109851
- return path119.join("evidence", String(phase), `sast-baseline.json.tmp.${Date.now()}.${process.pid}`);
110418
+ return path120.join("evidence", String(phase), `sast-baseline.json.tmp.${Date.now()}.${process.pid}`);
109852
110419
  }
109853
110420
  function lockRelPath(phase) {
109854
- return path119.join("evidence", String(phase), "sast-baseline.json.lock");
110421
+ return path120.join("evidence", String(phase), "sast-baseline.json.lock");
109855
110422
  }
109856
110423
  function getLine(lines, idx) {
109857
110424
  if (idx < 0 || idx >= lines.length)
@@ -109972,8 +110539,8 @@ async function captureOrMergeBaseline(directory, phase, findings, engine, scanne
109972
110539
  message: e instanceof Error ? e.message : "Path validation failed"
109973
110540
  };
109974
110541
  }
109975
- fs89.mkdirSync(path119.dirname(baselinePath), { recursive: true });
109976
- fs89.mkdirSync(path119.dirname(tempPath), { recursive: true });
110542
+ fs89.mkdirSync(path120.dirname(baselinePath), { recursive: true });
110543
+ fs89.mkdirSync(path120.dirname(tempPath), { recursive: true });
109977
110544
  const releaseLock = await acquireLock2(lockPath);
109978
110545
  try {
109979
110546
  let existing = null;
@@ -110246,9 +110813,9 @@ async function sastScan(input, directory, config3) {
110246
110813
  _filesSkipped++;
110247
110814
  continue;
110248
110815
  }
110249
- const resolvedPath = path120.isAbsolute(filePath) ? filePath : path120.resolve(directory, filePath);
110250
- const resolvedDirectory = path120.resolve(directory);
110251
- if (!resolvedPath.startsWith(resolvedDirectory + path120.sep) && resolvedPath !== resolvedDirectory) {
110816
+ const resolvedPath = path121.isAbsolute(filePath) ? filePath : path121.resolve(directory, filePath);
110817
+ const resolvedDirectory = path121.resolve(directory);
110818
+ if (!resolvedPath.startsWith(resolvedDirectory + path121.sep) && resolvedPath !== resolvedDirectory) {
110252
110819
  _filesSkipped++;
110253
110820
  continue;
110254
110821
  }
@@ -110563,18 +111130,18 @@ function validatePath(inputPath, baseDir, workspaceDir) {
110563
111130
  let resolved;
110564
111131
  const isWinAbs = isWindowsAbsolutePath(inputPath);
110565
111132
  if (isWinAbs) {
110566
- resolved = path121.win32.resolve(inputPath);
110567
- } else if (path121.isAbsolute(inputPath)) {
110568
- resolved = path121.resolve(inputPath);
111133
+ resolved = path122.win32.resolve(inputPath);
111134
+ } else if (path122.isAbsolute(inputPath)) {
111135
+ resolved = path122.resolve(inputPath);
110569
111136
  } else {
110570
- resolved = path121.resolve(baseDir, inputPath);
111137
+ resolved = path122.resolve(baseDir, inputPath);
110571
111138
  }
110572
- const workspaceResolved = path121.resolve(workspaceDir);
111139
+ const workspaceResolved = path122.resolve(workspaceDir);
110573
111140
  let relative25;
110574
111141
  if (isWinAbs) {
110575
- relative25 = path121.win32.relative(workspaceResolved, resolved);
111142
+ relative25 = path122.win32.relative(workspaceResolved, resolved);
110576
111143
  } else {
110577
- relative25 = path121.relative(workspaceResolved, resolved);
111144
+ relative25 = path122.relative(workspaceResolved, resolved);
110578
111145
  }
110579
111146
  if (relative25.startsWith("..")) {
110580
111147
  return "path traversal detected";
@@ -110639,7 +111206,7 @@ async function runLintOnFiles(linter, files, workspaceDir) {
110639
111206
  if (typeof file3 !== "string") {
110640
111207
  continue;
110641
111208
  }
110642
- const resolvedPath = path121.resolve(file3);
111209
+ const resolvedPath = path122.resolve(file3);
110643
111210
  const validationError = validatePath(resolvedPath, workspaceDir, workspaceDir);
110644
111211
  if (validationError) {
110645
111212
  continue;
@@ -110796,7 +111363,7 @@ async function runSecretscanWithFiles(files, directory) {
110796
111363
  skippedFiles++;
110797
111364
  continue;
110798
111365
  }
110799
- const resolvedPath = path121.resolve(file3);
111366
+ const resolvedPath = path122.resolve(file3);
110800
111367
  const validationError = validatePath(resolvedPath, directory, directory);
110801
111368
  if (validationError) {
110802
111369
  skippedFiles++;
@@ -110814,7 +111381,7 @@ async function runSecretscanWithFiles(files, directory) {
110814
111381
  };
110815
111382
  }
110816
111383
  for (const file3 of validatedFiles) {
110817
- const ext = path121.extname(file3).toLowerCase();
111384
+ const ext = path122.extname(file3).toLowerCase();
110818
111385
  if (DEFAULT_EXCLUDE_EXTENSIONS2.has(ext)) {
110819
111386
  skippedFiles++;
110820
111387
  continue;
@@ -111033,7 +111600,7 @@ function classifySastFindings(findings, changedLineRanges, directory) {
111033
111600
  const preexistingFindings = [];
111034
111601
  for (const finding of findings) {
111035
111602
  const filePath = finding.location.file;
111036
- const normalised = path121.relative(directory, filePath).replace(/\\/g, "/");
111603
+ const normalised = path122.relative(directory, filePath).replace(/\\/g, "/");
111037
111604
  const changedLines = changedLineRanges.get(normalised);
111038
111605
  if (changedLines?.has(finding.location.line)) {
111039
111606
  newFindings.push(finding);
@@ -111084,7 +111651,7 @@ async function runPreCheckBatch(input, workspaceDir, contextDir) {
111084
111651
  warn(`pre_check_batch: Invalid file path: ${file3}`);
111085
111652
  continue;
111086
111653
  }
111087
- changedFiles.push(path121.resolve(directory, file3));
111654
+ changedFiles.push(path122.resolve(directory, file3));
111088
111655
  }
111089
111656
  if (changedFiles.length === 0) {
111090
111657
  warn("pre_check_batch: No valid files after validation, skipping all tools (fail-closed)");
@@ -111285,9 +111852,9 @@ var pre_check_batch = createSwarmTool({
111285
111852
  };
111286
111853
  return JSON.stringify(errorResult, null, 2);
111287
111854
  }
111288
- const resolvedDirectory = path121.resolve(typedArgs.directory);
111289
- const workspaceAnchor = path121.resolve(directory);
111290
- if (resolvedDirectory !== workspaceAnchor && resolvedDirectory.startsWith(workspaceAnchor + path121.sep)) {
111855
+ const resolvedDirectory = path122.resolve(typedArgs.directory);
111856
+ const workspaceAnchor = path122.resolve(directory);
111857
+ if (resolvedDirectory !== workspaceAnchor && resolvedDirectory.startsWith(workspaceAnchor + path122.sep)) {
111291
111858
  const subDirError = `directory "${typedArgs.directory}" is a subdirectory of the project root — pre_check_batch requires the project root directory "${workspaceAnchor}"`;
111292
111859
  const subDirResult = {
111293
111860
  gates_passed: false,
@@ -111338,7 +111905,7 @@ var pre_check_batch = createSwarmTool({
111338
111905
  });
111339
111906
  // src/tools/repo-map.ts
111340
111907
  init_zod();
111341
- import * as path122 from "node:path";
111908
+ import * as path123 from "node:path";
111342
111909
  init_path_security();
111343
111910
  init_create_tool();
111344
111911
  var VALID_ACTIONS = [
@@ -111363,7 +111930,7 @@ function validateFile(p) {
111363
111930
  return "file contains control characters";
111364
111931
  if (containsPathTraversal(p))
111365
111932
  return "file contains path traversal";
111366
- if (path122.isAbsolute(p) || /^[a-zA-Z]:[\\/]/.test(p)) {
111933
+ if (path123.isAbsolute(p) || /^[a-zA-Z]:[\\/]/.test(p)) {
111367
111934
  return "file must be a workspace-relative path, not absolute";
111368
111935
  }
111369
111936
  return null;
@@ -111386,8 +111953,8 @@ function ok(action, payload) {
111386
111953
  }
111387
111954
  function toRelativeGraphPath(input, workspaceRoot) {
111388
111955
  const normalized = input.replace(/\\/g, "/");
111389
- if (path122.isAbsolute(normalized)) {
111390
- const rel = path122.relative(workspaceRoot, normalized).replace(/\\/g, "/");
111956
+ if (path123.isAbsolute(normalized)) {
111957
+ const rel = path123.relative(workspaceRoot, normalized).replace(/\\/g, "/");
111391
111958
  return normalizeGraphPath2(rel);
111392
111959
  }
111393
111960
  return normalizeGraphPath2(normalized);
@@ -111532,7 +112099,7 @@ var repo_map = createSwarmTool({
111532
112099
  init_zod();
111533
112100
  init_create_tool();
111534
112101
  import * as fs92 from "node:fs";
111535
- import * as path123 from "node:path";
112102
+ import * as path124 from "node:path";
111536
112103
  var SPEC_FILE = ".swarm/spec.md";
111537
112104
  var EVIDENCE_DIR4 = ".swarm/evidence";
111538
112105
  var OBLIGATION_KEYWORDS = ["MUST", "SHOULD", "SHALL"];
@@ -111601,7 +112168,7 @@ function readTouchedFiles(evidenceDir, phase, cwd) {
111601
112168
  return [];
111602
112169
  }
111603
112170
  for (const entry of entries) {
111604
- const entryPath = path123.join(evidenceDir, entry);
112171
+ const entryPath = path124.join(evidenceDir, entry);
111605
112172
  try {
111606
112173
  const stat8 = fs92.statSync(entryPath);
111607
112174
  if (!stat8.isDirectory()) {
@@ -111617,11 +112184,11 @@ function readTouchedFiles(evidenceDir, phase, cwd) {
111617
112184
  if (entryPhase !== String(phase)) {
111618
112185
  continue;
111619
112186
  }
111620
- const evidenceFilePath = path123.join(entryPath, "evidence.json");
112187
+ const evidenceFilePath = path124.join(entryPath, "evidence.json");
111621
112188
  try {
111622
- const resolvedPath = path123.resolve(evidenceFilePath);
111623
- const evidenceDirResolved = path123.resolve(evidenceDir);
111624
- if (!resolvedPath.startsWith(evidenceDirResolved + path123.sep)) {
112189
+ const resolvedPath = path124.resolve(evidenceFilePath);
112190
+ const evidenceDirResolved = path124.resolve(evidenceDir);
112191
+ if (!resolvedPath.startsWith(evidenceDirResolved + path124.sep)) {
111625
112192
  continue;
111626
112193
  }
111627
112194
  const stat8 = fs92.lstatSync(evidenceFilePath);
@@ -111655,7 +112222,7 @@ function readTouchedFiles(evidenceDir, phase, cwd) {
111655
112222
  if (Array.isArray(diffEntry.files_changed)) {
111656
112223
  for (const file3 of diffEntry.files_changed) {
111657
112224
  if (typeof file3 === "string") {
111658
- touchedFiles.add(path123.resolve(cwd, file3));
112225
+ touchedFiles.add(path124.resolve(cwd, file3));
111659
112226
  }
111660
112227
  }
111661
112228
  }
@@ -111668,8 +112235,8 @@ function readTouchedFiles(evidenceDir, phase, cwd) {
111668
112235
  }
111669
112236
  function searchFileForKeywords(filePath, keywords, cwd) {
111670
112237
  try {
111671
- const resolvedPath = path123.resolve(filePath);
111672
- const cwdResolved = path123.resolve(cwd);
112238
+ const resolvedPath = path124.resolve(filePath);
112239
+ const cwdResolved = path124.resolve(cwd);
111673
112240
  if (!resolvedPath.startsWith(cwdResolved)) {
111674
112241
  return false;
111675
112242
  }
@@ -111803,7 +112370,7 @@ var req_coverage = createSwarmTool({
111803
112370
  }, null, 2);
111804
112371
  }
111805
112372
  const cwd = inputDirectory || directory;
111806
- const specPath = path123.join(cwd, SPEC_FILE);
112373
+ const specPath = path124.join(cwd, SPEC_FILE);
111807
112374
  let specContent;
111808
112375
  try {
111809
112376
  specContent = fs92.readFileSync(specPath, "utf-8");
@@ -111830,7 +112397,7 @@ var req_coverage = createSwarmTool({
111830
112397
  message: "No FR requirements found in spec.md"
111831
112398
  }, null, 2);
111832
112399
  }
111833
- const evidenceDir = path123.join(cwd, EVIDENCE_DIR4);
112400
+ const evidenceDir = path124.join(cwd, EVIDENCE_DIR4);
111834
112401
  const touchedFiles = readTouchedFiles(evidenceDir, phase, cwd);
111835
112402
  const analyzedRequirements = [];
111836
112403
  let coveredCount = 0;
@@ -111856,7 +112423,7 @@ var req_coverage = createSwarmTool({
111856
112423
  requirements: analyzedRequirements
111857
112424
  };
111858
112425
  const reportFilename = `req-coverage-phase-${phase}.json`;
111859
- const reportPath = path123.join(evidenceDir, reportFilename);
112426
+ const reportPath = path124.join(evidenceDir, reportFilename);
111860
112427
  try {
111861
112428
  if (!fs92.existsSync(evidenceDir)) {
111862
112429
  fs92.mkdirSync(evidenceDir, { recursive: true });
@@ -111944,7 +112511,7 @@ init_qa_gate_profile();
111944
112511
  init_file_locks();
111945
112512
  import * as crypto11 from "node:crypto";
111946
112513
  import * as fs93 from "node:fs";
111947
- import * as path124 from "node:path";
112514
+ import * as path125 from "node:path";
111948
112515
  init_ledger();
111949
112516
  init_manager();
111950
112517
  init_state();
@@ -112022,8 +112589,8 @@ async function executeSavePlan(args2, fallbackDir) {
112022
112589
  };
112023
112590
  }
112024
112591
  if (args2.working_directory && fallbackDir) {
112025
- const resolvedTarget = path124.resolve(args2.working_directory);
112026
- const resolvedRoot = path124.resolve(fallbackDir);
112592
+ const resolvedTarget = path125.resolve(args2.working_directory);
112593
+ const resolvedRoot = path125.resolve(fallbackDir);
112027
112594
  let fallbackExists = false;
112028
112595
  try {
112029
112596
  fs93.accessSync(resolvedRoot, fs93.constants.F_OK);
@@ -112032,7 +112599,7 @@ async function executeSavePlan(args2, fallbackDir) {
112032
112599
  fallbackExists = false;
112033
112600
  }
112034
112601
  if (fallbackExists) {
112035
- const isSubdirectory = resolvedTarget.startsWith(resolvedRoot + path124.sep);
112602
+ const isSubdirectory = resolvedTarget.startsWith(resolvedRoot + path125.sep);
112036
112603
  if (isSubdirectory) {
112037
112604
  return {
112038
112605
  success: false,
@@ -112048,7 +112615,7 @@ async function executeSavePlan(args2, fallbackDir) {
112048
112615
  let specMtime;
112049
112616
  let specHash;
112050
112617
  if (process.env.SWARM_SKIP_SPEC_GATE !== "1") {
112051
- const specPath = path124.join(targetWorkspace, ".swarm", "spec.md");
112618
+ const specPath = path125.join(targetWorkspace, ".swarm", "spec.md");
112052
112619
  try {
112053
112620
  const stat8 = await fs93.promises.stat(specPath);
112054
112621
  specMtime = stat8.mtime.toISOString();
@@ -112064,7 +112631,7 @@ async function executeSavePlan(args2, fallbackDir) {
112064
112631
  }
112065
112632
  }
112066
112633
  if (process.env.SWARM_SKIP_GATE_SELECTION !== "1") {
112067
- const contextPath = path124.join(targetWorkspace, ".swarm", "context.md");
112634
+ const contextPath = path125.join(targetWorkspace, ".swarm", "context.md");
112068
112635
  let contextContent = "";
112069
112636
  try {
112070
112637
  contextContent = await fs93.promises.readFile(contextPath, "utf8");
@@ -112321,7 +112888,7 @@ async function executeSavePlan(args2, fallbackDir) {
112321
112888
  }
112322
112889
  await writeCheckpoint(dir).catch(() => {});
112323
112890
  try {
112324
- const markerPath = path124.join(dir, ".swarm", ".plan-write-marker");
112891
+ const markerPath = path125.join(dir, ".swarm", ".plan-write-marker");
112325
112892
  const marker = JSON.stringify({
112326
112893
  source: "save_plan",
112327
112894
  timestamp: new Date().toISOString(),
@@ -112344,7 +112911,7 @@ async function executeSavePlan(args2, fallbackDir) {
112344
112911
  return {
112345
112912
  success: true,
112346
112913
  message: "Plan saved successfully",
112347
- plan_path: path124.join(dir, ".swarm", "plan.json"),
112914
+ plan_path: path125.join(dir, ".swarm", "plan.json"),
112348
112915
  phases_count: plan.phases.length,
112349
112916
  tasks_count: tasksCount,
112350
112917
  ...resolvedProfile !== undefined ? { execution_profile: resolvedProfile } : {},
@@ -112409,7 +112976,7 @@ var save_plan = createSwarmTool({
112409
112976
  init_zod();
112410
112977
  init_manager2();
112411
112978
  import * as fs94 from "node:fs";
112412
- import * as path125 from "node:path";
112979
+ import * as path126 from "node:path";
112413
112980
 
112414
112981
  // src/sbom/detectors/index.ts
112415
112982
  init_utils();
@@ -113259,7 +113826,7 @@ function findManifestFiles(rootDir) {
113259
113826
  try {
113260
113827
  const entries = fs94.readdirSync(dir, { withFileTypes: true });
113261
113828
  for (const entry of entries) {
113262
- const fullPath = path125.join(dir, entry.name);
113829
+ const fullPath = path126.join(dir, entry.name);
113263
113830
  if (entry.name.startsWith(".") || entry.name === "node_modules" || entry.name === "dist" || entry.name === "build" || entry.name === "target") {
113264
113831
  continue;
113265
113832
  }
@@ -113268,7 +113835,7 @@ function findManifestFiles(rootDir) {
113268
113835
  } else if (entry.isFile()) {
113269
113836
  for (const pattern of patterns) {
113270
113837
  if (simpleGlobToRegex(pattern).test(entry.name)) {
113271
- manifestFiles.push(path125.relative(rootDir, fullPath));
113838
+ manifestFiles.push(path126.relative(rootDir, fullPath));
113272
113839
  break;
113273
113840
  }
113274
113841
  }
@@ -113286,11 +113853,11 @@ function findManifestFilesInDirs(directories, workingDir) {
113286
113853
  try {
113287
113854
  const entries = fs94.readdirSync(dir, { withFileTypes: true });
113288
113855
  for (const entry of entries) {
113289
- const fullPath = path125.join(dir, entry.name);
113856
+ const fullPath = path126.join(dir, entry.name);
113290
113857
  if (entry.isFile()) {
113291
113858
  for (const pattern of patterns) {
113292
113859
  if (simpleGlobToRegex(pattern).test(entry.name)) {
113293
- found.push(path125.relative(workingDir, fullPath));
113860
+ found.push(path126.relative(workingDir, fullPath));
113294
113861
  break;
113295
113862
  }
113296
113863
  }
@@ -113303,11 +113870,11 @@ function findManifestFilesInDirs(directories, workingDir) {
113303
113870
  function getDirectoriesFromChangedFiles(changedFiles, workingDir) {
113304
113871
  const dirs = new Set;
113305
113872
  for (const file3 of changedFiles) {
113306
- let currentDir = path125.dirname(file3);
113873
+ let currentDir = path126.dirname(file3);
113307
113874
  while (true) {
113308
- if (currentDir && currentDir !== "." && currentDir !== path125.sep) {
113309
- dirs.add(path125.join(workingDir, currentDir));
113310
- const parent = path125.dirname(currentDir);
113875
+ if (currentDir && currentDir !== "." && currentDir !== path126.sep) {
113876
+ dirs.add(path126.join(workingDir, currentDir));
113877
+ const parent = path126.dirname(currentDir);
113311
113878
  if (parent === currentDir)
113312
113879
  break;
113313
113880
  currentDir = parent;
@@ -113391,7 +113958,7 @@ var sbom_generate = createSwarmTool({
113391
113958
  const changedFiles = obj.changed_files;
113392
113959
  const relativeOutputDir = obj.output_dir || DEFAULT_OUTPUT_DIR;
113393
113960
  const workingDir = directory;
113394
- const outputDir = path125.isAbsolute(relativeOutputDir) ? relativeOutputDir : path125.join(workingDir, relativeOutputDir);
113961
+ const outputDir = path126.isAbsolute(relativeOutputDir) ? relativeOutputDir : path126.join(workingDir, relativeOutputDir);
113395
113962
  let manifestFiles = [];
113396
113963
  if (scope === "all") {
113397
113964
  manifestFiles = findManifestFiles(workingDir);
@@ -113414,7 +113981,7 @@ var sbom_generate = createSwarmTool({
113414
113981
  const processedFiles = [];
113415
113982
  for (const manifestFile of manifestFiles) {
113416
113983
  try {
113417
- const fullPath = path125.isAbsolute(manifestFile) ? manifestFile : path125.join(workingDir, manifestFile);
113984
+ const fullPath = path126.isAbsolute(manifestFile) ? manifestFile : path126.join(workingDir, manifestFile);
113418
113985
  if (!fs94.existsSync(fullPath)) {
113419
113986
  continue;
113420
113987
  }
@@ -113431,7 +113998,7 @@ var sbom_generate = createSwarmTool({
113431
113998
  const bom = generateCycloneDX(allComponents);
113432
113999
  const bomJson = serializeCycloneDX(bom);
113433
114000
  const filename = generateSbomFilename();
113434
- const outputPath = path125.join(outputDir, filename);
114001
+ const outputPath = path126.join(outputDir, filename);
113435
114002
  fs94.writeFileSync(outputPath, bomJson, "utf-8");
113436
114003
  const verdict = processedFiles.length > 0 ? "pass" : "pass";
113437
114004
  try {
@@ -113475,7 +114042,7 @@ var sbom_generate = createSwarmTool({
113475
114042
  init_zod();
113476
114043
  init_create_tool();
113477
114044
  import * as fs95 from "node:fs";
113478
- import * as path126 from "node:path";
114045
+ import * as path127 from "node:path";
113479
114046
  var SPEC_CANDIDATES = [
113480
114047
  "openapi.json",
113481
114048
  "openapi.yaml",
@@ -113507,12 +114074,12 @@ function normalizePath4(p) {
113507
114074
  }
113508
114075
  function discoverSpecFile(cwd, specFileArg) {
113509
114076
  if (specFileArg) {
113510
- const resolvedPath = path126.resolve(cwd, specFileArg);
113511
- const normalizedCwd = cwd.endsWith(path126.sep) ? cwd : cwd + path126.sep;
114077
+ const resolvedPath = path127.resolve(cwd, specFileArg);
114078
+ const normalizedCwd = cwd.endsWith(path127.sep) ? cwd : cwd + path127.sep;
113512
114079
  if (!resolvedPath.startsWith(normalizedCwd) && resolvedPath !== cwd) {
113513
114080
  throw new Error("Invalid spec_file: path traversal detected");
113514
114081
  }
113515
- const ext = path126.extname(resolvedPath).toLowerCase();
114082
+ const ext = path127.extname(resolvedPath).toLowerCase();
113516
114083
  if (!ALLOWED_EXTENSIONS.includes(ext)) {
113517
114084
  throw new Error(`Invalid spec_file: must end in .json, .yaml, or .yml, got ${ext}`);
113518
114085
  }
@@ -113526,7 +114093,7 @@ function discoverSpecFile(cwd, specFileArg) {
113526
114093
  return resolvedPath;
113527
114094
  }
113528
114095
  for (const candidate of SPEC_CANDIDATES) {
113529
- const candidatePath = path126.resolve(cwd, candidate);
114096
+ const candidatePath = path127.resolve(cwd, candidate);
113530
114097
  if (fs95.existsSync(candidatePath)) {
113531
114098
  const stats = fs95.statSync(candidatePath);
113532
114099
  if (stats.size <= MAX_SPEC_SIZE) {
@@ -113538,7 +114105,7 @@ function discoverSpecFile(cwd, specFileArg) {
113538
114105
  }
113539
114106
  function parseSpec(specFile) {
113540
114107
  const content = fs95.readFileSync(specFile, "utf-8");
113541
- const ext = path126.extname(specFile).toLowerCase();
114108
+ const ext = path127.extname(specFile).toLowerCase();
113542
114109
  if (ext === ".json") {
113543
114110
  return parseJsonSpec(content);
113544
114111
  }
@@ -113614,7 +114181,7 @@ function extractRoutes(cwd) {
113614
114181
  return;
113615
114182
  }
113616
114183
  for (const entry of entries) {
113617
- const fullPath = path126.join(dir, entry.name);
114184
+ const fullPath = path127.join(dir, entry.name);
113618
114185
  if (entry.isSymbolicLink()) {
113619
114186
  continue;
113620
114187
  }
@@ -113624,7 +114191,7 @@ function extractRoutes(cwd) {
113624
114191
  }
113625
114192
  walkDir(fullPath);
113626
114193
  } else if (entry.isFile()) {
113627
- const ext = path126.extname(entry.name).toLowerCase();
114194
+ const ext = path127.extname(entry.name).toLowerCase();
113628
114195
  const baseName = entry.name.toLowerCase();
113629
114196
  if (![".ts", ".js", ".mjs"].includes(ext)) {
113630
114197
  continue;
@@ -113792,7 +114359,7 @@ init_bun_compat();
113792
114359
  init_path_security();
113793
114360
  init_create_tool();
113794
114361
  import * as fs96 from "node:fs";
113795
- import * as path127 from "node:path";
114362
+ import * as path128 from "node:path";
113796
114363
  var DEFAULT_MAX_RESULTS = 100;
113797
114364
  var DEFAULT_MAX_LINES = 200;
113798
114365
  var REGEX_TIMEOUT_MS = 5000;
@@ -113828,11 +114395,11 @@ function containsWindowsAttacks3(str) {
113828
114395
  }
113829
114396
  function isPathInWorkspace3(filePath, workspace) {
113830
114397
  try {
113831
- const resolvedPath = path127.resolve(workspace, filePath);
114398
+ const resolvedPath = path128.resolve(workspace, filePath);
113832
114399
  const realWorkspace = fs96.realpathSync(workspace);
113833
114400
  const realResolvedPath = fs96.realpathSync(resolvedPath);
113834
- const relativePath = path127.relative(realWorkspace, realResolvedPath);
113835
- if (relativePath.startsWith("..") || path127.isAbsolute(relativePath)) {
114401
+ const relativePath = path128.relative(realWorkspace, realResolvedPath);
114402
+ if (relativePath.startsWith("..") || path128.isAbsolute(relativePath)) {
113836
114403
  return false;
113837
114404
  }
113838
114405
  return true;
@@ -113845,11 +114412,11 @@ function validatePathForRead2(filePath, workspace) {
113845
114412
  }
113846
114413
  function findRgInEnvPath() {
113847
114414
  const searchPath = process.env.PATH ?? "";
113848
- for (const dir of searchPath.split(path127.delimiter)) {
114415
+ for (const dir of searchPath.split(path128.delimiter)) {
113849
114416
  if (!dir)
113850
114417
  continue;
113851
114418
  const isWindows = process.platform === "win32";
113852
- const candidate = path127.join(dir, isWindows ? "rg.exe" : "rg");
114419
+ const candidate = path128.join(dir, isWindows ? "rg.exe" : "rg");
113853
114420
  if (fs96.existsSync(candidate))
113854
114421
  return candidate;
113855
114422
  }
@@ -113979,8 +114546,8 @@ function collectFiles(dir, workspace, includeGlobs, excludeGlobs) {
113979
114546
  try {
113980
114547
  const entries = fs96.readdirSync(dir, { withFileTypes: true });
113981
114548
  for (const entry of entries) {
113982
- const fullPath = path127.join(dir, entry.name);
113983
- const relativePath = path127.relative(workspace, fullPath);
114549
+ const fullPath = path128.join(dir, entry.name);
114550
+ const relativePath = path128.relative(workspace, fullPath);
113984
114551
  if (!validatePathForRead2(fullPath, workspace)) {
113985
114552
  continue;
113986
114553
  }
@@ -114021,7 +114588,7 @@ async function fallbackSearch(opts) {
114021
114588
  const matches = [];
114022
114589
  let total = 0;
114023
114590
  for (const file3 of files) {
114024
- const fullPath = path127.join(opts.workspace, file3);
114591
+ const fullPath = path128.join(opts.workspace, file3);
114025
114592
  if (!validatePathForRead2(fullPath, opts.workspace)) {
114026
114593
  continue;
114027
114594
  }
@@ -114389,7 +114956,7 @@ init_config();
114389
114956
  init_schema();
114390
114957
  init_create_tool();
114391
114958
  import { mkdir as mkdir21, rename as rename9, writeFile as writeFile16 } from "node:fs/promises";
114392
- import * as path128 from "node:path";
114959
+ import * as path129 from "node:path";
114393
114960
  var MAX_SPEC_BYTES = 256 * 1024;
114394
114961
  var spec_write = createSwarmTool({
114395
114962
  description: "Write the canonical project spec to .swarm/spec.md. Atomic write, size-bounded (256 KiB), heading-required. Honors spec_writer.allow_spec_write.",
@@ -114430,8 +114997,8 @@ var spec_write = createSwarmTool({
114430
114997
  reason: 'spec must contain at least one top-level "# Heading"'
114431
114998
  }, null, 2);
114432
114999
  }
114433
- const target = path128.join(directory, ".swarm", "spec.md");
114434
- await mkdir21(path128.dirname(target), { recursive: true });
115000
+ const target = path129.join(directory, ".swarm", "spec.md");
115001
+ await mkdir21(path129.dirname(target), { recursive: true });
114435
115002
  const tmp = `${target}.tmp-${process.pid}-${Date.now()}`;
114436
115003
  let finalContent = content;
114437
115004
  if (mode === "append") {
@@ -114460,13 +115027,13 @@ init_zod();
114460
115027
  init_loader();
114461
115028
  import {
114462
115029
  existsSync as existsSync74,
114463
- mkdirSync as mkdirSync32,
115030
+ mkdirSync as mkdirSync33,
114464
115031
  readFileSync as readFileSync64,
114465
115032
  renameSync as renameSync20,
114466
115033
  unlinkSync as unlinkSync16,
114467
115034
  writeFileSync as writeFileSync24
114468
115035
  } from "node:fs";
114469
- import path129 from "node:path";
115036
+ import path130 from "node:path";
114470
115037
  init_create_tool();
114471
115038
  init_resolve_working_directory();
114472
115039
  var VerdictSchema2 = exports_external.object({
@@ -114596,7 +115163,7 @@ var submit_phase_council_verdicts = createSwarmTool({
114596
115163
  }
114597
115164
  });
114598
115165
  function getPhaseMutationGapFinding(phaseNumber, workingDir) {
114599
- const mutationGatePath = path129.join(workingDir, ".swarm", "evidence", String(phaseNumber), "mutation-gate.json");
115166
+ const mutationGatePath = path130.join(workingDir, ".swarm", "evidence", String(phaseNumber), "mutation-gate.json");
114600
115167
  try {
114601
115168
  const raw = readFileSync64(mutationGatePath, "utf-8");
114602
115169
  const parsed = JSON.parse(raw);
@@ -114658,9 +115225,9 @@ function getPhaseMutationGapFinding(phaseNumber, workingDir) {
114658
115225
  }
114659
115226
  }
114660
115227
  function writePhaseCouncilEvidence(workingDir, synthesis) {
114661
- const evidenceDir = path129.join(workingDir, ".swarm", "evidence", String(synthesis.phaseNumber));
114662
- mkdirSync32(evidenceDir, { recursive: true });
114663
- const evidenceFile = path129.join(evidenceDir, "phase-council.json");
115228
+ const evidenceDir = path130.join(workingDir, ".swarm", "evidence", String(synthesis.phaseNumber));
115229
+ mkdirSync33(evidenceDir, { recursive: true });
115230
+ const evidenceFile = path130.join(evidenceDir, "phase-council.json");
114664
115231
  const evidenceBundle = {
114665
115232
  entries: [
114666
115233
  {
@@ -114813,16 +115380,20 @@ var swarm_memory_propose = createSwarmTool({
114813
115380
  }, {
114814
115381
  config: config3.memory
114815
115382
  });
114816
- const proposal = await gateway.propose(parsed.data);
114817
- return JSON.stringify({
114818
- success: proposal.status !== "rejected",
114819
- proposal_id: proposal.id,
114820
- status: proposal.status,
114821
- operation: proposal.operation,
114822
- memory_id: proposal.proposedRecord?.id,
114823
- rejection_reason: proposal.rejectionReason,
114824
- message: proposal.status === "pending" ? "Memory proposal created. Durable memory was not written." : "Memory proposal was captured with policy rejection metadata."
114825
- }, null, 2);
115383
+ try {
115384
+ const proposal = await gateway.propose(parsed.data);
115385
+ return JSON.stringify({
115386
+ success: proposal.status !== "rejected",
115387
+ proposal_id: proposal.id,
115388
+ status: proposal.status,
115389
+ operation: proposal.operation,
115390
+ memory_id: proposal.proposedRecord?.id,
115391
+ rejection_reason: proposal.rejectionReason,
115392
+ message: proposal.status === "pending" ? "Memory proposal created. Durable memory was not written." : "Memory proposal was captured with policy rejection metadata."
115393
+ }, null, 2);
115394
+ } finally {
115395
+ await gateway.dispose();
115396
+ }
114826
115397
  }
114827
115398
  });
114828
115399
  var _internals51 = {
@@ -114886,15 +115457,23 @@ var swarm_memory_recall = createSwarmTool({
114886
115457
  }, {
114887
115458
  config: config3.memory
114888
115459
  });
114889
- const bundle = await gateway.recall(parsed.data);
114890
- return JSON.stringify({
114891
- success: true,
114892
- bundle_id: bundle.id,
114893
- memory_ids: bundle.items.map((item) => item.record.id),
114894
- total: bundle.items.length,
114895
- token_estimate: bundle.tokenEstimate,
114896
- prompt_block: bundle.promptBlock
114897
- }, null, 2);
115460
+ try {
115461
+ const bundle = await gateway.recall(parsed.data);
115462
+ return JSON.stringify({
115463
+ success: true,
115464
+ bundle_id: bundle.id,
115465
+ memory_ids: bundle.items.map((item) => item.record.id),
115466
+ total: bundle.items.length,
115467
+ token_estimate: bundle.tokenEstimate,
115468
+ signals: bundle.items.map((item) => ({
115469
+ memory_id: item.record.id,
115470
+ ...item.signals
115471
+ })),
115472
+ prompt_block: bundle.promptBlock
115473
+ }, null, 2);
115474
+ } finally {
115475
+ await gateway.dispose();
115476
+ }
114898
115477
  }
114899
115478
  });
114900
115479
  var RecallArgsSchema = exports_external.object({
@@ -114917,7 +115496,7 @@ init_zod();
114917
115496
  init_path_security();
114918
115497
  init_create_tool();
114919
115498
  import * as fs97 from "node:fs";
114920
- import * as path130 from "node:path";
115499
+ import * as path131 from "node:path";
114921
115500
  var WINDOWS_RESERVED_NAMES4 = /^(con|prn|aux|nul|com[1-9]|lpt[1-9])(\.|:|$)/i;
114922
115501
  function containsWindowsAttacks4(str) {
114923
115502
  if (/:[^\\/]/.test(str))
@@ -114931,14 +115510,14 @@ function containsWindowsAttacks4(str) {
114931
115510
  }
114932
115511
  function isPathInWorkspace4(filePath, workspace) {
114933
115512
  try {
114934
- const resolvedPath = path130.resolve(workspace, filePath);
115513
+ const resolvedPath = path131.resolve(workspace, filePath);
114935
115514
  if (!fs97.existsSync(resolvedPath)) {
114936
115515
  return true;
114937
115516
  }
114938
115517
  const realWorkspace = fs97.realpathSync(workspace);
114939
115518
  const realResolvedPath = fs97.realpathSync(resolvedPath);
114940
- const relativePath = path130.relative(realWorkspace, realResolvedPath);
114941
- if (relativePath.startsWith("..") || path130.isAbsolute(relativePath)) {
115519
+ const relativePath = path131.relative(realWorkspace, realResolvedPath);
115520
+ if (relativePath.startsWith("..") || path131.isAbsolute(relativePath)) {
114942
115521
  return false;
114943
115522
  }
114944
115523
  return true;
@@ -115146,7 +115725,7 @@ var suggestPatch = createSwarmTool({
115146
115725
  });
115147
115726
  continue;
115148
115727
  }
115149
- const fullPath = path130.resolve(directory, change.file);
115728
+ const fullPath = path131.resolve(directory, change.file);
115150
115729
  if (!fs97.existsSync(fullPath)) {
115151
115730
  errors5.push({
115152
115731
  success: false,
@@ -115450,11 +116029,11 @@ var lean_turbo_acquire_locks = createSwarmTool({
115450
116029
  init_zod();
115451
116030
  init_constants();
115452
116031
  import * as fs99 from "node:fs";
115453
- import * as path132 from "node:path";
116032
+ import * as path133 from "node:path";
115454
116033
 
115455
116034
  // src/turbo/lean/conflicts.ts
115456
116035
  import * as fs98 from "node:fs";
115457
- import * as path131 from "node:path";
116036
+ import * as path132 from "node:path";
115458
116037
  var DEFAULT_GLOBAL_FILES = [
115459
116038
  "package.json",
115460
116039
  "package-lock.json",
@@ -115581,7 +116160,7 @@ function isProtectedPath2(normalizedPath) {
115581
116160
  return false;
115582
116161
  }
115583
116162
  function readTaskScopes(directory, taskId) {
115584
- const scopePath = path131.join(directory, ".swarm", "scopes", `scope-${taskId}.json`);
116163
+ const scopePath = path132.join(directory, ".swarm", "scopes", `scope-${taskId}.json`);
115585
116164
  try {
115586
116165
  if (!fs98.existsSync(scopePath)) {
115587
116166
  return null;
@@ -115969,7 +116548,7 @@ function createEmptyPlan(phaseNumber, planId) {
115969
116548
  // src/tools/lean-turbo-plan-lanes.ts
115970
116549
  init_create_tool();
115971
116550
  function readPlanJson(directory) {
115972
- const planPath = path132.join(directory, ".swarm", "plan.json");
116551
+ const planPath = path133.join(directory, ".swarm", "plan.json");
115973
116552
  if (!fs99.existsSync(planPath)) {
115974
116553
  return null;
115975
116554
  }
@@ -116024,7 +116603,7 @@ init_config();
116024
116603
  // src/turbo/lean/reviewer.ts
116025
116604
  init_state();
116026
116605
  import * as fs100 from "node:fs/promises";
116027
- import * as path133 from "node:path";
116606
+ import * as path134 from "node:path";
116028
116607
  init_state3();
116029
116608
  var DEFAULT_CONFIG3 = {
116030
116609
  reviewerAgent: "",
@@ -116140,9 +116719,9 @@ function parseReviewerVerdict(responseText) {
116140
116719
  return { verdict, reason };
116141
116720
  }
116142
116721
  async function writeReviewerEvidence(directory, phase, verdict, reason) {
116143
- const evidenceDir = path133.join(directory, ".swarm", "evidence", String(phase));
116722
+ const evidenceDir = path134.join(directory, ".swarm", "evidence", String(phase));
116144
116723
  await fs100.mkdir(evidenceDir, { recursive: true });
116145
- const evidencePath = path133.join(evidenceDir, "lean-turbo-reviewer.json");
116724
+ const evidencePath = path134.join(evidenceDir, "lean-turbo-reviewer.json");
116146
116725
  const content = JSON.stringify({
116147
116726
  phase,
116148
116727
  verdict,
@@ -116947,7 +117526,7 @@ var lean_turbo_status = createSwarmTool({
116947
117526
  init_spec_schema();
116948
117527
  init_create_tool();
116949
117528
  import * as fs101 from "node:fs";
116950
- import * as path134 from "node:path";
117529
+ import * as path135 from "node:path";
116951
117530
  var SPEC_FILE_NAME = "spec.md";
116952
117531
  var SWARM_DIR2 = ".swarm";
116953
117532
  var OBLIGATION_KEYWORDS2 = ["MUST", "SHALL", "SHOULD", "MAY"];
@@ -117000,7 +117579,7 @@ var lint_spec = createSwarmTool({
117000
117579
  async execute(_args, directory) {
117001
117580
  const errors5 = [];
117002
117581
  const warnings = [];
117003
- const specPath = path134.join(directory, SWARM_DIR2, SPEC_FILE_NAME);
117582
+ const specPath = path135.join(directory, SWARM_DIR2, SPEC_FILE_NAME);
117004
117583
  if (!fs101.existsSync(specPath)) {
117005
117584
  const result2 = {
117006
117585
  valid: false,
@@ -117071,12 +117650,12 @@ var lint_spec = createSwarmTool({
117071
117650
  // src/tools/mutation-test.ts
117072
117651
  init_zod();
117073
117652
  import * as fs102 from "node:fs";
117074
- import * as path136 from "node:path";
117653
+ import * as path137 from "node:path";
117075
117654
 
117076
117655
  // src/mutation/engine.ts
117077
117656
  import { spawnSync as spawnSync3 } from "node:child_process";
117078
117657
  import { unlinkSync as unlinkSync17, writeFileSync as writeFileSync25 } from "node:fs";
117079
- import * as path135 from "node:path";
117658
+ import * as path136 from "node:path";
117080
117659
 
117081
117660
  // src/mutation/equivalence.ts
117082
117661
  function isStaticallyEquivalent(originalCode, mutatedCode) {
@@ -117222,7 +117801,7 @@ async function executeMutation(patch, testCommand, _testFiles, workingDir) {
117222
117801
  let patchFile;
117223
117802
  try {
117224
117803
  const safeId2 = patch.id.replace(/[^a-zA-Z0-9_-]/g, "_");
117225
- patchFile = path135.join(workingDir, `.mutation_patch_${safeId2}.diff`);
117804
+ patchFile = path136.join(workingDir, `.mutation_patch_${safeId2}.diff`);
117226
117805
  try {
117227
117806
  writeFileSync25(patchFile, patch.patch);
117228
117807
  } catch (writeErr) {
@@ -117626,7 +118205,7 @@ var mutation_test = createSwarmTool({
117626
118205
  ];
117627
118206
  for (const filePath of uniquePaths) {
117628
118207
  try {
117629
- const resolvedPath = path136.resolve(cwd, filePath);
118208
+ const resolvedPath = path137.resolve(cwd, filePath);
117630
118209
  sourceFiles.set(filePath, fs102.readFileSync(resolvedPath, "utf-8"));
117631
118210
  } catch {}
117632
118211
  }
@@ -117646,7 +118225,7 @@ init_zod();
117646
118225
  init_manager2();
117647
118226
  init_detector();
117648
118227
  import * as fs103 from "node:fs";
117649
- import * as path137 from "node:path";
118228
+ import * as path138 from "node:path";
117650
118229
  init_create_tool();
117651
118230
  var MAX_FILE_SIZE2 = 2 * 1024 * 1024;
117652
118231
  var BINARY_CHECK_BYTES = 8192;
@@ -117712,7 +118291,7 @@ async function syntaxCheck(input, directory, config3) {
117712
118291
  if (languages?.length) {
117713
118292
  const lowerLangs = languages.map((l) => l.toLowerCase());
117714
118293
  filesToCheck = filesToCheck.filter((file3) => {
117715
- const ext = path137.extname(file3.path).toLowerCase();
118294
+ const ext = path138.extname(file3.path).toLowerCase();
117716
118295
  const langDef = getLanguageForExtension(ext);
117717
118296
  const fileProfile = getProfileForFile(file3.path);
117718
118297
  const langId = fileProfile?.id || langDef?.id;
@@ -117725,7 +118304,7 @@ async function syntaxCheck(input, directory, config3) {
117725
118304
  let skippedCount = 0;
117726
118305
  for (const fileInfo of filesToCheck) {
117727
118306
  const { path: filePath } = fileInfo;
117728
- const fullPath = path137.isAbsolute(filePath) ? filePath : path137.join(directory, filePath);
118307
+ const fullPath = path138.isAbsolute(filePath) ? filePath : path138.join(directory, filePath);
117729
118308
  const result = {
117730
118309
  path: filePath,
117731
118310
  language: "",
@@ -117774,7 +118353,7 @@ async function syntaxCheck(input, directory, config3) {
117774
118353
  results.push(result);
117775
118354
  continue;
117776
118355
  }
117777
- const ext = path137.extname(filePath).toLowerCase();
118356
+ const ext = path138.extname(filePath).toLowerCase();
117778
118357
  const langDef = getLanguageForExtension(ext);
117779
118358
  result.language = profile?.id || langDef?.id || "unknown";
117780
118359
  const errors5 = extractSyntaxErrors(parser, content);
@@ -117872,7 +118451,7 @@ init_utils();
117872
118451
  init_create_tool();
117873
118452
  init_path_security();
117874
118453
  import * as fs104 from "node:fs";
117875
- import * as path138 from "node:path";
118454
+ import * as path139 from "node:path";
117876
118455
  var MAX_TEXT_LENGTH = 200;
117877
118456
  var MAX_FILE_SIZE_BYTES11 = 1024 * 1024;
117878
118457
  var SUPPORTED_EXTENSIONS4 = new Set([
@@ -117938,9 +118517,9 @@ function validatePathsInput(paths, cwd) {
117938
118517
  return { error: "paths contains path traversal", resolvedPath: null };
117939
118518
  }
117940
118519
  try {
117941
- const resolvedPath = path138.resolve(paths);
117942
- const normalizedCwd = path138.resolve(cwd);
117943
- const normalizedResolved = path138.resolve(resolvedPath);
118520
+ const resolvedPath = path139.resolve(paths);
118521
+ const normalizedCwd = path139.resolve(cwd);
118522
+ const normalizedResolved = path139.resolve(resolvedPath);
117944
118523
  if (!normalizedResolved.startsWith(normalizedCwd)) {
117945
118524
  return {
117946
118525
  error: "paths must be within the current working directory",
@@ -117956,7 +118535,7 @@ function validatePathsInput(paths, cwd) {
117956
118535
  }
117957
118536
  }
117958
118537
  function isSupportedExtension(filePath) {
117959
- const ext = path138.extname(filePath).toLowerCase();
118538
+ const ext = path139.extname(filePath).toLowerCase();
117960
118539
  return SUPPORTED_EXTENSIONS4.has(ext);
117961
118540
  }
117962
118541
  function findSourceFiles3(dir, files = []) {
@@ -117971,7 +118550,7 @@ function findSourceFiles3(dir, files = []) {
117971
118550
  if (SKIP_DIRECTORIES5.has(entry)) {
117972
118551
  continue;
117973
118552
  }
117974
- const fullPath = path138.join(dir, entry);
118553
+ const fullPath = path139.join(dir, entry);
117975
118554
  let stat8;
117976
118555
  try {
117977
118556
  stat8 = fs104.statSync(fullPath);
@@ -118083,7 +118662,7 @@ var todo_extract = createSwarmTool({
118083
118662
  filesToScan.push(scanPath);
118084
118663
  } else {
118085
118664
  const errorResult = {
118086
- error: `unsupported file extension: ${path138.extname(scanPath)}`,
118665
+ error: `unsupported file extension: ${path139.extname(scanPath)}`,
118087
118666
  total: 0,
118088
118667
  byPriority: { high: 0, medium: 0, low: 0 },
118089
118668
  entries: []
@@ -118132,17 +118711,17 @@ init_schema();
118132
118711
  init_qa_gate_profile();
118133
118712
  init_gate_evidence();
118134
118713
  import * as fs108 from "node:fs";
118135
- import * as path142 from "node:path";
118714
+ import * as path143 from "node:path";
118136
118715
 
118137
118716
  // src/hooks/diff-scope.ts
118138
118717
  init_bun_compat();
118139
118718
  import * as fs106 from "node:fs";
118140
- import * as path140 from "node:path";
118719
+ import * as path141 from "node:path";
118141
118720
 
118142
118721
  // src/utils/gitignore-warning.ts
118143
118722
  init_bun_compat();
118144
118723
  import * as fs105 from "node:fs";
118145
- import * as path139 from "node:path";
118724
+ import * as path140 from "node:path";
118146
118725
  var _internals58 = { bunSpawn };
118147
118726
  var _swarmGitExcludedChecked = false;
118148
118727
  function fileCoversSwarm(content) {
@@ -118216,10 +118795,10 @@ async function ensureSwarmGitExcluded(directory, options = {}) {
118216
118795
  const excludeRelPath = excludePathRaw.trim();
118217
118796
  if (!excludeRelPath)
118218
118797
  return;
118219
- const excludePath = path139.isAbsolute(excludeRelPath) ? excludeRelPath : path139.join(directory, excludeRelPath);
118798
+ const excludePath = path140.isAbsolute(excludeRelPath) ? excludeRelPath : path140.join(directory, excludeRelPath);
118220
118799
  if (checkIgnoreExitCode !== 0) {
118221
118800
  try {
118222
- fs105.mkdirSync(path139.dirname(excludePath), { recursive: true });
118801
+ fs105.mkdirSync(path140.dirname(excludePath), { recursive: true });
118223
118802
  let existing = "";
118224
118803
  try {
118225
118804
  existing = fs105.readFileSync(excludePath, "utf8");
@@ -118263,7 +118842,7 @@ async function ensureSwarmGitExcluded(directory, options = {}) {
118263
118842
  var _internals59 = { bunSpawn };
118264
118843
  function getDeclaredScope(taskId, directory) {
118265
118844
  try {
118266
- const planPath = path140.join(directory, ".swarm", "plan.json");
118845
+ const planPath = path141.join(directory, ".swarm", "plan.json");
118267
118846
  if (!fs106.existsSync(planPath))
118268
118847
  return null;
118269
118848
  const raw = fs106.readFileSync(planPath, "utf-8");
@@ -118369,7 +118948,7 @@ init_telemetry();
118369
118948
  // src/turbo/lean/task-completion.ts
118370
118949
  init_file_locks();
118371
118950
  import * as fs107 from "node:fs";
118372
- import * as path141 from "node:path";
118951
+ import * as path142 from "node:path";
118373
118952
  var _internals60 = {
118374
118953
  listActiveLocks,
118375
118954
  verifyLeanTurboTaskCompletion
@@ -118388,7 +118967,7 @@ var TIER_3_PATTERNS = [
118388
118967
  ];
118389
118968
  function matchesTier3Pattern(files) {
118390
118969
  for (const file3 of files) {
118391
- const fileName = path141.basename(file3);
118970
+ const fileName = path142.basename(file3);
118392
118971
  for (const pattern of TIER_3_PATTERNS) {
118393
118972
  if (pattern.test(fileName)) {
118394
118973
  return true;
@@ -118400,7 +118979,7 @@ function matchesTier3Pattern(files) {
118400
118979
  function verifyLeanTurboTaskCompletion(directory, taskId, sessionID) {
118401
118980
  let persisted = null;
118402
118981
  try {
118403
- const statePath = path141.join(directory, ".swarm", "turbo-state.json");
118982
+ const statePath = path142.join(directory, ".swarm", "turbo-state.json");
118404
118983
  if (!fs107.existsSync(statePath)) {
118405
118984
  return {
118406
118985
  ok: false,
@@ -118484,11 +119063,11 @@ function verifyLeanTurboTaskCompletion(directory, taskId, sessionID) {
118484
119063
  };
118485
119064
  }
118486
119065
  const phase = runState.phase ?? 0;
118487
- const evidencePath = path141.join(directory, ".swarm", "evidence", String(phase), "lean-turbo", `${lane.laneId}.json`);
118488
- const expectedDir = path141.join(directory, ".swarm", "evidence", String(phase), "lean-turbo");
118489
- const resolvedPath = path141.resolve(evidencePath);
118490
- const resolvedDir = path141.resolve(expectedDir);
118491
- if (!resolvedPath.startsWith(resolvedDir + path141.sep) && resolvedPath !== resolvedDir) {
119066
+ const evidencePath = path142.join(directory, ".swarm", "evidence", String(phase), "lean-turbo", `${lane.laneId}.json`);
119067
+ const expectedDir = path142.join(directory, ".swarm", "evidence", String(phase), "lean-turbo");
119068
+ const resolvedPath = path142.resolve(evidencePath);
119069
+ const resolvedDir = path142.resolve(expectedDir);
119070
+ if (!resolvedPath.startsWith(resolvedDir + path142.sep) && resolvedPath !== resolvedDir) {
118492
119071
  return {
118493
119072
  ok: false,
118494
119073
  reason: `Lane ID causes path traversal: ${lane.laneId}`,
@@ -118528,7 +119107,7 @@ function verifyLeanTurboTaskCompletion(directory, taskId, sessionID) {
118528
119107
  }
118529
119108
  let filesTouched = [];
118530
119109
  try {
118531
- const planPath = path141.join(directory, ".swarm", "plan.json");
119110
+ const planPath = path142.join(directory, ".swarm", "plan.json");
118532
119111
  const planRaw = fs107.readFileSync(planPath, "utf-8");
118533
119112
  const plan = JSON.parse(planRaw);
118534
119113
  for (const planPhase of plan.phases ?? []) {
@@ -118612,7 +119191,7 @@ var TIER_3_PATTERNS2 = [
118612
119191
  ];
118613
119192
  function matchesTier3Pattern2(files) {
118614
119193
  for (const file3 of files) {
118615
- const fileName = path142.basename(file3);
119194
+ const fileName = path143.basename(file3);
118616
119195
  for (const pattern of TIER_3_PATTERNS2) {
118617
119196
  if (pattern.test(fileName)) {
118618
119197
  return true;
@@ -118651,7 +119230,7 @@ function checkReviewerGate(taskId, workingDirectory, stageBParallelEnabled = fal
118651
119230
  if (!skipStandardTurboBypass && hasActiveTurboMode()) {
118652
119231
  const resolvedDir2 = workingDirectory;
118653
119232
  try {
118654
- const planPath = path142.join(resolvedDir2, ".swarm", "plan.json");
119233
+ const planPath = path143.join(resolvedDir2, ".swarm", "plan.json");
118655
119234
  const planRaw = fs108.readFileSync(planPath, "utf-8");
118656
119235
  const plan = JSON.parse(planRaw);
118657
119236
  for (const planPhase of plan.phases ?? []) {
@@ -118729,7 +119308,7 @@ function checkReviewerGate(taskId, workingDirectory, stageBParallelEnabled = fal
118729
119308
  }
118730
119309
  if (resolvedDir) {
118731
119310
  try {
118732
- const planPath = path142.join(resolvedDir, ".swarm", "plan.json");
119311
+ const planPath = path143.join(resolvedDir, ".swarm", "plan.json");
118733
119312
  const planRaw = fs108.readFileSync(planPath, "utf-8");
118734
119313
  const plan = JSON.parse(planRaw);
118735
119314
  for (const planPhase of plan.phases ?? []) {
@@ -118966,8 +119545,8 @@ async function executeUpdateTaskStatus(args2, fallbackDir, ctx) {
118966
119545
  };
118967
119546
  }
118968
119547
  }
118969
- normalizedDir = path142.normalize(args2.working_directory);
118970
- const pathParts = normalizedDir.split(path142.sep);
119548
+ normalizedDir = path143.normalize(args2.working_directory);
119549
+ const pathParts = normalizedDir.split(path143.sep);
118971
119550
  if (pathParts.includes("..")) {
118972
119551
  return {
118973
119552
  success: false,
@@ -118977,10 +119556,10 @@ async function executeUpdateTaskStatus(args2, fallbackDir, ctx) {
118977
119556
  ]
118978
119557
  };
118979
119558
  }
118980
- const resolvedDir = path142.resolve(normalizedDir);
119559
+ const resolvedDir = path143.resolve(normalizedDir);
118981
119560
  try {
118982
119561
  const realPath = fs108.realpathSync(resolvedDir);
118983
- const planPath = path142.join(realPath, ".swarm", "plan.json");
119562
+ const planPath = path143.join(realPath, ".swarm", "plan.json");
118984
119563
  if (!fs108.existsSync(planPath)) {
118985
119564
  return {
118986
119565
  success: false,
@@ -119011,9 +119590,9 @@ async function executeUpdateTaskStatus(args2, fallbackDir, ctx) {
119011
119590
  directory = fallbackDir;
119012
119591
  }
119013
119592
  if (fallbackDir && directory !== fallbackDir) {
119014
- const canonicalDir = fs108.realpathSync(path142.resolve(directory));
119015
- const canonicalRoot = fs108.realpathSync(path142.resolve(fallbackDir));
119016
- if (canonicalDir.startsWith(canonicalRoot + path142.sep)) {
119593
+ const canonicalDir = fs108.realpathSync(path143.resolve(directory));
119594
+ const canonicalRoot = fs108.realpathSync(path143.resolve(fallbackDir));
119595
+ if (canonicalDir.startsWith(canonicalRoot + path143.sep)) {
119017
119596
  return {
119018
119597
  success: false,
119019
119598
  message: `Invalid working_directory: "${directory}" is a subdirectory of ` + `the project root "${fallbackDir}". Pass the project root path or ` + `omit working_directory entirely.`,
@@ -119025,8 +119604,8 @@ async function executeUpdateTaskStatus(args2, fallbackDir, ctx) {
119025
119604
  }
119026
119605
  if (args2.status === "in_progress") {
119027
119606
  try {
119028
- const evidencePath = path142.join(directory, ".swarm", "evidence", `${args2.task_id}.json`);
119029
- fs108.mkdirSync(path142.dirname(evidencePath), { recursive: true });
119607
+ const evidencePath = path143.join(directory, ".swarm", "evidence", `${args2.task_id}.json`);
119608
+ fs108.mkdirSync(path143.dirname(evidencePath), { recursive: true });
119030
119609
  const fd = fs108.openSync(evidencePath, "wx");
119031
119610
  let writeOk = false;
119032
119611
  try {
@@ -119050,7 +119629,7 @@ async function executeUpdateTaskStatus(args2, fallbackDir, ctx) {
119050
119629
  recoverTaskStateFromDelegations(args2.task_id, directory);
119051
119630
  let phaseRequiresReviewer = true;
119052
119631
  try {
119053
- const planPath = path142.join(directory, ".swarm", "plan.json");
119632
+ const planPath = path143.join(directory, ".swarm", "plan.json");
119054
119633
  const planRaw = fs108.readFileSync(planPath, "utf-8");
119055
119634
  const plan = JSON.parse(planRaw);
119056
119635
  const taskPhase = plan.phases.find((p) => p.tasks.some((t) => t.id === args2.task_id));
@@ -119362,7 +119941,7 @@ init_ledger();
119362
119941
  init_manager();
119363
119942
  init_create_tool();
119364
119943
  import fs109 from "node:fs";
119365
- import path143 from "node:path";
119944
+ import path144 from "node:path";
119366
119945
  function normalizeVerdict(verdict) {
119367
119946
  switch (verdict) {
119368
119947
  case "APPROVED":
@@ -119410,7 +119989,7 @@ async function executeWriteDriftEvidence(args2, directory) {
119410
119989
  entries: [evidenceEntry]
119411
119990
  };
119412
119991
  const filename = "drift-verifier.json";
119413
- const relativePath = path143.join("evidence", String(phase), filename);
119992
+ const relativePath = path144.join("evidence", String(phase), filename);
119414
119993
  let validatedPath;
119415
119994
  try {
119416
119995
  validatedPath = validateSwarmPath(directory, relativePath);
@@ -119421,10 +120000,10 @@ async function executeWriteDriftEvidence(args2, directory) {
119421
120000
  message: error93 instanceof Error ? error93.message : "Failed to validate path"
119422
120001
  }, null, 2);
119423
120002
  }
119424
- const evidenceDir = path143.dirname(validatedPath);
120003
+ const evidenceDir = path144.dirname(validatedPath);
119425
120004
  try {
119426
120005
  await fs109.promises.mkdir(evidenceDir, { recursive: true });
119427
- const tempPath = path143.join(evidenceDir, `.${filename}.tmp`);
120006
+ const tempPath = path144.join(evidenceDir, `.${filename}.tmp`);
119428
120007
  await fs109.promises.writeFile(tempPath, JSON.stringify(evidenceContent, null, 2), "utf-8");
119429
120008
  await fs109.promises.rename(tempPath, validatedPath);
119430
120009
  let snapshotInfo;
@@ -119520,7 +120099,7 @@ var write_drift_evidence = createSwarmTool({
119520
120099
  init_zod();
119521
120100
  init_loader();
119522
120101
  import fs110 from "node:fs";
119523
- import path144 from "node:path";
120102
+ import path145 from "node:path";
119524
120103
  init_utils2();
119525
120104
  init_manager();
119526
120105
  init_create_tool();
@@ -119608,7 +120187,7 @@ async function executeWriteFinalCouncilEvidence(args2, directory) {
119608
120187
  timestamp: synthesis.timestamp
119609
120188
  };
119610
120189
  const filename = "final-council.json";
119611
- const relativePath = path144.join("evidence", filename);
120190
+ const relativePath = path145.join("evidence", filename);
119612
120191
  let validatedPath;
119613
120192
  try {
119614
120193
  validatedPath = validateSwarmPath(directory, relativePath);
@@ -119622,10 +120201,10 @@ async function executeWriteFinalCouncilEvidence(args2, directory) {
119622
120201
  const evidenceContent = {
119623
120202
  entries: [evidenceEntry]
119624
120203
  };
119625
- const evidenceDir = path144.dirname(validatedPath);
120204
+ const evidenceDir = path145.dirname(validatedPath);
119626
120205
  try {
119627
120206
  await fs110.promises.mkdir(evidenceDir, { recursive: true });
119628
- const tempPath = path144.join(evidenceDir, `.${filename}.tmp`);
120207
+ const tempPath = path145.join(evidenceDir, `.${filename}.tmp`);
119629
120208
  await fs110.promises.writeFile(tempPath, JSON.stringify(evidenceContent, null, 2), "utf-8");
119630
120209
  await fs110.promises.rename(tempPath, validatedPath);
119631
120210
  return JSON.stringify({
@@ -119684,7 +120263,7 @@ init_zod();
119684
120263
  init_utils2();
119685
120264
  init_create_tool();
119686
120265
  import fs111 from "node:fs";
119687
- import path145 from "node:path";
120266
+ import path146 from "node:path";
119688
120267
  function normalizeVerdict2(verdict) {
119689
120268
  switch (verdict) {
119690
120269
  case "APPROVED":
@@ -119732,7 +120311,7 @@ async function executeWriteHallucinationEvidence(args2, directory) {
119732
120311
  entries: [evidenceEntry]
119733
120312
  };
119734
120313
  const filename = "hallucination-guard.json";
119735
- const relativePath = path145.join("evidence", String(phase), filename);
120314
+ const relativePath = path146.join("evidence", String(phase), filename);
119736
120315
  let validatedPath;
119737
120316
  try {
119738
120317
  validatedPath = validateSwarmPath(directory, relativePath);
@@ -119743,10 +120322,10 @@ async function executeWriteHallucinationEvidence(args2, directory) {
119743
120322
  message: error93 instanceof Error ? error93.message : "Failed to validate path"
119744
120323
  }, null, 2);
119745
120324
  }
119746
- const evidenceDir = path145.dirname(validatedPath);
120325
+ const evidenceDir = path146.dirname(validatedPath);
119747
120326
  try {
119748
120327
  await fs111.promises.mkdir(evidenceDir, { recursive: true });
119749
- const tempPath = path145.join(evidenceDir, `.${filename}.tmp`);
120328
+ const tempPath = path146.join(evidenceDir, `.${filename}.tmp`);
119750
120329
  await fs111.promises.writeFile(tempPath, JSON.stringify(evidenceContent, null, 2), "utf-8");
119751
120330
  await fs111.promises.rename(tempPath, validatedPath);
119752
120331
  return JSON.stringify({
@@ -119795,7 +120374,7 @@ init_zod();
119795
120374
  init_utils2();
119796
120375
  init_create_tool();
119797
120376
  import fs112 from "node:fs";
119798
- import path146 from "node:path";
120377
+ import path147 from "node:path";
119799
120378
  function normalizeVerdict3(verdict) {
119800
120379
  switch (verdict) {
119801
120380
  case "PASS":
@@ -119869,7 +120448,7 @@ async function executeWriteMutationEvidence(args2, directory) {
119869
120448
  entries: [evidenceEntry]
119870
120449
  };
119871
120450
  const filename = "mutation-gate.json";
119872
- const relativePath = path146.join("evidence", String(phase), filename);
120451
+ const relativePath = path147.join("evidence", String(phase), filename);
119873
120452
  let validatedPath;
119874
120453
  try {
119875
120454
  validatedPath = validateSwarmPath(directory, relativePath);
@@ -119880,10 +120459,10 @@ async function executeWriteMutationEvidence(args2, directory) {
119880
120459
  message: error93 instanceof Error ? error93.message : "Failed to validate path"
119881
120460
  }, null, 2);
119882
120461
  }
119883
- const evidenceDir = path146.dirname(validatedPath);
120462
+ const evidenceDir = path147.dirname(validatedPath);
119884
120463
  try {
119885
120464
  await fs112.promises.mkdir(evidenceDir, { recursive: true });
119886
- const tempPath = path146.join(evidenceDir, `.${filename}.tmp`);
120465
+ const tempPath = path147.join(evidenceDir, `.${filename}.tmp`);
119887
120466
  await fs112.promises.writeFile(tempPath, JSON.stringify(evidenceContent, null, 2), "utf-8");
119888
120467
  await fs112.promises.rename(tempPath, validatedPath);
119889
120468
  return JSON.stringify({
@@ -120233,7 +120812,7 @@ async function initializeOpenCodeSwarm(ctx) {
120233
120812
  const { PreflightTriggerManager: PTM } = await Promise.resolve().then(() => (init_trigger(), exports_trigger));
120234
120813
  preflightTriggerManager = new PTM(automationConfig);
120235
120814
  const { AutomationStatusArtifact: ASA } = await Promise.resolve().then(() => (init_status_artifact(), exports_status_artifact));
120236
- const swarmDir = path148.resolve(ctx.directory, ".swarm");
120815
+ const swarmDir = path149.resolve(ctx.directory, ".swarm");
120237
120816
  statusArtifact = new ASA(swarmDir);
120238
120817
  statusArtifact.updateConfig(automationConfig.mode, automationConfig.capabilities);
120239
120818
  if (automationConfig.capabilities?.evidence_auto_summaries === true) {
@@ -120412,30 +120991,29 @@ async function initializeOpenCodeSwarm(ctx) {
120412
120991
  swarm_command: createSwarmCommandTool(agentDefinitionMap)
120413
120992
  },
120414
120993
  config: async (opencodeConfig) => {
120415
- if (!opencodeConfig.agent || typeof opencodeConfig.agent !== "object") {
120416
- opencodeConfig.agent = {};
120417
- }
120418
- if (!opencodeConfig.agent) {
120419
- opencodeConfig.agent = { ...agents };
120420
- } else {
120421
- Object.assign(opencodeConfig.agent, agents);
120994
+ const isObjectRecord = (value) => typeof value === "object" && value !== null;
120995
+ const pluginConfig = opencodeConfig;
120996
+ if (!isObjectRecord(pluginConfig.agent)) {
120997
+ pluginConfig.agent = {};
120422
120998
  }
120999
+ const agentConfig = pluginConfig.agent;
121000
+ Object.assign(agentConfig, agents);
120423
121001
  const autoSelect = config3?.auto_select_architect;
120424
121002
  if (autoSelect) {
120425
121003
  const hasArchitect = Object.keys(agents).some((name2) => stripKnownSwarmPrefix(name2) === "architect");
120426
121004
  if (hasArchitect) {
120427
121005
  for (const builtin of ["build", "plan"]) {
120428
- const existing = opencodeConfig.agent?.[builtin];
120429
- if (existing && typeof existing === "object" && existing.disable === true) {
121006
+ const existing = agentConfig[builtin];
121007
+ if (isObjectRecord(existing) && existing.disable === true) {
120430
121008
  continue;
120431
121009
  }
120432
- opencodeConfig.agent[builtin] = {
120433
- ...existing && typeof existing === "object" ? existing : {},
121010
+ agentConfig[builtin] = {
121011
+ ...isObjectRecord(existing) ? existing : {},
120434
121012
  disable: true
120435
121013
  };
120436
121014
  }
120437
121015
  if (autoSelect === true) {
120438
- const primaryArchitects = Object.entries(agents).filter(([name2, cfg]) => stripKnownSwarmPrefix(name2) === "architect" && cfg.mode === "primary");
121016
+ const primaryArchitects = Object.entries(agents).filter(([name2, cfg]) => stripKnownSwarmPrefix(name2) === "architect" && isObjectRecord(cfg) && cfg.mode === "primary");
120439
121017
  if (primaryArchitects.length > 1) {
120440
121018
  const names = primaryArchitects.map(([n]) => n).join(", ");
120441
121019
  addDeferredWarning(`[swarm] auto_select_architect is true but ${primaryArchitects.length} architect agents are primary (${names}). Consider setting auto_select_architect to a specific agent name.`);
@@ -120447,22 +121025,19 @@ async function initializeOpenCodeSwarm(ctx) {
120447
121025
  if (targetIsArchitect) {
120448
121026
  for (const [name2, cfg] of Object.entries(agents)) {
120449
121027
  if (stripKnownSwarmPrefix(name2) === "architect" && name2 !== targetName) {
120450
- if (opencodeConfig.agent && typeof opencodeConfig.agent === "object") {
120451
- opencodeConfig.agent[name2] = {
120452
- ...cfg && typeof cfg === "object" ? cfg : {},
120453
- mode: "subagent"
120454
- };
120455
- }
121028
+ agentConfig[name2] = {
121029
+ ...isObjectRecord(cfg) ? cfg : {},
121030
+ mode: "subagent"
121031
+ };
120456
121032
  }
120457
121033
  }
120458
- if (opencodeConfig.agent && typeof opencodeConfig.agent === "object") {
120459
- const targetExisting = opencodeConfig.agent[targetName];
120460
- opencodeConfig.agent[targetName] = {
120461
- ...targetExisting && typeof targetExisting === "object" ? targetExisting : {},
120462
- ...agents[targetName] && typeof agents[targetName] === "object" ? agents[targetName] : {},
120463
- mode: "primary"
120464
- };
120465
- }
121034
+ const targetExisting = agentConfig[targetName];
121035
+ const targetAgent = agents[targetName];
121036
+ agentConfig[targetName] = {
121037
+ ...isObjectRecord(targetExisting) ? targetExisting : {},
121038
+ ...isObjectRecord(targetAgent) ? targetAgent : {},
121039
+ mode: "primary"
121040
+ };
120466
121041
  } else {
120467
121042
  addDeferredWarning(`[swarm] auto_select_architect is set to "${targetName}" but that is not a known architect agent. No architect demotion applied.`);
120468
121043
  }
@@ -120817,7 +121392,7 @@ ${promptRaw}`;
120817
121392
  "ci-failure-resolver": "CI/CD failure resolution"
120818
121393
  };
120819
121394
  const skillPaths = topSkills.map((s) => {
120820
- const dirName = path148.basename(path148.dirname(s.skillPath));
121395
+ const dirName = path149.basename(path149.dirname(s.skillPath));
120821
121396
  const desc = SKILL_DESCRIPTIONS[dirName] ?? dirName;
120822
121397
  return `file:${s.skillPath} (-- ${desc})`;
120823
121398
  }).join(", ");
@@ -120826,7 +121401,7 @@ ${promptRaw}`;
120826
121401
 
120827
121402
  ${promptRaw}`;
120828
121403
  argsRecord.prompt = newPrompt;
120829
- const skillNames = topSkills.map((s) => `${path148.basename(s.skillPath)} (score: ${s.score.toFixed(2)})`).join(", ");
121404
+ const skillNames = topSkills.map((s) => `${path149.basename(s.skillPath)} (score: ${s.score.toFixed(2)})`).join(", ");
120830
121405
  console.warn(`[skill-propagation-gate] Injected skills: ${skillNames}`);
120831
121406
  for (const skill of topSkills) {
120832
121407
  try {